24 Commits

Author SHA1 Message Date
f7b97f3e84 feat: 迁移配置 完善reload命令 2018-05-15 13:47:03 +00:00
89cab251c7 feat: 分离TellRaw类库 2018-05-15 13:33:52 +00:00
3d3bf20acd feat: 完善MiaoChat的Bukkit版本 2018-05-14 16:42:55 +00:00
423c7cc844 feat: 补全内部引入方法的参数 2018-05-14 16:42:35 +00:00
8df9ad9ec7 feat: 调整Event载入提示 完善Bukkit的聊天发送 2018-05-14 16:42:08 +00:00
39d9c67c75 feat: 调整API引入结构 2018-05-14 16:41:33 +00:00
6f1a103aca feat: 新增MiaoChat插件 2018-05-13 16:18:26 +00:00
f79acd43c5 feat: 更新API相关类 2018-05-13 16:18:14 +00:00
f19e51d8a7 feat: 调整相关API名称 2018-05-13 16:17:48 +00:00
d5aa98b716 feat: 新增Object.values垫片 2018-05-13 16:16:01 +00:00
04a7b99ce5 feat: 新增工具类 2018-05-13 16:14:35 +00:00
a672b85678 feat: 更新MiaoScriptPackageManager 2018-05-13 16:14:14 +00:00
288619ddb7 fix: 修复命令执行相关BUG 2018-05-13 16:13:57 +00:00
3df2625e65 feat: 新增聊天相关API 2018-05-13 16:13:32 +00:00
a041e8e2d2 feat: 优化方法调用 2018-03-18 12:06:52 +00:00
320cc0479e feat: 调整get方法 data 参数自动转query 2018-03-18 12:06:27 +00:00
755d4b005d feat: 优化插件代码结构 2018-03-18 12:04:56 +00:00
e290f17771 fix: 修复玩家人数获取错误 更新插件 2018-01-11 14:47:34 +00:00
be95acd001 feat: 更新http类库 server通过orElse返回undefined 2018-01-11 14:46:47 +00:00
75340fd824 feat: 更新基础类库 2018-01-11 13:47:49 +00:00
51499b3b52 feat: 新增插件管理模块 2018-01-10 12:59:55 +00:00
54b5909875 fix: 修复主线程加载的BUG 2018-01-10 12:59:29 +00:00
fe6d0e7250 feat: 修复fs相关BUG 优化插件加载 优化命令补全 2018-01-10 12:58:58 +00:00
bf6d52d8cc feat: 更新.gitignore文件 2018-01-10 01:57:19 +00:00
31 changed files with 964 additions and 201 deletions

97
.gitignore vendored
View File

@ -1,44 +1,53 @@
# Eclipse stuff # Eclipse stuff
/.settings /.settings
# netbeans # netbeans
/nbproject /nbproject
# we use maven! # we use maven!
/build.xml /build.xml
# maven # maven
/target /target
/repo /repo
# vim # vim
.*.sw[a-p] .*.sw[a-p]
# various other potential build files # various other potential build files
/build /build
/bin /bin
/dist /dist
/manifest.mf /manifest.mf
/world # Mac filesystem dust
*.DS_Store
# Mac filesystem dust
*.DS_Store # intellij
*.iml
# intellij *.ipr
*.iml *.iws
*.ipr .idea/
*.iws
.idea/ # Project Stuff
/src/main/resources/Soulbound
# Project Stuff
/src/main/resources/Soulbound # Atlassian Stuff
/atlassian-ide-plugin.xml
# Atlassian Stuff
/atlassian-ide-plugin.xml # Eclipse
.project
/src/main/resources/cache/ .classpath
.settings
# ThinkPHP
vendor/ # Visual Studio Code
composer.lock .vscode
# NodeJs PHP LOCK File
*.lock
# PHP Vendor
vendor/
# Minecraft Data
/world

View File

@ -0,0 +1,9 @@
/*global Java, base, module, exports, require*/
function ChatHandlerDefault() {
this.tellraw = function(sender, raw) {
this.json(sender, JSON.stringify(raw));
}
}
var ChatHandler = Object.assign(new ChatHandlerDefault(), requireInternal('chat'));
exports = module.exports = ChatHandler;

View File

@ -1,2 +1,2 @@
/*global Java, base, module, exports, require*/ /*global Java, base, module, exports, require*/
module.exports = require('./msp.js').command; module.exports = requireInternal('command');

View File

@ -12,6 +12,8 @@ function EventHandlerDefault() {
this.listenerMap = []; this.listenerMap = [];
this.baseEventDir = ''; this.baseEventDir = '';
var self = this;
/** /**
* 扫描包 org.bukkit.event 下的所有事件 * 扫描包 org.bukkit.event 下的所有事件
* 映射简写名称 org.bukkit.event.player.PlayerLoginEvent => playerloginevent * 映射简写名称 org.bukkit.event.player.PlayerLoginEvent => playerloginevent
@ -40,8 +42,8 @@ function EventHandlerDefault() {
// 继承于 org.bukkit.event.Event 访问符为Public // 继承于 org.bukkit.event.Event 访问符为Public
if (this.isVaildEvent(clz)) { if (this.isVaildEvent(clz)) {
// noinspection JSUnresolvedVariable // noinspection JSUnresolvedVariable
var simpleName = this.class2Name(clz); var simpleName = this.class2Name(clz).toLowerCase();
console.debug("Mapping Event [%s] => %s".format(clz.name, simpleName)); console.debug("Mapping Event [%s] => %s".format(clz.canonicalName, simpleName));
this.mapEvent[simpleName] = clz; this.mapEvent[simpleName] = clz;
count++; count++;
} }
@ -56,11 +58,11 @@ function EventHandlerDefault() {
} }
this.class2Name = function class2Name(clazz) { this.class2Name = function class2Name(clazz) {
return clazz.simpleName.toLowerCase(); return clazz.simpleName;
} }
this.name2Class = function name2Class(name, event) { this.name2Class = function name2Class(name, event) {
var eventCls = this.mapEvent[event] || this.mapEvent[event.toLowerCase()] || this.mapEvent[event + 'Event'] || this.mapEvent[event.toLowerCase() + 'event']; var eventCls = this.mapEvent[event.toLowerCase()] || this.mapEvent[event.toLowerCase() + 'event'];
if (!eventCls) { if (!eventCls) {
try { try {
eventCls = base.getClass(eventCls); eventCls = base.getClass(eventCls);
@ -128,7 +130,7 @@ function EventHandlerDefault() {
if (!listenerMap[name]) listenerMap[name] = []; if (!listenerMap[name]) listenerMap[name] = [];
var offExec = function () { var offExec = function () {
this.unregister(eventCls, listener); this.unregister(eventCls, listener);
console.debug('插件 %s 注销事件 %s'.format(name, eventCls.name.substring(eventCls.name.lastIndexOf(".") + 1))); console.debug('插件 %s 注销事件 %s'.format(name, this.class2Name(eventCls)));
}.bind(this); }.bind(this);
var off = { var off = {
event: eventCls, event: eventCls,
@ -137,7 +139,7 @@ function EventHandlerDefault() {
}; };
listenerMap[name].push(off); listenerMap[name].push(off);
// noinspection JSUnresolvedVariable // noinspection JSUnresolvedVariable
console.debug('插件 %s 注册事件 %s => %s'.format(name, eventCls.name.substring(eventCls.name.lastIndexOf(".") + 1), exec.name === '' ? '匿名方法' : exec.name)); console.debug('插件 %s 注册事件 %s => %s'.format(name, this.class2Name(eventCls), exec.name === '' ? '匿名方法' : exec.name));
return off; return off;
} }
} }
@ -147,9 +149,9 @@ console.info('%s 事件映射完毕 共计 %s 个事件!'.format(DetectServerTyp
module.exports = { module.exports = {
on: EventHandler.listen.bind(EventHandler), on: EventHandler.listen.bind(EventHandler),
disable: function (jsp) { disable: function (jsp) {
var jspl = EventHandler.listenerMap[jsp.description.name]; var eventCache = EventHandler.listenerMap[jsp.description.name];
if (jspl) { if (eventCache) {
jspl.forEach(function (t) t.off.call(EventHandler)); eventCache.forEach(function (t) t.off.call(EventHandler));
delete EventHandler.listenerMap[jsp.description.name]; delete EventHandler.listenerMap[jsp.description.name];
} }
} }

View File

@ -1,2 +1,2 @@
/*global Java, base, module, exports, require*/ /*global Java, base, module, exports, require*/
module.exports = require('./msp.js').item; module.exports = requireInternal('item');

View File

@ -1,13 +0,0 @@
/*global Java, base, module, exports, require*/
function impl(name) {
return require('../internal/' + DetectServerType + '/' + name, {warnNotFound: false});
}
exports = module.exports = {
command: impl('command'),
event: impl('event'),
permission: impl('permission'),
server: impl('server'),
task: impl('task'),
item: impl('item')
};

View File

@ -1,2 +1,2 @@
/*global Java, base, module, exports, require*/ /*global Java, base, module, exports, require*/
module.exports = require('./msp.js').permission; module.exports = requireInternal('permission', {warnNotFound: false});

View File

@ -50,14 +50,15 @@ function createUpdate(path) {
* @param files * @param files
*/ */
function loadZipPlugins(files) { function loadZipPlugins(files) {
// // TODO ZIP类型插件加载 files.filter(function (file) {
// files.filter(function (file) { return file.name.endsWith(".zip");
// return file.name.endsWith(".zip"); }).forEach(function (file) {
// }).forEach(function (file) { // console.log(file);
// zip.unzip(fs.file(plugins_dir, file)); // console.log(fs.file(file,"!package.json"))
// var dir = new File(plugins_dir, file.name.split(".")[0]); // zip.unzip(fs.file(plugins_dir, file));
// // TODO 添加文件夹类型的插件兼容 // var dir = new File(plugins_dir, file.name.split(".")[0]);
// }); // TODO 添加文件夹类型的插件兼容
});
} }
/** /**
@ -67,16 +68,23 @@ function loadJsPlugins(files) {
files.filter(function (file) { files.filter(function (file) {
return file.name.endsWith(".js") return file.name.endsWith(".js")
}).forEach(function (file) { }).forEach(function (file) {
try { loadPlugin(file)
loadPlugin(file);
} catch (ex) {
console.console('§6插件 §b%s §6初始化时发生错误 §4%s'.format(fs.path(file), ex.message));
console.ex(ex);
}
}) })
} }
function loadPlugin(file) { function loadPlugin(file) {
try {
var plugin = readPlugin(file);
initPlugin(plugin);
plugins[plugin.description.name] = plugin;
return plugin
} catch (ex) {
console.console('§6插件 §b%s §6初始化时发生错误 §4%s'.format(file.name, ex.message));
console.ex(ex);
}
}
function readPlugin(file) {
var update = fs.file(fs.file(file.parentFile, 'update'), file.name); var update = fs.file(fs.file(file.parentFile, 'update'), file.name);
if (update.exists()) { if (update.exists()) {
console.info('自动升级插件 %s'.format(file.name)); console.info('自动升级插件 %s'.format(file.name));
@ -89,13 +97,17 @@ function loadPlugin(file) {
} }
}) })
console.debug("插件编译结果: %s".format(JSON.stringify(plugin))); console.debug("插件编译结果: %s".format(JSON.stringify(plugin)));
plugin.__FILE__ = file;
return plugin;
}
function initPlugin(plugin) {
var desc = plugin.description; var desc = plugin.description;
if (!desc || !desc.name) { if (!desc || !desc.name) {
console.warn("文件 %s 不存在 description 描述信息 无法加载插件!".format(file)); throw new Error("文件 %s 不存在 description 描述信息 无法加载插件!".format(plugin.__FILE__));
} else { } else {
initPlugin(file, plugin); internalInitPlugin(plugin);
afterLoadHook(plugin); afterLoadHook(plugin);
plugins[plugin.description.name] = plugin;
console.info('载入插件 %s 版本 %s By %s'.format(desc.name, desc.version || '未知', desc.author || '未知')); console.info('载入插件 %s 版本 %s By %s'.format(desc.name, desc.version || '未知', desc.author || '未知'));
} }
return plugin; return plugin;
@ -106,9 +118,9 @@ function beforeLoadHook(origin) {
// 处理 event 为了不影响 正常逻辑 event 还是手动require吧 // 处理 event 为了不影响 正常逻辑 event 还是手动require吧
// result = result + 'var event = {}; module.exports.event = event;'; // result = result + 'var event = {}; module.exports.event = event;';
// 注入 console 对象 // 给插件注入单独的 console // 注入 console 对象 // 给插件注入单独的 console
result = result + 'var console = new Console(); module.exports.console = console;'; result += '\nvar console = new Console(); module.exports.console = console;';
// 插件注入 self 对象 // 插件注入 self 对象
result = result + 'var self = {}; module.exports.self = self;'; result += '\nvar self = {}; module.exports.self = self;';
return result; return result;
} }
@ -123,11 +135,9 @@ function afterLoadHook(plugin) {
/** /**
* 初始化插件内容(提供config,__DATA__等参数) * 初始化插件内容(提供config,__DATA__等参数)
*/ */
function initPlugin(file, plugin) { function internalInitPlugin(plugin) {
// 初始化 __FILE__
plugin.__FILE__ = file;
// 初始化 __DATA__ // 初始化 __DATA__
plugin.__DATA__ = plugin.dataFolder = fs.file(file.parentFile, plugin.description.name); plugin.__DATA__ = plugin.dataFolder = fs.file(plugin.__FILE__.parentFile, plugin.description.name);
// 初始化 getDataFolder() // 初始化 getDataFolder()
plugin.getDataFolder = function getDataFolder() { plugin.getDataFolder = function getDataFolder() {
return plugin.__DATA__; return plugin.__DATA__;
@ -180,9 +190,13 @@ function initPluginConfig(plugin) {
* @constructor (file, content) * @constructor (file, content)
*/ */
plugin.saveConfig = function () { plugin.saveConfig = function () {
// 判断插件目录是否存在 并且不为文件 否则删除重建
if (!plugin.configFile.parentFile.isDirectory()) {
fs.del(plugin.configFile.parentFile);
}
plugin.configFile.parentFile.mkdirs();
switch (arguments.length) { switch (arguments.length) {
case 0: case 0:
plugin.configFile.parentFile.mkdirs();
fs.save(plugin.configFile, yaml.safeDump(plugin.config)); fs.save(plugin.configFile, yaml.safeDump(plugin.config));
break; break;
case 2: case 2:
@ -204,13 +218,14 @@ function checkAndGet(args) {
} }
var name = args[0]; var name = args[0];
// 如果是插件 则直接返回 // 如果是插件 则直接返回
if (name.description) { if (name && name.description) {
return [name]; return [name];
} }
if (!exports.plugins[name]) { var plugin = exports.plugins[name];
if (!plugin) {
throw new Error("插件 " + name + " 不存在!"); throw new Error("插件 " + name + " 不存在!");
} }
return [exports.plugins[name]]; return [plugin];
} }
function checkAndRun(args, name, ext) { function checkAndRun(args, name, ext) {
@ -221,7 +236,7 @@ function checkAndRun(args, name, ext) {
try { try {
// 绑定方法的this到插件自身 // 绑定方法的this到插件自身
if (typeof exec === "function") exec.call(jsp); if (typeof exec === "function") exec.call(jsp);
if (ext) ext.call(jsp); if (typeof ext === "function") ext.call(jsp);
} catch (ex) { } catch (ex) {
console.console('§6插件 §b%s §6执行 §d%s §6方法时发生错误 §4%s'.format(jsp.description.name, name, ex.message)); console.console('§6插件 §b%s §6执行 §d%s §6方法时发生错误 §4%s'.format(jsp.description.name, name, ex.message));
console.ex(ex); console.ex(ex);
@ -270,5 +285,6 @@ exports = module.exports = {
load: load, load: load,
enable: enable, enable: enable,
disable: disable, disable: disable,
reload: reload reload: reload,
loadPlugin: loadPlugin
} }

View File

@ -1,2 +1,2 @@
/*global Java, base, module, exports, require*/ /*global Java, base, module, exports, require*/
module.exports = require('./msp.js').server; module.exports = requireInternal('server');

View File

@ -1,2 +1,2 @@
/*global Java, base, module, exports, require*/ /*global Java, base, module, exports, require*/
module.exports = require('./msp.js').task; module.exports = requireInternal('task');

View File

@ -35,7 +35,7 @@ var global = this;
var pluginYml; var pluginYml;
function checkClassLoader() { function checkClassLoader() {
var classLoader = java.lang.Thread.currentThread().getContextClassLoader(); var classLoader = java.lang.Thread.currentThread().contextClassLoader;
pluginYml = classLoader.getResource("plugin.yml"); pluginYml = classLoader.getResource("plugin.yml");
if (pluginYml === null) { if (pluginYml === null) {
log.info("==================== ERROR ===================="); log.info("==================== ERROR ====================");

View File

@ -45,19 +45,19 @@ function file() {
* 创建目录 * 创建目录
* @param file * @param file
*/ */
function mkdirs(file) { function mkdirs(path) {
// noinspection JSUnresolvedVariable // noinspection JSUnresolvedVariable
file.parentFile.mkdirs(); fs.file(path).parentFile.mkdirs();
}; };
/** /**
* 创建文件 * 创建文件
* @param file * @param file
*/ */
function create(file) { function create(path) {
f = file(file); var file = fs.file(path)
if (!f.exists()) { if (!file.exists()) {
mkdirs(f); mkdirs(file);
f.createNewFile(); file.createNewFile();
} }
}; };
/** /**
@ -67,7 +67,7 @@ function create(file) {
*/ */
function path(file) { function path(file) {
// noinspection JSUnresolvedVariable // noinspection JSUnresolvedVariable
return file.canonicalPath; return fs.file(file).canonicalPath;
}; };
/** /**
* 复制文件 * 复制文件
@ -80,10 +80,10 @@ function copy(inputStream, target, override) {
}; };
/** /**
* 读取文件 * 读取文件
* @param file 文件路径 * @param path 文件路径
*/ */
function read(f) { function read(path) {
var file = exports.file(f); var file = fs.file(path);
if (!file.exists()) { if (!file.exists()) {
console.warn('读取文件', file, '错误 文件不存在!'); console.warn('读取文件', file, '错误 文件不存在!');
return; return;
@ -98,11 +98,9 @@ function read(f) {
* @param override 是否覆盖 * @param override 是否覆盖
*/ */
function save(path, content, override) { function save(path, content, override) {
var file = new File(path); var file = fs.file(path);
file.getParentFile().mkdirs(); file.getParentFile().mkdirs();
Files.write(file.toPath(), Files.write(file.toPath(), new java.lang.String(content).getBytes("UTF-8"));
content.getBytes("UTF-8"),
override ? StandardCopyOption['REPLACE_EXISTING'] : StandardCopyOption['ATOMIC_MOVE']);
}; };
/** /**
* 列出目录文件 * 列出目录文件
@ -123,12 +121,12 @@ function list(path) {
* @param override 是否覆盖 * @param override 是否覆盖
*/ */
function move(src, des, override) { function move(src, des, override) {
Files.move(file(src).toPath(), file(des).toPath(), Files.move(fs.file(src).toPath(), fs.file(des).toPath(),
override ? StandardCopyOption['REPLACE_EXISTING'] : StandardCopyOption['ATOMIC_MOVE']) override ? StandardCopyOption['REPLACE_EXISTING'] : StandardCopyOption['ATOMIC_MOVE'])
}; };
function del(file) { function del(file) {
file = exports.file(file); file = fs.file(file);
if (!file.exists()) { return; } if (!file.exists()) { return; }
if (file.isDirectory()) { if (file.isDirectory()) {
Files.list(file.toPath()).collect(Collectors.toList()).forEach(function (f) { del(f); }) Files.list(file.toPath()).collect(Collectors.toList()).forEach(function (f) { del(f); })
@ -136,17 +134,25 @@ function del(file) {
Files.delete(file.toPath()); Files.delete(file.toPath());
} }
exports = module.exports = { function exists(file) {
canonical: path, return fs.file(file).exists()
}
var fs = {};
fs.path = fs.canonical = fs.realpath = path
fs.write = fs.save = save
fs.readdir = fs.list = list
fs.rename = fs.move = move
fs.delete = fs.del = del
Object.assign(fs, {
concat: concat, concat: concat,
create: create, create: create,
mkdirs: mkdirs, mkdirs: mkdirs,
file: file, file: file,
path: path,
copy: copy, copy: copy,
read: read, read: read
save: save, })
list: list,
move: move, exports = module.exports = fs
del: del
}

View File

@ -8,7 +8,7 @@
global.noop = function () { global.noop = function () {
}; };
loadCore(); loadCore();
loadExt(); loadPatch();
loadRequire(); loadRequire();
try { try {
loadServerLib(); loadServerLib();
@ -42,15 +42,15 @@
// 初始化加载器 // 初始化加载器
global.require = engineLoad(root + '/core/require.js')(root); global.require = engineLoad(root + '/core/require.js')(root);
global.requireInternal = function requireInternal(name) { global.requireInternal = function requireInternal(name) {
return require(root + '/internal/' + DetectServerType + '/' + name + '.js'); return require(root + '/internal/' + DetectServerType + '/' + name + '.js', arguments[1]);
} }
} }
/** /**
* 加载补丁 * 加载补丁
*/ */
function loadExt() { function loadPatch() {
java.nio.file.Files.list(new java.io.File(root, 'core/ext').toPath()).forEach(function (path) { java.nio.file.Files.list(new java.io.File(root, 'core/patch').toPath()).forEach(function (path) {
console.log('加载扩展类库', path); console.log('加载扩展类库', path);
try { try {
load(path.toFile()); load(path.toFile());

View File

@ -0,0 +1,18 @@
/**
* 补丁和方法扩展
*/
(function () {
if (!Array.prototype.copyPartialMatches) {
Object.defineProperty(Array.prototype, "copyPartialMatches", {
enumerable: false,
value: function (token, array) {
this.forEach(function (e) {
if (e.toLowerCase().startsWith(token.toLowerCase())) {
array.push(e)
}
})
return array
}
});
}
})();

View File

@ -28,16 +28,37 @@
} }
}); });
} }
// // JSON快捷方法 if (!Object.values) {
Object.defineProperty(Object, "values", {
enumerable: false,
configurable: true,
writable: true,
value: function(target) {
"use strict";
var vals = [];
for (var key in target) {
var desc = Object.getOwnPropertyDescriptor(target, key);
if (desc !== undefined && desc.enumerable) vals.push(target[key]);
}
return vals;
}
});
}
// JSON快捷方法
if(!Object.toJson){ if(!Object.toJson){
Object.defineProperty(Object.prototype, "toJson", { Object.defineProperty(Object.prototype, "toJson", {
enumerable: false, enumerable: false,
configurable: true,
writable: true,
value: function() { value: function() {
return JSON.stringify(this); return JSON.stringify(this);
} }
}); });
} }
// Object.prototype.toJson = function () { // Object.prototype.toJson = function () {
// return JSON.stringify(this); // return JSON.stringify(this);
// }; // };

View File

@ -0,0 +1,52 @@
/*global Java, base, module, exports, require*/
var bukkit = require('api/server');
var nmsChatSerializerClass;
var nmsIChatBaseComponentClass;
var packetTypeClass;
var nmsChatMessageTypeClass;
var chatMessageTypes;
var String = Java.type('java.lang.String');
function init () {
nmsChatSerializerClass = bukkit.nmsCls(bukkit.nmsVersion.split("_")[1] > 7 ? "IChatBaseComponent$ChatSerializer" : "ChatSerializer");
nmsIChatBaseComponentClass = bukkit.nmsCls('IChatBaseComponent');
packetTypeClass = bukkit.nmsCls("PacketPlayOutChat");
var packetTypeConstructor;
Java.from(packetTypeClass.class.constructors).forEach(function (c) {
if (c.parameterTypes.length == 2) { packetTypeConstructor = c };
})
nmsChatMessageTypeClass = packetTypeConstructor.parameterTypes[1];
if (nmsChatMessageTypeClass.isEnum()) {
chatMessageTypes = nmsChatMessageTypeClass.getEnumConstants();
} else {
switch (nmsChatMessageTypeClass.name) {
case "int":
nmsChatMessageTypeClass = java.lang.Integer;
case "byte":
nmsChatMessageTypeClass = java.lang.Byte;
}
}
}
function json(sender, json) {
send(sender, json, 0);
}
function send(sender, json, type) {
var serialized = nmsChatSerializerClass.a(json)
var typeObj = chatMessageTypes == null ? nmsChatMessageTypeClass.valueOf(String.valueOf(type)) : chatMessageTypes[type];
sendPacket(sender, new packetTypeClass(serialized, typeObj))
}
function sendPacket(player, p) {
player.handle.playerConnection.sendPacket(p);
}
init();
exports = module.exports = {
json: json
};

View File

@ -67,7 +67,8 @@ function on(jsp, name, exec) {
try { try {
return exec.cmd(sender, command, args); return exec.cmd(sender, command, args);
} catch (ex) { } catch (ex) {
console.console('§6玩家 §a%s §6执行 §b%s §6插件 §d%s %s §6命令时发生异常 §4%s'.format(sender.name, jsp.description.name, command, Java.from(args).join(' '), ex)); console.console('§6玩家 §a%s §6执行 §b%s §6插件 §d%s %s §6命令时发生异常 §4%s'
.format(sender.name, jsp.description.name, command, Java.from(args).join(' '), ex));
console.ex(ex); console.ex(ex);
} }
} }
@ -78,12 +79,12 @@ function on(jsp, name, exec) {
c.setTabCompleter(new org.bukkit.command.TabCompleter({ c.setTabCompleter(new org.bukkit.command.TabCompleter({
onTabComplete: function (sender, cmd, command, args) { onTabComplete: function (sender, cmd, command, args) {
try { try {
var completions = new ArrayList();
var token = args[args.length - 1]; var token = args[args.length - 1];
StringUtil.copyPartialMatches(token, Arrays.asList(exec.tab(sender, command, args)), completions); var complate = exec.tab(sender, command, args) || []
return completions; return Arrays.asList(complate.copyPartialMatches(token, []));
} catch (ex) { } catch (ex) {
console.console('§6玩家 §a%s §6执行 §b%s §6插件 §d%s %s §6补全时发生异常 §4%s'.format(sender.name, jsp.description.name, command, Java.from(args).join(' '), ex)); console.console('§6玩家 §a%s §6执行 §b%s §6插件 §d%s %s §6补全时发生异常 §4%s'
.format(sender.name, jsp.description.name, command, Java.from(args).join(' '), ex));
console.ex(ex); console.ex(ex);
} }
} }

View File

@ -19,6 +19,12 @@ exports.nmsVersion = Bukkit.server.class.name.split('.')[3];
exports.nmsCls = function (name) { exports.nmsCls = function (name) {
return Java.type(['net.minecraft.server', exports.nmsVersion, name].join('.')); return Java.type(['net.minecraft.server', exports.nmsVersion, name].join('.'));
}; };
/**
* 获取OBC类
*/
exports.obcCls = function (name) {
return Java.type(['org.bukkit.craftbukkit', exports.nmsVersion, name].join('.'));
};
/** /**
* 获取玩家 * 获取玩家
*/ */

View File

@ -0,0 +1,9 @@
/*global Java, base, module, exports, require*/
var TextSerializers = Java.type('org.spongepowered.api.text.serializer.TextSerializers');
function json(sender, json) {
sender.sendMessage(TextSerializers.JSON.deserialize(json));
}
exports = module.exports = {
json: json
};

View File

@ -23,19 +23,19 @@ var Arrays = Java.type('java.util.Arrays');
var commandMap=[]; var commandMap=[];
var SimpleCommandCallable = function (name) { var SimpleCommandCallable = function (command) {
var that = this; var that = this;
this.name = name; this.name = command.name;
this.cmd = noop; this.cmd = noop;
this.tab = function() { return new ArrayList(); }; this.tab = function() { return new ArrayList(); };
this.callable = new CommandCallable({ this.callable = new CommandCallable({
//CommandResult process(CommandSource source, String arguments) throws CommandException; //CommandResult process(CommandSource source, String arguments) throws CommandException;
process: function (src, args) { process: function (src, args) {
return that.cmd(src, name, args.split(" ")) ? CommandResult.success() : CommandResult.empty(); return that.cmd(src, that.name, args.length === 0 ? [] : args.split(" ")) ? CommandResult.success() : CommandResult.empty();
}, },
//List<String> getSuggestions(CommandSource source, String arguments, @Nullable Location<World> targetPosition) throws CommandException; //List<String> getSuggestions(CommandSource source, String arguments, @Nullable Location<World> targetPosition) throws CommandException;
getSuggestions: function (src, args, target) { getSuggestions: function (src, args, target) {
return that.tab(src, name, args.split(" ")); return that.tab(src, that.name, args.length === 0 ? [] : args.split(" "));
}, },
//boolean testPermission(CommandSource source); //boolean testPermission(CommandSource source);
testPermission: function () { testPermission: function () {
@ -43,7 +43,7 @@ var SimpleCommandCallable = function (name) {
}, },
//Optional<Text> getShortDescription(CommandSource source); //Optional<Text> getShortDescription(CommandSource source);
getShortDescription: function () { getShortDescription: function () {
return Optional.of(Text.of("")); return Optional.of(Text.of(command.description || '暂无描述!'));
}, },
//Optional<Text> getHelp(CommandSource source); //Optional<Text> getHelp(CommandSource source);
getHelp: function () { getHelp: function () {
@ -70,7 +70,8 @@ function enable(jsp) {
for (var name in commands) { for (var name in commands) {
var command = commands[name]; var command = commands[name];
if (typeof command !== 'object') continue; if (typeof command !== 'object') continue;
create(jsp, name) command.name = name
create(jsp, command)
console.debug('插件 %s 注册命令 %s ...'.format(jsp.description.name, name)); console.debug('插件 %s 注册命令 %s ...'.format(jsp.description.name, name));
} }
} }
@ -79,37 +80,38 @@ function enable(jsp) {
function get(name) { function get(name) {
} }
function create(jsp, name) { function create(jsp, command) {
var commandKey = jsp.description.name.toLowerCase() + ":" + name; var commandKey = jsp.description.name.toLowerCase() + ":" + command.name;
if(!commandMap[commandKey]){ if(!commandMap[commandKey]){
commandMap[commandKey] = new SimpleCommandCallable(); commandMap[commandKey] = new SimpleCommandCallable(command);
commandMap[commandKey].name = name; Sponge.getCommandManager().register(plugin, commandMap[commandKey].callable, command.name, commandKey);
Sponge.getCommandManager().register(plugin, commandMap[commandKey].callable, name, commandKey);
} }
return commandMap[commandKey]; return commandMap[commandKey];
} }
function on(jsp, name, exec) { function on(jsp, name, exec) {
var c = create(jsp, name); var c = create(jsp, {name: name});
console.debug('插件 %s 设置命令 %s 执行器 ...'.format(jsp.description.name, name)); console.debug('插件 %s 设置命令 %s 执行器 ...'.format(jsp.description.name, name));
if (exec.cmd) { if (exec.cmd) {
c.setExecutor(function (sender, command, args) { c.setExecutor(function execCmd(sender, command, args) {
try { try {
return exec.cmd(sender, command, args); return exec.cmd(sender, command, args);
} catch (ex) { } catch (ex) {
console.log(args) console.console('§6玩家 §a%s §6执行 §b%s §6插件 §d%s %s §6命令时发生异常'
console.console('§6玩家 §a%s §6执行 §b%s §6插件 §d%s %s §6命令时发生异常 §4%s'.format(sender.name, jsp.description.name, command, args, ex)); .format(sender.name, jsp.description.name, command, args.join(' ')));
console.ex(ex); console.ex(ex);
} }
}); });
} }
if (exec.tab) { if (exec.tab) {
c.setTabCompleter(function (sender, command, args) { c.setTabCompleter(function execTab(sender, command, args) {
try { try {
var token = args[args.length - 1]; var token = args[args.length - 1];
return Arrays.asList(exec.tab(sender, command, args)); var complate = exec.tab(sender, command, args) || []
return Arrays.asList(complate.copyPartialMatches(token, []));
} catch (ex) { } catch (ex) {
console.console('§6玩家 §a%s §6执行 §b%s §6插件 §d%s %s §6补全时发生异常 §4%s'.format(sender.name, jsp.description.name, command, args, ex)); console.console('§6玩家 §a%s §6执行 §b%s §6插件 §d%s %s §6补全时发生异常'
.format(sender.name, jsp.description.name, command, args.join(' ')));
console.ex(ex); console.ex(ex);
} }
}); });

View File

@ -32,7 +32,7 @@ function isVaildEvent(clz) {
} }
function class2Name(clazz) { function class2Name(clazz) {
return clazz.name.substring(clazz.name.lastIndexOf(".") + 1).replace(/\$/g, '.').toLowerCase(); return clazz.canonicalName.substring(clazz.name.lastIndexOf(".") + 1);
} }
function register(eventCls, exec, priority, ignoreCancel) { function register(eventCls, exec, priority, ignoreCancel) {

View File

@ -24,7 +24,7 @@ exports.plugin = {
* @returns {*} * @returns {*}
*/ */
get: function (name) { get: function (name) {
return PluginManager.getPlugin(name); return PluginManager.getPlugin(name).orElse(undefined);
}, },
/** /**
* 载入插件 并且返回结果 * 载入插件 并且返回结果
@ -38,7 +38,7 @@ exports.plugin = {
} }
return PluginManager.isPluginEnabled(name); return PluginManager.isPluginEnabled(name);
}, },
self: PluginManager.getPlugin('miaoscript').get() self: PluginManager.getPlugin('miaoscript').orElse(undefined)
}; };
/** /**
* 获取玩家 * 获取玩家
@ -48,9 +48,9 @@ exports.player = function () {
case 0: case 0:
return undefined; return undefined;
case 1: case 1:
return Server.getPlayer(arguments[0]).get(); return Server.getPlayer(arguments[0]).orElse(undefined);
default: default:
return Server.getPlayer(arguments[0]).get(); return Server.getPlayer(arguments[0]).orElse(undefined);
} }
}; };
/** /**
@ -59,8 +59,10 @@ exports.player = function () {
exports.players = function () { exports.players = function () {
switch (arguments.length) { switch (arguments.length) {
case 1: case 1:
// 此处的forEach是Collection接口的
return Server.onlinePlayers.forEach(arguments[0]); return Server.onlinePlayers.forEach(arguments[0]);
default: default:
return Server.onlinePlayers; // 此处会转换为JS原生的Array
return Java.from(Server.onlinePlayers.toArray());
} }
}; };

View File

@ -39,7 +39,8 @@ var SSLSocketFactory = function initSSLSocketFactory() {
var config = { var config = {
Charset: 'UTF-8', Charset: 'UTF-8',
ConnectTimeout: 10000, ConnectTimeout: 10000,
ReadTimeout: 10000 ReadTimeout: 10000,
Debug: false
} }
function open(url, method, header) { function open(url, method, header) {
@ -54,8 +55,10 @@ function open(url, method, header) {
conn.setDoInput(true); conn.setDoInput(true);
conn.setConnectTimeout(config.ConnectTimeout); conn.setConnectTimeout(config.ConnectTimeout);
conn.setReadTimeout(config.ReadTimeout); conn.setReadTimeout(config.ReadTimeout);
for (var key in header) { if (header) {
conn.setRequestProperty(key, header[key]); for (var key in header) {
conn.setRequestProperty(key, header[key]);
}
} }
return conn; return conn;
} }
@ -66,24 +69,28 @@ function buildUrl(url, params) {
if (queryStart == -1) { if (queryStart == -1) {
url += '?'; url += '?';
} }
for (var key in params) { return url += object2URLSearchParams(params);
url += key;
url += '=';
url += params[key];
url += '&';
}
return url.substr(0, url.length - 1);
} }
return url; return url;
} }
function request(url, method, header, params, body) { function request(config) {
var conn = open(buildUrl(url, params), method, header); var conn = open(buildUrl(config.url, config.query), config.method, config.header);
try { try {
conn.connect(); conn.connect();
if (body) { var data = config.data;
if (data) {
var out = conn.getOutputStream(); var out = conn.getOutputStream();
out.write(new String(body).getBytes(config.Charset)); if (typeof data === "object") {
var type = config.header['Content-Type'];
switch (type) {
case "application/x-www-form-urlencoded":
data = object2URLSearchParams(params);
default:
data = JSON.stringify(data)
}
}
out.write(new String(data).getBytes(config.Charset));
out.flush(); out.flush();
out.close(); out.close();
} }
@ -102,14 +109,37 @@ function response (conn) {
return result; return result;
} }
function object2URLSearchParams (params) {
var temp = []
for (var key in params) {
temp.push('%s=%s'.format(encodeURIComponent(key), encodeURIComponent(params[key])))
}
return temp.join('&')
}
var http = { var http = {
config: config config: config,
request: request
}; };
['GET', 'POST', 'PUT', 'DELETE', 'HEADER'].forEach(function(method){ ['GET', 'DELETE', 'HEAD', 'OPTIONS'].forEach(function (method) {
http[method.toLowerCase()] = function (url, header, params, body) { http[method.toLowerCase()] = function __likeGet__(url, data, config) {
return request(url, method, header, params, body); return this.request(Object.assign(config || {}, {
url: url,
method: method,
query: data
}));
} }
}) });
['POST', 'PUT', 'PATCH'].forEach(function (method) {
http[method.toLowerCase()] = function __likePost__(url, data, config) {
return this.request(Object.assign(config || {}, {
url: url,
method: method,
data: data
}));
}
});
exports = module.exports = http; exports = module.exports = http;

View File

@ -0,0 +1,139 @@
/*global Java, base, module, exports, require*/
var chat = require('api/chat');
var ChatMessagePart = function () {
var text;
var clickEventAction;
var clickEventValue;
var hoverEventAction;
var hoverEventValue;
var insertion;
this.click = function (action, value) {
this.clickEventAction = action;
this.clickEventValue = value;
}
this.hover = function (action, value) {
this.hoverEventAction = action;
this.hoverEventValue = value;
console.log(this.toJson());
}
this.convert = function () {
var str = {};
if (this.text) {
str.text = this.text;
}
if (this.clickEventAction) {
str.clickEvent = {
"action": this.clickEventAction,
"value": this.clickEventValue
}
}
if (this.hoverEventAction) {
str.hoverEvent = {
"action": this.hoverEventAction,
"value": this.hoverEventValue
}
}
if (this.insertion) {
str.insertion = this.insertion;
}
return str;
}
}
var Tellraw = function () {
var parts = [new ChatMessagePart()];
var self = this;
var cache = null;
this.then = function (part) {
if (typeof part === "string") {
var newPart = new ChatMessagePart();
newPart.text = part;
this.then(newPart);
return self;
}
var last = this.latest();
if (!last.text) {
last.text = part.text;
} else {
parts.push(part);
}
this.cache = null;
}
this.text = function (text) {
this.latest().text = text;
return this;
}
this.tip = function (str) {
if (toString.call(str) === "[object Array]") {
str = str.join("\n");
}
this.latest().hover("show_text", str);
return this;
}
this.item = function (str) {
this.latest().hover("show_item", str);
return this;
}
this.cmd = this.command = function (command) {
this.latest().click("run_command", command);
return this;
}
this.suggest = function (url) {
this.latest().click("suggest_command", url);
return this;
}
this.file = function (path) {
this.latest().click("open_file", path);
return this;
}
this.link = function (url) {
this.latest().click("open_url", url);
return this;
}
this.latest = function () {
return parts[parts.length - 1];
}
this.json = function () {
if (!this.cache) {
var temp = [];
parts.forEach(function (t) {
temp.push(t.convert());
})
this.cache = JSON.stringify(temp);
console.debug(this.cache);
}
return this.cache;
}
this.send = function (player) {
chat.json(player, self.json());
}
this.sendAll = function () {
server.players(function sendAllMessage(p) {
self.send(p);
})
}
}
Tellraw.create = function () {
return new Tellraw().then(Tellraw.duplicateChar);
}
Tellraw.duplicateChar = '§卐';
exports = module.exports = Tellraw;

View File

@ -0,0 +1,35 @@
'use strict';
/**
* 常用工具类
* Created by 蒋天蓓 on 2018/5/12 0009.
*/
/*global Java, base, module, exports, require, __FILE__*/
var Arrays = Java.type('java.util.Arrays');
function toStr(obj) {
if (obj.class) {
return Arrays.toString()
}
}
function compare(prop) {
return function (obj1, obj2) {
var val1 = obj1[prop];
var val2 = obj2[prop];
if (!isNaN(Number(val1)) && !isNaN(Number(val2))) {
val1 = Number(val1);
val2 = Number(val2);
}
if (val1 < val2) {
return -1;
} else if (val1 > val2) {
return 1;
} else {
return 0;
}
}
}
exports = module.exports = {
compare: compare
}

View File

@ -52,7 +52,7 @@ function send(event, player){
console.debug('玩家', player.getName(), "触发事件", event.class.simpleName); console.debug('玩家', player.getName(), "触发事件", event.class.simpleName);
setTimeout(function () { setTimeout(function () {
// noinspection JSUnresolvedVariable // noinspection JSUnresolvedVariable
player.sendMessage("§a欢迎来到 §bMiaoScript §a的世界! 当前在线: " + server.players.length) player.sendMessage("§a欢迎来到 §bMiaoScript §a的世界! 当前在线: " + server.players().length)
}, 10); }, 10);
} }

View File

@ -1,14 +1,13 @@
'use strict'; 'use strict';
/*global Java, base, module, exports, require*/ /*global Java, base, module, exports, require*/
var event = require('api/event');
var wrapper = require('api/wrapper');
var command = require('api/command');
var server = require('api/server'); var server = require('api/server');
var event = require('api/event');
var task = require('api/task');
var http = require('http'); var http = require('http');
var fs = require('fs'); var fs = require('fs');
var nameMap = []; var Keys;
var description = { var description = {
name: 'ItemTag', name: 'ItemTag',
@ -20,10 +19,12 @@ var itemConfig;
function load() { function load() {
var itemFile = self.file('item.yml'); var itemFile = self.file('item.yml');
if (!itemFile.exists()) { task.async(function () {
base.save(itemFile, http.get('https://data.yumc.pw/config/Item_zh_CN.yml')); if (!itemFile.exists()) {
} fs.save(itemFile, http.get('https://data.yumc.pw/config/Item_zh_CN.yml'))
itemConfig = self.getConfig('item.yml'); }
itemConfig = self.getConfig('item.yml')
})
} }
function enable() { function enable() {
@ -39,10 +40,11 @@ function enable() {
}) })
break; break;
case ServerType.Sponge: case ServerType.Sponge:
event.on(self, 'itemmergeitemevent', function (event) { Keys = Java.type('org.spongepowered.api.data.key.Keys');
event.on(self, 'ItemMergeItemEvent', function (event) {
// Sponge 暂未实现当前事件 // Sponge 暂未实现当前事件
}) })
event.on(self, 'spawnentityevent', function (event) { event.on(self, 'SpawnEntityEvent', function (event) {
event.entities.forEach(function (entity) { event.entities.forEach(function (entity) {
if (entity.type.name === "item") sponge(entity); if (entity.type.name === "item") sponge(entity);
}) })
@ -51,13 +53,8 @@ function enable() {
} }
} }
function getItemName(name) {
return itemConfig[(name + '').toUpperCase()] || name;
}
function bukkit(item , amount) { function bukkit(item , amount) {
var amounts = amount == 1 ? "" : "*" + amount; item.setCustomName('§b' + getItemName(item.itemStack.type) + getItemCount(amount));
item.setCustomName('§b' + getItemName(item.itemStack.type) + amounts);
item.setCustomNameVisible(true); item.setCustomNameVisible(true);
} }
@ -65,12 +62,20 @@ function sponge(entity) {
var itemOptional = entity.get(Keys.REPRESENTED_ITEM); var itemOptional = entity.get(Keys.REPRESENTED_ITEM);
if (itemOptional.isPresent()) { if (itemOptional.isPresent()) {
var item = itemOptional.get(); var item = itemOptional.get();
var amounts = item.count == 1 ? "" : "*" + item.count; var itemName = '§b' + getItemName(item.type.name.split(':')[1]) + getItemCount(item.count);
entity.offer(org.spongepowered.api.data.key.Keys.DISPLAY_NAME, org.spongepowered.api.text.Text.of('§b' + getItemName(item.type.name.split(':')[1]) + amounts)); entity.offer(Keys.DISPLAY_NAME, org.spongepowered.api.text.Text.of(itemName));
entity.offer(org.spongepowered.api.data.key.Keys.CUSTOM_NAME_VISIBLE, true); entity.offer(Keys.CUSTOM_NAME_VISIBLE, true);
} }
} }
function getItemName(name) {
return itemConfig[(name + '').toUpperCase()] || name;
}
function getItemCount(amount){
return amount == 1 ? "" : "*" + amount;
}
module.exports = { module.exports = {
description: description, description: description,
load: load, load: load,

View File

@ -0,0 +1,252 @@
'use strict';
/**
* MiaoChat 喵式聊天插件
*/
/*global Java, base, module, exports, require*/
var event = require('api/event');
var wrapper = require('api/wrapper');
var command = require('api/command');
var server = require('api/server');
var fs = require('fs');
var tellraw = require('tellraw');
var utils = require('utils')
var description = {
name: 'MiaoChat',
version: '1.0',
author: '喵呜',
commands: {
'mchat': {
description: 'MiaoChat登录命令'
}
},
permissions: {
'MiaoChat.default': {
default: true,
description: '默认权限 赋予玩家'
},
'MiaoChat.admin': {
default: false,
description: '管理权限'
}
},
config: {
"Version":"1.8.5",
"BungeeCord":true,
"Server":"生存服",
"ChatFormats":{
"default":{
"index":50,
"permission":"MiaoChat.default",
"range":0,
"format":"[world][player]: ",
"item":true,
"itemformat":"&6[&b%s&6]&r"
},
"admin":{
"index":49,
"permission":"MiaoChat.admin",
"format":"[admin][world][player][help]: ",
"range":0,
"item":true,
"itemformat":"&6[&b%s&6]&r"
}
},
StyleFormats: {
"world":{
"text":"&6[&a%player_world%&6]",
"hover":[
"&6当前所在位置:",
"&6世界: &d%player_world%",
"&6坐标: &aX:%player_x% Y: %player_y% Z: %player_z%",
"",
"&c点击即可TP我!"
],
"click":{
"type":"COMMAND",
"command":"/tpa %player_name%"
}
},
"player":{
"text":"&b%player_name%",
"hover":[
"&6玩家名称: &b%player_name%",
"&6玩家等级: &a%player_level%",
"&6玩家血量: &c%player_health%",
"&6玩家饥饿: &d%player_food_level%",
"&6游戏模式: &4%player_gamemode%",
"",
"&c点击与我聊天"
],
"click":{
"type":"SUGGEST",
"command":"/tell %player_name%"
}
},
"admin":{
"text":"&6[&c管理员&6]"
},
"help":{
"text":"&4[求助]",
"hover":[
"点击求助OP"
],
"click":{
"type":"COMMAND",
"command":"管理员@%player_name% 我需要你的帮助!"
}
}
}
}
};
var chat_formats;
var style_formats;
function load() {
chat_formats = Object.values(self.config.ChatFormats);
chat_formats.sort(utils.compare('index'));
initFormat(chat_formats);
style_formats = self.config.StyleFormats;
}
// 用于匹配 '[xx]' 聊天格式
var FORMAT_PATTERN = /[\[]([^\[\]]+)[\]]/ig;
function initFormat(chat_formats) {
chat_formats.forEach(function (chat_format) {
var chat_format_str = chat_format.format;
var temp = [];
var r = [];
while(r = FORMAT_PATTERN.exec(chat_format_str)) {
temp.push(r[1]);
}
var format_list = []
temp.forEach(function splitStyle(t) {
var arr = chat_format_str.split('[' + t + ']', 2);
if (arr[0]) {
format_list.push(arr[0]);
}
format_list.push(t);
chat_format_str = arr[1];
});
if (chat_format_str) {
format_list.push(chat_format_str);
}
chat_format.format_list = format_list;
})
}
function enable() {
registerCommand();
registerEvent();
}
function registerCommand() {
command.on(self, 'mchat', {
cmd: mchat
});
}
function mchat(sender, command, args) {
return true;
}
function registerEvent() {
switch (DetectServerType) {
case ServerType.Bukkit:
event.on(self, 'AsyncPlayerChatEvent', handlerBukkitChat);
break;
case ServerType.Sponge:
event.on(self, 'MessageChannelEvent.Chat', handlerSpongeChat);
break;
}
}
function handlerBukkitChat(event) {
sendChat(event.player, event.message, function() { event.setCancelled(true); });
}
function handlerSpongeChat(event) {
var player = event.getCause().first(org.spongepowered.api.entity.living.player.Player.class).orElse(null);
if (player == null) { return; }
var plain = event.getRawMessage().toPlain();
if (plain.startsWith(tellraw.duplicateChar)) {
return;
}
sendChat(player, plain, function() { event.setMessageCancelled(true) });
}
function sendChat(player, plain, callback) {
var chat_format = getChatFormat(player);
if (!chat_format) {
console.debug('未获得用户', player.name, '的 ChatRule 跳过执行...')
return;
}
callback();
var tr = tellraw.create();
chat_format.format_list.forEach(function setStyle(format) {
var style = style_formats[format];
if (style) {
tr.then(style.text);
if (style.hover) {
tr.tip(style.hover);
}
if (style.click && style.click.type && style.click.command) {
switch (style.click.type) {
case "COMMAND":
tr.command(style.click.command);
break;
case "OPENURL":
tr.link(style.click.command);
break;
case "SUGGEST":
tr.suggest(style.click.command);
break;
default:
}
}
} else {
tr.then(format);
}
})
tr.then(plain).sendAll();
}
function getChatFormat(player) {
for (var i in chat_formats){
var format = chat_formats[i];
if (player.hasPermission(format.permission)) {
return format;
}
}
return null;
}
function replace(target) {
if (toString.call(target) === "[object Array]") {
for (var i in target) {
target[i] = replaceStr(target[i]);
}
} else {
target = replaceStr(target);
}
return target;
}
function replaceStr(target) {
return target;
}
function disable() {
console.log('卸载', description.name, '插件!');
}
module.exports = {
description: description,
load: load,
enable: enable,
disable: disable
};

View File

@ -0,0 +1,162 @@
'use strict'
/*global Java, base, module, exports, require*/
var wrapper = require('api/wrapper')
var command = require('api/command')
var manager = require('api/plugin')
var task = require('api/task')
var http = require('http')
var fs = require('fs')
var pluginCache = []
var packageCache = []
var packageNameCache = []
var description = {
name: 'MiaoScriptPackageManager',
version: '1.0',
author: '喵♂呜',
description: 'MiaoScript包管理工具',
commands: {
'mpm': {
description: 'MiaoScriptPackageManager主命令'
}
},
config: {
center: 'https://ms.yumc.pw/api/package/list'
}
}
var help = [
'§6========= §a' + description.name + ' §6帮助 §aBy §b喵♂呜 §6=========',
'§6/mpm §ainstall <插件名称> §6- §3安装插件',
'§6/mpm §alist §6- §3列出仓库插件',
'§6/mpm §aupdate <插件名称> §6- §3更新插件(无插件名称则更新源)',
'§6/mpm §aupgrade <插件名称> §6- §3及时更新插件(update需要重启生效)',
'§6/mpm §areload <插件名称> §6- §3重载插件(无插件名称则重载自生)',
]
function load() {
task.async(function () {
JSON.parse(http.get(self.config.center)).data.forEach(function cachePackageName(pkg) {
packageCache[pkg.name] = pkg
packageNameCache.push(pkg.name)
})
pluginCache = Object.keys(manager.plugins)
})
}
function enable() {
command.on(this, 'mpm', {
cmd: function (sender, command, args) {
if (args.length > 0) {
switch (args[0]) {
case "list":
console.sender(sender, '§6当前 §bMiaoScriptPackageCenter §6中存在下列插件:')
for (var pkgName in packageCache) {
var pkg = packageCache[pkgName]
console.sender(sender, '§6插件名称: §b%s §6版本: §a%s'.format(pkg.name, pkg.version))
}
break
case "install":
if (args.length > 1) {
download(sender, args[1]);
} else {
console.sender(sender, '§c请输入插件名称!')
}
break
case "update":
if (args.length > 1) {
update(sender, args[1]);
} else {
load();
console.sender(sender, "§a仓库缓存刷新成功 共存在 §b" + pluginCache.length + " §a个插件!")
}
break
case "upgrade":
break
case "delete":
if (args.length > 1) {
del(sender, args[1]);
} else {
console.sender(sender, '§c请输入插件名称!')
}
break
case "reload":
if (args.length > 1) {
var pname = args[1]
if (pluginCache.indexOf(pname) !== -1) {
manager.reload(pname)
} else {
console.sender(sender, '§c插件 %s 不存在!'.format(pname))
}
} else {
self.reloadConfig();
load();
}
break
case "help":
sendHelp(sender);
break;
}
} else {
sendHelp(sender);
}
},
tab: function (sender, command, args) {
if (args.length === 1) return ['list', 'install', 'update', 'upgrade', 'reload']
if (args.length > 1) {
switch (args[0]) {
case "install":
return packageNameCache;
case "update":
case "upgrade":
case "reload":
return pluginCache;
}
}
}
})
}
function sendHelp(sender){
help.forEach(function (msg) {
console.sender(sender, msg);
})
}
function del(sender, name) {
if (pluginCache.indexOf(name) !== -1) {
console.sender(sender, '§c插件 %s 不存在!'.format(name));
return;
}
manager.disable(name);
fs.delete(plugin.__FILE__);
}
function download(sender, name) {
var plugin = packageCache[name];
if (!plugin) {
console.sender(sender, '§c插件§b', name, '§c不存在')
return;
}
var pfile = fs.file(__dirname, pname + '.js')
console.sender(sender, '§6开始下载插件: §b%s'.format(pkg.name))
console.sender(sender, '§6插件下载地址: §b%s'.format(pkg.url))
fs.save(pfile, http.get(pkg.url))
console.sender(sender, '§6插件 §b%s §a下载完毕 开始加载 ...'.format(pname))
manager.loadPlugin(pfile)
console.sender(sender, '§6插件 §b%s §a安装成功!'.format(pname))
}
function disable() {
}
module.exports = {
description: description,
load: load,
enable: enable,
disable: disable
}