feat: 完善任务功能 增加命令 优化代码

Signed-off-by: 502647092 <admin@yumc.pw>
This commit is contained in:
2017-10-09 21:17:24 +08:00
parent 2fb73aee53
commit c13ef6f393
14 changed files with 328 additions and 135 deletions

View File

@ -0,0 +1,74 @@
package pw.yumc.MiaoScript;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.stream.Collectors;
import lombok.val;
import pw.yumc.YumCore.annotation.NotProguard;
import pw.yumc.YumCore.bukkit.Log;
import pw.yumc.YumCore.bukkit.compatible.C;
import pw.yumc.YumCore.mc.MinecraftTools;
/**
* Created with IntelliJ IDEA
*
* @author 喵♂呜
* Created on 2017/10/9 12:40.
*/
@NotProguard
public class Base {
public Class getClass(String name) throws ClassNotFoundException {
return Class.forName(name);
}
public Class getLog() {
return Log.class;
}
public String read(String path) throws IOException {
Log.d("读取文件 %s ...", path);
return new String(Files.readAllBytes(new File(path).toPath()), "UTF-8");
}
public void save(String path, String content) throws IOException {
Log.d("保存文件 %s ...", path);
File file = new File(path);
file.getParentFile().mkdirs();
Files.write(file.toPath(), content.getBytes("UTF-8"));
}
public void delete(String path) throws IOException {
delete(new File(path).toPath());
}
public void delete(Path path) throws IOException {
val file = path.toFile();
if (!file.exists()) { return; }
Log.d("删除文件 %s ...", path);
if (file.isDirectory()) {
for (Path f : Files.list(file.toPath()).collect(Collectors.toList())) {
delete(f);
}
}
Files.delete(path);
}
public Class getActionBar() {
return C.ActionBar.class;
}
public Class getTitle() {
return C.Title.class;
}
public Class getPlayer() {
return C.Player.class;
}
public Class getTools() {
return MinecraftTools.class;
}
}

View File

@ -1,26 +0,0 @@
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;
}
}

View File

@ -1,24 +1,23 @@
package pw.yumc.MiaoScript; package pw.yumc.MiaoScript;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.FileReader;
import java.io.InputStreamReader; import java.io.InputStreamReader;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.stream.Collectors;
import javax.script.ScriptEngineManager; import javax.script.ScriptEngineManager;
import javax.script.ScriptException; import javax.script.ScriptException;
import org.bukkit.command.CommandSender;
import org.bukkit.plugin.java.JavaPlugin; import org.bukkit.plugin.java.JavaPlugin;
import lombok.val; import lombok.SneakyThrows;
import pw.yumc.YumCore.annotation.NotProguard;
import pw.yumc.YumCore.bukkit.Log; import pw.yumc.YumCore.bukkit.Log;
import pw.yumc.YumCore.bukkit.P; import pw.yumc.YumCore.bukkit.P;
import pw.yumc.YumCore.bukkit.compatible.C; import pw.yumc.YumCore.commands.CommandSub;
import pw.yumc.YumCore.commands.annotation.Cmd;
import pw.yumc.YumCore.commands.annotation.Help;
import pw.yumc.YumCore.commands.interfaces.Executor;
import pw.yumc.YumCore.engine.MiaoScriptEngine; import pw.yumc.YumCore.engine.MiaoScriptEngine;
import pw.yumc.YumCore.mc.MinecraftTools;
/** /**
* 喵式脚本 * 喵式脚本
@ -26,22 +25,35 @@ import pw.yumc.YumCore.mc.MinecraftTools;
* @author 喵♂呜 * @author 喵♂呜
* @since 2016年8月29日 上午7:50:39 * @since 2016年8月29日 上午7:50:39
*/ */
public class MiaoScript extends JavaPlugin { public class MiaoScript extends JavaPlugin implements Executor {
private MiaoScriptEngine engine; private MiaoScriptEngine engine;
@Override @Override
public void onEnable() { public void onEnable() {
saveScript(); saveScript();
loadEngine(); loadEngine();
new CommandSub("ms", this);
} }
@Override @Cmd
public void onDisable() { @Help("执行 JS 代码")
try { @SneakyThrows
engine.invokeFunction("disable"); public void js(CommandSender sender, String script) {
} catch (ScriptException | NoSuchMethodException e) { result(sender, engine.eval(script));
Log.w("脚本引擎关闭失败! %s:%s", e.getClass().getName(), e.getMessage()); }
Log.d(e);
@Cmd
@Help("执行 JS 代码文件")
@SneakyThrows
public void file(CommandSender sender, String file) {
result(sender, engine.eval(new FileReader(new File(getDataFolder(), file))));
}
private void result(CommandSender sender, Object result) {
if (result == null) {
Log.sender(sender, "§a运行成功! §c没有返回结果!");
} else {
Log.sender(sender, "§a运行成功! §b数据类型: §r%s §d结果: §r%s", result.getClass().getName(), result);
} }
} }
@ -66,58 +78,13 @@ public class MiaoScript extends JavaPlugin {
} }
} }
@NotProguard @Override
public static class Base { public void onDisable() {
public Class getClass(String name) throws ClassNotFoundException { try {
return Class.forName(name); engine.invokeFunction("disable");
} } catch (ScriptException | NoSuchMethodException e) {
Log.w("脚本引擎关闭失败! %s:%s", e.getClass().getName(), e.getMessage());
public Class getLog() { Log.d(e);
return Log.class;
}
public String read(String path) throws IOException {
Log.d("读取文件 %s ...", path);
return new String(Files.readAllBytes(new File(path).toPath()), "UTF-8");
}
public void save(String path, String content) throws IOException {
Log.d("保存文件 %s ...", path);
File file = new File(path);
file.getParentFile().mkdirs();
Files.write(file.toPath(), content.getBytes("UTF-8"));
}
public void delete(String path) throws IOException {
delete(new File(path).toPath());
}
public void delete(Path path) throws IOException {
val file = path.toFile();
if (!file.exists()) { return; }
Log.d("删除文件 %s ...", path);
if (file.isDirectory()) {
for (Path f : Files.list(file.toPath()).collect(Collectors.toList())) {
delete(f);
}
}
Files.delete(path);
}
public Class getActionBar() {
return C.ActionBar.class;
}
public Class getTitle() {
return C.Title.class;
}
public Class getPlayer() {
return C.Player.class;
}
public Class getTools() {
return MinecraftTools.class;
} }
} }
} }

View File

@ -1,6 +1,8 @@
package pw.yumc.MiaoScript; package pw.yumc.MiaoScript;
import org.bukkit.event.Cancellable; import org.bukkit.event.Cancellable;
import org.bukkit.event.Event;
import org.bukkit.event.HandlerList;
import jdk.nashorn.api.scripting.ScriptObjectMirror; import jdk.nashorn.api.scripting.ScriptObjectMirror;
@ -10,7 +12,7 @@ import jdk.nashorn.api.scripting.ScriptObjectMirror;
* @author 喵♂呜 * @author 喵♂呜
* Created on 2017/9/30 21:32. * Created on 2017/9/30 21:32.
*/ */
public class ScriptEvent extends BaseEvent implements Cancellable { public class ScriptEvent extends Event implements Cancellable {
private ScriptObjectMirror mirror; private ScriptObjectMirror mirror;
private boolean cancelled = false; private boolean cancelled = false;
@ -35,4 +37,15 @@ public class ScriptEvent extends BaseEvent implements Cancellable {
public void setCancelled(boolean cancel) { public void setCancelled(boolean cancel) {
this.cancelled = cancel; this.cancelled = cancel;
} }
private static HandlerList handlerList = new HandlerList();
public static HandlerList getHandlerList() {
return handlerList;
}
@Override
public HandlerList getHandlers() {
return handlerList;
}
} }

View File

@ -8,6 +8,7 @@ function init(root, plugin) {
initDir(); initDir();
loadCore(); loadCore();
loadRequire(); loadRequire();
loadLib4Bukkit();
loadPlugins(plugin); loadPlugins(plugin);
} }
@ -30,6 +31,7 @@ function loadCore() {
// 加载基础模块 // 加载基础模块
load(core_dir + '/ext.js'); load(core_dir + '/ext.js');
load(core_dir + '/static.js'); load(core_dir + '/static.js');
load(core_dir + '/console.js');
} }
/** /**
@ -40,6 +42,23 @@ function loadRequire() {
global.require = load(core_dir + '/require.js')(root, core_dir, miao_module_dir); global.require = load(core_dir + '/require.js')(root, core_dir, miao_module_dir);
} }
function loadLib4Bukkit() {
require('modules/event');
var task = require('modules/task');
global.setTimeout = function (func, time) {
return task.later(func, time)
};
global.clearTimeout = function (task) {
task.cancel();
};
global.setInterval = function (func, time) {
return task.timer(func, time)
};
global.clearInterval = function (task) {
task.cancel();
};
}
/** /**
* 加载JS插件 * 加载JS插件
*/ */

View File

@ -20,6 +20,7 @@
if (_canonical(name)) { if (_canonical(name)) {
name = _canonical(name); name = _canonical(name);
} }
// 如果不是 .js 结尾就加上
if (!name.match(/.*\.js/)) { if (!name.match(/.*\.js/)) {
name += ".js"; name += ".js";
} }
@ -77,12 +78,12 @@
/** /**
* 加载模块 * 加载模块
* @param name 模块名称 * @param name 模块名称
* @param parent 父目录 * @param path 路径
* @returns {*} * @returns {*}
* @private * @private
*/ */
function _require(name, parent) { function _require(name, path) {
var file = findModule(name, parent); var file = findModule(name, path);
// 重定向文件名称 // 重定向文件名称
name = file.name.split(".")[0]; name = file.name.split(".")[0];
var id = _canonical(file); var id = _canonical(file);
@ -91,6 +92,7 @@
return module; return module;
} }
log.d('加载模块 %s 位于 %s', name, id); log.d('加载模块 %s 位于 %s', name, id);
// noinspection JSUnresolvedVariable
module = { module = {
loaded: false, loaded: false,
id: id, id: id,
@ -110,7 +112,7 @@
log.d(ex); log.d(ex);
} }
cacheModules[id] = module; cacheModules[id] = module;
return cacheModules[id]; return module;
} }
/** /**

View File

@ -0,0 +1,5 @@
'use strict';
/**
* Bukkit 命令相关类
*/
/*global Java, base, module, exports, require, __FILE__*/

View File

@ -10,13 +10,13 @@ var Modifier = Java.type("java.lang.reflect.Modifier");
var BukkitEvent = Java.type("org.bukkit.event.Event"); var BukkitEvent = Java.type("org.bukkit.event.Event");
var EventPriority = Java.type("org.bukkit.event.EventPriority"); var EventPriority = Java.type("org.bukkit.event.EventPriority");
var EventExecutor = Java.type("org.bukkit.plugin.EventExecutor"); var EventExecutor = Java.type("org.bukkit.plugin.EventExecutor");
var IllegalStateException = Java.type("java.lang.IllegalStateException");
var mapEvent = []; var mapEvent = [];
var plugin = require('plugin').$;
/** /**
* 映射事件名称 org.bukkit.event.player.PlayerLoginEvent => playerloginevent * 扫描包 org.bukkit.event 下的所有事件
* 映射简写名称 org.bukkit.event.player.PlayerLoginEvent => playerloginevent
*/ */
function mapEventName() { function mapEventName() {
var eventPackageDir = "org/bukkit/event"; var eventPackageDir = "org/bukkit/event";
@ -32,10 +32,12 @@ function mapEventName() {
while (entries.hasMoreElements()) { while (entries.hasMoreElements()) {
var entry = entries.nextElement(); var entry = entries.nextElement();
var name = entry.name; var name = entry.name;
// 以 org/bukkit/event 开头 并且以 .class 结尾
if (name.startsWith(eventPackageDir) && name.endsWith(".class")) { if (name.startsWith(eventPackageDir) && name.endsWith(".class")) {
var i = name.replaceAll('/', '.'); var i = name.replaceAll('/', '.');
try { try {
var clz = base.getClass(i.substring(0, i.length - 6)); var clz = base.getClass(i.substring(0, i.length - 6));
// 继承于 org.bukkit.event.Event 访问符为Public
if (isVaildEvent(clz)) { if (isVaildEvent(clz)) {
// noinspection JSUnresolvedVariable // noinspection JSUnresolvedVariable
var simpleName = clz.simpleName.toLowerCase(); var simpleName = clz.simpleName.toLowerCase();
@ -51,9 +53,18 @@ function mapEventName() {
} }
} }
/**
* 判断是否为一个有效的事件类
* @param clz
* @returns {*|boolean}
*/
function isVaildEvent(clz) { function isVaildEvent(clz) {
// noinspection JSUnresolvedVariable // noinspection JSUnresolvedVariable 继承于 org.bukkit.event.Event
return BukkitEvent.class.isAssignableFrom(clz) && Modifier.isPublic(clz.getModifiers()) && !Modifier.isAbstract(clz.getModifiers()); return BukkitEvent.class.isAssignableFrom(clz) &&
// 访问符为Public
Modifier.isPublic(clz.getModifiers()) &&
// 不是抽象类
!Modifier.isAbstract(clz.getModifiers());
} }
/** /**
@ -70,15 +81,16 @@ function listen(event, exec, priority, ignoreCancel) {
eventCls = base.getClass(eventCls); eventCls = base.getClass(eventCls);
} catch (ex) { } catch (ex) {
log.w("事件 %s 未找到!"); log.w("事件 %s 未找到!");
}
return; return;
} }
}
if (priority === undefined) { if (priority === undefined) {
priority = 'NORMAL' priority = 'NORMAL'
} }
if (ignoreCancel === undefined) { if (ignoreCancel === undefined) {
ignoreCancel = false; ignoreCancel = false;
} }
var listener = new Listener({});
// noinspection JSUnusedGlobalSymbols // noinspection JSUnusedGlobalSymbols
/** /**
* @param event Event type to register * @param event Event type to register
@ -90,30 +102,41 @@ function listen(event, exec, priority, ignoreCancel) {
*/ */
Bukkit.getPluginManager().registerEvent( Bukkit.getPluginManager().registerEvent(
eventCls, eventCls,
new Listener({}), listener,
EventPriority[priority], EventPriority[priority],
new Java.extend(EventExecutor, { new EventExecutor({
execute: function (listener, event) { execute: function (listener, event) {
exec(event); exec(event);
} }
}), }),
plugin, require('plugin').$,
ignoreCancel); ignoreCancel);
// noinspection JSUnresolvedVariable
log.d('注册事件 %s 方法 %s', eventCls.simpleName, exec.name === '' ? '匿名方法' : exec.name);
return { return {
event: eventCls, event: eventCls,
listener: listener listener: listener
} }
} }
// 映射事件名称
mapEventName();
exports.on = listen;
/** /**
* 取消事件监听 * 取消事件监听
* @param listener 监听结果 * @param listener 监听结果
*/ */
exports.off = function (listener) { function unlisten(listener) {
if (!listener.event || !listener.listener) {
throw new IllegalStateException("非法的监听器对象 无法取消事件!");
}
listener.event.getMethod("getHandlerList").invoke(null).unregister(listener.listener);
// noinspection JSUnresolvedVariable // noinspection JSUnresolvedVariable
listener.event.handlerList.unregister(listener.listener); log.d('注销事件 %s', eventCls.simpleName);
}
// 映射事件名称
mapEventName();
log.i('Bukkit 事件映射完毕 共计 %s 个事件!', mapEvent.length);
module.exports = {
on: listen,
off: unlisten
}; };

View File

@ -15,7 +15,7 @@ if (bukkit.plugin.load("PlaceholderAPI")) {
} }
} }
} }
exports.$ = function (player, str) { exports.$ = function () {
if (arguments.length > 1) { if (arguments.length > 1) {
return PlaceholderAPI.setPlaceholders(arguments[0], arguments[1]); return PlaceholderAPI.setPlaceholders(arguments[0], arguments[1]);
} else { } else {

View File

@ -3,7 +3,7 @@
* MiaoScript脚本插件加载类 * MiaoScript脚本插件加载类
*/ */
/*global Java, base, module, exports, require, __FILE__*/ /*global Java, base, module, exports, require, __FILE__*/
var zip = require("core/zip"); // var zip = require("core/zip");
var fs = require('core/fs'); var fs = require('core/fs');
/** /**
@ -56,37 +56,74 @@ function loadJsPlugin(files) {
return file.name.endsWith(".js") return file.name.endsWith(".js")
}).forEach(function (file) { }).forEach(function (file) {
var p = require(file); var p = require(file);
log.d("插件编译结果: %s", JSON.stringify(p));
if (!p.description || !p.description.name) { if (!p.description || !p.description.name) {
log.w("文件 %s 不存在 description 描述信息 无法加载插件!"); log.w("文件 %s 不存在 description 描述信息 无法加载插件!", file);
} else { } else {
exports.plugins.push(p); plugins.push(p);
plugins[p.description.name] = p;
log.i('插件 %s 版本 %s 加载成功!', p.description.name, p.description.version);
} }
}) })
} }
function runAndCatch(name, exec) {
if (exec) {
try {
exec();
} catch (ex) {
log.w('插件 %s 执行 %s 发生错误: %s', name, exec.name, ex.message);
ex.printStackTrace();
}
}
}
function checkAndGet(name) {
if (!exports.plugins[name]) {
throw new Error("插件 " + name + "不存在!");
}
return exports.plugins[name];
}
var plugins = [];
exports.$ = undefined; exports.$ = undefined;
exports.plugins = []; exports.plugins = plugins;
exports.init = function (plugin, path) { exports.init = function (plugin, path) {
if (plugin !== null) { if (plugin !== null) {
// 如果过plugin不等于null 则代表是正式环境 // 如果过plugin不等于null 则代表是正式环境
exports.$ = plugin; exports.$ = plugin;
log.i("Init MiaoScript Engine Version: %s", plugin.description.version); log.i("初始化 MiaoScript 插件系统 版本: %s", plugin.description.version);
require('./event');
} }
loadPlugins(path); loadPlugins(path);
}; };
exports.load = function () { exports.load = function () {
exports.plugins.forEach(function (p) { if (arguments.length === 0) {
p.load(); plugins.forEach(function (p) {
runAndCatch(p.description.name, p.load);
}) })
} else {
var p = checkAndGet(arguments[0]);
runAndCatch(p.description.name, p.load);
}
}; };
exports.enable = function () { exports.enable = function () {
exports.plugins.forEach(function (p) { if (arguments.length === 0) {
p.enable(); plugins.forEach(function (p) {
runAndCatch(p.description.name, p.enable);
}) })
} else {
var p = checkAndGet(arguments[0]);
runAndCatch(p.description.name, p.enable);
}
}; };
exports.disable = function () { exports.disable = function () {
exports.plugins.forEach(function (p) { if (arguments.length === 0) {
p.disable(); plugins.forEach(function (p) {
runAndCatch(p.description.name, p.disable);
}) })
} else {
var p = checkAndGet(arguments[0]);
runAndCatch(p.description.name, p.disable);
}
}; };

View File

@ -0,0 +1,71 @@
'use strict';
/*global Java, base, module, exports, require, __FILE__*/
/**
* 任务计划
* Created by 蒋天蓓 on 2017/2/9 0009.
*/
var plugin = require('modules/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]);
}
};

View File

@ -11,6 +11,9 @@ commands:
description: ${project.artifactId} - ${project.description} description: ${project.artifactId} - ${project.description}
aliases: aliases:
- ms - ms
- mjs
- script
- mscript
usage: §b使用/${project.artifactId} help 查看帮助! usage: §b使用/${project.artifactId} help 查看帮助!
permission: ${project.artifactId}.reload permission: ${project.artifactId}.reload
permission-message: §c你没有 <permission> 的权限来执行此命令! permission-message: §c你没有 <permission> 的权限来执行此命令!

View File

@ -2,11 +2,12 @@
/** /**
* Hello Wrold 测试插件 * Hello Wrold 测试插件
*/ */
/*global Java, base, module, exports, require*/
var papi = require("modules/ext/papi"); var papi = require("modules/ext/papi");
var event = require('modules/event'); var event = require('modules/event');
var join; var join;
/*global Java, base, module, exports, require*/
var description = { var description = {
name: 'HelloWorld', name: 'HelloWorld',
version: '1.0' version: '1.0'
@ -18,9 +19,13 @@ function load() {
function enable() { function enable() {
log.i('启用 Hello Wrold 测试插件!'); log.i('启用 Hello Wrold 测试插件!');
join = event.on('playerloginevent', function (event) { join = event.on('playerloginevent', function join(event) {
// noinspection JSUnresolvedVariable // noinspection JSUnresolvedVariable
event.player.sendMessage(papi.$(event.player, "§a欢迎来到 §bMiaoScript §a的世界! 当前在线: %server_onlone%")); log.d('玩家 %s 触发事件 %s', event.player.name, event.name);
setTimeout(function () {
// noinspection JSUnresolvedVariable
event.player.sendMessage(papi.$(event.player, "§a欢迎来到 §bMiaoScript §a的世界! 当前在线: %server_online%"));
}, 10);
}); });
} }
@ -29,7 +34,7 @@ function disable() {
event.off(join); event.off(join);
} }
exports = { module.exports = {
description: description, description: description,
load: load, load: load,
enable: enable, enable: enable,

View File

@ -26,7 +26,7 @@ public class MiaoScriptTest {
try { try {
ScriptEngineManager manager = new ScriptEngineManager(); ScriptEngineManager manager = new ScriptEngineManager();
this.engine = new MiaoScriptEngine(manager); this.engine = new MiaoScriptEngine(manager);
this.engine.put("base", new MiaoScript.Base()); this.engine.put("base", new Base());
this.engine.eval(new FileReader("src/main/resources/bios.js")); this.engine.eval(new FileReader("src/main/resources/bios.js"));
engine.invokeFunction("boot", null, engine); engine.invokeFunction("boot", null, engine);
} catch (Exception e) { } catch (Exception e) {