119 Commits

Author SHA1 Message Date
ebf218e534 feat: release 0.3.1
Signed-off-by: MiaoWoo <admin@yumc.pw>
2020-03-03 01:07:12 +08:00
fd5c2aa087 feat: update require registry
Signed-off-by: MiaoWoo <admin@yumc.pw>
2020-03-03 00:57:19 +08:00
ea8e62b696 feat: optimize decompression
Signed-off-by: MiaoWoo <admin@yumc.pw>
2020-03-02 10:34:30 +08:00
367b732f7c feat: support Nukkit and async init engine
Signed-off-by: MiaoWoo <admin@yumc.pw>
2020-02-29 17:32:53 +08:00
9bcd4cd748 feat: update to 0.2.0
Signed-off-by: MiaoWoo <admin@yumc.pw>
2020-02-24 00:27:54 +08:00
2ed9614bc4 fix: load source map file error
Signed-off-by: MiaoWoo <admin@yumc.pw>
2020-02-16 14:48:54 +08:00
00287ff80a feat: optimize ployfill
Signed-off-by: MiaoWoo <admin@yumc.pw>
2020-02-02 02:16:05 +08:00
2a891c1117 feat: add ts defiend
Signed-off-by: MiaoWoo <admin@yumc.pw>
2020-02-01 02:41:24 +08:00
46925f9b52 feat: add system level
Signed-off-by: MiaoWoo <admin@yumc.pw>
2020-02-01 02:41:00 +08:00
57926ba788 feat: move ployfill to @ms/ployfill
Signed-off-by: MiaoWoo <admin@yumc.pw>
2020-02-01 02:40:39 +08:00
8933afeb71 fix: Plugin Resources get error
Signed-off-by: MiaoWoo <admin@yumc.pw>
2020-01-19 01:57:50 +08:00
0b0cea9e50 feat: add bungee support & ProxyClass
Signed-off-by: MiaoWoo <admin@yumc.pw>
2020-01-17 18:40:51 +08:00
1c21792572 feat: add global.trace and check node module
Signed-off-by: MiaoWoo <admin@yumc.pw>
2020-01-17 18:39:23 +08:00
31351fc393 feat: define XMLHttpRequest
Signed-off-by: MiaoWoo <admin@yumc.pw>
2019-09-27 18:41:26 +08:00
c859605738 feat: auto remove temp file at exit
Signed-off-by: MiaoWoo <admin@yumc.pw>
2019-09-24 10:52:51 +08:00
388e1e9135 fix: module download error at windows remove okhttp lib
Signed-off-by: MiaoWoo <admin@yumc.pw>
2019-09-24 10:10:17 +08:00
996a63ba2d fix: module name resolve error
Signed-off-by: MiaoWoo <admin@yumc.pw>
2019-09-24 00:19:39 +08:00
548c76f154 feat: support get module from npm
Signed-off-by: MiaoWoo <admin@yumc.pw>
2019-09-23 18:46:32 +08:00
8be38800b0 feat: add okhttp lib
Signed-off-by: MiaoWoo <admin@yumc.pw>
2019-09-23 09:02:34 +08:00
0dfe04040e feat: compatible windows and support disable function
Signed-off-by: MiaoWoo <admin@yumc.pw>
2019-09-19 14:45:06 +08:00
7dad0e7abc refactor: remove old file & update bios.js
Signed-off-by: MiaoWoo <admin@yumc.pw>
2019-09-10 17:15:53 +08:00
96639d0978 feat: add comment
Signed-off-by: MiaoWoo <admin@yumc.pw>
2019-09-09 14:48:19 +08:00
0df2d2b71f feat: add reload support
Signed-off-by: MiaoWoo <admin@yumc.pw>
2019-09-09 10:50:49 +08:00
de18b0f628 feat: compatible node_modules load logic
Signed-off-by: MiaoWoo <admin@yumc.pw>
2019-09-07 12:20:11 +08:00
bbf08816ba feat: create new runtime
Signed-off-by: MiaoWoo <admin@yumc.pw>
2019-09-05 15:58:24 +08:00
160e7f4118 feat: compatible symbolic links require 2019-09-01 23:58:07 +08:00
2d4bc3dd24 feat: add jtar lib
Signed-off-by: MiaoWoo <admin@yumc.pw>
2019-08-31 10:42:21 +08:00
c5b7a45605 feat: move plugin file & optimize bios
Signed-off-by: MiaoWoo <admin@yumc.pw>
2019-08-29 10:08:29 +08:00
4653bbc091 fix: item lib error
Signed-off-by: MiaoWoo <admin@yumc.pw>
2019-04-28 19:32:24 +08:00
565419a292 feat: optimize item lib
Signed-off-by: MiaoWoo <admin@yumc.pw>
2019-04-28 19:18:53 +08:00
a28386401c feat: update plugins
Signed-off-by: MiaoWoo <admin@yumc.pw>
2019-04-28 18:08:47 +08:00
a78e6482e8 feat: optimize framework
Signed-off-by: MiaoWoo <admin@yumc.pw>
2019-04-28 18:06:42 +08:00
03129b8797 doc: update doc
Signed-off-by: MiaoWoo <admin@yumc.pw>
2019-04-24 09:33:00 +08:00
c2d0c05bcf fix: server console load error
Signed-off-by: MiaoWoo <admin@yumc.pw>
2019-04-24 09:25:02 +08:00
b611da5e27 style: format file
Signed-off-by: MiaoWoo <admin@yumc.pw>
2019-04-23 18:56:34 +08:00
93d7389047 refactor: compatible commonjs loader
Signed-off-by: MiaoWoo <admin@yumc.pw>
2019-04-23 18:44:15 +08:00
a875a6ca8e feat: Optimizing Code
Signed-off-by: MiaoWoo <admin@yumc.pw>
2019-03-25 17:15:27 +08:00
135d0f2b90 feat: add version check 2019-03-25 17:14:32 +08:00
8cf8dccbe4 feat: Optimizing Framework Code
Signed-off-by: MiaoWoo <admin@yumc.pw>
2019-03-25 17:13:54 +08:00
478bff9599 feat: Core Framework Optimization 2019-03-13 17:27:17 +08:00
2013b3b07c style: code format
Signed-off-by: MiaoWoo <admin@yumc.pw>
2019-03-09 10:29:47 +08:00
2dff086a01 feat: print stack on game
Signed-off-by: MiaoWoo <admin@yumc.pw>
2019-03-09 10:29:06 +08:00
8d5902600f feat: complate 1.13 2019-03-09 10:28:44 +08:00
e455cbf996 feat: Core Framework Optimization
Signed-off-by: MiaoWoo <admin@yumc.pw>
2019-03-09 10:28:14 +08:00
8d40a69ac7 fix: error throw error
Signed-off-by: MiaoWoo <admin@yumc.pw>
2019-03-09 10:26:36 +08:00
f98814bf2d feat: Optimization framework
Signed-off-by: MiaoWoo <admin@yumc.pw>
2019-03-02 00:29:46 +08:00
72ae1b4b29 style: format code
Signed-off-by: MiaoWoo <admin@yumc.pw>
2019-02-26 09:43:54 +00:00
ee4072526b feat: throw error
Signed-off-by: MiaoWoo <admin@yumc.pw>
2019-02-26 09:42:59 +00:00
2cd6e019c6 fix: console error
Signed-off-by: MiaoWoo <admin@yumc.pw>
2019-02-26 09:40:00 +00:00
6766c3b0ce fix: via command error
Signed-off-by: MiaoWoo <admin@yumc.pw>
2019-02-26 09:38:08 +00:00
150c18957c feat: remove YumCore depend
Signed-off-by: MiaoWoo <admin@yumc.pw>
2019-02-26 09:30:30 +00:00
bdc0a62e36 refactor: 优化代码
Signed-off-by: MiaoWoo <admin@yumc.pw>
2019-02-26 02:08:34 +00:00
ccdbd8b683 style: formatting code 2019-02-23 16:00:53 +00:00
c2c17a46d4 feat: Optimization code 2019-02-23 16:00:03 +00:00
997820d117 fix: compatible bukkit command
1. fix bukkit command error
2. fix bukkit task error
3. fix bukkit class loader error
4. optimization require
2019-02-23 15:51:04 +00:00
d67f2843b0 feat: 修改脚本作者名称 2018-07-29 13:05:51 +00:00
7822803376 feat: 优化代码逻辑 2018-07-29 03:07:05 +00:00
ee496c5bda feat: MSPM异步处理命令 2018-05-30 14:09:20 +00:00
324fbee2e5 fix: 修复papi数组处理错误 2018-05-30 13:11:28 +00:00
c955670658 feat: 抽离command类库 2018-05-30 13:10:28 +00:00
33fecc7372 feat: 调整server类库 2018-05-30 13:09:46 +00:00
b33826bbe9 feat: 更新版本号 2018-05-20 03:31:19 +00:00
8e2e2bca82 feat: 新增MiaoBoard插件 2018-05-19 17:14:19 +00:00
5ea78a60e5 feat: 新增MiaoAuth插件 2018-05-19 17:13:50 +00:00
c873031cc2 feat: 修改初始化函数名称 2018-05-19 17:11:48 +00:00
9504ec8b12 fix: file.js修复一个语法错误 2018-05-19 17:10:56 +00:00
abdfbce125 feat: 新增config默认值绑定 匿名函数添加名称 2018-05-19 17:10:29 +00:00
e6af7b1828 feat: PAPI支持直接替换数组 2018-05-19 17:09:14 +00:00
8f5bae006a feat: 调整Task任务模块 2018-05-19 17:08:48 +00:00
f94fa71f36 feat: 新增模板预编译插件功能 2018-05-19 17:08:26 +00:00
fcc1f18336 feat: 清除不必要的代码 2018-05-18 15:12:35 +00:00
823ff1c70b feat: 新增MiaoChat插件描述 2018-05-17 12:40:13 +00:00
2360dd9b0e feat: MiaoScriptPackageManager 新增restart和run方法 2018-05-17 12:39:52 +00:00
f94653249d fix: 修复Sponge命令参数存在空字符串的问题 2018-05-17 12:35:38 +00:00
c095593c41 fix: 修复混淆导致的重载方法丢失 2018-05-17 12:35:08 +00:00
202dc9f00c feat: 新增引擎Shutdown方法 关闭资源 2018-05-17 12:34:35 +00:00
88d71abb2a feat: 格式化代码 添加d.ts文件 去除引擎无关代码 清理单元测试 2018-05-17 18:30:40 +08:00
967e7d1beb fix: 修复TellRaw类库错误 2018-05-16 17:05:47 +00:00
e97de1f8d0 fix: 修复pkg不存在的问题 2018-05-16 16:57:06 +00:00
bc6e07cfc8 fix: 修复下载错误的问题 2018-05-16 16:55:44 +00:00
4dec6bca98 feat: 更新版本号 2018-05-16 16:49:58 +00:00
f8ec9b9f6e feat: 新增Hook提示 2018-05-16 16:30:05 +00:00
1735417887 feat: 调整列表载入顺序 2018-05-16 16:11:23 +00:00
9819a82265 feat: 完善MiaoChat的PAPI的替换 2018-05-16 16:09:26 +00:00
d2ebd8fa7e feat: 完善服务获取类 2018-05-16 16:08:27 +00:00
0492275eb2 feat: 新增PAPI代理类 2018-05-16 16:07:52 +00:00
3fe1feccff feat: 去除调试代码 2018-05-16 16:07:30 +00:00
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
fb65f95658 feat: 新增案例插件 更新插件版本 2018-01-09 12:22:24 +00:00
96f93754e6 feat: 优化API 修复http模块错误 2018-01-09 12:19:02 +00:00
a6be26206e feat: 更新 fs 类库 优化 require 2018-01-09 12:16:36 +00:00
318a7cdcfd feat: 安全起见暂时屏蔽load方法和disable方法 2018-01-09 11:28:00 +00:00
d519bface0 fix: 修复调试信息错误 2018-01-08 09:12:36 +00:00
0fc6504c6a feat: require新增基础目录api 2018-01-08 09:12:08 +00:00
5f41e1593f doc: 新增README 2018-01-08 09:11:48 +00:00
6272553e9b fix: 修复重载命令无效的BUG 2018-01-07 18:16:57 +00:00
97 changed files with 1871 additions and 7172 deletions

99
.gitignore vendored
View File

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

87
README.md Normal file
View File

@ -0,0 +1,87 @@
# MiaoScript
> 排版什么的 不存在的 这辈子都不会有排版的 除非什么时候论坛支持 `MarkDown` 了
### 简介
> 这个坑是我自己刨的 但是发现坑太大 需要更多的人一起填
#### 起源
- 诞生于 `2016年08月25日` 这是 Git 上的第一个提交 具体啥时候我也忘了
- 起初 `MiaoScript` 只是用于服务器其他插件的变量执行 并且依赖于PAPI(不知道是啥的自己百度)
- 比如 [`MiaoMenu`](http://w.yumc.pw/zc/MiaoMenu.html) 的部分复杂脚本
- 比如 [`MiaoChat`](http://mcbbs.net/thread-631240-1-1.html) 的聊天变量
- 突然有一天 圈内的大佬 `QSB` @qiu1995 过来找我 说能不能用脚本监听玩家的事件
- PS: 这货自从用过 `DeluxeMenu` 之后就喜欢上了用JS写菜单
- 当初感觉没啥问题 就出了第一个简易的 `MiaoScript` 版本 还是用 yml 做的配置文件
- 但是由于设计 BukkitAPI 等内容 对Java要求太高 后来 邱也弃坑了 我也弃坑了
#### 刨坑
- 时隔多年(也就一年) 看到了Sponge的兴起 (估摸着是MCPC系列的MOD端都弃坑了)
- 同时 这期间 收到很多腐竹的单子 但是又是非常基础的东西
- 比如 开服给玩家发一条消息啦
- 比如 修改玩家某些数据啦
- 这些东西实际上也就几行代码的事情
- 同时 很多想入坑 插件开发 但是又有一些被卡死在环境搭建上
- 比如 `Bukkit` 需要 `BukkitAPI`
- `Sponge` 需要 `SpongeAPI` 如果涉及 `MOD` 还要 `Forge` 环境
- 再或者 BungeeCord 的插件开发 我也是经常懒得搞
- 当然 最主要的是 某个 咕咕咕的群 天天有人问我 喵系插件能不能支持 Sponge
- 内心当然是拒绝的 现在要上班养老婆孩子(咳咳 不要以为我是大叔 我也才刚毕业而已) 那里还有时间免费给你们写插件
- 于是乎 我又想起了当初的 `MiaoScript`
- 突发奇想 一个插件的雏形出现在我的脑海中
- 可以兼容多种服务器
- 不需要开发环境 有记事本就可以开发
- 语法要简单 比如 JavaScript
- 能够自动搜索安装依赖(毕竟很多人天天问我为何喵系插件跑不起来 都是缺少PAPI)
- 能够不重启更新插件(当然得保证代码安全的前提下)
- 在 2017年9月14号(距离 第一个版本正式版发布(2016-09-21) 相差一年整)
- 一个全新的 `MiaoScript` 诞生了
- Java部分代码 只有一个启动类
- 核心全部由 JS 编写
- 兼容 `CommonJS` 规范
- 实时重载
- 不兼容 MOD 服 (咳咳 当然现在已经支持了)
- 基础结构如下
```txt
└─src
└─main
├─java 引导类
└─resources
├─bios.js 核心启动类 用于释放文件和初始化
├─api 全平台兼容的接口
├─core 核心代码 例如 require 模块
│ └─ext 扩展代码 例如 Object.toJson()
├─internal 内部实现 用于各个平台实现API
│ ├─bukkit BukkitAPI内部实现
│ └─sponge SpongeAPI内部实现
├─modules JS模块 例如 js-yaml, http 等
└─plugins 这里当然是插件啦
├─bukkit 只兼容bukkit的插件
├─sponge 只兼容Sponge的插件
└─ext 插件扩展类库 用于多个插件共用代码 当然最好是是用 `modules` 啦
```
- 没错 第一个版本只兼容了 BukkitAPI
- 我还用 `MiaoScript` 给某位腐竹写了一个抽奖插件
- 当时因为没解决 MOD 服兼容问题 所以就退款了 放上[源码](http://paste.yumc.pw/pknd8q6e1)
- 由于当时没有封装相关的API所以很多方法是直接调用了 `Bukkit` 原生的代码
- 所以不兼容 `Sponge`
### 进展
- [项目发布](https://git.yumc.pw/502647092/MiaoScript/releases)
- [项目代码](https://git.yumc.pw/502647092/MiaoScript)
- [项目脑图](http://naotu.baidu.com/file/293b9a0fc7cef23c69de81c55e3617d5?token=1eee8fd759198eb7)
### 规划
- 初期只会支持JS类型的插件开发
- 二期会出一个建议版本的MS脚本 可以用简单的语法实现简单的功能
- 各个层级会有依赖控制 比如 `MS脚本 => JS脚本 => 调用Java原生API`
### 填坑
- 实际上说了那么多 最终希望的就是 有大佬能一起来填坑 毕竟这个坑太大了

105
obf.dict
View File

@ -1,105 +0,0 @@
™™
▄™
▒™
░™
▓™
™▄
▄▄
▒▄
░▄
▓▄
™▒
▄▒
▒▒
░▒
▓▒
™░
▄░
▒░
░░
▓░
™▓
▄▓
▒▓
░▓
▓▓
™▄
™▒
™░
™▓
▄™
▄▄
▄▒
▄░
▄▓
▒™
▒▄
▒░
▒▓
░™
░▄
░▒
░▓
▓™
▓▄
▓▒
▓░
™™™
▄™▄
▒™▒
░™░
▓™▓
™▄™
▄▄▄
▒▄▒
░▄░
▓▄▓
™▒™
▄▒▄
▒▒▒
░▒░
▓▒▓
™░™
▄░▄
▒░▒
░░░
▓░▓
™▓™
▄▓▄
▒▓▒
░▓░
▓▓▓
™ ™
™▄™
™▒™
™░™
™▓™
▄™▄
▄ ▄
▄▒▄
▄░▄
▄▓▄
▒™▒
▒▄▒
▒ ▒
▒░▒
▒▓▒
░™░
░▄░
░▒░
░ ░
░▓░
▓™▓
▓▄▓
▓▒▓
▓░▓
▓ ▓

173
pom.xml
View File

@ -3,7 +3,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>pw.yumc</groupId>
<artifactId>MiaoScript</artifactId>
<version>1.2.0</version>
<version>0.3.1</version>
<developers>
<developer>
<id>502647092</id>
@ -18,7 +18,7 @@
<resource>
<directory>src/main/resources</directory>
<excludes>
<exclude>plugins/**.js</exclude>
<exclude>dev-plugins/**</exclude>
</excludes>
<filtering>true</filtering>
</resource>
@ -27,51 +27,21 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>2.4.3</version>
<version>3.2.1</version>
<configuration>
<createDependencyReducedPom>false</createDependencyReducedPom>
<artifactSet>
<includes>
<include>org.kamranzafar:jtar</include>
</includes>
</artifactSet>
</configuration>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<createDependencyReducedPom>false</createDependencyReducedPom>
<minimizeJar>true</minimizeJar>
<artifactSet>
<includes>
<include>pw.yumc:YumCore</include>
</includes>
</artifactSet>
<relocations>
<relocation>
<pattern>pw.yumc.YumCore</pattern>
<shadedPattern>${project.groupId}.${project.artifactId}</shadedPattern>
</relocation>
</relocations>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>com.github.wvengen</groupId>
<artifactId>proguard-maven-plugin</artifactId>
<version>2.0.13</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>proguard</goal>
</goals>
<configuration>
<options>
<option>-repackageclasses \ʼ.ʽ.ʾ.${project.artifactId}</option>
<option>-keep class ${project.groupId}.${project.artifactId}.${project.artifactId}</option>
<option>-keep class ${project.groupId}.${project.artifactId}.${project.artifactId}Bungee</option>
</options>
<libs>
<lib>${java.home}/lib/rt.jar</lib>
</libs>
</configuration>
</execution>
</executions>
</plugin>
@ -79,25 +49,99 @@
</build>
<ciManagement>
<system>Jenkins</system>
<url>http://ci.yumc.pw/job/${project.artifactId}/</url>
<url>https://ci.yumc.pw/job/Minecraft/job/${project.artifactId}/</url>
</ciManagement>
<properties>
<env.GIT_COMMIT>DEV</env.GIT_COMMIT>
<update.changes>
§620-03-03 §afeat: require 新增 淘宝镜像源拉取;
§620-02-27 §afeat: 异步加载脚本引擎;
§620-02-25 §afeat: 新增 Nukkit 的支持;
§620-02-16 §afeat: 新增 Source Map 支持;
§620-02-02 §afeat: 迁移 ployfill 到 @ms/ployfill;
§620-01-14 §afeat: 新增 Bungee 支持;
      §afeat: 新增 instance 实例获取
</update.changes>
<update.changelog>
§619-09-24 §cremove: 移除 okhttp3 类库;
      §afeat: 新增require自动下载模块功能;
§619-09-21 §afeat: 新增 okhttp3 类库;
§619-08-31 §afeat: 新增 tar 类库 支持 tar.gz 解压;
§619-08-29 §erefactor: 移动插件文件 默认自带MSPM插件 优化bios;
§618-5-20 §afeat: 新增MiaoBoard插件;
§618-5-20 §afeat: 新增MiaoAuth插件;
§618-5-20 §afeat: 修改初始化函数名称;
§618-5-20 §cfix: file.js修复一个语法错误;
§618-5-20 §afeat: 新增config默认值绑定 匿名函数添加名称;
§618-5-20 §afeat: PAPI支持直接替换数组;
§618-5-20 §afeat: 调整Task任务模块;
§618-5-20 §afeat: 新增模板预编译插件功能;
§618-5-18 §afeat: 清除不必要的代码;
§618-5-17 §afeat: 新增MiaoChat插件描述;
§618-5-17 §afeat: MiaoScriptPackageManager 新增restart和run方法;
§618-5-17 §cfix: 修复Sponge命令参数存在空字符串的问题;
§618-5-17 §cfix: 修复混淆导致的重载方法丢失;
§618-5-17 §afeat: 新增引擎Shutdown方法 关闭资源;
§618-5-17 §afeat: 格式化代码 添加d.ts文件 去除引擎无关代码 清理单元测试;
§618-5-17 §cfix: 修复TellRaw类库错误;
§618-5-17 §cfix: 修复pkg不存在的问题;
§618-5-17 §cfix: 修复下载错误的问题;
§618-5-17 §afeat: 更新版本号;
§618-05-17 §afeat: 新增Hook提示;
§618-05-17 §afeat: 调整列表载入顺序;
§618-05-17 §afeat: 完善MiaoChat的PAPI的替换;
§618-05-17 §afeat: 完善服务获取类;
§618-05-17 §afeat: 新增PAPI代理类;
§618-05-17 §afeat: 去除调试代码;
§618-05-17 §afeat: 迁移配置 完善reload命令;
§618-05-15 §afeat: 分离TellRaw类库;
§618-05-15 §afeat: 完善MiaoChat的Bukkit版本;
§618-05-15 §afeat: 补全内部引入方法的参数;
§618-05-15 §afeat: 调整Event载入提示 完善Bukkit的聊天发送;
§618-05-15 §afeat: 调整API引入结构;
§618-05-15 §afeat: 新增MiaoChat插件;
§618-05-14 §afeat: 更新API相关类;
§618-05-14 §afeat: 调整相关API名称;
§618-05-14 §afeat: 新增Object.values垫片;
§618-05-14 §afeat: 新增工具类;
§618-05-14 §afeat: 更新MiaoScriptPackageManager;
§618-05-14 §cfix: 修复命令执行相关BUG;
§618-05-14 §afeat: 新增聊天相关API;
§618-05-14 §afeat: 优化方法调用;
§618-03-18 §afeat: 调整get方法 data 参数自动转query;
§618-03-18 §afeat: 优化插件代码结构;
§618-03-18 §cfix: 修复玩家人数获取错误 更新插件;
§618-01-11 §afeat: 更新http类库 server通过orElse返回undefined;
§618-01-11 §afeat: 更新基础类库;
§618-01-11 §afeat: 新增插件管理模块;
§618-01-10 §cfix: 修复主线程加载的BUG;
§618-01-10 §afeat: 修复fs相关BUG 优化插件加载 优化命令补全;
§618-01-10 §afeat: 更新.gitignore文件;
§618-01-10 §afeat: 新增案例插件 更新插件版本;
§618-01-09 §afeat: 优化API 修复http模块错误;
§618-01-09 §afeat: 更新 fs 类库 优化 require;
§618-01-09 §afeat: 安全起见暂时屏蔽load方法和disable方法;
§618-01-09 §cfix: 修复调试信息错误;
§618-01-08 §afeat: require新增基础目录api;
§618-01-08 §3doc: 新增README;
§618-01-08 §cfix: 修复重载命令无效的BUG;
§618-01-09 §afeat: 优化加载流程 完善事件注册;
§618-01-02 §afeat: 新增http网络访问模块;
§617-12-28 §afeat: 完善Sponge事件注册 新增player封装类;
§617-11-30 §afeat: 新增Sponge的兼容;
§617-11-03 §afeat: 新增抽奖插件;
§617-10-16 §cfix: 修复关闭MiaoScript时task异常;
§617-10-15 §6alpha: 第一个版本发布;
</update.changes>
<update.changelog></update.changelog>
</update.changelog>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<repo.url>https://repo.yumc.pw</repo.url>
</properties>
<repositories>
<repository>
<id>yumc-repo</id>
<url>http://repo.yumc.pw/content/groups/public/</url>
<url>${repo.url}/repository/maven-public/</url>
</repository>
<repository>
<id>sponge</id>
@ -107,33 +151,46 @@
<pluginRepositories>
<pluginRepository>
<id>yumc-repo</id>
<url>http://repo.yumc.pw/content/groups/public/</url>
<url>${repo.url}/repository/maven-public/</url>
</pluginRepository>
</pluginRepositories>
<distributionManagement>
<repository>
<id>jtb</id>
<name>YUMC</name>
<url>http://repo.yumc.pw/content/repositories/yumcenter/</url>
<url>${repo.url}/repository/yumcenter/</url>
</repository>
</distributionManagement>
<dependencies>
<dependency>
<groupId>pw.yumc</groupId>
<artifactId>YumCore</artifactId>
<type>jar</type>
<version>[1.8,)</version>
<exclusions>
<exclusion>
<groupId>org.bukkit</groupId>
<artifactId>craftbukkit</artifactId>
</exclusion>
</exclusions>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.6</version>
</dependency>
<dependency>
<groupId>org.kamranzafar</groupId>
<artifactId>jtar</artifactId>
<version>2.3</version>
</dependency>
<dependency>
<groupId>org.spigotmc</groupId>
<artifactId>spigot-api</artifactId>
<version>1.14.4-R0.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.spongepowered</groupId>
<artifactId>spongeapi</artifactId>
<version>6.0.0</version>
<version>7.1.0</version>
</dependency>
<dependency>
<groupId>net.md-5</groupId>
<artifactId>bungeecord-api</artifactId>
<version>1.12-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>cn.nukkit</groupId>
<artifactId>nukkit</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
</dependencies>
</project>

View File

@ -1,61 +0,0 @@
# -----不优化-----
-dontoptimize
# -----忽略所有警告-----
-dontwarn
-dontnote
# -----混淆时应用侵入式重载-----
-overloadaggressively
# -----启用混淆字典-----
-obfuscationdictionary obf.dict
-classobfuscationdictionary obf.dict
-packageobfuscationdictionary obf.dict
# -----保留所有属性
-keepattributes **
# -----保护所有实体中的字段名称-----
-keepclassmembers class * implements java.io.Serializable { <fields>; }
# -----保护监听方法不被清理-----
-keepclassmembers class * implements org.bukkit.event.Listener {
@org.bukkit.event.EventHandler <methods>;
}
-keepclassmembers class * implements net.md_5.bungee.api.plugin.Listener {
@net.md_5.bungee.event.EventHandler <methods>;
}
-keepclassmembers class * {
@org.spongepowered.api.event.Listener <methods>;
}
# -----保护继承事件不被清理-----
-keep class ** extends org.bukkit.event.Event {*;}
# -----保护枚举方法的完整性-----
-keepclassmembers enum * {
public static **[] values();
public static ** valueOf(java.lang.String);
}
# -----保护配置注入不被清理-----
-keepclassmembers class * extends **.config.inject.Inject** {
<fields>;
public <init>(org.bukkit.configuration.ConfigurationSection);
}
# -----保护注解命令方法不被清理-----
-keepclassmembers class **.commands.annotation.** {<methods>;}
-keepclassmembers class * implements **.commands.interfaces.Executor {<methods>;}
# -----保护注解命令方法不被清理-----
-keep @org.spongepowered.api.plugin.Plugin class * {*;}
# -----保护注解NotProguard标记-----
-keep class **.NotProguard
-keep @**.NotProguard class * {*;}
-keepclassmembers class * {
@**.NotProguard <fields>;
@**.NotProguard <methods>;
}

View File

@ -7,8 +7,6 @@ import java.nio.file.Path;
import java.util.stream.Collectors;
import lombok.val;
import pw.yumc.YumCore.annotation.NotProguard;
import pw.yumc.YumCore.mc.MinecraftTools;
/**
* Created with IntelliJ IDEA
@ -16,12 +14,25 @@ import pw.yumc.YumCore.mc.MinecraftTools;
* @author 喵♂呜
* Created on 2017/10/9 12:40.
*/
@NotProguard
public class Base {
private Object instance;
public Base(Object instance) {
this.instance = instance;
}
public Class getClass(String name) throws ClassNotFoundException {
return Class.forName(name);
}
public Object getInstance() {
return this.instance;
}
public Class getProxyClass() {
return ProxyClass.class;
}
public String read(String path) throws IOException {
return new String(Files.readAllBytes(new File(path).toPath()), "UTF-8");
}
@ -46,8 +57,4 @@ public class Base {
}
Files.delete(path);
}
public Class getTools() {
return MinecraftTools.class;
}
}

View File

@ -1,19 +1,8 @@
package pw.yumc.MiaoScript;
import java.io.File;
import org.bukkit.Bukkit;
import org.bukkit.command.CommandSender;
import org.bukkit.event.HandlerList;
import org.bukkit.plugin.java.JavaPlugin;
import lombok.SneakyThrows;
import lombok.val;
import pw.yumc.YumCore.bukkit.Log;
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;
/**
* 喵式脚本
@ -21,62 +10,15 @@ import pw.yumc.YumCore.commands.interfaces.Executor;
* @author 喵♂呜
* @since 2016年8月29日 上午7:50:39
*/
public class MiaoScript extends JavaPlugin implements Executor {
public class MiaoScript extends JavaPlugin {
private ScriptEngine engine;
@Override
@SneakyThrows
public void onEnable() {
new CommandSub("ms", this);
engine = new ScriptEngine(getDataFolder().getCanonicalPath(), getLogger());
enableEngine();
}
@Cmd
@Help("执行 JS 代码")
@SneakyThrows
public void js(CommandSender sender, String script) {
result(sender, engine.getEngine().eval(script));
}
@Cmd
@Help("执行 JS 代码文件")
@SneakyThrows
public void file(CommandSender sender, String file) {
result(sender, engine.getEngine().eval("load('" + new File(getDataFolder(), file).getCanonicalPath() + "')"));
}
@Cmd
@Help("重启脚本引擎")
public void reload(CommandSender sender) {
engine.disableEngine();
val server = Bukkit.getServer();
try {
server.getScheduler().cancelTasks(this);
server.getServicesManager().unregisterAll(this);
HandlerList.unregisterAll(this);
server.getMessenger().unregisterIncomingPluginChannel(this);
server.getMessenger().unregisterOutgoingPluginChannel(this);
} catch (Exception ex) {
Log.d("Error reload", ex);
}
enableEngine();
Log.sender(sender, "§bMiaoScript §eEngine §a重启完成!");
}
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);
}
}
private void enableEngine() {
val origin = Thread.currentThread().getContextClassLoader();
Thread.currentThread().setContextClassLoader(getClassLoader());
engine = new ScriptEngine(getDataFolder().getCanonicalPath(), getLogger(), this);
engine.enableEngine();
Thread.currentThread().setContextClassLoader(origin);
}
@Override

View File

@ -0,0 +1,27 @@
package pw.yumc.MiaoScript;
import lombok.SneakyThrows;
import net.md_5.bungee.api.plugin.Plugin;
/**
* Created with IntelliJ IDEA
*
* @author MiaoWoo
* Created on 2020/1/14 16:02.
*/
public class MiaoScriptBungee extends Plugin {
private ScriptEngine engine;
@Override
@SneakyThrows
public void onEnable() {
Thread.currentThread().setContextClassLoader(this.getClass().getClassLoader());
engine = new ScriptEngine(getDataFolder().getCanonicalPath(), getLogger(), this);
engine.enableEngine();
}
@Override
public void onDisable() {
engine.disableEngine();
}
}

View File

@ -0,0 +1,182 @@
package pw.yumc.MiaoScript;
import java.io.File;
import java.io.Reader;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.HashMap;
import javax.script.Bindings;
import javax.script.Invocable;
import javax.script.ScriptContext;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineFactory;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
import javax.script.SimpleBindings;
import lombok.val;
/**
* 喵式脚本引擎
*
* @author 喵♂呜
* @since 2016年8月29日 上午7:51:43
*/
public class MiaoScriptEngine implements ScriptEngine, Invocable {
private static MiaoScriptEngine DEFAULT;
private static ScriptEngineManager manager;
private ScriptEngine engine;
static {
manager = new ScriptEngineManager(ClassLoader.getSystemClassLoader());
}
public static void setBindings(Bindings bindings) {
manager.setBindings(bindings);
}
public static Bindings getBindings() {
return manager.getBindings();
}
public MiaoScriptEngine() {
this("js");
}
public MiaoScriptEngine(final String engineType) {
this(manager, engineType);
}
public MiaoScriptEngine(ScriptEngineManager engineManager) {
this(engineManager, "js");
}
public MiaoScriptEngine(ScriptEngineManager engineManager, final String engineType) {
try {
engine = engineManager.getEngineByName(engineType);
} catch (final NullPointerException ignored) {
}
if (engine == null) {
val dirs = System.getProperty("java.ext.dirs").split(File.pathSeparator);
for (String dir : dirs) {
File nashorn = new File(dir, "nashorn.jar");
if (nashorn.exists()) {
try {
Method method = URLClassLoader.class.getDeclaredMethod("addURL", URL.class);
// 设置方法的访问权限
method.setAccessible(true);
// 获取系统类加载器
URL url = nashorn.toURI().toURL();
method.invoke(Thread.currentThread().getContextClassLoader(), url);
engineManager = new ScriptEngineManager();
engine = engineManager.getEngineByName(engineType);
} catch (NoSuchMethodException | MalformedURLException | IllegalAccessException | InvocationTargetException | NullPointerException ignored) {
}
return;
}
}
throw new UnsupportedOperationException("当前环境不支持 " + engineType + " 脚本类型!");
}
}
public static MiaoScriptEngine getDefault() {
if (DEFAULT == null) {
DEFAULT = new MiaoScriptEngine();
}
return DEFAULT;
}
@Override
public Bindings createBindings() {
return new SimpleBindings(new HashMap<>(engine.getBindings(ScriptContext.GLOBAL_SCOPE)));
}
@Override
public Object eval(final Reader reader) throws ScriptException {
return engine.eval(reader);
}
@Override
public Object eval(final Reader reader, final Bindings n) throws ScriptException {
return engine.eval(reader, n);
}
@Override
public Object eval(final Reader reader, final ScriptContext context) throws ScriptException {
return engine.eval(reader, context);
}
@Override
public Object eval(final String script) throws ScriptException {
return engine.eval(script);
}
@Override
public Object eval(final String script, final Bindings n) throws ScriptException {
return engine.eval(script, n);
}
@Override
public Object eval(final String script, final ScriptContext context) throws ScriptException {
return engine.eval(script, context);
}
@Override
public Object get(final String key) {
return engine.get(key);
}
@Override
public Bindings getBindings(final int scope) {
return engine.getBindings(scope);
}
@Override
public ScriptContext getContext() {
return engine.getContext();
}
@Override
public ScriptEngineFactory getFactory() {
return engine.getFactory();
}
@Override
public <T> T getInterface(final Class<T> clasz) {
return ((Invocable) engine).getInterface(clasz);
}
@Override
public <T> T getInterface(final Object thiz, final Class<T> clasz) {
return ((Invocable) engine).getInterface(thiz, clasz);
}
@Override
public Object invokeFunction(final String name, final Object... args) throws ScriptException, NoSuchMethodException {
return ((Invocable) engine).invokeFunction(name, args);
}
@Override
public Object invokeMethod(final Object thiz, final String name, final Object... args) throws ScriptException, NoSuchMethodException {
return ((Invocable) engine).invokeMethod(thiz, name, args);
}
@Override
public void put(final String key, final Object value) {
engine.put(key, value);
}
@Override
public void setBindings(final Bindings bindings, final int scope) {
engine.setBindings(bindings, scope);
}
@Override
public void setContext(final ScriptContext context) {
engine.setContext(context);
}
}

View File

@ -0,0 +1,24 @@
package pw.yumc.MiaoScript;
import cn.nukkit.plugin.PluginBase;
import lombok.SneakyThrows;
/**
* @author MiaoWoo
*/
public class MiaoScriptNukkit extends PluginBase {
private ScriptEngine engine;
@Override
@SneakyThrows
public void onEnable() {
Thread.currentThread().setContextClassLoader(this.getClass().getClassLoader());
engine = new ScriptEngine(getDataFolder().getCanonicalPath(), getLogger(), this);
engine.enableEngine();
}
@Override
public void onDisable() {
engine.disableEngine();
}
}

View File

@ -1,23 +1,14 @@
package pw.yumc.MiaoScript;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import javax.script.ScriptException;
import org.slf4j.Logger;
import org.spongepowered.api.Sponge;
import org.spongepowered.api.command.CommandResult;
import org.spongepowered.api.command.CommandSource;
import org.spongepowered.api.command.args.GenericArguments;
import org.spongepowered.api.command.spec.CommandSpec;
import org.spongepowered.api.config.ConfigDir;
import org.spongepowered.api.event.Listener;
import org.spongepowered.api.event.game.state.GameInitializationEvent;
import org.spongepowered.api.event.game.GameReloadEvent;
import org.spongepowered.api.event.game.state.GameStartedServerEvent;
import org.spongepowered.api.event.game.state.GameStoppingServerEvent;
import org.spongepowered.api.plugin.Plugin;
import org.spongepowered.api.text.Text;
import com.google.inject.Inject;
import lombok.SneakyThrows;
@ -38,78 +29,24 @@ public class MiaoScriptSponge {
@ConfigDir(sharedRoot = false)
private File pluginConfigDir;
@Listener
public void onInit(GameInitializationEvent event) {
}
private CommandSpec main() {
return CommandSpec.builder()
.description(Text.of("喵式脚本主命令"))
.permission("MiaoScript.admin")
.child(js(), "js")
.child(file(), "file")
.child(reload(), "reload")
.build();
}
private CommandSpec js() {
return CommandSpec.builder()
.description(Text.of("执行JS命令"))
.arguments(GenericArguments.onlyOne(GenericArguments.remainingJoinedStrings(Text.of("js"))))
.executor((src, args) -> {
try {
result(src, engine.getEngine().eval(args.<String>getOne("js").orElse("")));
} catch (ScriptException e) {
e.printStackTrace();
}
return CommandResult.success();
})
.build();
}
private CommandSpec file() {
return CommandSpec.builder()
.description(Text.of("执行JS文件"))
.arguments(GenericArguments.onlyOne(GenericArguments.remainingJoinedStrings(Text.of("js"))))
.executor((src, args) -> {
try {
result(src, engine.getEngine().eval(new FileReader(new File(pluginConfigDir, args.<String>getOne("js").orElse("")))));
} catch (ScriptException | IOException e) {
e.printStackTrace();
}
return CommandResult.success();
})
.build();
}
private CommandSpec reload() {
return CommandSpec.builder()
.description(Text.of("重载 JS 引擎"))
.executor((src, args) -> {
engine.disableEngine();
Sponge.getEventManager().unregisterPluginListeners(this);
engine.enableEngine();
src.sendMessage(Text.of("§6[§bMiaoScript§6]§r §bMiaoScript §eEngine §a重启完成!"));
return CommandResult.success();
})
.build();
}
private void result(CommandSource sender, Object result) {
if (result == null) {
sender.sendMessage(Text.of("§a运行成功! §c没有返回结果!"));
} else {
sender.sendMessage(Text.of(String.format("§a运行成功! §b数据类型: §r%s §d结果: §r%s", result.getClass().getName(), result)));
}
}
@Listener
@SneakyThrows
public void onStart(GameStartedServerEvent event) {
Sponge.getServer().getConsole();
Sponge.getCommandManager().register(this, main(), "ms", "mscript", "MiaoScript");
engine = new ScriptEngine(pluginConfigDir.getCanonicalPath(), logger);
engine = new ScriptEngine(pluginConfigDir.getCanonicalPath(), logger, this);
engine.enableEngine();
}
@Listener
@SneakyThrows
public void onStop(GameStoppingServerEvent event) {
engine.disableEngine();
}
@Listener
@SneakyThrows
public void reload(GameReloadEvent event) {
engine.disableEngine();
engine = new ScriptEngine(pluginConfigDir.getCanonicalPath(), logger, this);
engine.enableEngine();
}
}

View File

@ -0,0 +1,51 @@
package pw.yumc.MiaoScript;
import javax.script.Bindings;
import javax.script.ScriptEngine;
import javax.script.ScriptException;
/**
* Created with IntelliJ IDEA
*
* @author MiaoWoo
* Created on 2020/1/16 9:04.
*/
public class ProxyClass {
private ScriptEngine engine;
private String script;
private Bindings bindings;
public ProxyClass(ScriptEngine engine, String script, Bindings bindings) {
this.engine = engine;
this.script = script;
this.bindings = bindings;
}
public Object method(Object args) throws ScriptException {
bindings.put("args", args);
return engine.eval(script, bindings);
}
public Object one(Object arg1) throws ScriptException {
bindings.put("arg1", arg1);
return engine.eval(script, bindings);
}
public Object two(Object arg1, Object arg2) throws ScriptException {
bindings.put("arg1", arg1);
bindings.put("arg2", arg2);
return engine.eval(script, bindings);
}
public Object three(Object arg1, Object arg2, Object arg3) throws ScriptException {
bindings.put("arg1", arg1);
bindings.put("arg2", arg2);
bindings.put("arg3", arg3);
return engine.eval(script, bindings);
}
public Object args(Object... args) throws ScriptException {
bindings.put("args", args);
return engine.eval(script, bindings);
}
}

View File

@ -8,7 +8,6 @@ import java.nio.file.Paths;
import javax.script.ScriptEngineManager;
import lombok.SneakyThrows;
import pw.yumc.YumCore.engine.MiaoScriptEngine;
/**
* Created with IntelliJ IDEA
@ -19,18 +18,22 @@ import pw.yumc.YumCore.engine.MiaoScriptEngine;
public class ScriptEngine {
private String root;
private Object logger;
private Base base;
private MiaoScriptEngine engine;
private ScriptEngineManager manager;
public ScriptEngine(String root, Object logger) {
public ScriptEngine(String root, Object logger, Object instance) {
this.root = root;
this.logger = logger;
this.base = new Base(instance);
this.manager = new ScriptEngineManager();
}
@SneakyThrows
public void enableEngine() {
ScriptEngineManager manager = new ScriptEngineManager();
this.engine = new MiaoScriptEngine(manager, "nashorn");
this.engine.put("base", new Base());
this.engine.put("base", this.base);
this.engine.put("ScriptEngineContextHolder", this);
Path bios = Paths.get(root, "bios.js");
// 如果存在自定义bios就加载自定义的
if (Files.exists(bios)) {
@ -43,7 +46,8 @@ public class ScriptEngine {
@SneakyThrows
public void disableEngine() {
engine.invokeFunction("disable");
this.engine.invokeFunction("engineDisable");
this.engine = null;
}
public MiaoScriptEngine getEngine() {

View File

@ -1,51 +0,0 @@
package pw.yumc.MiaoScript;
import org.bukkit.event.Cancellable;
import org.bukkit.event.Event;
import org.bukkit.event.HandlerList;
import jdk.nashorn.api.scripting.ScriptObjectMirror;
/**
* Created with IntelliJ IDEA
*
* @author 喵♂呜
* Created on 2017/9/30 21:32.
*/
public class ScriptEvent extends Event implements Cancellable {
private ScriptObjectMirror mirror;
private boolean cancelled = false;
public ScriptEvent(ScriptObjectMirror mirror) {
this.mirror = mirror;
}
public ScriptObjectMirror getMirror() {
return mirror;
}
public void setMirror(ScriptObjectMirror mirror) {
this.mirror = mirror;
}
@Override
public boolean isCancelled() {
return cancelled;
}
@Override
public void setCancelled(boolean cancel) {
this.cancelled = cancel;
}
private static HandlerList handlerList = new HandlerList();
public static HandlerList getHandlerList() {
return handlerList;
}
@Override
public HandlerList getHandlers() {
return handlerList;
}
}

View File

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

View File

@ -1,156 +0,0 @@
'use strict';
/**
* Bukkit 事件相关类
*/
/*global Java, base, module, exports, require, __FILE__*/
function EventHandlerDefault() {
var Thread = Java.type("java.lang.Thread");
this.plugin = require('./server').plugin.self;
this.mapEvent = [];
this.listenerMap = [];
this.baseEventDir = '';
/**
* 扫描包 org.bukkit.event 下的所有事件
* 映射简写名称 org.bukkit.event.player.PlayerLoginEvent => playerloginevent
*/
this.mapEventName = function mapEventName() {
if (this.baseEventDir === "") {
throw new Error("事件基础包名为空 无法进行事件映射!");
}
var count = 0;
var dirs = Thread.currentThread().getContextClassLoader().getResources(this.baseEventDir);
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(this.baseEventDir) && name.endsWith(".class")) {
var i = name.replaceAll('/', '.');
try {
var clz = base.getClass(i.substring(0, i.length - 6));
// 继承于 org.bukkit.event.Event 访问符为Public
if (this.isVaildEvent(clz)) {
// noinspection JSUnresolvedVariable
var simpleName = this.class2Name(clz);
console.debug("Mapping Event [%s] => %s".format(clz.name, simpleName));
this.mapEvent[simpleName] = clz;
count++;
}
} catch (ex) {
//ignore already loaded class
}
}
}
}
}
return count;
}
this.class2Name = function class2Name(clazz) {
return clazz.simpleName.toLowerCase();
}
this.name2Class = function name2Class(name, event) {
var eventCls = this.mapEvent[event] || this.mapEvent[event.toLowerCase()] || this.mapEvent[event + 'Event'] || this.mapEvent[event.toLowerCase() + 'event'];
if (!eventCls) {
try {
eventCls = base.getClass(eventCls);
this.mapEvent[event] = eventCls;
} catch (ex) {
console.console("§6插件 §b%s §6注册事件 §c%s §6失败 §4事件未找到!".format(name, event));
console.ex(new Error("插件 %s 注册事件 %s 失败 事件未找到!".format(name, event)))
return;
}
}
return eventCls;
}
/**
* 判断是否为一个有效的事件类
* @param clz
* @returns {*|boolean}
*/
this.isVaildEvent = function isVaildEvent(clz) {
throw new Error("当前服务器不支持事件系统!");
}
this.register = function register(eventCls, exec, priority, ignoreCancel) {
throw new Error("当前服务器不支持事件系统!");
}
this.unregister = function unregister(event, listener) {
throw new Error("当前服务器不支持事件系统!");
}
this.execute = function execute(name, exec, eventCls) {
return function execute() {
try {
exec(arguments[arguments.length - 1]);
} catch (ex) {
console.console('§6插件 §b%s §6处理 §d%s §6事件时发生异常 §4%s'.format(name, this.class2Name(eventCls), ex));
console.ex(ex);
}
}.bind(this);
}
/**
* 添加事件监听
* @param jsp
* @param event
* @param exec {function}
* @param priority [LOWEST,LOW,NORMAL,HIGH,HIGHEST,MONITOR]
* @param ignoreCancel
*/
this.listen = function listen(jsp, event, exec, priority, ignoreCancel) {
var name = jsp.description.name;
if (ext.isNull(name)) throw new TypeError('插件名称为空 请检查传入参数!');
var eventCls = this.name2Class(name, event);
if (!eventCls) { return; }
if (typeof priority === 'boolean') {
ignoreCancel = priority;
priority = 'NORMAL';
}
priority = priority || 'NORMAL';
ignoreCancel = ignoreCancel || false;
// noinspection JSUnusedGlobalSymbols
var listener = this.register(eventCls, this.execute(name, exec, eventCls), priority, ignoreCancel);
var listenerMap = this.listenerMap;
// 添加到缓存 用于关闭插件的时候关闭事件
if (!listenerMap[name]) listenerMap[name] = [];
var offExec = function () {
this.unregister(eventCls, listener);
console.debug('插件 %s 注销事件 %s'.format(name, this.class2Name(eventCls)));
}.bind(this);
var off = {
event: eventCls,
listener: listener,
off: offExec
};
listenerMap[name].push(off);
// noinspection JSUnresolvedVariable
console.debug('插件 %s 注册事件 %s => %s'.format(name, eventCls.name.substring(eventCls.name.lastIndexOf(".") + 1), exec.name === '' ? '匿名方法' : exec.name));
return off;
}
}
var EventHandler = Object.assign(new EventHandlerDefault(), requireInternal('event'));
// 映射事件名称
console.info('%s 事件映射完毕 共计 %s 个事件!'.format(DetectServerType, EventHandler.mapEventName().toFixed(0)));
module.exports = {
on: EventHandler.listen.bind(EventHandler),
disable: function (jsp) {
var jspl = EventHandler.listenerMap[jsp.description.name];
if (jspl) {
jspl.forEach(function (t) t.off.call(EventHandler));
delete EventHandler.listenerMap[jsp.description.name];
}
}
};

View File

@ -1,2 +0,0 @@
/*global Java, base, module, exports, require*/
module.exports = require('./msp.js').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 +0,0 @@
/*global Java, base, module, exports, require*/
module.exports = require('./msp.js').permission;

View File

@ -1,281 +0,0 @@
'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('./event');
var server = require('./server');
var command = require('./command');
var permission = require('./permission');
/**
* 载入插件
* @param dir
*/
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());
});
fs.list(fs.file(plugin, DetectServerType)).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) {
try {
loadPlugin(file);
} catch (ex) {
console.console('§6插件 §b%s §6初始化时发生错误 §4%s'.format(fs.path(file), ex.message));
console.ex(ex);
}
})
}
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(JSON.stringify(plugin)));
var desc = plugin.description;
if (!desc || !desc.name) {
console.warn("文件 %s 不存在 description 描述信息 无法加载插件!".format(file));
} else {
initPlugin(file, plugin);
afterLoadHook(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
Object.assign(plugin.self, plugin);
}
/**
* 初始化插件内容(提供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);
if (command.enable) command.enable(plugin);
if (permission.enable) 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, yaml.safeDump(plugin.config));
break;
case 2:
base.save(arguments[0], yaml.safeDump(arguments[1]));
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, name, ext) {
}
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]];
}
function checkAndRun(args, name, ext) {
var pls = checkAndGet(args);
for (var i in pls) {
var jsp = pls[i];
var exec = jsp[name];
if (exec) {
try {
// 绑定方法的this到插件自身
exec.bind(jsp)();
if (ext) ext.bind(jsp)();
} catch (ex) {
console.console('§6插件 §b%s §6执行 §d%s §6方法时发生错误 §4%s'.format(jsp.description.name, name, ex.message));
console.ex(ex);
}
}
}
}
var plugins = [];
function init(path) {
var plugin = exports.$
if (plugin !== null) {
// 如果过plugin不等于null 则代表是正式环境
console.info("初始化 MiaoScript 插件系统: %s".format(plugin));
}
loadPlugins(path);
};
function load() {
checkAndRun(arguments, 'load');
};
function enable() {
checkAndRun(arguments, 'enable');
};
function disable() {
checkAndRun(arguments, 'disable', function eventDisable() {
event.disable(this);
});
};
function reload() {
checkAndRun(arguments, function (p) {
disable(p);
p = loadPlugin(p.__FILE__);
load(p);
enable(p);
});
};
exports = module.exports = {
$: server.plugin.self,
plugins: plugins,
init: init,
load: load,
enable: enable,
disable: disable,
reload: reload
}

View File

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

View File

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

View File

@ -1,5 +0,0 @@
/*global Java, base, module, exports, require*/
var player = requireInternal('wrapper/player');
module.exports = {
player: player.$
}

View File

@ -1,60 +1,64 @@
'use strict';
var log;
var boot;
var disable;
var engineDisable;
var global = this;
/**
* 初始化框架引擎
* Init MiaoScriptEngine Runtime
*/
(function () {
(function() {
var loader;
boot = function (root, logger) {
boot = function(root, logger) {
log = logger;
// 开发环境下初始化
// Development Env Detect
root = root || "src/main/resources";
if (__FILE__ !== "<eval>") {
logger.info('载入自定义 BIOS 文件 ' + __FILE__);
logger.info('Loading custom BIOS file ' + __FILE__);
global.debug = true;
}
if (java.nio.file.Files.exists(java.nio.file.Paths.get(root, "debug"))) {
logger.info('已开启调试模式!');
logger.info('Running in debug mode...');
global.debug = true;
}
// 检查类加载器 防止找不到核心文件
loader = checkClassLoader();
// 解压文件到根目录 非调试模式直接从jar解压覆盖
release(root, '(api|core|internal|modules)+/.*', !global.debug);
load(root + '/core/init.js');
try {
init(root);
} catch (ex) {
ex.printStackTrace();
if (java.nio.file.Files.exists(java.nio.file.Paths.get(root, "level"))) {
global.level = base.read(java.nio.file.Paths.get(root, "level"))
logger.info('Set system level to [' + global.level + ']...');
}
// Check Class Loader, Sometimes Server will can't find plugin.yml file
loader = checkClassLoader();
// Force decompression core|node_modules to folder when not debug mode
release(root, '(core)+/.*', !global.debug);
// Async Loading MiaoScript Engine
new java.lang.Thread(function() {
load(root + '/core/ployfill.js')(root, logger);
engineDisable = require('@ms/core').default;
}, "MiaoScript thread").start()
};
var pluginYml;
function checkClassLoader() {
var classLoader = java.lang.Thread.currentThread().getContextClassLoader();
var classLoader = java.lang.Thread.currentThread().contextClassLoader;
pluginYml = classLoader.getResource("plugin.yml");
if (pluginYml === null) {
log.info("==================== ERROR ====================");
log.info("异常的类加载器: " + classLoader.class.name);
log.info("==================== ERROR ====================");
throw Error('MiaoScript核心类库初始化失败 异常的类加载器!');
throw Error("Error class loader: " + classLoader.class.name + " Please contact the author MiaoWoo!");
} else {
log.info("Class loader compatible: " + classLoader.class.name);
if (classLoader.parent) {
log.info("Parent class loader: " + classLoader.parent.class.name);
}
}
return classLoader;
}
function release(root, regex, replace) {
var upath = pluginYml.getFile().substring(pluginYml.getFile().indexOf("/") + 1);
var jarPath = java.net.URLDecoder.decode(upath.substring(0, upath.indexOf('!')));
var filePath = pluginYml.getFile().substring(pluginYml.getFile().indexOf("/") + 1);
var jarPath = java.net.URLDecoder.decode(filePath.substring(0, filePath.indexOf('!')));
if (!java.nio.file.Files.exists(java.nio.file.Paths.get(jarPath))) {
jarPath = "/" + jarPath;
}
var jar = new java.util.jar.JarFile(jarPath);
var r = new RegExp(regex);// "[core|modules]/.*"
jar.stream().forEach(function (entry) {
var r = new RegExp(regex);
jar.stream().forEach(function(entry) {
try {
if (!entry.isDirectory()) {
if (r.test(entry.name)) {
@ -71,4 +75,4 @@ var global = this;
}
})
}
})();
})();

View File

@ -0,0 +1,5 @@
name: ${project.artifactId}
description: ${project.description}
main: ${project.groupId}.${project.artifactId}.${project.artifactId}Bungee
version: ${project.version}
author: MiaoWoo

View File

@ -1,10 +0,0 @@
#MySQL数据库配置
DataBase:
#默认数据库
def:
#数据库需要自行建立
database: minecraft
username: root
password: root
ip: 127.0.0.1
port: 3306

View File

@ -1,60 +1,29 @@
/**
* 控制台输出类
*/
/*global base*/
(function (global) {
var Arrays = Java.type('java.util.Arrays');
var Level = Java.type('java.util.logging.Level');
global.ConsoleDefault = function ConsoleDefault(name) {
Object.defineProperty(this, 'name', {
get: function () {
return this._name;
}.bind(this),
set: function (name) {
this._name = name ? '[' + name + '] ' : '';
this.prefix = name ? '§6[§cMS§6][§b' + name + '§6]§r ' : '§6[§bMiaoScript§6]§r ';
}.bind(this)
});
this.name = name;
this.log = this.info = function () {
log.info(this.name + Array.prototype.join.call(arguments, ' '));
};
this.warn = function () {
log.warning(this.name + Array.prototype.join.call(arguments, ' '));
};
this.error = function () {
log.log(Level.SEVERE, this.name + Array.prototype.join.call(arguments, ' '));
};
this.debug = function () {
log.info(this.name + '[DEBUG] ' + Array.prototype.join.call(arguments, ' '));
};
this.debug = global.debug ? this.debug : global.noop;
this.sender = this.info;
this.console = this.info;
this.object = function (obj) {
for (var i in obj) {
this.log(i, '=>', obj[i])
// @ts-check
(
/**
* @param {{ info: (arg0: string) => void; }} logger
*/
function(logger) {
function log() {
logger.info(Array.prototype.join.call(arguments, ' '))
}
/**
* @param {string} prefix
*/
function _proxy(prefix) {
return function() {
log('[' + prefix + ']', Array.prototype.join.call(arguments, ' '))
}
}
this.ex = function (message, ex) {
if (!ex) {
this.console('§4' + message);
ex = message;
} else {
this.console('§4' + message + ' ' + ex);
}
var track = ex.getStackTrace();
if (track.class) {
track = Arrays.asList(track)
}
track.forEach(function (stack) {
if (stack.className.startsWith('<')) {
this.console(' §e位于§c', stack.fileName, '=>§c', stack.methodName, '§4行', stack.lineNumber);
} else {// %s.%s(§4%s:%s§c)
this.console(' §e位于§c', stack.className + '.' + stack.methodName + '(§4' + stack.fileName + ':' + stack.lineNumber + '§c)');
}
}.bind(this));
return {
log: log,
info: log,
ex: log,
// @ts-ignore
trace: global.level === "trace" ? _proxy('TRACE') : global.noop,
// @ts-ignore
debug: global.debug ? _proxy('DEBUG') : global.noop,
warn: _proxy('WARN'),
error: _proxy('ERROR')
};
}
global.Console = ConsoleDefault;
})(global);
})

View File

@ -1,31 +0,0 @@
/**
* 服务器探测类
*/
/*global base*/
var ServerType = {
Bukkit: 'bukkit',
Sponge: 'sponge'
};
var MServer;
var DetectServerType = ServerType.Bukkit;
try {
MServer = Java.type("org.bukkit.Bukkit");
DetectServerType = ServerType.Bukkit;
} catch (ex) {
// IGNORE
}
try {
MServer = Java.type("org.spongepowered.api.Sponge");
DetectServerType = ServerType.Sponge;
} catch (ex) {
// IGNORE
}
/**
* 尝试加载特殊的Console类
*/
try {
load(root + '/internal/' + DetectServerType + '/console.js');
} catch (ex) {
// IGNORE
}
global.console = new global.Console();

View File

@ -1,39 +0,0 @@
/*global Java, base, module, exports, require, __FILE__*/
/**
* 菜单基础扩展脚本
* Created by 蒋天蓓 on 2017/2/8 0008.
*/
var ext = {};
/**
* 获得静态类
* @param name 类名
* @returns {*}
*/
ext.getStatic = function (name) {
return base.getClass(name).static;
};
/**
* 获得随机数
* @param max 最大值
* @param min 最小值
*/
ext.random = function (max, min) {
min = min === undefined ? 0 : min;
return Math.floor(Math.random() * (max - min) + min);
};
/**
* 判断对象是否为Null
* @param obj 对象
* @returns {boolean} notNull返回True
*/
ext.notNull = function (obj) {
return obj !== undefined && obj !== null;
};
/**
* 判断对象是否为Null
* @param obj 对象
* @returns {boolean} Null返回True
*/
ext.isNull = function (obj) {
return obj === undefined || obj === null;
};

View File

@ -1,30 +0,0 @@
/**
* 补丁和方法扩展
*/
(function () {
/**
* 日期格式化
* 例: new Date().format('yyyy-MM-dd hh:mm:ss.s') => "2017-08-24 16:15:40.693"
* @param fmt 格式化字符串
* @returns {*}
*/
Date.prototype.format = function (fmt) { //author: meizz
var o = {
"M+": this.getMonth() + 1, //月份
"d+": this.getDate(), //日
"h+": this.getHours(), //小时
"m+": this.getMinutes(), //分
"s+": this.getSeconds(), //秒
"q+": Math.floor((this.getMonth() + 3) / 3), //季度
"S": this.getMilliseconds() //毫秒
};
if (/(y+)/.test(fmt)) fmt = fmt.replace(RegExp.$1, (this.getFullYear() + "").substr(4 - RegExp.$1.length));
for (var k in o) {
if (new RegExp("(" + k + ")").test(fmt)) {
fmt = fmt.replace(RegExp.$1, (RegExp.$1.length === 1) ? o[k] : (("00" + o[k]).substr(("" + o[k]).length)));
}
}
return fmt;
};
})();

View File

@ -1,50 +0,0 @@
/**
* 补丁和方法扩展
*/
(function () {
// Object.assign Polyfill
if (!Object.assign) {
Object.defineProperty(Object, "assign", {
enumerable: false,
configurable: true,
writable: true,
value: function(target) {
"use strict";
if (target === undefined || target === null)
throw new TypeError("Cannot convert first argument to object");
var to = Object(target);
for (var i = 1; i < arguments.length; i++) {
var nextSource = arguments[i];
if (nextSource === undefined || nextSource === null) continue;
var keysArray = Object.keys(Object(nextSource));
for (var nextIndex = 0, len = keysArray.length; nextIndex < len; nextIndex++) {
var nextKey = keysArray[nextIndex];
var desc = Object.getOwnPropertyDescriptor(nextSource, nextKey);
if (desc !== undefined && desc.enumerable) to[nextKey] = nextSource[nextKey];
}
}
return to;
}
});
}
// // JSON快捷方法
if(!Object.toJson){
Object.defineProperty(Object.prototype, "toJson", {
enumerable: false,
value: function() {
return JSON.stringify(this);
}
});
}
// Object.prototype.toJson = function () {
// return JSON.stringify(this);
// };
// // YAML快速生成
// var yaml = require('modules/yaml');
// Object.prototype.toYaml = function () {
// return yaml.safeDump(this);
// };
})();

View File

@ -1,11 +0,0 @@
/**
* 补丁和方法扩展
*/
(function () {
// Java格式化方法
var str = Java.type('java.lang.String');
String.prototype.format = function () {
return str.format(this, Array.prototype.slice.call(arguments, 0))
};
})();

View File

@ -1,131 +0,0 @@
'use strict';
/*global Java, base, module, exports, require, __FILE__*/
var File = Java.type("java.io.File");
var Files = Java.type("java.nio.file.Files");
var separatorChar = File.separatorChar;
var StandardCopyOption = Java.type("java.nio.file.StandardCopyOption");
/**
* 用文件分割符合并路径
*/
function concat() {
return Array.prototype.join.call(arguments, separatorChar);
};
/**
* 获得文件
* @constructor(file)
* @constructor(dir,file)
* @returns {*}
*/
function file() {
if (!arguments[0]) {
console.warn("文件名称不得为 undefined 或者 null !");
}
switch (arguments.length) {
case 1:
if (path(arguments[0])) {
return arguments[0];
}
return new File(arguments[0]);
case 2:
return new File(exports.file(arguments[0]), arguments[1]);
}
};
/**
* 创建目录
* @param file
*/
function mkdirs(file) {
// noinspection JSUnresolvedVariable
file.parentFile.mkdirs();
};
/**
* 创建文件
* @param file
*/
function create(file) {
f = file(file);
if (!f.exists()) {
mkdirs(f);
f.createNewFile();
}
};
/**
* 获得文件规范路径
* @param file
* @returns {*}
*/
function path(file) {
// noinspection JSUnresolvedVariable
return file.canonicalPath;
};
/**
* 复制文件
* @param inputStream 输入流
* @param target 目标文件
* @param override 是否覆盖
*/
function copy(inputStream, target, override) {
Files.copy(inputStream, target.toPath(), StandardCopyOption[override ? 'REPLACE_EXISTING' : 'ATOMIC_MOVE']);
};
/**
* 读取文件
* @param file 文件路径
*/
function read(file) {
f = file(file);
if (!f.exists()) {
console.warn('读取文件', f, '错误 文件不存在!');
return;
}
// noinspection JSPrimitiveTypeWrapperUsage
return new java.lang.String(Files.readAllBytes(f.toPath()), "UTF-8");
};
/**
* 保存内容文件
* @param path 路径
* @param content 内容
* @param override 是否覆盖
*/
function save(path, content, override) {
Files.write(new File(path).toPath(),
content.getBytes("UTF-8"),
override ? StandardCopyOption['REPLACE_EXISTING'] : StandardCopyOption['ATOMIC_MOVE']);
};
/**
* 列出目录文件
* @param path
*/
function list(path) {
var dir = file(path);
if (dir.isDirectory()) {
return Files.list(dir.toPath());
}
console.debug('路径', path, '不是一个目录 返回空数组!');
return [];
};
/**
* 移动文件
* @param src 原始目录
* @param des 目标目录
* @param override 是否覆盖
*/
function move(src, des, override) {
Files.move(file(src).toPath(), file(des).toPath(),
override ? StandardCopyOption['REPLACE_EXISTING'] : StandardCopyOption['ATOMIC_MOVE'])
};
exports = module.exports = {
canonical: path,
concat: concat,
create: create,
mkdirs: mkdirs,
file: file,
path: path,
copy: copy,
read: read,
save: save,
list: list,
move: move
}

View File

@ -1,103 +0,0 @@
'use strict';
/*global base*/
(function (global) {
// noinspection JSUnusedLocalSymbols
global.init = function init(root) {
global.root = root;
global.noop = function () {
};
loadCore();
loadExt();
loadRequire();
try {
loadServerLib();
loadPlugins();
} catch (ex) {
console.console("§4初始化插件基础系统库错误:§c", ex);
console.ex(ex);
}
};
/**
* 初始化核心
*/
function loadCore() {
// 加载基础模块
load(root + '/core/ext.js');
// 加载Console
load(root + '/core/console.js');
// 探测服务器类型
load(root + '/core/detect.js');
}
/**
* 初始化模块
*/
function loadRequire() {
// 初始化加载器
global.require = load(root + '/core/require.js')(root);
global.requireInternal = function (name) {
return require(root + '/internal/' + DetectServerType + '/' + name + '.js');
}
}
/**
* 加载补丁
*/
function loadExt() {
java.nio.file.Files.list(new java.io.File(root, 'core/ext').toPath()).forEach(function (path) {
console.log('加载扩展类库', path);
try {
load(path.toFile());
} catch (ex) {
console.ex(ex);
}
})
}
/**
* 加载系统类库
*/
function loadServerLib() {
var task = require('api/task');
global.setTimeout = function (func, time, _async) {
return _async ? task.laterAsync(func, time) : task.later(func, time);
};
global.clearTimeout = function (task) {
task.cancel();
};
global.setInterval = function (func, time, _async) {
return _async ? task.timerAsync(func, time) : task.timer(func, time);
};
global.clearInterval = function (task) {
task.cancel();
};
}
/**
* 加载JS插件
*/
function loadPlugins() {
// 初始化本体插件
global.manager = require('api/plugin');
if (global.manager && global.manager.$) {
global.manager.init('plugins');
// 只有当在正式环境运行的时候才加载
global.manager.load();
global.manager.enable();
} else {
console.console('§4当前服务器不支持使用MiaoScript插件系统!');
}
}
// noinspection JSUnusedLocalSymbols
/**
* 关闭插件Hook
*/
global.disable = function disable() {
if (global.manager && global.manager.$) {
global.manager.disable();
}
}
})(global);

View File

@ -0,0 +1,21 @@
(
/**
* @param {string} root
* @param {any} logger
*/
function(root, logger) {
// Init Global Value
global.root = root;
global.logger = logger;
global.NashornEngineStartTime = new Date().getTime()
global.engineLoad = load;
global.noop = global.engineDisable = engineDisable = function() { };
global.load = load = function __PreventGlobalLoadFunction__() { throw new Error('Internal engine system not allow use `load` function!'); }
global.setGlobal = function(key, value) { global[key] = value; };
// Init console and require
global.console = engineLoad(global.root + '/core/console.js')(logger);
console.log("Loading Engine at Thread", java.lang.Thread.currentThread().name)
global.require = engineLoad(global.root + '/core/require.js')(root);
require('@ms/ployfill')
}
);

View File

@ -9,7 +9,7 @@
* 2. 如果模块以 `./` `../` 开头
* a. 尝试使用 resolveAsFile(dir/xx) 加载文件
* b. 尝试使用 resolveAsDirectory(dir/xx) 加载目录
* 3. 尝试去 root root/core root/modules => xx 加载模块
* 3. 尝试去 root root/node_modules => xx 加载模块
* a. 尝试使用 resolveAsFile(xx/xx) 加载文件
* b. 尝试使用 resolveAsDirectory(xx/xx) 加载目录
* 4. 抛出 not found 异常
@ -23,248 +23,372 @@
* 2. 如果 xx/index.js 存在 则使用 resolveAsFile(xx/index.js) 加载
* 3. 如果 xx/index.json 存在 则使用 `xx/index.json` 解析为对象加载 并停止执行
* 暂不支持 4. 如果 xx/index.msm 是一个文件 则使用MScript解析器解析 并停止执行
* 注: MiaoScript 暂不支持多层 modules 加载 暂时不需要(估计以后也不会需要)
*/
/*global Java, base*/
(function (parent) {
'use strict';
var File = Java.type("java.io.File");
var separatorChar = File.separatorChar;
var cacheDir = parent + separatorChar + "runtime";
var paths = [parent, parent + separatorChar + 'core', parent + separatorChar + 'modules'];
try{
base.delete(cacheDir);
} catch (ex) {
console.ex(ex);
}
// @ts-check
/// <reference types="@ms/nashorn" />
(
/**
* 判断是否为一个文件
* @param file
* @returns {*}
* @private
* @param {any} parent
*/
function _isFile(file) {
return file.isFile && file.isFile();
}
function(parent) {
'use strict';
var File = Java.type('java.io.File');
var Paths = Java.type('java.nio.file.Paths');
var Files = Java.type('java.nio.file.Files');
var StandardCopyOption = Java.type('java.nio.file.StandardCopyOption');
var FileNotFoundException = Java.type('java.io.FileNotFoundException');
/**
* 获得文件规范路径
* @param file
* @returns {*}
* @private
*/
function _canonical(file) {
// noinspection JSUnresolvedVariable
return file.canonicalPath;
}
var TarInputStream = Java.type('org.kamranzafar.jtar.TarInputStream');
var GZIPInputStream = Java.type('java.util.zip.GZIPInputStream');
var BufferedInputStream = Java.type('java.io.BufferedInputStream');
/**
* 获得缓存的文件名称
* @param file
* @returns {string}
* @private
*/
function _cacheFile(file) {
return _canonical(file).replace(parent, cacheDir);
}
var URL = Java.type('java.net.URL')
var JavaString = Java.type('java.lang.String')
var separatorChar = File.separatorChar;
/**
* 解析模块名称为文件
* 按照下列顺序查找
* 当前目录 ./
* 父目录 ../
* 核心目录 /core
* 模块目录 /modules
* @param name 模块名称
* @param parent 父目录
*/
function resolve(name, parent) {
name = _canonical(name) || name;
// 解析本地目录
if (name.startsWith('./') || name.startsWith('../')) {
return resolveAsFile(parent, name) || resolveAsDirectory(parent, name) || undefined;
} else {
// 查找可能存在的路径
for (var i in paths) {
var path = paths[i];
var result = resolveAsFile(path, name) || resolveAsDirectory(path, name);
if (result) {
return result;
var CoreModules = ['assert', 'async_hooks', 'child_process', 'cluster', 'crypto', 'dns', 'domain', 'events', 'fs', 'http', 'http2', 'https', 'inspector', 'net', 'os', 'path', 'vm', 'url', 'util', 'zlib', 'worker_threads']
/**
* @param {...object} t
*/
function __assign(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
if (s === undefined) { continue; };
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
t[p] = s[p];
}
return t;
};
/**
* 判断是否为一个文件
* @param {any} file
* @returns {*}
*/
function _isFile(file) {
return file.isFile && file.isFile();
}
/**
* 获得文件规范路径
* @param {any} file
* @returns {*}
*/
function _canonical(file) {
return file.canonicalPath;
}
/**
* 获得文件绝对路径
* @param {any} file
* @returns {*}
*/
function _absolute(file) {
return file.absolutePath;
}
/**
* 解析模块名称为文件
* 按照下列顺序查找
* 当前目录 ./
* 父目录 ../
* 模块目录 /node_modules
* @param {string} name 模块名称
* @param {string} parent 父目录
*/
function resolve(name, parent) {
name = _canonical(name) || name;
// 解析本地目录
if (name.startsWith('./') || name.startsWith('../')) {
return resolveAsFile(name, parent) || resolveAsDirectory(name, parent) || undefined;
} else {
// 解析Node目录
var dir = [parent, 'node_modules'].join(separatorChar);
if (cacheModuleIds[name]) return cacheModuleIds[name]
cacheModuleIds[name] = resolveAsFile(name, dir) || resolveAsDirectory(name, dir) ||
// @ts-ignore
(parent && parent.toString().startsWith(root) ? resolve(name, new File(parent).getParent()) : undefined);
return cacheModuleIds[name];
}
}
/**
* 解析文件
* @param {string} file 文件
* @param {string | undefined} dir 目录
* @returns {*}
*/
function resolveAsFile(file, dir) {
file = dir != undefined ? new File(dir, file) : new File(file);
// 直接文件
// @ts-ignore
if (file.isFile()) {
return file;
}
// JS文件
var js = new File(normalizeName(_absolute(file), '.js'));
if (js.isFile()) {
return js;
}
// JSON文件
var json = new File(normalizeName(_absolute(file), '.json'));
if (json.isFile()) {
return json;
}
}
/**
* 解析目录
* @param {string} file 文件
* @param {string | undefined} dir 目录
* @returns {*}
*/
function resolveAsDirectory(file, dir) {
dir = dir != undefined ? new File(dir, file) : new File(file);
var _package = new File(dir, 'package.json');
if (_package.exists()) {
// @ts-ignore
var json = JSON.parse(base.read(_package));
if (json.main) {
return resolveAsFile(json.main, dir);
}
}
// if no package or package.main exists, look for index.js
return resolveAsFile('index.js', dir);
}
return undefined;
}
/**
* 解析文件
* @returns {*}
*/
function resolveAsFile(dir, file) {
file = ext.notNull(dir) ? new File(dir, file) : new File(file);
// 直接文件
if (file.isFile()) {
return file;
}
// JS文件
var js = new File(normalizeName(_canonical(file), ".js"));
if (js.isFile()) {
return js;
}
// JSON文件
var json = new File(normalizeName(_canonical(file), ".json"));
if (json.isFile()) {
return json;
}
}
/**
* 解析目录
* @returns {*}
*/
function resolveAsDirectory(dir, file) {
dir = ext.notNull(dir) ? new File(dir, file) : new File(file);
var _package = new File(dir, 'package.json');
if (_package.exists()) {
var json = JSON.parse(base.read(_package));
if (json.main) {
return resolveAsFile(dir, json.main);
/**
* 后缀检测和添加
* @param {string} fileName 文件名称
* @param {string} ext 后缀
* @returns {*}
*/
function normalizeName(fileName, ext) {
var extension = ext || '.js';
if (fileName.endsWith(extension)) {
return fileName;
}
return fileName + extension;
}
// if no package or package.main exists, look for index.js
return resolveAsFile(dir, 'index.js');
}
/**
* 后缀检测和添加
* @param fileName 文件名称
* @param ext 后缀
* @returns {*}
*/
function normalizeName(fileName, ext) {
var extension = ext || '.js';
if (fileName.endsWith(extension)) {
return fileName;
/**
* 检查模块缓存
* @param {string} id 模块ID
* @param {string} name 模块名称
* @param {any} file 模块文件
* @param {any} optional 附加选项
* @returns {Object}
*/
function getCacheModule(id, name, file, optional) {
var module = cacheModules[id];
if (optional.cache && module) {
return module;
}
return createModule(id, name, file, optional)
}
return fileName + extension;
}
/**
* 编译模块
* @param id 模块ID
* @param name 模块名称
* @param file 模块文件
* @param optional 附加选项
* @returns {Object}
*/
function getCacheModule(id, name, file, optional) {
var module = cacheModules[id];
if (optional.cache && module) {
/**
* 编译模块
* @param {string} id 模块ID
* @param {string} name 模块名称
* @param {any} file 模块文件
* @param {any} optional 附加选项
* @returns {Object}
*/
function createModule(id, name, file, optional) {
console.trace('Loading module', name + '(' + id + ')', 'Optional', JSON.stringify(optional));
var module = {
id: id,
exports: {},
loaded: false,
require: getRequire(file.parentFile, id)
};
cacheModules[id] = module;
var cfile = _canonical(file);
if (cfile.endsWith('.js')) {
compileJs(module, file, optional);
} else if (cfile.endsWith('.json')) {
compileJson(module, file);
} else if (cfile.endsWith('.msm')) {
throw Error('Unsupported MiaoScript module!');
} else {
throw Error('Unknown file type ' + cfile);
}
return module;
}
console.debug('加载模块', name, '位于', id, 'Optional', JSON.stringify(optional));
// noinspection JSUnresolvedVariable
module = {
id: id,
exports: {},
loaded: false,
require: exports(file.parentFile)
};
cacheModules[id] = module;
try {
if (_canonical(file).endsWith('.js')) {
compileJs(module, file, optional);
/**
* 预编译JS
* @param {any} module JS模块
* @param {any} file JS文件
* @param {any} optional 附加选项
* @returns {void}
*/
function compileJs(module, file, optional) {
// @ts-ignore
var origin = base.read(file);
if (optional.hook) {
origin = optional.hook(origin);
}
if (_canonical(file).endsWith('.json')) {
compileJson(module, file, optional);
// 2019-09-19 使用 扩展函数直接 load 无需保存/删除文件
// 2020-02-16 结尾新增换行 防止有注释导致加载失败
// @ts-ignore
var compiledWrapper = engineLoad({ script: '(function $(module, exports, require, __dirname, __filename) {' + origin + '\n});', name: file });
compiledWrapper.apply(module.exports, [
module, module.exports, module.require, file.parentFile, file
]);
module.loaded = true;
}
/**
* 预编译Json
* @param {{ id?: string | null; exports?: {}; loaded: any; require?: any; }} module Json模块
* @param {any} file Json 文件
* @returns {void}
*/
function compileJson(module, file) {
// @ts-ignore
module.exports = JSON.parse(base.read(file));
module.loaded = true;
}
/**
* 尝试从网络下载依赖包
* @param {string} name 包名称
*/
function download(name) {
// handle name es6-map/implement => es6-map @ms/common/dist/reflect => @ms/common
var name_arr = name.split('/');
var module_name = name.startsWith('@') ? name_arr[0] + '/' + name_arr[1] : name_arr[0];
// at windows need replace file name java.lang.IllegalArgumentException: Invalid prefix or suffix
var tempFile = Files.createTempFile(module_name.replace('/', '_'), '.json');
var info = fetchPackageInfo(module_name, tempFile);
var url = info.versions[info['dist-tags']['latest']].dist.tarball;
console.log('fetch node_module ' + module_name + ' from ' + url + ' waiting...')
var tis = new TarInputStream(new BufferedInputStream(new GZIPInputStream(new URL(url).openStream())));
// @ts-ignore
var entry; var target = root + separatorChar + 'node_modules' + separatorChar + module_name;
while ((entry = tis.getNextEntry()) != null) {
var targetPath = Paths.get(target + separatorChar + entry.getName().substring(8));
targetPath.toFile().getParentFile().mkdirs();
Files.copy(tis, targetPath, StandardCopyOption.REPLACE_EXISTING);
}
if (_canonical(file).endsWith('.msm')) {
throw Error("暂不支持解析 MiaoScript 模块");
return name;
}
function fetchPackageInfo(module_name, tempFile) {
try {
Files.copy(new URL('https://registry.npm.taobao.org/' + module_name).openStream(), tempFile, StandardCopyOption.REPLACE_EXISTING);
} catch (ex) {
console.debug('can\'t fetch package ' + module_name + ' from taobao registry. try fetch from yumc registry...')
Files.copy(new URL('https://repo.yumc.pw/repository/npm/' + module_name).openStream(), tempFile, StandardCopyOption.REPLACE_EXISTING);
}
} catch (ex) {
console.console('§4警告! §c模块§a', name, '§c编译失败! §4ERR:', ex);
console.ex(ex);
tempFile.toFile().deleteOnExit();
return JSON.parse(new JavaString(Files.readAllBytes(tempFile), 'UTF-8'));
}
return module;
}
/**
* 预编译JS
* @param file JS文件
* @param optional 附加选项
* @returns {Object}
*/
function compileJs(module, file, optional) {
var cacheFile = _cacheFile(file);
var origin = base.read(file);
if (optional.hook) {
origin = optional.hook(origin);
}
base.save(cacheFile, "(function __init__(module, exports, require, __dirname, __filename) {" + origin + "});");
// 使用 load 可以保留行号和文件名称
var compiledWrapper = load(cacheFile);
try {
base.delete(cacheFile);
} catch (ex) {
cacheFile.deleteOnExit();
}
compiledWrapper.apply(module.exports, [
module, module.exports, module.require, file.parentFile, file
]);
module.loaded = true;
}
/**
* 预编译Json
* @param file Json 文件
* @param optional 附加选项
* @returns {Object}
*/
function compileJson(module, file, optional) {
module.exports = JSON.parse(base.read(file));
module.loaded = true;
}
/**
* 加载模块
* @param name 模块名称
* @param path 路径
* @param optional 附加选项
* @returns {*}
* @private
*/
function _require(name, path, optional) {
var file = new File(name);
file = _isFile(file) ? file : resolve(name, path);
optional = Object.assign({cache: true, warnNotFound: true}, optional);
if (file === undefined) {
if (optional.warnNotFound) {
console.console('§c目录§b', path, '§c下模块§a', name, '§c加载失败! §4未找到该模块!');
/**
* 检查核心模块
* @param {string} name
*/
function checkCoreModule(name) {
if (CoreModules.indexOf(name) != -1) {
throw new Error("Can't load nodejs core module " + name + " . maybe later will auto replace to @ms/" + name + ' to compatible...')
}
return {exports: {}};
}
// 重定向文件名称和类型
return getCacheModule(_canonical(file), file.name.split(".")[0], file, optional);
}
/**
* 闭包方法
* @param parent 父目录
* @returns {Function}
*/
function exports(parent) {
return function (path, optional) {
return _require(path, parent, optional).exports;
};
}
/**
* 加载模块
* @param {string} name 模块名称
* @param {string} path 路径
* @param {any} optional 附加选项
* @returns {*}
*/
function _require(name, path, optional) {
checkCoreModule(name);
var file = new File(name);
file = _isFile(file) ? file : resolve(name, path);
optional = __assign({ cache: true }, optional);
if (file === undefined) {
try {
// excloud local dir, prevent too many recursive call and cache not found module
if (name.startsWith('.') || name.startsWith('/') || optional.recursive || notFoundModules[name]) {
console.log(name, path, optional, notFoundModules[name])
throw new Error("Can't found module " + name + '(' + JSON.stringify(optional) + ') at local ' + path + ' or network!')
}
optional.recursive = true;
return _require(download(name), path, optional);
} catch (ex) {
notFoundModules[name] = true;
throw new FileNotFoundException("Can't found module " + name + ' in directory ' + path + ' ERROR: ' + ex)
}
}
// 重定向文件名称和类型
return getCacheModule(_canonical(file), file.name.split('.')[0], file, optional);
}
// 判断是否存在 isFile 不存在说明 parent 是一个字符串 需要转成File
if (parent.isFile) {
parent = new File(parent);
}
var cacheModules = [];
console.debug("初始化 require 模块组件 父目录 ", _canonical(parent));
return exports(parent);
});
/**
* 闭包方法
* @param {string} parent 父目录
* @param {string} parentId
* @returns {Function}
*/
function exports(parent, parentId) {
var __DynamicRequire__ =
/**
* @param {string} path
* @param {any} optional
*/
function __DynamicRequire__(path, optional) {
return _require(path, parent, __assign({ parentId: parentId }, optional)).exports;
}
return __DynamicRequire__
}
/**
* @param {string} parent
* @param {string} parentId
*/
function getRequire(parent, parentId) {
/**
* @type {any} require
*/
var require = exports(parent, parentId)
require.resolve =
/**
* @param {string} name
*/
function __DynamicResolve__(name) {
return _canonical(new File(resolve(name, parent)))
}
require.clear =
/**
* @param {string} name
*/
function __DynamicClear__(name) {
var moduleId = require.resolve(name)
console.trace('Clear module ' + name + '(' + moduleId + ') ...')
return delete cacheModules[moduleId]
}
return require;
}
if (typeof parent === 'string') {
parent = new File(parent);
}
/**
* @type {{[key:string]:any}} cacheModules
*/
var cacheModules = {};
/**
* @type {{[key:string]:string}} cacheModules
*/
var cacheModuleIds = {};
/**
* @type {{[key:string]:boolean}} cacheModules
*/
var notFoundModules = {};
console.info('Initialization require module. ParentDir:', _canonical(parent));
return getRequire(parent, "null");
});

View File

@ -13,6 +13,7 @@ var fs = require('fs');
var description = {
name: 'HelloWorld',
version: '1.0',
author: 'MiaoWoo',
commands: {
'hello': {
description: 'HelloWorld主命令'
@ -25,34 +26,34 @@ function load() {
}
function enable() {
// noinspection JSUnusedLocalSymbols
command.on(this, 'hello', {
cmd: function (sender, command, args) {
global.load(fs.file(root, 'test.js'));
cmd: function(sender, command, args) {
engineLoad(fs.file(root, 'test.js'));
return true;
}
});
console.log('启用 Hello World 测试插件!');
switch (DetectServerType) {
case ServerType.Bukkit:
event.on(this, 'playerloginevent', function join(event) {
event.on(this, 'PlayerLoginEvent', function join(event) {
send(event, wrapper.player(event.player));
});
break;
case ServerType.Sponge:
// clientconnectionevent.join
event.on(this, 'clientconnectionevent.join', function join(event) {
event.on(this, 'ClientConnectionEvent.Join', function join(event) {
send(event, wrapper.player(event.targetEntity));
});
break;
}
}
function send(event, player){
function send(event, player) {
// noinspection JSUnresolvedVariable
console.debug('玩家', player.name, "触发事件", event.class.simpleName);
setTimeout(function () {
console.debug('玩家', player.getName(), "触发事件", event.class.simpleName);
setTimeout(function() {
// noinspection JSUnresolvedVariable
player.sendMessage("§a欢迎来到 §bMiaoScript §a的世界! 当前在线: " + server.players.length)
player.sendMessage("§a欢迎来到 §bMiaoScript §a的世界! 当前在线: " + server.players().length)
}, 10);
}
@ -65,4 +66,4 @@ module.exports = {
load: load,
enable: enable,
disable: disable
};
};

View File

@ -0,0 +1,88 @@
'use strict';
/*global Java, base, module, exports, require*/
var event = require('api/event');
var task = require('api/task');
var http = require('http');
var fs = require('fs');
var Keys;
var description = {
name: 'ItemTag',
version: '1.0',
author: 'MiaoWoo'
};
var itemConfig;
function load() {
var itemFile = self.file('item.yml');
task.async(function() {
if (!itemFile.exists()) {
fs.save(itemFile, http.get('https://data.yumc.pw/config/Item_zh_CN.yml'))
}
itemConfig = self.getConfig('item.yml')
})
}
function enable() {
switch (DetectServerType) {
case ServerType.Bukkit:
var i = require('api/item').create('STONE')
if (!i.setCustomName) { return }
event.on(self, 'ItemMergeEvent', function(event) {
bukkit(event.target, event.entity.itemStack.amount + event.target.itemStack.amount);
});
event.on(self, 'ItemSpawnEvent', function(event) {
if (event.entity.itemStack) {
bukkit(event.entity, event.entity.itemStack.amount);
}
});
break;
case ServerType.Sponge:
Keys = Java.type('org.spongepowered.api.data.key.Keys');
event.on(self, 'ItemMergeItemEvent', function(event) {
// Sponge 暂未实现当前事件
});
event.on(self, 'SpawnEntityEvent', function(event) {
event.entities.forEach(function(entity) {
if (entity.type.name === "item") sponge(entity);
})
});
break;
}
}
function bukkit(item, amount) {
item.setCustomName('§b' + getItemName(item.itemStack.type) + getItemCount(amount));
item.setCustomNameVisible(true);
}
function sponge(entity) {
var itemOptional = entity.get(Keys['REPRESENTED_ITEM']);
if (itemOptional.isPresent()) {
var item = itemOptional.get();
var itemName = '§b' + getItemName(item.type.name.split(':')[1]) + getItemCount(item.count);
entity.offer(Keys['DISPLAY_NAME'], org.spongepowered.api.text.Text.of(itemName));
entity.offer(Keys['CUSTOM_NAME_VISIBLE'], true);
}
}
function getItemName(name) {
return itemConfig[(name + '').toUpperCase()] || name;
}
function getItemCount(amount) {
return amount === 1 ? "" : "*" + amount;
}
function disable() {
console.log('卸载', description.name, '插件!');
}
module.exports = {
description: description,
load: load,
enable: enable,
disable: disable
};

View File

@ -0,0 +1,70 @@
'use strict';
/**
* MiaoAuth简易登录系统
*/
/*global Java, base, module, exports, require*/
var event = require('api/event');
var wrapper = require('api/wrapper');
var command = require('api/command');
var description = {
name: 'MiaoAuth',
version: '1.0',
author: 'MiaoWoo',
commands: {
'l': {
description: 'MiaoAuth登录命令'
},
'r': {
description: 'MiaoAuth注册命令'
}
}
};
function load() {
console.log('载入 MiaoAuth 插件!');
}
function enable() {
command.on(this, 'l', {
cmd: function(sender, command, args) {
return true;
}
});
command.on(this, 'r', {
cmd: function(sender, command, args) {
return true;
}
});
console.log('启用 MiaoAuth 测试插件!');
switch (DetectServerType) {
case ServerType.Bukkit:
event.on(this, 'playerloginevent', function join(event) {
send(wrapper.player(event.player));
});
break;
case ServerType.Sponge:
event.on(this, 'clientconnectionevent.join', function join(event) {
send(wrapper.player(event.targetEntity));
});
break;
}
}
function send(player) {
setTimeout(function sendMessage() {
player.sendMessage('§a输入 /l <密码> 以登录!');
}, 1000);
}
function disable() {
console.log('卸载 MiaoAuth 测试插件!');
}
module.exports = {
description: description,
load: load,
enable: enable,
disable: disable
};

View File

@ -0,0 +1,261 @@
'use strict';
/**
* MiaoChat 喵式聊天插件
*/
/*global Java, base, module, exports, require*/
var event = require('api/event');
var command = require('api/command');
var tellraw = require('tellraw');
var papi = require('papi');
var utils = require('utils');
var Player;
var description = {
name: 'MiaoChat',
version: '1.0',
author: 'MiaoWoo',
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]&7: ",
"item": true,
"itemformat": "&6[&b%s&6]&r"
},
"admin": {
"index": 49,
"permission": "MiaoChat.admin",
"format": "[admin][world][player][help]&7: ",
"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: mainCommand
});
}
// noinspection JSUnusedLocalSymbols
function mainCommand(sender, command, args) {
return true;
}
function registerEvent() {
switch (DetectServerType) {
case ServerType.Bukkit:
event.on(self, 'AsyncPlayerChatEvent', handlerBukkitChat);
break;
case ServerType.Sponge:
Player = org.spongepowered.api.entity.living.player.Player;
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(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(replace(player, style.text));
if (style.hover) {
tr.tip(replace(player, style.hover));
}
if (style.click && style.click.type && style.click.command) {
var command = replace(player, style.click.command);
switch (style.click.type) {
case "COMMAND":
tr.command(command);
break;
case "OPENURL":
tr.link(command);
break;
case "SUGGEST":
tr.suggest(command);
break;
default:
}
}
} else {
tr.then(replace(player, format));
}
});
tr.then(replace(player, 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(player, target) {
if (toString.call(target) === "[object Array]") {
for (var i in target) {
target[i] = replaceStr(player, target[i]);
}
} else {
target = replaceStr(player, target);
}
return target;
}
function replaceStr(player, target) {
return papi.$(player, target);
}
function disable() {
console.log('卸载', description.name, '插件!');
}
module.exports = {
description: description,
load: load,
enable: enable,
disable: disable
};

View File

@ -12,9 +12,12 @@ var item = require('api/item');
var Arrays = Java.type('java.util.Arrays');
var ItemStackArray = Java.type('org.bukkit.inventory.ItemStack[]');
var PANE = 'STAINED_GLASS_PANE'
var description = {
name: 'Lottery',
version: '1.0',
author: 'MiaoWoo',
commands: {
'lottery': {
description: 'Lottery主命令'
@ -22,11 +25,15 @@ var description = {
},
config: {
title: '§m§s§a幸运抽奖',
panel: '160:13',
control: {
panel: PANE + ':13',
ok: PANE + ':14',
no: PANE + ':15',
},
list: [
{
box: {
id: 160,
id: PANE,
damage: 1,
name: '§a箱子',
lore: [
@ -34,7 +41,7 @@ var description = {
]
},
key: {
id: 160,
id: PANE,
damage: 2,
name: '§b钥匙',
lore: [
@ -46,7 +53,7 @@ var description = {
percent: 10,
command: 'money give %player% 100',
item: {
id: 160,
id: PANE,
damage: 3,
name: '§c奖品1',
lore: [
@ -58,7 +65,7 @@ var description = {
percent: 20,
command: 'money give %player% 200',
item: {
id: 160,
id: PANE,
damage: 4,
name: '§c奖品2',
lore: [
@ -72,25 +79,18 @@ var description = {
}
};
var panel = item.create(160, 1, 13);
var panel;
var config;
var items;
function load() {
config = this.config;
if (config.panel) {
var arr = config.panel.split(':');
if (arr.length === 2) {
panel = newItem(arr[0], arr[1]);
} else {
panel = newItem(arr[0]);
}
}
panel = newItemFromString(config.control.panel || PANE + ':13')
items = new ItemStackArray(54);
item.setName(panel, '');
var ok = newItem(160, 14);
var ok = newItemFromString(config.control.ok || PANE + ':14')
item.setName(ok, '§a确定抽奖');
var no = newItem(160, 15);
var no = newItemFromString(config.control.no || PANE + ':15')
item.setName(no, '§c取消抽奖');
Arrays.fill(items, 0, 10, panel);
Arrays.fill(items, 11, 16, panel);
@ -113,6 +113,15 @@ function newItem(name, sub) {
return item.create(name, 1, sub || 0);
}
function newItemFromString(str) {
var arr = str.split(':');
if (arr.length === 2) {
return newItem(arr[0], arr[1]);
} else {
return newItem(arr[0]);
}
}
function newItemFromConfig(config) {
var i = newItem(config.id, config.damage);
if (config.name) item.setName(i, config.name);
@ -121,12 +130,15 @@ function newItemFromConfig(config) {
}
function enable() {
// noinspection JSUnusedLocalSymbols
command.on(this, 'l', {
cmd: function (sender, command, args) {
cmd: function(sender, command, args) {
sender.inventory.addItem(newItemFromConfig(config.list[0].box))
sender.inventory.addItem(newItemFromConfig(config.list[0].key))
if (!sender.openInventory) {
console.sender(sender, "§4当前用户无法使用该命令!");
}
var inv = bukkit.$.createInventory(null, 54, config.title);
var inv = MServer.createInventory(null, 54, config.title);
inv.setContents(items);
sender.openInventory(inv);
return true;
@ -134,7 +146,7 @@ function enable() {
});
event.on(this, 'InventoryClick', function click(event) {
var inv = event.inventory;
if (inv.title !== config.title) return;
if (inv && inv.title !== config.title) return;
var player = event.whoClicked;
var slot = event.rawSlot;
if (slot > 53 || slot < 0) {
@ -159,6 +171,10 @@ function enable() {
}
var litem;
var box = inv.getItem(10);
if (!box) {
console.sender(player, '§c请先放入抽奖物品和钥匙!');
return;
}
var key = inv.getItem(16);
if (box && box.typeId !== 0 && key && key.typeId !== 0) {
for (var i = 0; i < config.list.length; i++) {
@ -178,14 +194,14 @@ function enable() {
console.sender(player, '§c抽奖物品和钥匙不匹配!');
return;
}
var resultlist = [];
litem.result.forEach(function (t) {
var resultList = [];
litem.result.forEach(function(t) {
for (var i = 0; i < t.percent; i++) {
resultlist.push(t);
resultList.push(t);
}
});
var ri = ext.random(resultlist.length);
var result = resultlist[ri];
var ri = random(resultList.length);
var result = resultList[ri];
box.amount = box.amount - 1;
key.amount = key.amount - 1;
inv.setItem(10, box);
@ -199,6 +215,11 @@ function enable() {
});
}
function random(max, min) {
min = min === undefined ? 0 : min;
return Math.floor(Math.random() * (max - min) + min);
};
function disable() {
}

View File

@ -13,7 +13,7 @@ var fakeTag;
var description = {
name: 'MiaoTag',
version: '1.1',
author: '喵♂呜',
author: 'MiaoWoo',
config: {
format: '§4§l❤'
},
@ -40,18 +40,23 @@ var config;
function load() {
config = self.getConfig();
fakeTag = new FakeTag(config.format);
}
function enable() {
registryCommand()
fakeTag = new FakeTag(config.format);
registryEvent()
}
function registryCommand() {
command.on(self, 'mtag', {
cmd: function cmd(sender, command, args) {
var subcommand = args[0];
switch (subcommand) {
var subCommand = args[0];
switch (subCommand) {
case 'reload':
self.reloadConfig();
fakeTag = new FakeTag(config.format);
console.sender(sender, "§a配置文件重载完成!", "TEST");
console.sender(sender, "§a配置文件重载完成!");
break;
}
},
@ -59,30 +64,46 @@ function enable() {
return ['reload'];
}
});
bukkit.players(function (p) fakeTag.set(p));
event.on(self, 'PlayerJoin', function (event) fakeTag.set(event.player));
var entityUpdate = function (event) {
var player = event.entity || event.player;
if (player instanceof org.bukkit.entity.Player) {
setTimeout(function () {
fakeTag.update(player);
}, 1);
}
};
}
function registryEvent() {
bukkit.players(function(p) { fakeTag.set(p) });
event.on(self, 'PlayerJoin', function(event) { fakeTag.set(event.player) });
event.on(self, 'EntityRegainHealth', entityUpdate, false);
event.on(self, 'EntityDamage', entityUpdate, false);
event.on(self, 'EntityRegainHealth', entityUpdate, false);
event.on(self, 'PlayerRespawn', entityUpdate, false);
//event.on(this, 'playerquitevent', function quit(event) removeTask(event.player));
}
function entityUpdate(event) {
var player = event.entity || event.player;
if (player instanceof org.bukkit.entity.Player) {
setTimeout(function() {
fakeTag.update(player);
}, 1);
}
};
function disable() {
fakeTag.disable();
if (fakeTag) { fakeTag.disable() };
}
function FakeTag(name) {
var ver1_13 = false;
// NMS CLASS
var ScoreboardBaseCriteria = bukkit.nmsCls('ScoreboardBaseCriteria');
try {
var ScoreboardBaseCriteria = bukkit.nmsCls('ScoreboardBaseCriteria');
} catch (ex) {
try {
var IScoreboardCriteria = bukkit.nmsCls('IScoreboardCriteria');
var ScoreboardServer = bukkit.nmsCls("ScoreboardServer");
var ChatComponentText = bukkit.nmsCls('ChatComponentText');
ver1_13 = true;
} catch (ex) {
console.log(ex);
throw ex;
}
}
var PacketPlayOutScoreboardScore = bukkit.nmsCls('PacketPlayOutScoreboardScore');
var PacketPlayOutScoreboardObjective = bukkit.nmsCls('PacketPlayOutScoreboardObjective');
var PacketPlayOutScoreboardDisplayObjective = bukkit.nmsCls('PacketPlayOutScoreboardDisplayObjective');
@ -90,13 +111,31 @@ function FakeTag(name) {
var scoreboardManager = bukkit.$.scoreboardManager;
var mainScoreboard = scoreboardManager.mainScoreboard.handle;
// 注销对象
var objective = mainScoreboard.getObjective(name);
if (objective) {
mainScoreboard.unregisterObjective(objective);
}
try {
// 注册tag对象
mainScoreboard.registerObjective(name, new ScoreboardBaseCriteria(name));
if (!ver1_13) {
// 注册tag对象
objective = mainScoreboard.registerObjective(name, new ScoreboardBaseCriteria(name));
} else {
// 注册tag对象
objective = mainScoreboard.registerObjective(name,
IScoreboardCriteria.HEALTH,
new ChatComponentText(name),
IScoreboardCriteria.EnumScoreboardHealthDisplay.HEARTS);
}
} catch (ex) {
throw ex
// ignore 忽略创建错误 eg: java.lang.IllegalArgumentException: An objective with the name 'xxxxx' already exists!
}
var objective = mainScoreboard.getObjective(name);
if (!objective) {
throw Error("Error Can't Found MainScoreboard Objective " + name)
}
// 缓存虚拟的tag包
var cache = {
@ -108,28 +147,34 @@ function FakeTag(name) {
player.handle.playerConnection.sendPacket(p);
}
this.set = function (player) {
this.set = function(player) {
sendPacket(player, cache.objective);
sendPacket(player, cache.display);
this.update(player);
};
this.update = function (player) {
var score = mainScoreboard.getPlayerScoreForObjective(player.name, objective);
score.setScore(player.getHealth());
var scorePack = new PacketPlayOutScoreboardScore(score);
function createScore(player) {
if (!ver1_13) {
var score = mainScoreboard.getPlayerScoreForObjective(player.name, objective);
score.setScore(player.health);
return new PacketPlayOutScoreboardScore(score);
} else {
return new PacketPlayOutScoreboardScore(ScoreboardServer.Action.CHANGE, name, player.name, player.health)
}
}
this.update = function update(player) {
var scorePack = createScore(player);
//把其他玩家缓存的包发给这个玩家
bukkit.players(function (t) {
bukkit.players(function(t) {
sendPacket(t, scorePack);
if (t.name !== player.name) {
var outher = mainScoreboard.getPlayerScoreForObjective(t.name, objective);
outher.setScore(t.getHealth());
sendPacket(player, new PacketPlayOutScoreboardScore(outher));
sendPacket(player, createScore(t));
}
});
};
this.disable = function () {
this.disable = function() {
// 注销tag对象
mainScoreboard.unregisterObjective(objective);
}

View File

@ -0,0 +1,48 @@
'use strict';
/**
* WorldEdit 插件
*/
/*global Java, base, module, exports, require*/
var item = require('/api/item');
var command = require('api/command');
var Material = Java.type("org.bukkit.Material");
var description = {
name: 'WorldEdit',
version: '1.0',
author: 'MiaoWoo',
commands: {
'/up': {
description: 'Up Player And Set Block'
}
}
};
function load() {
}
function enable() {
command.on(this, '/up', {
cmd: function(sender, command, args) {
if (!sender.openInventory) {
return;
}
var player = sender;
var location = player.location;
var type = item.type(args[0], 'STONE');
player.velocity = player.velocity.setY(0.5);
setTimeout(function() {
location.block.type = type
}, 6);
return true;
},
tab: function(sender, command, args) {
}
});
}
module.exports = {
description: description,
enable: enable
};

View File

@ -0,0 +1,32 @@
## MiaoChat for MiaoScript
![](https://dn-coding-net-production-pp.qbox.me/f459067b-7829-45ec-9713-bb559d1e0118.png)
> 注意: MiaoScript 在Windows环境下 暂不支持 reload 所以 Windows 环境请重启服务器
> 注意: MiaoScript 将不会计划兼容 非 `Sponge` 的MOD端
- 基于 `MiaoScript` 开发 同时兼容 `Sponge``Bukkit`
- 支持PAPI
- `Bukkit``me.clip.placeholderapi.PlaceholderAPI`
- `Sponge``me.rojo8399.placeholderapi.PlaceholderService`
- 支持悬浮提示
- 支持点击执行命令
- 支持点击命令补全
### Feature(开发规划)
- 悬浮物品提示
- 兼容 `BungeeCord` 支持跨服聊天
- 兼容其他聊天插件 保护插件
### 安装教程
- 下载 MiaoChat 本体并安装
- [下载地址-论坛](http://www.mcbbs.net/thread-774401-1-1.html)
- [下载地址-备用](https://git.yumc.pw/502647092/MiaoScript/releases)
- 安装到服务端对应的目录
- Bukkit => plugins
- Sponge => mods
- 重启服务器
- 下载 安装 `MiaoScriptPackageManager`
- [安装教程](http://www.mcbbs.net/thread-774797-1-1.html)
- 使用 `MiaoScriptPackageManager` 安装插件
- 执行 `mpm install MiaoChat` 即可安装成功

View File

@ -0,0 +1,220 @@
'use strict';
/**
* MiaoBoard 喵式聊天插件
*/
/*global Java, base, module, exports, require*/
var task = require('api/task');
var event = require('api/event');
var server = require('api/server');
var command = require('api/command');
var papi = require('papi');
var Player;
var boards = [];
var description = {
name: 'MiaoBoard',
version: '1.0',
author: 'MiaoWoo',
commands: {
'mboard': {
description: '喵式记分板主命令'
}
},
permissions: {
'mb.default': {
default: true,
description: '默认权限 赋予玩家'
},
'mb.admin': {
default: false,
description: '管理权限'
}
},
config: {
"Version": 2,
"UpdateTime": 10,
"DisableWorld": [
"WorldName"
],
"Boards": {
"default": {
"index": 50,
"time": {
"start": "2016-01-01 00:00:00",
"end": "2020-01-01 00:00:00"
},
"title": "玩家信息",
"permission": "mb.default",
"lines": [
"&6名 称: &a%player_displayname%",
"&6世 界: &b%player_world%",
"&6位 置: &3%player_x%,%player_y%,%player_z%",
"&6等 级: &e%player_level%",
"&6血 量: &c%player_health%",
"&6模 式: &4%player_gamemode%"
]
},
"admin": {
"index": 49,
"title": "服务器信息",
"permission": "mb.reload",
"lines": [
"&6名 称: &aMiaoBoard",
"&6版 本: &b1.0.0",
"&6作 者: &cMiaoWoo",
"&6人 数: &c%server_online%/%server_max%",
"&6内 存: &a%server_ram_used%/%server_ram_total%/%server_ram_max%"
]
}
}
}
}
var update_task;
var board_formats;
function load() {
board_formats = self.config.Boards;
}
function enable() {
registerCommand();
registerEvent();
registerTask();
updatePlayers()
}
function registerCommand() {
command.on(self, 'mboard', {
cmd: mainCommand
});
}
function mainCommand(sender, command, args) {
if (!args[0]) {
return;
}
switch (args[0]) {
case "reload":
self.reloadConfig();
load();
break;
}
}
function registerEvent() {
switch (DetectServerType) {
case ServerType.Bukkit:
//event.on(self, 'PlayerLoginEvent', handlerPlayerJoin);
break;
case ServerType.Sponge:
Player = org.spongepowered.api.entity.living.player.Player;
event.on(self, 'ClientConnectionEvent.Join', handlerPlayerJoin);
event.on(self, 'ClientConnectionEvent.Disconnect', handlerPlayerQuit);
break;
}
}
function updatePlayers() {
switch (DetectServerType) {
case ServerType.Bukkit:
//event.on(self, 'PlayerLoginEvent', handlerPlayerJoin);
break;
case ServerType.Sponge:
server.players(function(player) {
boards[player.name] = new MiaoBoard(player);
})
break;
}
}
function handlerPlayerJoin(event) {
var player = event.player || event.targetEntity;
boards[player.name] = new MiaoBoard(player);
}
function handlerPlayerQuit(event) {
var player = event.player || event.targetEntity;
delete boards[player.name];
}
function registerTask() {
update_task = task.timerAsync(updateBoard, self.config.UpdateTime);
}
function updateBoard() {
for (var i in boards) {
var player = server.player(i);
if (player.isOnline()) {
var format = getBoardFormat(player);
if (format) {
boards[i].update(papi.$(player, format.title), papi.$(player, format.lines));
} else {
boards[i].clear();
}
} else {
delete boards[i];
}
}
}
function getBoardFormat(player) {
for (var i in board_formats) {
var format = board_formats[i];
if (player.hasPermission(format.permission)) {
return format;
}
}
return null;
}
function disable() {
if (update_task) { update_task.cancel(); }
}
function MiaoBoard(player) {
var Scoreboard = Java.type('org.spongepowered.api.scoreboard.Scoreboard');
var Objective = Java.type('org.spongepowered.api.scoreboard.objective.Objective');
var Criteria = Java.type('org.spongepowered.api.scoreboard.critieria.Criteria');
var Text = Java.type('org.spongepowered.api.text.Text');
var DisplaySlots = Java.type('org.spongepowered.api.scoreboard.displayslot.DisplaySlots');
var uuid = player.uniqueId;
var scoreboard = Scoreboard.builder().build();
var sidebar = Objective.builder().criterion(Criteria.DUMMY).displayName(Text.EMPTY).name("Sidebar").build();
var origin = [];
scoreboard.addObjective(sidebar);
player.setScoreboard(scoreboard);
this.update = function(title, lines) {
this.updateBuffer(title, lines);
}
this.updateBuffer = function(title, lines) {
sidebar.scores.values().forEach(function removeScore(score) {
sidebar.removeScore(score);
})
var i = 0;
sidebar.setDisplayName(Text.of(title));
lines.forEach(function addScore(line) {
sidebar.getOrCreateScore(Text.of(line)).setScore(lines.length - i++);
})
scoreboard.updateDisplaySlot(sidebar, DisplaySlots.SIDEBAR);
}
this.clear = function() {
player.setScoreboard(Scoreboard.builder().build());
}
}
module.exports = {
description: description,
load: load,
enable: enable,
disable: disable
};

View File

@ -1,99 +0,0 @@
'use strict';
/**
* Bukkit 命令相关类
*/
/*global Java, base, module, exports, require, __FILE__*/
var ref = require('modules/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 disable(jsp) {
var commands = jsp.description.commands;
if (commands) {
for (var name in commands) {
//TODO 删除插件命令
}
}
}
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;
}
function on(jsp, name, exec) {
var c = get(name) || create(jsp, name);
console.debug('插件 %s 设置命令 %s(%s) 执行器 ...'.format(jsp.description.name, name, c));
if (exec.cmd) {
// 必须指定需要实现的接口类型 否则MOD服会报错
c.setExecutor(new org.bukkit.command.CommandExecutor({
onCommand: 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'.format(sender.name, jsp.description.name, command, Java.from(args).join(' '), ex));
console.ex(ex);
}
}
}));
}
if (exec.tab) {
// 必须指定需要实现的接口类型 否则MOD服会报错
c.setTabCompleter(new org.bukkit.command.TabCompleter({
onTabComplete: 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'.format(sender.name, jsp.description.name, command, Java.from(args).join(' '), ex));
console.ex(ex);
}
}
}));
}
}
exports.enable = enable;
exports.on = on;
exports.off = function () {
};

View File

@ -1,17 +0,0 @@
/*global Java, base, module, exports, require, __FILE__*/
(function (global) {
global.Console = function BukkitConsole() {
ConsoleDefault.call(this);
this.sender = function () {
var sender = arguments[0];
if (!(sender instanceof org.bukkit.command.CommandSender)) {
this.error("第一个参数未实现 org.bukkit.command.CommandSender 无法发送消息!")
}
var args = Array.prototype.slice.call(arguments, 1);
sender.sendMessage(console.prefix + args.join(' '));
};
this.console = function () {
this.sender(MServer.consoleSender, Array.prototype.join.call(arguments, ' '));
};
};
})(global);

View File

@ -1,50 +0,0 @@
'use strict';
/**
* Sponge 事件相关类
*/
/*global Java, base, module, exports, require, __FILE__*/
var ref = require('reflect');
var Event = Java.type("org.bukkit.event.Event");
var Modifier = Java.type("java.lang.reflect.Modifier");
var Listener = Java.type("org.bukkit.event.Listener");
var EventPriority = Java.type("org.bukkit.event.EventPriority");
var EventExecutor = Java.type("org.bukkit.plugin.EventExecutor");
/**
* 判断是否为一个有效的事件类
* @param clz
* @returns {*|boolean}
*/
function isVaildEvent(clz) {
// noinspection JSUnresolvedVariable 继承于 org.bukkit.event.Event
return Event.class.isAssignableFrom(clz) &&
// 访问符为Public
Modifier.isPublic(clz.getModifiers()) &&
// 不是抽象类
!Modifier.isAbstract(clz.getModifiers());
}
function register(eventCls, exec, priority, ignoreCancel) {
var listener = new Listener({});
MServer.getPluginManager().registerEvent(
eventCls,
listener,
EventPriority[priority],
new EventExecutor({
execute: exec
}),
this.plugin,
ignoreCancel);
return listener;
}
function unregister(event, listener) {
ref.on(event).call('getHandlerList').get().unregister(listener);
}
exports = module.exports = {
baseEventDir: 'org/bukkit/event',
isVaildEvent: isVaildEvent,
register: register,
unregister: unregister
};

View File

@ -1,99 +0,0 @@
'use strict';
/**
* 物品快速生成类
* Created by 蒋天蓓 on 2017/2/9 0009.
*/
/*global Java, base, module, exports, require, __FILE__*/
var Bukkit = MServer;
var item = {};
var ItemStack = Java.type("org.bukkit.inventory.ItemStack");
var Material = Java.type('org.bukkit.Material');
/**
* 创建一个物品
* @constructor (ID)
* @constructor (ID,数量)
* @constructor (ID,数量,子ID)
*/
item.create = function () {
var idOrType = arguments[0];
if (isNaN(Number(idOrType))) {
idOrType = Material[idOrType];
}
switch (arguments.length) {
case 1:
return new ItemStack(idOrType);
case 2:
return new ItemStack(idOrType, arguments[1]);
case 3:
return new ItemStack(idOrType, arguments[1], arguments[2]);
}
};
/**
* 创建一个头颅
* @constructor (玩家名称)
*/
item.head = function (name) {
var head = item.create(397, 1, 3);
var skullMeta = head.getItemMeta();
skullMeta.setOwner(name);
head.setItemMeta(skullMeta);
return head;
};
/**
* 给玩家添加物品
* @param player 玩家
* @param items 物品数组
* @param drop 满背包是否掉落
*/
item.add = function (player, items, drop) {
var drops = player.getInventory().addItem(items).values();
if (drops.size() !== 0 && drop) {
drops.forEach(function (itemStack) {
item.drop(player.getLocation(), itemStack);
});
}
};
/**
* 指定地点掉落物品
* @param loc 地点
* @param item 物品
*/
item.drop = function (loc, item) {
setTimeout(function () {
loc.getWorld().dropItem(loc, item);
}, 1);
};
/**
* 设置物品名称
* @param item 物品
* @param name
* @returns {*}
*/
item.setName = function (item, name) {
if (item.getType().name() !== "AIR") {
var meta = item.hasItemMeta() ? item.getItemMeta() : Bukkit.getItemFactory().getItemMeta(item.getType());
meta.setDisplayName(name);
item.setItemMeta(meta);
}
return item;
};
/**
* 设置物品Lore
* @param item 物品
* @param lores Lore
* @returns {*} 物品
*/
item.setLore = item.setLores = function (item, lores) {
if (item.getType().name() !== "AIR") {
var meta = item.hasItemMeta() ? item.getItemMeta() : Bukkit.getItemFactory().getItemMeta(item.getType());
if (typeof(lores) === 'string') {
lores = lores.split("\n")
}
meta.setLore(lores);
item.setItemMeta(meta);
}
return item;
};
module.exports = item;

View File

@ -1,48 +0,0 @@
'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;

View File

@ -1,112 +0,0 @@
'use strict';
/**
* Bukkit基础操作
* Created by 蒋天蓓 on 2017/2/9 0009.
*/
/*global Java, base, module, exports, require, __FILE__*/
var Bukkit = MServer;
var Server = Bukkit.server;
var PluginManager = Server.pluginManager;
exports.$ = Bukkit;
/**
* 获取NMS版本
*/
exports.nmsVersion = Bukkit.server.class.name.split('.')[3];
/**
* 获取NMS类
*/
exports.nmsCls = function (name) {
return Java.type(['net.minecraft.server', exports.nmsVersion, name].join('.'));
};
/**
* 获取玩家
*/
exports.player = function () {
switch (arguments.length) {
case 0:
return undefined;
case 1:
return Server.getPlayer(arguments[0]);
default:
return Server.getPlayerExtra(arguments[0]);
}
};
/**
* 获取在线玩家
*/
exports.players = function () {
switch (arguments.length) {
case 1:
return Server.onlinePlayers.forEach(arguments[0]);
default:
return Server.onlinePlayers;
}
};
/**
* 插件管理
* @type {{manager: *, get: exports.plugin.get, load: exports.plugin.load}}
*/
exports.plugin = {
/**
* 插件管理工具
*/
manager: PluginManager,
/**
* 获得插件实例
* @param name 插件名称
* @returns {*}
*/
get: function (name) {
return PluginManager.getPlugin(name);
},
/**
* 载入插件 并且返回结果
* @param name 插件名称
* @returns {*}
*/
load: function (name) {
var plugin = this.get(name);
if (ext.notNull(plugin) && !plugin.isEnabled()) {
PluginManager.enablePlugin(plugin);
}
return PluginManager.isPluginEnabled(name);
},
self: PluginManager.getPlugin('MiaoScript')
};
/**
* 公告
* @param message 消息
*/
exports.broadcast = function (message) {
Bukkit.broadcastMessage(message);
};
/**
* 执行名称
* @param player 玩家
* @param command 命令
*/
exports.command = function (player, command) {
Bukkit.dispatchCommand(player, command);
};
/**
* 执行控制台命令
* @param command 命令
*/
exports.console = function (command) {
exports.command(Bukkit.getConsoleSender(), command);
};
/**
* 玩家以OP权限执行命令
* @param player
* @param exper
*/
exports.opcommand = function (player, exper) {
var origin = player.isOp();
player.setOp(true);
try {
exports.command(player, exper);
} finally {
player.setOp(origin);
}
};

View File

@ -1,71 +0,0 @@
'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]);
}
};

View File

@ -1,18 +0,0 @@
/**
* Bukkit 玩家方法代理类
* Created by 蒋天蓓 on 2018/1/5 0009.
*/
/*global Java, base, module, exports, require*/
var ref = require('reflect');
var Player = {
createNew: function createNew(inner) {
var player = {};
player.handler = inner;
player.sendMessage = function (msg) {
this.handler.sendMessage(msg);
};
return Object.assign(ref.mapToObject(inner), player);
}
};
exports.$ = Player.createNew;

View File

@ -1,130 +0,0 @@
'use strict';
/**
* Sponge 命令相关类
*/
/*global Java, base, module, exports, require, __FILE__*/
var Sponge = MServer;
var server = require('./server');
var plugin = server.plugin.self;
var CommandManager = server.CommandManager;
var CommandSpec = Java.type('org.spongepowered.api.command.spec.CommandSpec');
var CommandCallable = Java.type('org.spongepowered.api.command.CommandCallable');
var CommandResult = Java.type('org.spongepowered.api.command.CommandResult');
var Text = Java.type('org.spongepowered.api.text.Text');
var Optional = Java.type('java.util.Optional');
var ArrayList = Java.type('java.util.ArrayList');
var Arrays = Java.type('java.util.Arrays');
var commandMap=[];
var SimpleCommandCallable = function (name) {
var that = this;
this.name = name;
this.cmd = noop;
this.tab = function() { return new ArrayList(); };
this.callable = new CommandCallable({
//CommandResult process(CommandSource source, String arguments) throws CommandException;
process: function (src, args) {
return that.cmd(src, name, args.split(" ")) ? CommandResult.success() : CommandResult.empty();
},
//List<String> getSuggestions(CommandSource source, String arguments, @Nullable Location<World> targetPosition) throws CommandException;
getSuggestions: function (src, args, target) {
return that.tab(src, name, args.split(" "));
},
//boolean testPermission(CommandSource source);
testPermission: function () {
return true;
},
//Optional<Text> getShortDescription(CommandSource source);
getShortDescription: function () {
return Optional.of(Text.of(""));
},
//Optional<Text> getHelp(CommandSource source);
getHelp: function () {
return Optional.of(Text.of(""));
},
//Text getUsage(CommandSource source);
getUsage: function () {
return Text.of('');
}
});
this.setExecutor = function (exec) {
that.cmd = exec;
};
this.setTabCompleter = function (exec) {
that.tab = exec;
}
}
function enable(jsp) {
var pname = jsp.description.name;
var commands = jsp.description.commands;
if (commands) {
var pluginCmds = [];
for (var name in commands) {
var command = commands[name];
if (typeof command !== 'object') continue;
create(jsp, name)
console.debug('插件 %s 注册命令 %s ...'.format(jsp.description.name, name));
}
}
}
function get(name) {
}
function create(jsp, name) {
var commandKey = jsp.description.name.toLowerCase() + ":" + name;
if(!commandMap[commandKey]){
commandMap[commandKey] = new SimpleCommandCallable();
commandMap[commandKey].name = name;
Sponge.getCommandManager().register(plugin, commandMap[commandKey].callable, name, commandKey);
}
return commandMap[commandKey];
}
function on(jsp, name, exec) {
var c = create(jsp, name);
console.debug('插件 %s 设置命令 %s 执行器 ...'.format(jsp.description.name, name));
if (exec.cmd) {
c.setExecutor(function (sender, command, args) {
try {
return exec.cmd(sender, command, args);
} catch (ex) {
console.log(args)
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.ex(ex);
}
});
}
if (exec.tab) {
c.setTabCompleter(function (sender, command, args) {
try {
var token = args[args.length - 1];
return Arrays.asList(exec.tab(sender, command, args));
} 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.ex(ex);
}
});
}
}
var exist = Sponge.getCommandManager().getOwnedBy(plugin);
exist.forEach(function(commandMapping) {
if (!commandMapping.getAllAliases().contains("ms")) {
Sponge.getCommandManager().removeMapping(commandMapping);
}
});
exports = module.exports = {
enable: enable,
on: on,
off: noop
}

View File

@ -1,21 +0,0 @@
/*global Java, base, module, exports, require, __FILE__*/
(function (global) {
global.Console = function SpongeConsole() {
ConsoleDefault.call(this);
this.sender = function () {
var Text = Java.type("org.spongepowered.api.text.Text");
var sender = arguments[0];
if (!(sender instanceof org.spongepowered.api.command.CommandSource)) {
this.error("第一个参数未实现 org.spongepowered.api.command.CommandSource 无法发送消息!")
}
var args = Array.prototype.slice.call(arguments, 1);
sender.sendMessage(Text.of(console.prefix + args.join(' ')));
};
this.console = function () {
this.sender(MServer.server.console, Array.prototype.join.call(arguments, ' '));
};
this.warn = function () {
log.warn(this.name + Array.prototype.join.call(arguments, ' '));
};
};
})(global);

View File

@ -1,55 +0,0 @@
'use strict';
/**
* Sponge 事件相关类
*/
/*global Java, base, module, exports, require, __FILE__*/
var Modifier = Java.type("java.lang.reflect.Modifier");
var Order = Java.type("org.spongepowered.api.event.Order");
var Event = Java.type("org.spongepowered.api.event.Event");
var EventListener = Java.type("org.spongepowered.api.event.EventListener");
var priorityMap = {
'LOWEST': 'PRE',
'LOW': 'FIRST',
'NORMAL': 'DEFAULT',
'HIGH': 'LATE',
'HIGHEST': 'LAST',
'MONITOR': 'POST'
}
/**
* 判断是否为一个有效的事件类
* @param clz
* @returns {*|boolean}
*/
function isVaildEvent(clz) {
// noinspection JSUnresolvedVariable 继承于 org.spongepowered.api.event.Event
return Event.class.isAssignableFrom(clz) &&
// 访问符为Public
Modifier.isPublic(clz.getModifiers()) &&
// Sponge的事件都是接口
Modifier.isAbstract(clz.getModifiers());
}
function class2Name(clazz) {
return clazz.name.substring(clazz.name.lastIndexOf(".") + 1).replace(/\$/g, '.').toLowerCase();
}
function register(eventCls, exec, priority, ignoreCancel) {
var listener = new EventListener({
handle: exec
});
MServer.getEventManager().registerListener(this.plugin, eventCls, Order[priorityMap[priority]], listener);
return listener;
}
function unregister(event, listener) {
MServer.getEventManager().unregisterListeners(listener);
}
exports = module.exports = {
baseEventDir: 'org/spongepowered/api/event',
isVaildEvent: isVaildEvent,
class2Name: class2Name,
register: register,
unregister: unregister
};

View File

@ -1,66 +0,0 @@
'use strict';
/**
* Sponge基础操作
* Created by 蒋天蓓 on 2017/10/27 0009.
*/
/*global Java, base, module, exports, require, __FILE__*/
var Sponge = MServer;
var Server = Sponge.server;
var PluginManager = Sponge.pluginManager;
exports.$ = Sponge;
/**
* 插件管理
* @type {{manager: *, get: exports.plugin.get, load: exports.plugin.load}}
*/
exports.plugin = {
/**
* 插件管理工具
*/
manager: PluginManager,
/**
* 获得插件实例
* @param name 插件名称
* @returns {*}
*/
get: function (name) {
return PluginManager.getPlugin(name);
},
/**
* 载入插件 并且返回结果
* @param name 插件名称
* @returns {*}
*/
load: function (name) {
var plugin = this.get(name);
if (ext.notNull(plugin) && !plugin.isEnabled()) {
PluginManager.enablePlugin(plugin);
}
return PluginManager.isPluginEnabled(name);
},
self: PluginManager.getPlugin('miaoscript').get()
};
/**
* 获取玩家
*/
exports.player = function () {
switch (arguments.length) {
case 0:
return undefined;
case 1:
return Server.getPlayer(arguments[0]).get();
default:
return Server.getPlayer(arguments[0]).get();
}
};
/**
* 获取在线玩家
*/
exports.players = function () {
switch (arguments.length) {
case 1:
return Server.onlinePlayers.forEach(arguments[0]);
default:
return Server.onlinePlayers;
}
};

View File

@ -1,78 +0,0 @@
'use strict';
/*global Java, base, module, exports, require, __FILE__*/
/**
* 任务计划
* Created by 蒋天蓓 on 2017/2/9 0009.
*/
var plugin = require('./server').plugin.self;
var Comsumer = Java.type('java.util.function.Consumer');
var Task = Java.type("org.spongepowered.api.scheduler.Task");
/**
* 创建任务对象
* @param func 任务
*/
exports.create = function (func) {
return Task.builder().execute(new Comsumer(function () {
try {
func();
} catch (ex) {
console.ex('§4插件执行任务时发生错误', ex);
}
}));
};
/**
* 运行任务
* @param func 任务
*/
exports.run = function (func) {
return exports.create(func).submit(plugin);
};
/**
* 延时运行任务
* @param func 任务
* @param time 延时时间
*/
exports.later = function (func, time) {
return exports.create(func).delayTicks(time).submit(plugin);
};
/**
* 运行循环任务
* @constructor (任务,执行间隔).
* @constructor (任务,首次延时,执行间隔)
*/
exports.timer = function () {
switch (arguments.length) {
case 2:
return exports.create(arguments[0]).intervalTicks(arguments[1]).submit(plugin);
case 3:
return exports.create(arguments[0]).delayTicks(arguments[1]).intervalTicks(arguments[2]).submit(plugin);
}
};
/**
* 运行异步任务
* @param func function 任务
*/
exports.async = function (func) {
return exports.create(func).async().submit(plugin);
};
/**
* 延时运行异步任务
* @param func 任务
* @param time 延时时间
*/
exports.laterAsync = function (func, time) {
return exports.create(func).async().delayTicks(time).submit(plugin);
};
/**
* 运行异步循环任务
* @constructor (任务,执行间隔).
* @constructor (任务,首次延时,执行间隔)
*/
exports.timerAsync = function () {
switch (arguments.length) {
case 2:
return exports.create(arguments[0]).async().intervalTicks(arguments[1]).submit(plugin);
case 3:
return exports.create(arguments[0]).async().delayTicks(arguments[1]).intervalTicks(arguments[2]).submit(plugin);
}
};

View File

@ -1,19 +0,0 @@
/**
* Sponge 玩家方法代理类
* Created by 蒋天蓓 on 2018/1/5 0009.
*/
/*global Java, base, module, exports, require*/
var ref = require('reflect');
var Text = Java.type('org.spongepowered.api.text.Text');
var Player = {
createNew: function createNew(inner) {
var player = {};
player.handler = inner;
player.sendMessage = function (msg) {
this.handler.sendMessage(Text.of(msg));
};
return Object.assign(ref.mapToObject(inner), player);
}
};
exports.$ = Player.createNew;

View File

@ -1,225 +0,0 @@
/*
* $Id: base64.js,v 2.15 2014/04/05 12:58:57 dankogai Exp dankogai $
*
* Licensed under the BSD 3-Clause License.
* http://opensource.org/licenses/BSD-3-Clause
*
* References:
* http://en.wikipedia.org/wiki/Base64
*/
(function (global) {
'use strict';
// existing version for noConflict()
var _Base64 = global.Base64;
var version = "2.3.2";
// if node.js, we use Buffer
var buffer;
if (typeof module !== 'undefined' && module.exports) {
try {
buffer = require('buffer').Buffer;
} catch (err) {
}
}
// constants
var b64chars
= 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
var b64tab = function (bin) {
var t = {};
for (var i = 0, l = bin.length; i < l; i++) t[bin.charAt(i)] = i;
return t;
}(b64chars);
var fromCharCode = String.fromCharCode;
// encoder stuff
var cb_utob = function (c) {
if (c.length < 2) {
var cc = c.charCodeAt(0);
return cc < 0x80 ? c
: cc < 0x800 ? (fromCharCode(0xc0 | (cc >>> 6))
+ fromCharCode(0x80 | (cc & 0x3f)))
: (fromCharCode(0xe0 | ((cc >>> 12) & 0x0f))
+ fromCharCode(0x80 | ((cc >>> 6) & 0x3f))
+ fromCharCode(0x80 | ( cc & 0x3f)));
} else {
var ccc = 0x10000
+ (c.charCodeAt(0) - 0xD800) * 0x400
+ (c.charCodeAt(1) - 0xDC00);
return (fromCharCode(0xf0 | ((ccc >>> 18) & 0x07))
+ fromCharCode(0x80 | ((ccc >>> 12) & 0x3f))
+ fromCharCode(0x80 | ((ccc >>> 6) & 0x3f))
+ fromCharCode(0x80 | ( ccc & 0x3f)));
}
};
var re_utob = /[\uD800-\uDBFF][\uDC00-\uDFFFF]|[^\x00-\x7F]/g;
var utob = function (u) {
return u.replace(re_utob, cb_utob);
};
var cb_encode = function (ccc) {
var padlen = [0, 2, 1][ccc.length % 3],
ord = ccc.charCodeAt(0) << 16
| ((ccc.length > 1 ? ccc.charCodeAt(1) : 0) << 8)
| ((ccc.length > 2 ? ccc.charCodeAt(2) : 0)),
chars = [
b64chars.charAt(ord >>> 18),
b64chars.charAt((ord >>> 12) & 63),
padlen >= 2 ? '=' : b64chars.charAt((ord >>> 6) & 63),
padlen >= 1 ? '=' : b64chars.charAt(ord & 63)
];
return chars.join('');
};
var btoa = global.btoa ? function (b) {
return global.btoa(b);
} : function (b) {
return b.replace(/[\s\S]{1,3}/g, cb_encode);
};
var _encode = buffer ?
buffer.from && buffer.from !== Uint8Array.from ? function (u) {
return (u.constructor === buffer.constructor ? u : buffer.from(u))
.toString('base64')
}
: function (u) {
return (u.constructor === buffer.constructor ? u : new buffer(u))
.toString('base64')
}
: function (u) {
return btoa(utob(u))
}
;
var encode = function (u, urisafe) {
return !urisafe
? _encode(String(u))
: _encode(String(u)).replace(/[+\/]/g, function (m0) {
return m0 === '+' ? '-' : '_';
}).replace(/=/g, '');
};
var encodeURI = function (u) {
return encode(u, true)
};
// decoder stuff
var re_btou = new RegExp([
'[\xC0-\xDF][\x80-\xBF]',
'[\xE0-\xEF][\x80-\xBF]{2}',
'[\xF0-\xF7][\x80-\xBF]{3}'
].join('|'), 'g');
var cb_btou = function (cccc) {
switch (cccc.length) {
case 4:
var cp = ((0x07 & cccc.charCodeAt(0)) << 18)
| ((0x3f & cccc.charCodeAt(1)) << 12)
| ((0x3f & cccc.charCodeAt(2)) << 6)
| (0x3f & cccc.charCodeAt(3)),
offset = cp - 0x10000;
return (fromCharCode((offset >>> 10) + 0xD800)
+ fromCharCode((offset & 0x3FF) + 0xDC00));
case 3:
return fromCharCode(
((0x0f & cccc.charCodeAt(0)) << 12)
| ((0x3f & cccc.charCodeAt(1)) << 6)
| (0x3f & cccc.charCodeAt(2))
);
default:
return fromCharCode(
((0x1f & cccc.charCodeAt(0)) << 6)
| (0x3f & cccc.charCodeAt(1))
);
}
};
var btou = function (b) {
return b.replace(re_btou, cb_btou);
};
var cb_decode = function (cccc) {
var len = cccc.length,
padlen = len % 4,
n = (len > 0 ? b64tab[cccc.charAt(0)] << 18 : 0)
| (len > 1 ? b64tab[cccc.charAt(1)] << 12 : 0)
| (len > 2 ? b64tab[cccc.charAt(2)] << 6 : 0)
| (len > 3 ? b64tab[cccc.charAt(3)] : 0),
chars = [
fromCharCode(n >>> 16),
fromCharCode((n >>> 8) & 0xff),
fromCharCode(n & 0xff)
];
chars.length -= [0, 0, 2, 1][padlen];
return chars.join('');
};
var atob = global.atob ? function (a) {
return global.atob(a);
} : function (a) {
return a.replace(/[\s\S]{1,4}/g, cb_decode);
};
var _decode = buffer ?
buffer.from && buffer.from !== Uint8Array.from ? function (a) {
return (a.constructor === buffer.constructor
? a : buffer.from(a, 'base64')).toString();
}
: function (a) {
return (a.constructor === buffer.constructor
? a : new buffer(a, 'base64')).toString();
}
: function (a) {
return btou(atob(a))
};
var decode = function (a) {
return _decode(
String(a).replace(/[-_]/g, function (m0) {
return m0 === '-' ? '+' : '/'
})
.replace(/[^A-Za-z0-9+\/]/g, '')
);
};
var noConflict = function () {
var Base64 = global.Base64;
global.Base64 = _Base64;
return Base64;
};
// export Base64
global.Base64 = {
VERSION: version,
atob: atob,
btoa: btoa,
fromBase64: decode,
toBase64: encode,
utob: utob,
encode: encode,
encodeURI: encodeURI,
btou: btou,
decode: decode,
noConflict: noConflict
};
// if ES5 is available, make Base64.extendString() available
if (typeof Object.defineProperty === 'function') {
var noEnum = function (v) {
return {value: v, enumerable: false, writable: true, configurable: true};
};
global.Base64.extendString = function () {
Object.defineProperty(
String.prototype, 'fromBase64', noEnum(function () {
return decode(this)
}));
Object.defineProperty(
String.prototype, 'toBase64', noEnum(function (urisafe) {
return encode(this, urisafe)
}));
Object.defineProperty(
String.prototype, 'toBase64URI', noEnum(function () {
return encode(this, true)
}));
};
}
// module.exports and AMD are mutually exclusive.
// module.exports has precedence.
if (typeof module !== 'undefined' && module.exports) {
module.exports = global.Base64;
}
else if (typeof define === 'function' && define.amd) {
// AMD. Register as an anonymous module.
define([], function () {
return global.Base64
});
}
// that's it!
})(typeof self !== 'undefined' ? self
: typeof window !== 'undefined' ? window
: typeof global !== 'undefined' ? global
: this
);

View File

@ -1,113 +0,0 @@
'use strict';
/**
* HTTP 网络类
* Created by 蒋天蓓 on 2017/2/9 0009.
*/
/*global Java, base, module, exports, require, __FILE__*/
var URL = Java.type("java.net.URL");
var Files = Java.type("java.nio.file.Files");
var Paths = Java.type("java.nio.file.Paths");
var String = Java.type("java.lang.String");
var HttpURLConnection = Java.type("java.net.HttpURLConnection");
var HttpsURLConnection = Java.type("javax.net.ssl.HttpsURLConnection");
var SSLContext = Java.type("javax.net.ssl.SSLContext");
var HostnameVerifier = Java.type("javax.net.ssl.HostnameVerifier");
var X509TrustManager = Java.type("javax.net.ssl.X509TrustManager");
var TrustAnyHostnameVerifier = new HostnameVerifier({
verify: function (hostname, session) {
return true;
}
})
var SSLSocketFactory = function initSSLSocketFactory() {
var sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, [new X509TrustManager({
getAcceptedIssuers: function () {
return null;
},
checkClientTrusted: function (chain, authType) {},
checkServerTrusted: function (chain, authType) {}
})], new java.security.SecureRandom());
return sslContext.getSocketFactory();
}();
var config = {
Charset: 'UTF-8',
ConnectTimeout: 10000,
ReadTimeout: 10000
}
function open(url, method, header) {
// conn.setRequestProperty
var conn = new URL(url).openConnection();
if (conn instanceof HttpsURLConnection) {
conn.setHostnameVerifier(TrustAnyHostnameVerifier);
conn.setSSLSocketFactory(TrustAnyHostnameVerifier);
}
conn.setRequestMethod(method);
conn.setDoOutput(true);
conn.setDoInput(true);
conn.setConnectTimeout(config.ConnectTimeout);
conn.setReadTimeout(config.ReadTimeout);
for (var key in header) {
conn.setRequestProperty(key, header[key]);
}
return conn;
}
function buildUrl(url, params) {
if (params && Object.keys(params).length > 0) {
var queryStart = url.indexOf('?');
if (queryStart == -1) {
url += '?';
}
for (var key in params) {
url += key;
url += '=';
url += params[key];
url += '&';
}
return url.substr(0, url.length - 1);
}
return url;
}
function request(url, method, header, params, body) {
var conn = open(buildUrl(url, params), method, header);
try {
conn.connect();
var out = conn.getOutputStream();
out.write(new String(body).getBytes(config.Charset));
out.flush();
out.close();
return response(conn);
} finally {
conn.disconnect();
}
}
function response (conn) {
var temp = Paths.get(java.lang.System.getProperty("java.io.tmpdir"), java.util.UUID.randomUUID().toString());
Files.copy(conn.getInputStream(), temp);
var result = new String(Files.readAllBytes(temp), config.Charset);
var tempFile = temp.toFile();
tempFile.delete() || tempFile.deleteOnExit();
return result;
}
var http = {
config: config
};
['GET', 'POST', 'PUT', 'DELETE', 'HEADER'].forEach(function(method){
http[method.toLowerCase()] = function (url, header, params, body) {
return request(url, method, header, params, body);
}
})
exports = module.exports = http;

View File

@ -1,185 +0,0 @@
'use strict';
/**
* 反射工具类
* Created by 蒋天蓓 on 2017/2/9 0009.
*/
/*global Java, base, module, exports, require, __FILE__*/
var Class = Java.type('java.lang.Class');
var NoSuchFieldException = Java.type('java.lang.NoSuchFieldException');
var methodCache = [];
function Reflect(obj) {
if (obj instanceof Class) {
this.obj = null;
this.class = obj;
} else {
this.obj = obj;
this.class = obj.class;
}
this.field = function (name) {
try {
// Try getting a public field
var field = this.class.field(name);
return on(field.get(this.obj));
} catch (ex) {
// Try again, getting a non-public field
try {
return on(accessible(declaredField(this.class, name)).get(this.obj));
} catch (ex) {
throw new NoSuchFieldException(ex);
}
}
};
this.call = function () {
var name = arguments[0];
var params = Array.prototype.slice.call(arguments, 1);
var method = declaredMethod(this.class, name, types(params));
return on(method.invoke(this.get(), params));
};
this.get = function () {
return arguments.length === 1 ? this.field(arguments[0]) : this.obj;
};
this.set = function (name, value) {
accessible(declaredField(this.class, name)).set(this.obj, value);
return this;
};
this.create = function () {
var param = Array.prototype.slice.call(arguments);
return on(declaredConstructor(this.class, param).newInstance(param));
};
}
/**
* Get an array of types for an array of objects
*/
function types(values, def) {
if (values === null) {
return [];
}
var result = [];
values.forEach(function (t) {
result.push((t || def) ? Object.class : t instanceof Class ? t : t.class)
});
return result;
}
function accessible(accessible) {
if (accessible === null) {
return null;
}
if (!accessible.isAccessible()) {
accessible.setAccessible(true);
}
return accessible;
}
function declaredConstructor(clazz, param) {
var constructor;
try {
constructor = clazz.getDeclaredConstructor(types(param));
} catch (ex) {
try {
constructor = clazz.getDeclaredConstructor(types(param, true));
} catch (ex) {
constructor = clazz.getDeclaredConstructors()[0];
}
}
return accessible(constructor);
}
function declaredField(clazz, name) {
var field = null;
// noinspection JSUnresolvedVariable
while (clazz !== java.lang.Object.class) {
try {
field = clazz.getDeclaredField(name);
if (field !== null) {
break;
}
} catch (e) {
clazz = clazz.getSuperclass();
}
}
if (field === null) {
throw new NoSuchFieldException(name + " is not found in " + clazz.name);
}
return field;
}
function declaredMethod(clazz, name, clazzs) {
var mkey = clazz.name + '.' + name + ':' + (clazzs || []).join(':');
if (!methodCache[mkey]) {
try {
methodCache[mkey] = clazz.getMethod(name, clazzs);
} catch (ex) {
methodCache[mkey] = clazz.getDeclaredMethod(name, clazzs);
}
}
return methodCache[mkey];
}
function declaredMethod(clazz, name, clazzs) {
var mkey = clazz.name + '.' + name + ':' + (clazzs || []).join(':');
if (!methodCache[mkey]) {
try {
methodCache[mkey] = clazz.getMethod(name, clazzs);
} catch (ex) {
methodCache[mkey] = clazz.getDeclaredMethod(name, clazzs);
}
}
return methodCache[mkey];
}
function declaredMethods(clazz) {
return clazz.declaredMethods;
}
var classMethodsCache = [];
function mapToObject(javaObj) {
if (!javaObj || !javaObj.class) { throw new TypeError('参数 %s 不是一个Java对象!'.format(javaObj)) }
var target = {};
getJavaObjectMethods(javaObj).forEach(function proxyMethod(t){ mapMethod(target, javaObj, t) })
return target;
}
function getJavaObjectMethods(javaObj) {
var className = javaObj.class.name
if (!classMethodsCache[className]) {
var names = [];
var methods = javaObj.class.methods;
for (var i in methods){
names.push(methods[i].name);
}
classMethodsCache[className] = names;
}
return classMethodsCache[className];
}
function mapMethod (target, source, name) {
target[name] = function __SimpleDynamicMethod__() {
if (arguments.length > 0) {
return source[name](Array.prototype.slice.call(arguments));
} else {
return source[name]();
}
};
}
function on(obj) {
if (!obj || !obj.class) { throw new TypeError('参数 %s 不是一个Java对象!'.format(obj)) }
return new Reflect(obj);
}
exports = module.exports = {
on: on,
accessible: accessible,
declaredMethods: declaredMethods,
mapToObject: mapToObject
}

View File

@ -1,39 +0,0 @@
'use strict';
var loader = require('./js-yaml/loader');
var dumper = require('./js-yaml/dumper');
function deprecated(name) {
return function () {
throw new Error('Function ' + name + ' is deprecated and cannot be used.');
};
}
module.exports.Type = require('./js-yaml/type');
module.exports.Schema = require('./js-yaml/schema');
module.exports.FAILSAFE_SCHEMA = require('./js-yaml/schema/failsafe');
module.exports.JSON_SCHEMA = require('./js-yaml/schema/json');
module.exports.CORE_SCHEMA = require('./js-yaml/schema/core');
module.exports.DEFAULT_SAFE_SCHEMA = require('./js-yaml/schema/default_safe');
module.exports.DEFAULT_FULL_SCHEMA = require('./js-yaml/schema/default_full');
module.exports.load = loader.load;
module.exports.loadAll = loader.loadAll;
module.exports.safeLoad = loader.safeLoad;
module.exports.safeLoadAll = loader.safeLoadAll;
module.exports.dump = dumper.dump;
module.exports.safeDump = dumper.safeDump;
module.exports.YAMLException = require('./js-yaml/exception');
// Deprecated schema names from JS-YAML 2.0.x
module.exports.MINIMAL_SCHEMA = require('./js-yaml/schema/failsafe');
module.exports.SAFE_SCHEMA = require('./js-yaml/schema/default_safe');
module.exports.DEFAULT_SCHEMA = require('./js-yaml/schema/default_full');
// Deprecated functions from JS-YAML 1.x.x
module.exports.scan = deprecated('scan');
module.exports.parse = deprecated('parse');
module.exports.compose = deprecated('compose');
module.exports.addConstructor = deprecated('addConstructor');

View File

@ -1,59 +0,0 @@
'use strict';
function isNothing(subject) {
return (typeof subject === 'undefined') || (subject === null);
}
function isObject(subject) {
return (typeof subject === 'object') && (subject !== null);
}
function toArray(sequence) {
if (Array.isArray(sequence)) return sequence;
else if (isNothing(sequence)) return [];
return [ sequence ];
}
function extend(target, source) {
var index, length, key, sourceKeys;
if (source) {
sourceKeys = Object.keys(source);
for (index = 0, length = sourceKeys.length; index < length; index += 1) {
key = sourceKeys[index];
target[key] = source[key];
}
}
return target;
}
function repeat(string, count) {
var result = '', cycle;
for (cycle = 0; cycle < count; cycle += 1) {
result += string;
}
return result;
}
function isNegativeZero(number) {
return (number === 0) && (Number.NEGATIVE_INFINITY === 1 / number);
}
module.exports.isNothing = isNothing;
module.exports.isObject = isObject;
module.exports.toArray = toArray;
module.exports.repeat = repeat;
module.exports.isNegativeZero = isNegativeZero;
module.exports.extend = extend;

View File

@ -1,819 +0,0 @@
'use strict';
/*eslint-disable no-use-before-define*/
var common = require('./common');
var YAMLException = require('./exception');
var DEFAULT_FULL_SCHEMA = require('./schema/default_full');
var DEFAULT_SAFE_SCHEMA = require('./schema/default_safe');
var _toString = Object.prototype.toString;
var _hasOwnProperty = Object.prototype.hasOwnProperty;
var CHAR_TAB = 0x09; /* Tab */
var CHAR_LINE_FEED = 0x0A; /* LF */
var CHAR_SPACE = 0x20; /* Space */
var CHAR_EXCLAMATION = 0x21; /* ! */
var CHAR_DOUBLE_QUOTE = 0x22; /* " */
var CHAR_SHARP = 0x23; /* # */
var CHAR_PERCENT = 0x25; /* % */
var CHAR_AMPERSAND = 0x26; /* & */
var CHAR_SINGLE_QUOTE = 0x27; /* ' */
var CHAR_ASTERISK = 0x2A; /* * */
var CHAR_COMMA = 0x2C; /* , */
var CHAR_MINUS = 0x2D; /* - */
var CHAR_COLON = 0x3A; /* : */
var CHAR_GREATER_THAN = 0x3E; /* > */
var CHAR_QUESTION = 0x3F; /* ? */
var CHAR_COMMERCIAL_AT = 0x40; /* @ */
var CHAR_LEFT_SQUARE_BRACKET = 0x5B; /* [ */
var CHAR_RIGHT_SQUARE_BRACKET = 0x5D; /* ] */
var CHAR_GRAVE_ACCENT = 0x60; /* ` */
var CHAR_LEFT_CURLY_BRACKET = 0x7B; /* { */
var CHAR_VERTICAL_LINE = 0x7C; /* | */
var CHAR_RIGHT_CURLY_BRACKET = 0x7D; /* } */
var ESCAPE_SEQUENCES = {};
ESCAPE_SEQUENCES[0x00] = '\\0';
ESCAPE_SEQUENCES[0x07] = '\\a';
ESCAPE_SEQUENCES[0x08] = '\\b';
ESCAPE_SEQUENCES[0x09] = '\\t';
ESCAPE_SEQUENCES[0x0A] = '\\n';
ESCAPE_SEQUENCES[0x0B] = '\\v';
ESCAPE_SEQUENCES[0x0C] = '\\f';
ESCAPE_SEQUENCES[0x0D] = '\\r';
ESCAPE_SEQUENCES[0x1B] = '\\e';
ESCAPE_SEQUENCES[0x22] = '\\"';
ESCAPE_SEQUENCES[0x5C] = '\\\\';
ESCAPE_SEQUENCES[0x85] = '\\N';
ESCAPE_SEQUENCES[0xA0] = '\\_';
ESCAPE_SEQUENCES[0x2028] = '\\L';
ESCAPE_SEQUENCES[0x2029] = '\\P';
var DEPRECATED_BOOLEANS_SYNTAX = [
'y', 'Y', 'yes', 'Yes', 'YES', 'on', 'On', 'ON',
'n', 'N', 'no', 'No', 'NO', 'off', 'Off', 'OFF'
];
function compileStyleMap(schema, map) {
var result, keys, index, length, tag, style, type;
if (map === null) return {};
result = {};
keys = Object.keys(map);
for (index = 0, length = keys.length; index < length; index += 1) {
tag = keys[index];
style = String(map[tag]);
if (tag.slice(0, 2) === '!!') {
tag = 'tag:yaml.org,2002:' + tag.slice(2);
}
type = schema.compiledTypeMap['fallback'][tag];
if (type && _hasOwnProperty.call(type.styleAliases, style)) {
style = type.styleAliases[style];
}
result[tag] = style;
}
return result;
}
function encodeHex(character) {
var string, handle, length;
string = character.toString(16).toUpperCase();
if (character <= 0xFF) {
handle = 'x';
length = 2;
} else if (character <= 0xFFFF) {
handle = 'u';
length = 4;
} else if (character <= 0xFFFFFFFF) {
handle = 'U';
length = 8;
} else {
throw new YAMLException('code point within a string may not be greater than 0xFFFFFFFF');
}
return '\\' + handle + common.repeat('0', length - string.length) + string;
}
function State(options) {
this.schema = options['schema'] || DEFAULT_FULL_SCHEMA;
this.indent = Math.max(1, (options['indent'] || 2));
this.skipInvalid = options['skipInvalid'] || false;
this.flowLevel = (common.isNothing(options['flowLevel']) ? -1 : options['flowLevel']);
this.styleMap = compileStyleMap(this.schema, options['styles'] || null);
this.sortKeys = options['sortKeys'] || false;
this.lineWidth = options['lineWidth'] || 80;
this.noRefs = options['noRefs'] || false;
this.noCompatMode = options['noCompatMode'] || false;
this.condenseFlow = options['condenseFlow'] || false;
this.implicitTypes = this.schema.compiledImplicit;
this.explicitTypes = this.schema.compiledExplicit;
this.tag = null;
this.result = '';
this.duplicates = [];
this.usedDuplicates = null;
}
// Indents every line in a string. Empty lines (\n only) are not indented.
function indentString(string, spaces) {
var ind = common.repeat(' ', spaces),
position = 0,
next = -1,
result = '',
line,
length = string.length;
while (position < length) {
next = string.indexOf('\n', position);
if (next === -1) {
line = string.slice(position);
position = length;
} else {
line = string.slice(position, next + 1);
position = next + 1;
}
if (line.length && line !== '\n') result += ind;
result += line;
}
return result;
}
function generateNextLine(state, level) {
return '\n' + common.repeat(' ', state.indent * level);
}
function testImplicitResolving(state, str) {
var index, length, type;
for (index = 0, length = state.implicitTypes.length; index < length; index += 1) {
type = state.implicitTypes[index];
if (type.resolve(str)) {
return true;
}
}
return false;
}
// [33] s-white ::= s-space | s-tab
function isWhitespace(c) {
return c === CHAR_SPACE || c === CHAR_TAB;
}
// Returns true if the character can be printed without escaping.
// From YAML 1.2: "any allowed characters known to be non-printable
// should also be escaped. [However,] This isnt mandatory"
// Derived from nb-char - \t - #x85 - #xA0 - #x2028 - #x2029.
function isPrintable(c) {
return (0x00020 <= c && c <= 0x00007E)
|| ((0x000A1 <= c && c <= 0x00D7FF) && c !== 0x2028 && c !== 0x2029)
|| ((0x0E000 <= c && c <= 0x00FFFD) && c !== 0xFEFF /* BOM */)
|| (0x10000 <= c && c <= 0x10FFFF);
}
// Simplified test for values allowed after the first character in plain style.
function isPlainSafe(c) {
// Uses a subset of nb-char - c-flow-indicator - ":" - "#"
// where nb-char ::= c-printable - b-char - c-byte-order-mark.
return isPrintable(c) && c !== 0xFEFF
// - c-flow-indicator
&& c !== CHAR_COMMA
&& c !== CHAR_LEFT_SQUARE_BRACKET
&& c !== CHAR_RIGHT_SQUARE_BRACKET
&& c !== CHAR_LEFT_CURLY_BRACKET
&& c !== CHAR_RIGHT_CURLY_BRACKET
// - ":" - "#"
&& c !== CHAR_COLON
&& c !== CHAR_SHARP;
}
// Simplified test for values allowed as the first character in plain style.
function isPlainSafeFirst(c) {
// Uses a subset of ns-char - c-indicator
// where ns-char = nb-char - s-white.
return isPrintable(c) && c !== 0xFEFF
&& !isWhitespace(c) // - s-white
// - (c-indicator ::=
// “-” | “?” | “:” | “,” | “[” | “]” | “{” | “}”
&& c !== CHAR_MINUS
&& c !== CHAR_QUESTION
&& c !== CHAR_COLON
&& c !== CHAR_COMMA
&& c !== CHAR_LEFT_SQUARE_BRACKET
&& c !== CHAR_RIGHT_SQUARE_BRACKET
&& c !== CHAR_LEFT_CURLY_BRACKET
&& c !== CHAR_RIGHT_CURLY_BRACKET
// | “#” | “&” | “*” | “!” | “|” | “>” | “'” | “"”
&& c !== CHAR_SHARP
&& c !== CHAR_AMPERSAND
&& c !== CHAR_ASTERISK
&& c !== CHAR_EXCLAMATION
&& c !== CHAR_VERTICAL_LINE
&& c !== CHAR_GREATER_THAN
&& c !== CHAR_SINGLE_QUOTE
&& c !== CHAR_DOUBLE_QUOTE
// | “%” | “@” | “`”)
&& c !== CHAR_PERCENT
&& c !== CHAR_COMMERCIAL_AT
&& c !== CHAR_GRAVE_ACCENT;
}
var STYLE_PLAIN = 1,
STYLE_SINGLE = 2,
STYLE_LITERAL = 3,
STYLE_FOLDED = 4,
STYLE_DOUBLE = 5;
// Determines which scalar styles are possible and returns the preferred style.
// lineWidth = -1 => no limit.
// Pre-conditions: str.length > 0.
// Post-conditions:
// STYLE_PLAIN or STYLE_SINGLE => no \n are in the string.
// STYLE_LITERAL => no lines are suitable for folding (or lineWidth is -1).
// STYLE_FOLDED => a line > lineWidth and can be folded (and lineWidth != -1).
function chooseScalarStyle(string, singleLineOnly, indentPerLevel, lineWidth, testAmbiguousType) {
var i;
var char;
var hasLineBreak = false;
var hasFoldableLine = false; // only checked if shouldTrackWidth
var shouldTrackWidth = lineWidth !== -1;
var previousLineBreak = -1; // count the first line correctly
var plain = isPlainSafeFirst(string.charCodeAt(0))
&& !isWhitespace(string.charCodeAt(string.length - 1));
if (singleLineOnly) {
// Case: no block styles.
// Check for disallowed characters to rule out plain and single.
for (i = 0; i < string.length; i++) {
char = string.charCodeAt(i);
if (!isPrintable(char)) {
return STYLE_DOUBLE;
}
plain = plain && isPlainSafe(char);
}
} else {
// Case: block styles permitted.
for (i = 0; i < string.length; i++) {
char = string.charCodeAt(i);
if (char === CHAR_LINE_FEED) {
hasLineBreak = true;
// Check if any line can be folded.
if (shouldTrackWidth) {
hasFoldableLine = hasFoldableLine ||
// Foldable line = too long, and not more-indented.
(i - previousLineBreak - 1 > lineWidth &&
string[previousLineBreak + 1] !== ' ');
previousLineBreak = i;
}
} else if (!isPrintable(char)) {
return STYLE_DOUBLE;
}
plain = plain && isPlainSafe(char);
}
// in case the end is missing a \n
hasFoldableLine = hasFoldableLine || (shouldTrackWidth &&
(i - previousLineBreak - 1 > lineWidth &&
string[previousLineBreak + 1] !== ' '));
}
// Although every style can represent \n without escaping, prefer block styles
// for multiline, since they're more readable and they don't add empty lines.
// Also prefer folding a super-long line.
if (!hasLineBreak && !hasFoldableLine) {
// Strings interpretable as another type have to be quoted;
// e.g. the string 'true' vs. the boolean true.
return plain && !testAmbiguousType(string)
? STYLE_PLAIN : STYLE_SINGLE;
}
// Edge case: block indentation indicator can only have one digit.
if (string[0] === ' ' && indentPerLevel > 9) {
return STYLE_DOUBLE;
}
// At this point we know block styles are valid.
// Prefer literal style unless we want to fold.
return hasFoldableLine ? STYLE_FOLDED : STYLE_LITERAL;
}
// Note: line breaking/folding is implemented for only the folded style.
// NB. We drop the last trailing newline (if any) of a returned block scalar
// since the dumper adds its own newline. This always works:
// • No ending newline => unaffected; already using strip "-" chomping.
// • Ending newline => removed then restored.
// Importantly, this keeps the "+" chomp indicator from gaining an extra line.
function writeScalar(state, string, level, iskey) {
state.dump = (function () {
if (string.length === 0) {
return "''";
}
if (!state.noCompatMode &&
DEPRECATED_BOOLEANS_SYNTAX.indexOf(string) !== -1) {
return "'" + string + "'";
}
var indent = state.indent * Math.max(1, level); // no 0-indent scalars
// As indentation gets deeper, let the width decrease monotonically
// to the lower bound min(state.lineWidth, 40).
// Note that this implies
// state.lineWidth ≤ 40 + state.indent: width is fixed at the lower bound.
// state.lineWidth > 40 + state.indent: width decreases until the lower bound.
// This behaves better than a constant minimum width which disallows narrower options,
// or an indent threshold which causes the width to suddenly increase.
var lineWidth = state.lineWidth === -1
? -1 : Math.max(Math.min(state.lineWidth, 40), state.lineWidth - indent);
// Without knowing if keys are implicit/explicit, assume implicit for safety.
var singleLineOnly = iskey
// No block styles in flow mode.
|| (state.flowLevel > -1 && level >= state.flowLevel);
function testAmbiguity(string) {
return testImplicitResolving(state, string);
}
switch (chooseScalarStyle(string, singleLineOnly, state.indent, lineWidth, testAmbiguity)) {
case STYLE_PLAIN:
return string;
case STYLE_SINGLE:
return "'" + string.replace(/'/g, "''") + "'";
case STYLE_LITERAL:
return '|' + blockHeader(string, state.indent)
+ dropEndingNewline(indentString(string, indent));
case STYLE_FOLDED:
return '>' + blockHeader(string, state.indent)
+ dropEndingNewline(indentString(foldString(string, lineWidth), indent));
case STYLE_DOUBLE:
return '"' + escapeString(string, lineWidth) + '"';
default:
throw new YAMLException('impossible error: invalid scalar style');
}
}());
}
// Pre-conditions: string is valid for a block scalar, 1 <= indentPerLevel <= 9.
function blockHeader(string, indentPerLevel) {
var indentIndicator = (string[0] === ' ') ? String(indentPerLevel) : '';
// note the special case: the string '\n' counts as a "trailing" empty line.
var clip = string[string.length - 1] === '\n';
var keep = clip && (string[string.length - 2] === '\n' || string === '\n');
var chomp = keep ? '+' : (clip ? '' : '-');
return indentIndicator + chomp + '\n';
}
// (See the note for writeScalar.)
function dropEndingNewline(string) {
return string[string.length - 1] === '\n' ? string.slice(0, -1) : string;
}
// Note: a long line without a suitable break point will exceed the width limit.
// Pre-conditions: every char in str isPrintable, str.length > 0, width > 0.
function foldString(string, width) {
// In folded style, $k$ consecutive newlines output as $k+1$ newlines—
// unless they're before or after a more-indented line, or at the very
// beginning or end, in which case $k$ maps to $k$.
// Therefore, parse each chunk as newline(s) followed by a content line.
var lineRe = /(\n+)([^\n]*)/g;
// first line (possibly an empty line)
var result = (function () {
var nextLF = string.indexOf('\n');
nextLF = nextLF !== -1 ? nextLF : string.length;
lineRe.lastIndex = nextLF;
return foldLine(string.slice(0, nextLF), width);
}());
// If we haven't reached the first content line yet, don't add an extra \n.
var prevMoreIndented = string[0] === '\n' || string[0] === ' ';
var moreIndented;
// rest of the lines
var match;
while ((match = lineRe.exec(string))) {
var prefix = match[1], line = match[2];
moreIndented = (line[0] === ' ');
result += prefix
+ (!prevMoreIndented && !moreIndented && line !== ''
? '\n' : '')
+ foldLine(line, width);
prevMoreIndented = moreIndented;
}
return result;
}
// Greedy line breaking.
// Picks the longest line under the limit each time,
// otherwise settles for the shortest line over the limit.
// NB. More-indented lines *cannot* be folded, as that would add an extra \n.
function foldLine(line, width) {
if (line === '' || line[0] === ' ') return line;
// Since a more-indented line adds a \n, breaks can't be followed by a space.
var breakRe = / [^ ]/g; // note: the match index will always be <= length-2.
var match;
// start is an inclusive index. end, curr, and next are exclusive.
var start = 0, end, curr = 0, next = 0;
var result = '';
// Invariants: 0 <= start <= length-1.
// 0 <= curr <= next <= max(0, length-2). curr - start <= width.
// Inside the loop:
// A match implies length >= 2, so curr and next are <= length-2.
while ((match = breakRe.exec(line))) {
next = match.index;
// maintain invariant: curr - start <= width
if (next - start > width) {
end = (curr > start) ? curr : next; // derive end <= length-2
result += '\n' + line.slice(start, end);
// skip the space that was output as \n
start = end + 1; // derive start <= length-1
}
curr = next;
}
// By the invariants, start <= length-1, so there is something left over.
// It is either the whole string or a part starting from non-whitespace.
result += '\n';
// Insert a break if the remainder is too long and there is a break available.
if (line.length - start > width && curr > start) {
result += line.slice(start, curr) + '\n' + line.slice(curr + 1);
} else {
result += line.slice(start);
}
return result.slice(1); // drop extra \n joiner
}
// Escapes a double-quoted string.
function escapeString(string) {
var result = '';
var char, nextChar;
var escapeSeq;
for (var i = 0; i < string.length; i++) {
char = string.charCodeAt(i);
// Check for surrogate pairs (reference Unicode 3.0 section "3.7 Surrogates").
if (char >= 0xD800 && char <= 0xDBFF/* high surrogate */) {
nextChar = string.charCodeAt(i + 1);
if (nextChar >= 0xDC00 && nextChar <= 0xDFFF/* low surrogate */) {
// Combine the surrogate pair and store it escaped.
result += encodeHex((char - 0xD800) * 0x400 + nextChar - 0xDC00 + 0x10000);
// Advance index one extra since we already used that char here.
i++; continue;
}
}
escapeSeq = ESCAPE_SEQUENCES[char];
result += !escapeSeq && isPrintable(char)
? string[i]
: escapeSeq || encodeHex(char);
}
return result;
}
function writeFlowSequence(state, level, object) {
var _result = '',
_tag = state.tag,
index,
length;
for (index = 0, length = object.length; index < length; index += 1) {
// Write only valid elements.
if (writeNode(state, level, object[index], false, false)) {
if (index !== 0) _result += ',' + (!state.condenseFlow ? ' ' : '');
_result += state.dump;
}
}
state.tag = _tag;
state.dump = '[' + _result + ']';
}
function writeBlockSequence(state, level, object, compact) {
var _result = '',
_tag = state.tag,
index,
length;
for (index = 0, length = object.length; index < length; index += 1) {
// Write only valid elements.
if (writeNode(state, level + 1, object[index], true, true)) {
if (!compact || index !== 0) {
_result += generateNextLine(state, level);
}
if (state.dump && CHAR_LINE_FEED === state.dump.charCodeAt(0)) {
_result += '-';
} else {
_result += '- ';
}
_result += state.dump;
}
}
state.tag = _tag;
state.dump = _result || '[]'; // Empty sequence if no valid values.
}
function writeFlowMapping(state, level, object) {
var _result = '',
_tag = state.tag,
objectKeyList = Object.keys(object),
index,
length,
objectKey,
objectValue,
pairBuffer;
for (index = 0, length = objectKeyList.length; index < length; index += 1) {
pairBuffer = state.condenseFlow ? '"' : '';
if (index !== 0) pairBuffer += ', ';
objectKey = objectKeyList[index];
objectValue = object[objectKey];
if (!writeNode(state, level, objectKey, false, false)) {
continue; // Skip this pair because of invalid key;
}
if (state.dump.length > 1024) pairBuffer += '? ';
pairBuffer += state.dump + (state.condenseFlow ? '"' : '') + ':' + (state.condenseFlow ? '' : ' ');
if (!writeNode(state, level, objectValue, false, false)) {
continue; // Skip this pair because of invalid value.
}
pairBuffer += state.dump;
// Both key and value are valid.
_result += pairBuffer;
}
state.tag = _tag;
state.dump = '{' + _result + '}';
}
function writeBlockMapping(state, level, object, compact) {
var _result = '',
_tag = state.tag,
objectKeyList = Object.keys(object),
index,
length,
objectKey,
objectValue,
explicitPair,
pairBuffer;
// Allow sorting keys so that the output file is deterministic
if (state.sortKeys === true) {
// Default sorting
objectKeyList.sort();
} else if (typeof state.sortKeys === 'function') {
// Custom sort function
objectKeyList.sort(state.sortKeys);
} else if (state.sortKeys) {
// Something is wrong
throw new YAMLException('sortKeys must be a boolean or a function');
}
for (index = 0, length = objectKeyList.length; index < length; index += 1) {
pairBuffer = '';
if (!compact || index !== 0) {
pairBuffer += generateNextLine(state, level);
}
objectKey = objectKeyList[index];
objectValue = object[objectKey];
if (!writeNode(state, level + 1, objectKey, true, true, true)) {
continue; // Skip this pair because of invalid key.
}
explicitPair = (state.tag !== null && state.tag !== '?') ||
(state.dump && state.dump.length > 1024);
if (explicitPair) {
if (state.dump && CHAR_LINE_FEED === state.dump.charCodeAt(0)) {
pairBuffer += '?';
} else {
pairBuffer += '? ';
}
}
pairBuffer += state.dump;
if (explicitPair) {
pairBuffer += generateNextLine(state, level);
}
if (!writeNode(state, level + 1, objectValue, true, explicitPair)) {
continue; // Skip this pair because of invalid value.
}
if (state.dump && CHAR_LINE_FEED === state.dump.charCodeAt(0)) {
pairBuffer += ':';
} else {
pairBuffer += ': ';
}
pairBuffer += state.dump;
// Both key and value are valid.
_result += pairBuffer;
}
state.tag = _tag;
state.dump = _result || '{}'; // Empty mapping if no valid pairs.
}
function detectType(state, object, explicit) {
var _result, typeList, index, length, type, style;
typeList = explicit ? state.explicitTypes : state.implicitTypes;
for (index = 0, length = typeList.length; index < length; index += 1) {
type = typeList[index];
if ((type.instanceOf || type.predicate) &&
(!type.instanceOf || ((typeof object === 'object') && (object instanceof type.instanceOf))) &&
(!type.predicate || type.predicate(object))) {
state.tag = explicit ? type.tag : '?';
if (type.represent) {
style = state.styleMap[type.tag] || type.defaultStyle;
if (_toString.call(type.represent) === '[object Function]') {
_result = type.represent(object, style);
} else if (_hasOwnProperty.call(type.represent, style)) {
_result = type.represent[style](object, style);
} else {
throw new YAMLException('!<' + type.tag + '> tag resolver accepts not "' + style + '" style');
}
state.dump = _result;
}
return true;
}
}
return false;
}
// Serializes `object` and writes it to global `result`.
// Returns true on success, or false on invalid object.
//
function writeNode(state, level, object, block, compact, iskey) {
state.tag = null;
state.dump = object;
if (!detectType(state, object, false)) {
detectType(state, object, true);
}
var type = _toString.call(state.dump);
if (block) {
block = (state.flowLevel < 0 || state.flowLevel > level);
}
var objectOrArray = type === '[object Object]' || type === '[object Array]',
duplicateIndex,
duplicate;
if (objectOrArray) {
duplicateIndex = state.duplicates.indexOf(object);
duplicate = duplicateIndex !== -1;
}
if ((state.tag !== null && state.tag !== '?') || duplicate || (state.indent !== 2 && level > 0)) {
compact = false;
}
if (duplicate && state.usedDuplicates[duplicateIndex]) {
state.dump = '*ref_' + duplicateIndex;
} else {
if (objectOrArray && duplicate && !state.usedDuplicates[duplicateIndex]) {
state.usedDuplicates[duplicateIndex] = true;
}
if (type === '[object Object]') {
if (block && (Object.keys(state.dump).length !== 0)) {
writeBlockMapping(state, level, state.dump, compact);
if (duplicate) {
state.dump = '&ref_' + duplicateIndex + state.dump;
}
} else {
writeFlowMapping(state, level, state.dump);
if (duplicate) {
state.dump = '&ref_' + duplicateIndex + ' ' + state.dump;
}
}
} else if (type === '[object Array]') {
if (block && (state.dump.length !== 0)) {
writeBlockSequence(state, level, state.dump, compact);
if (duplicate) {
state.dump = '&ref_' + duplicateIndex + state.dump;
}
} else {
writeFlowSequence(state, level, state.dump);
if (duplicate) {
state.dump = '&ref_' + duplicateIndex + ' ' + state.dump;
}
}
} else if (type === '[object String]') {
if (state.tag !== '?') {
writeScalar(state, state.dump, level, iskey);
}
} else {
if (state.skipInvalid) return false;
throw new YAMLException('unacceptable kind of an object to dump ' + type);
}
if (state.tag !== null && state.tag !== '?') {
state.dump = '!<' + state.tag + '> ' + state.dump;
}
}
return true;
}
function getDuplicateReferences(object, state) {
var objects = [],
duplicatesIndexes = [],
index,
length;
inspectNode(object, objects, duplicatesIndexes);
for (index = 0, length = duplicatesIndexes.length; index < length; index += 1) {
state.duplicates.push(objects[duplicatesIndexes[index]]);
}
state.usedDuplicates = new Array(length);
}
function inspectNode(object, objects, duplicatesIndexes) {
var objectKeyList,
index,
length;
if (object !== null && typeof object === 'object') {
index = objects.indexOf(object);
if (index !== -1) {
if (duplicatesIndexes.indexOf(index) === -1) {
duplicatesIndexes.push(index);
}
} else {
objects.push(object);
if (Array.isArray(object)) {
for (index = 0, length = object.length; index < length; index += 1) {
inspectNode(object[index], objects, duplicatesIndexes);
}
} else {
objectKeyList = Object.keys(object);
for (index = 0, length = objectKeyList.length; index < length; index += 1) {
inspectNode(object[objectKeyList[index]], objects, duplicatesIndexes);
}
}
}
}
}
function dump(input, options) {
options = options || {};
var state = new State(options);
if (!state.noRefs) getDuplicateReferences(input, state);
if (writeNode(state, 0, input, true, true)) return state.dump + '\n';
return '';
}
function safeDump(input, options) {
return dump(input, common.extend({ schema: DEFAULT_SAFE_SCHEMA }, options));
}
module.exports.dump = dump;
module.exports.safeDump = safeDump;

View File

@ -1,43 +0,0 @@
// YAML error class. http://stackoverflow.com/questions/8458984
//
'use strict';
function YAMLException(reason, mark) {
// Super constructor
Error.call(this);
this.name = 'YAMLException';
this.reason = reason;
this.mark = mark;
this.message = (this.reason || '(unknown reason)') + (this.mark ? ' ' + this.mark.toString() : '');
// Include stack trace in error object
if (Error.captureStackTrace) {
// Chrome and NodeJS
Error.captureStackTrace(this, this.constructor);
} else {
// FF, IE 10+ and Safari 6+. Fallback for others
this.stack = (new Error()).stack || '';
}
}
// Inherit from Error
YAMLException.prototype = Object.create(Error.prototype);
YAMLException.prototype.constructor = YAMLException;
YAMLException.prototype.toString = function toString(compact) {
var result = this.name + ': ';
result += this.reason || '(unknown reason)';
if (!compact && this.mark) {
result += ' ' + this.mark.toString();
}
return result;
};
module.exports = YAMLException;

File diff suppressed because it is too large Load Diff

View File

@ -1,76 +0,0 @@
'use strict';
var common = require('./common');
function Mark(name, buffer, position, line, column) {
this.name = name;
this.buffer = buffer;
this.position = position;
this.line = line;
this.column = column;
}
Mark.prototype.getSnippet = function getSnippet(indent, maxLength) {
var head, start, tail, end, snippet;
if (!this.buffer) return null;
indent = indent || 4;
maxLength = maxLength || 75;
head = '';
start = this.position;
while (start > 0 && '\x00\r\n\x85\u2028\u2029'.indexOf(this.buffer.charAt(start - 1)) === -1) {
start -= 1;
if (this.position - start > (maxLength / 2 - 1)) {
head = ' ... ';
start += 5;
break;
}
}
tail = '';
end = this.position;
while (end < this.buffer.length && '\x00\r\n\x85\u2028\u2029'.indexOf(this.buffer.charAt(end)) === -1) {
end += 1;
if (end - this.position > (maxLength / 2 - 1)) {
tail = ' ... ';
end -= 5;
break;
}
}
snippet = this.buffer.slice(start, end);
return common.repeat(' ', indent) + head + snippet + tail + '\n' +
common.repeat(' ', indent + this.position - start + head.length) + '^';
};
Mark.prototype.toString = function toString(compact) {
var snippet, where = '';
if (this.name) {
where += 'in "' + this.name + '" ';
}
where += 'at line ' + (this.line + 1) + ', column ' + (this.column + 1);
if (!compact) {
snippet = this.getSnippet();
if (snippet) {
where += ':\n' + snippet;
}
}
return where;
};
module.exports = Mark;

View File

@ -1,108 +0,0 @@
'use strict';
/*eslint-disable max-len*/
var common = require('./common');
var YAMLException = require('./exception');
var Type = require('./type');
function compileList(schema, name, result) {
var exclude = [];
schema.include.forEach(function (includedSchema) {
result = compileList(includedSchema, name, result);
});
schema[name].forEach(function (currentType) {
result.forEach(function (previousType, previousIndex) {
if (previousType.tag === currentType.tag && previousType.kind === currentType.kind) {
exclude.push(previousIndex);
}
});
result.push(currentType);
});
return result.filter(function (type, index) {
return exclude.indexOf(index) === -1;
});
}
function compileMap(/* lists... */) {
var result = {
scalar: {},
sequence: {},
mapping: {},
fallback: {}
}, index, length;
function collectType(type) {
result[type.kind][type.tag] = result['fallback'][type.tag] = type;
}
for (index = 0, length = arguments.length; index < length; index += 1) {
arguments[index].forEach(collectType);
}
return result;
}
function Schema(definition) {
this.include = definition.include || [];
this.implicit = definition.implicit || [];
this.explicit = definition.explicit || [];
this.implicit.forEach(function (type) {
if (type.loadKind && type.loadKind !== 'scalar') {
throw new YAMLException('There is a non-scalar type in the implicit list of a schema. Implicit resolving of such types is not supported.');
}
});
this.compiledImplicit = compileList(this, 'implicit', []);
this.compiledExplicit = compileList(this, 'explicit', []);
this.compiledTypeMap = compileMap(this.compiledImplicit, this.compiledExplicit);
}
Schema.DEFAULT = null;
Schema.create = function createSchema() {
var schemas, types;
switch (arguments.length) {
case 1:
schemas = Schema.DEFAULT;
types = arguments[0];
break;
case 2:
schemas = arguments[0];
types = arguments[1];
break;
default:
throw new YAMLException('Wrong number of arguments for Schema.create function');
}
schemas = common.toArray(schemas);
types = common.toArray(types);
if (!schemas.every(function (schema) { return schema instanceof Schema; })) {
throw new YAMLException('Specified list of super schemas (or a single Schema object) contains a non-Schema object.');
}
if (!types.every(function (type) { return type instanceof Type; })) {
throw new YAMLException('Specified list of YAML types (or a single Type object) contains a non-Type object.');
}
return new Schema({
include: schemas,
explicit: types
});
};
module.exports = Schema;

View File

@ -1,18 +0,0 @@
// Standard YAML's Core schema.
// http://www.yaml.org/spec/1.2/spec.html#id2804923
//
// NOTE: JS-YAML does not support schema-specific tag resolution restrictions.
// So, Core schema has no distinctions from JSON schema is JS-YAML.
'use strict';
var Schema = require('../schema');
module.exports = new Schema({
include: [
require('./json')
]
});

View File

@ -1,25 +0,0 @@
// JS-YAML's default schema for `load` function.
// It is not described in the YAML specification.
//
// This schema is based on JS-YAML's default safe schema and includes
// JavaScript-specific types: !!js/undefined, !!js/regexp and !!js/function.
//
// Also this schema is used as default base schema at `Schema.create` function.
'use strict';
var Schema = require('../schema');
module.exports = Schema.DEFAULT = new Schema({
include: [
require('./default_safe')
],
explicit: [
require('../type/js/undefined'),
require('../type/js/regexp'),
require('../type/js/function')
]
});

View File

@ -1,28 +0,0 @@
// JS-YAML's default schema for `safeLoad` function.
// It is not described in the YAML specification.
//
// This schema is based on standard YAML's Core schema and includes most of
// extra types described at YAML tag repository. (http://yaml.org/type/)
'use strict';
var Schema = require('../schema');
module.exports = new Schema({
include: [
require('./core')
],
implicit: [
require('../type/timestamp'),
require('../type/merge')
],
explicit: [
require('../type/binary'),
require('../type/omap'),
require('../type/pairs'),
require('../type/set')
]
});

View File

@ -1,17 +0,0 @@
// Standard YAML's Failsafe schema.
// http://www.yaml.org/spec/1.2/spec.html#id2802346
'use strict';
var Schema = require('../schema');
module.exports = new Schema({
explicit: [
require('../type/str'),
require('../type/seq'),
require('../type/map')
]
});

View File

@ -1,25 +0,0 @@
// Standard YAML's JSON schema.
// http://www.yaml.org/spec/1.2/spec.html#id2803231
//
// NOTE: JS-YAML does not support schema-specific tag resolution restrictions.
// So, this schema is not such strict as defined in the YAML specification.
// It allows numbers in binary notaion, use `Null` and `NULL` as `null`, etc.
'use strict';
var Schema = require('../schema');
module.exports = new Schema({
include: [
require('./failsafe')
],
implicit: [
require('../type/null'),
require('../type/bool'),
require('../type/int'),
require('../type/float')
]
});

View File

@ -1,61 +0,0 @@
'use strict';
var YAMLException = require('./exception');
var TYPE_CONSTRUCTOR_OPTIONS = [
'kind',
'resolve',
'construct',
'instanceOf',
'predicate',
'represent',
'defaultStyle',
'styleAliases'
];
var YAML_NODE_KINDS = [
'scalar',
'sequence',
'mapping'
];
function compileStyleAliases(map) {
var result = {};
if (map !== null) {
Object.keys(map).forEach(function (style) {
map[style].forEach(function (alias) {
result[String(alias)] = style;
});
});
}
return result;
}
function Type(tag, options) {
options = options || {};
Object.keys(options).forEach(function (name) {
if (TYPE_CONSTRUCTOR_OPTIONS.indexOf(name) === -1) {
throw new YAMLException('Unknown option "' + name + '" is met in definition of "' + tag + '" YAML type.');
}
});
// TODO: Add tag format check.
this.tag = tag;
this.kind = options['kind'] || null;
this.resolve = options['resolve'] || function () { return true; };
this.construct = options['construct'] || function (data) { return data; };
this.instanceOf = options['instanceOf'] || null;
this.predicate = options['predicate'] || null;
this.represent = options['represent'] || null;
this.defaultStyle = options['defaultStyle'] || null;
this.styleAliases = compileStyleAliases(options['styleAliases'] || null);
if (YAML_NODE_KINDS.indexOf(this.kind) === -1) {
throw new YAMLException('Unknown kind "' + this.kind + '" is specified for "' + tag + '" YAML type.');
}
}
module.exports = Type;

View File

@ -1,138 +0,0 @@
'use strict';
/*eslint-disable no-bitwise*/
var NodeBuffer;
// try {
// // A trick for browserified version, to not include `Buffer` shim
// var _require = require;
// NodeBuffer = _require('buffer').Buffer;
// } catch (__) {}
var Type = require('../type');
// [ 64, 65, 66 ] -> [ padding, CR, LF ]
var BASE64_MAP = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=\n\r';
function resolveYamlBinary(data) {
if (data === null) return false;
var code, idx, bitlen = 0, max = data.length, map = BASE64_MAP;
// Convert one by one.
for (idx = 0; idx < max; idx++) {
code = map.indexOf(data.charAt(idx));
// Skip CR/LF
if (code > 64) continue;
// Fail on illegal characters
if (code < 0) return false;
bitlen += 6;
}
// If there are any bits left, source was corrupted
return (bitlen % 8) === 0;
}
function constructYamlBinary(data) {
var idx, tailbits,
input = data.replace(/[\r\n=]/g, ''), // remove CR/LF & padding to simplify scan
max = input.length,
map = BASE64_MAP,
bits = 0,
result = [];
// Collect by 6*4 bits (3 bytes)
for (idx = 0; idx < max; idx++) {
if ((idx % 4 === 0) && idx) {
result.push((bits >> 16) & 0xFF);
result.push((bits >> 8) & 0xFF);
result.push(bits & 0xFF);
}
bits = (bits << 6) | map.indexOf(input.charAt(idx));
}
// Dump tail
tailbits = (max % 4) * 6;
if (tailbits === 0) {
result.push((bits >> 16) & 0xFF);
result.push((bits >> 8) & 0xFF);
result.push(bits & 0xFF);
} else if (tailbits === 18) {
result.push((bits >> 10) & 0xFF);
result.push((bits >> 2) & 0xFF);
} else if (tailbits === 12) {
result.push((bits >> 4) & 0xFF);
}
// Wrap into Buffer for NodeJS and leave Array for browser
if (NodeBuffer) {
// Support node 6.+ Buffer API when available
return NodeBuffer.from ? NodeBuffer.from(result) : new NodeBuffer(result);
}
return result;
}
function representYamlBinary(object /*, style*/) {
var result = '', bits = 0, idx, tail,
max = object.length,
map = BASE64_MAP;
// Convert every three bytes to 4 ASCII characters.
for (idx = 0; idx < max; idx++) {
if ((idx % 3 === 0) && idx) {
result += map[(bits >> 18) & 0x3F];
result += map[(bits >> 12) & 0x3F];
result += map[(bits >> 6) & 0x3F];
result += map[bits & 0x3F];
}
bits = (bits << 8) + object[idx];
}
// Dump tail
tail = max % 3;
if (tail === 0) {
result += map[(bits >> 18) & 0x3F];
result += map[(bits >> 12) & 0x3F];
result += map[(bits >> 6) & 0x3F];
result += map[bits & 0x3F];
} else if (tail === 2) {
result += map[(bits >> 10) & 0x3F];
result += map[(bits >> 4) & 0x3F];
result += map[(bits << 2) & 0x3F];
result += map[64];
} else if (tail === 1) {
result += map[(bits >> 2) & 0x3F];
result += map[(bits << 4) & 0x3F];
result += map[64];
result += map[64];
}
return result;
}
function isBinary(object) {
return NodeBuffer && NodeBuffer.isBuffer(object);
}
module.exports = new Type('tag:yaml.org,2002:binary', {
kind: 'scalar',
resolve: resolveYamlBinary,
construct: constructYamlBinary,
predicate: isBinary,
represent: representYamlBinary
});

View File

@ -1,35 +0,0 @@
'use strict';
var Type = require('../type');
function resolveYamlBoolean(data) {
if (data === null) return false;
var max = data.length;
return (max === 4 && (data === 'true' || data === 'True' || data === 'TRUE')) ||
(max === 5 && (data === 'false' || data === 'False' || data === 'FALSE'));
}
function constructYamlBoolean(data) {
return data === 'true' ||
data === 'True' ||
data === 'TRUE';
}
function isBoolean(object) {
return Object.prototype.toString.call(object) === '[object Boolean]';
}
module.exports = new Type('tag:yaml.org,2002:bool', {
kind: 'scalar',
resolve: resolveYamlBoolean,
construct: constructYamlBoolean,
predicate: isBoolean,
represent: {
lowercase: function (object) { return object ? 'true' : 'false'; },
uppercase: function (object) { return object ? 'TRUE' : 'FALSE'; },
camelcase: function (object) { return object ? 'True' : 'False'; }
},
defaultStyle: 'lowercase'
});

View File

@ -1,116 +0,0 @@
'use strict';
var common = require('../common');
var Type = require('../type');
var YAML_FLOAT_PATTERN = new RegExp(
// 2.5e4, 2.5 and integers
'^(?:[-+]?(?:0|[1-9][0-9_]*)(?:\\.[0-9_]*)?(?:[eE][-+]?[0-9]+)?' +
// .2e4, .2
// special case, seems not from spec
'|\\.[0-9_]+(?:[eE][-+]?[0-9]+)?' +
// 20:59
'|[-+]?[0-9][0-9_]*(?::[0-5]?[0-9])+\\.[0-9_]*' +
// .inf
'|[-+]?\\.(?:inf|Inf|INF)' +
// .nan
'|\\.(?:nan|NaN|NAN))$');
function resolveYamlFloat(data) {
if (data === null) return false;
if (!YAML_FLOAT_PATTERN.test(data) ||
// Quick hack to not allow integers end with `_`
// Probably should update regexp & check speed
data[data.length - 1] === '_') {
return false;
}
return true;
}
function constructYamlFloat(data) {
var value, sign, base, digits;
value = data.replace(/_/g, '').toLowerCase();
sign = value[0] === '-' ? -1 : 1;
digits = [];
if ('+-'.indexOf(value[0]) >= 0) {
value = value.slice(1);
}
if (value === '.inf') {
return (sign === 1) ? Number.POSITIVE_INFINITY : Number.NEGATIVE_INFINITY;
} else if (value === '.nan') {
return NaN;
} else if (value.indexOf(':') >= 0) {
value.split(':').forEach(function (v) {
digits.unshift(parseFloat(v, 10));
});
value = 0.0;
base = 1;
digits.forEach(function (d) {
value += d * base;
base *= 60;
});
return sign * value;
}
return sign * parseFloat(value, 10);
}
var SCIENTIFIC_WITHOUT_DOT = /^[-+]?[0-9]+e/;
function representYamlFloat(object, style) {
var res;
if (isNaN(object)) {
switch (style) {
case 'lowercase': return '.nan';
case 'uppercase': return '.NAN';
case 'camelcase': return '.NaN';
}
} else if (Number.POSITIVE_INFINITY === object) {
switch (style) {
case 'lowercase': return '.inf';
case 'uppercase': return '.INF';
case 'camelcase': return '.Inf';
}
} else if (Number.NEGATIVE_INFINITY === object) {
switch (style) {
case 'lowercase': return '-.inf';
case 'uppercase': return '-.INF';
case 'camelcase': return '-.Inf';
}
} else if (common.isNegativeZero(object)) {
return '-0.0';
}
res = object.toString(10);
// JS stringifier can build scientific format without dots: 5e-100,
// while YAML requres dot: 5.e-100. Fix it with simple hack
return SCIENTIFIC_WITHOUT_DOT.test(res) ? res.replace('e', '.e') : res;
}
function isFloat(object) {
return (Object.prototype.toString.call(object) === '[object Number]') &&
(object % 1 !== 0 || common.isNegativeZero(object));
}
module.exports = new Type('tag:yaml.org,2002:float', {
kind: 'scalar',
resolve: resolveYamlFloat,
construct: constructYamlFloat,
predicate: isFloat,
represent: representYamlFloat,
defaultStyle: 'lowercase'
});

View File

@ -1,172 +0,0 @@
'use strict';
var common = require('../common');
var Type = require('../type');
function isHexCode(c) {
return ((0x30/* 0 */ <= c) && (c <= 0x39/* 9 */)) ||
((0x41/* A */ <= c) && (c <= 0x46/* F */)) ||
((0x61/* a */ <= c) && (c <= 0x66/* f */));
}
function isOctCode(c) {
return ((0x30/* 0 */ <= c) && (c <= 0x37/* 7 */));
}
function isDecCode(c) {
return ((0x30/* 0 */ <= c) && (c <= 0x39/* 9 */));
}
function resolveYamlInteger(data) {
if (data === null) return false;
var max = data.length,
index = 0,
hasDigits = false,
ch;
if (!max) return false;
ch = data[index];
// sign
if (ch === '-' || ch === '+') {
ch = data[++index];
}
if (ch === '0') {
// 0
if (index + 1 === max) return true;
ch = data[++index];
// base 2, base 8, base 16
if (ch === 'b') {
// base 2
index++;
for (; index < max; index++) {
ch = data[index];
if (ch === '_') continue;
if (ch !== '0' && ch !== '1') return false;
hasDigits = true;
}
return hasDigits && ch !== '_';
}
if (ch === 'x') {
// base 16
index++;
for (; index < max; index++) {
ch = data[index];
if (ch === '_') continue;
if (!isHexCode(data.charCodeAt(index))) return false;
hasDigits = true;
}
return hasDigits && ch !== '_';
}
// base 8
for (; index < max; index++) {
ch = data[index];
if (ch === '_') continue;
if (!isOctCode(data.charCodeAt(index))) return false;
hasDigits = true;
}
return hasDigits && ch !== '_';
}
// base 10 (except 0) or base 60
// value should not start with `_`;
if (ch === '_') return false;
for (; index < max; index++) {
ch = data[index];
if (ch === '_') continue;
if (ch === ':') break;
if (!isDecCode(data.charCodeAt(index))) {
return false;
}
hasDigits = true;
}
// Should have digits and should not end with `_`
if (!hasDigits || ch === '_') return false;
// if !base60 - done;
if (ch !== ':') return true;
// base60 almost not used, no needs to optimize
return /^(:[0-5]?[0-9])+$/.test(data.slice(index));
}
function constructYamlInteger(data) {
var value = data, sign = 1, ch, base, digits = [];
if (value.indexOf('_') !== -1) {
value = value.replace(/_/g, '');
}
ch = value[0];
if (ch === '-' || ch === '+') {
if (ch === '-') sign = -1;
value = value.slice(1);
ch = value[0];
}
if (value === '0') return 0;
if (ch === '0') {
if (value[1] === 'b') return sign * parseInt(value.slice(2), 2);
if (value[1] === 'x') return sign * parseInt(value, 16);
return sign * parseInt(value, 8);
}
if (value.indexOf(':') !== -1) {
value.split(':').forEach(function (v) {
digits.unshift(parseInt(v, 10));
});
value = 0;
base = 1;
digits.forEach(function (d) {
value += (d * base);
base *= 60;
});
return sign * value;
}
return sign * parseInt(value, 10);
}
function isInteger(object) {
return (Object.prototype.toString.call(object)) === '[object Number]' &&
(object % 1 === 0 && !common.isNegativeZero(object));
}
module.exports = new Type('tag:yaml.org,2002:int', {
kind: 'scalar',
resolve: resolveYamlInteger,
construct: constructYamlInteger,
predicate: isInteger,
represent: {
binary: function (object) { return '0b' + object.toString(2); },
octal: function (object) { return '0' + object.toString(8); },
decimal: function (object) { return object.toString(10); },
hexadecimal: function (object) { return '0x' + object.toString(16).toUpperCase(); }
},
defaultStyle: 'decimal',
styleAliases: {
binary: [ 2, 'bin' ],
octal: [ 8, 'oct' ],
decimal: [ 10, 'dec' ],
hexadecimal: [ 16, 'hex' ]
}
});

View File

@ -1,84 +0,0 @@
'use strict';
var esprima;
// Browserified version does not have esprima
//
// 1. For node.js just require module as deps
// 2. For browser try to require mudule via external AMD system.
// If not found - try to fallback to window.esprima. If not
// found too - then fail to parse.
//
// try {
// // workaround to exclude package from browserify list.
// var _require = require;
// esprima = _require('esprima');
// } catch (_) {
// /*global window */
// if (typeof window !== 'undefined') esprima = window.esprima;
// }
var Type = require('../../type');
function resolveJavascriptFunction(data) {
if (data === null) return false;
try {
var source = '(' + data + ')',
ast = esprima.parse(source, { range: true });
if (ast.type !== 'Program' ||
ast.body.length !== 1 ||
ast.body[0].type !== 'ExpressionStatement' ||
ast.body[0].expression.type !== 'FunctionExpression') {
return false;
}
return true;
} catch (err) {
return false;
}
}
function constructJavascriptFunction(data) {
/*jslint evil:true*/
var source = '(' + data + ')',
ast = esprima.parse(source, { range: true }),
params = [],
body;
if (ast.type !== 'Program' ||
ast.body.length !== 1 ||
ast.body[0].type !== 'ExpressionStatement' ||
ast.body[0].expression.type !== 'FunctionExpression') {
throw new Error('Failed to resolve function');
}
ast.body[0].expression.params.forEach(function (param) {
params.push(param.name);
});
body = ast.body[0].expression.body.range;
// Esprima's ranges include the first '{' and the last '}' characters on
// function expressions. So cut them out.
/*eslint-disable no-new-func*/
return new Function(params, source.slice(body[0] + 1, body[1] - 1));
}
function representJavascriptFunction(object /*, style*/) {
return object.toString();
}
function isFunction(object) {
return Object.prototype.toString.call(object) === '[object Function]';
}
module.exports = new Type('tag:yaml.org,2002:js/function', {
kind: 'scalar',
resolve: resolveJavascriptFunction,
construct: constructJavascriptFunction,
predicate: isFunction,
represent: representJavascriptFunction
});

View File

@ -1,60 +0,0 @@
'use strict';
var Type = require('../../type');
function resolveJavascriptRegExp(data) {
if (data === null) return false;
if (data.length === 0) return false;
var regexp = data,
tail = /\/([gim]*)$/.exec(data),
modifiers = '';
// if regexp starts with '/' it can have modifiers and must be properly closed
// `/foo/gim` - modifiers tail can be maximum 3 chars
if (regexp[0] === '/') {
if (tail) modifiers = tail[1];
if (modifiers.length > 3) return false;
// if expression starts with /, is should be properly terminated
if (regexp[regexp.length - modifiers.length - 1] !== '/') return false;
}
return true;
}
function constructJavascriptRegExp(data) {
var regexp = data,
tail = /\/([gim]*)$/.exec(data),
modifiers = '';
// `/foo/gim` - tail can be maximum 4 chars
if (regexp[0] === '/') {
if (tail) modifiers = tail[1];
regexp = regexp.slice(1, regexp.length - modifiers.length - 1);
}
return new RegExp(regexp, modifiers);
}
function representJavascriptRegExp(object /*, style*/) {
var result = '/' + object.source + '/';
if (object.global) result += 'g';
if (object.multiline) result += 'm';
if (object.ignoreCase) result += 'i';
return result;
}
function isRegExp(object) {
return Object.prototype.toString.call(object) === '[object RegExp]';
}
module.exports = new Type('tag:yaml.org,2002:js/regexp', {
kind: 'scalar',
resolve: resolveJavascriptRegExp,
construct: constructJavascriptRegExp,
predicate: isRegExp,
represent: representJavascriptRegExp
});

View File

@ -1,28 +0,0 @@
'use strict';
var Type = require('../../type');
function resolveJavascriptUndefined() {
return true;
}
function constructJavascriptUndefined() {
/*eslint-disable no-undefined*/
return undefined;
}
function representJavascriptUndefined() {
return '';
}
function isUndefined(object) {
return typeof object === 'undefined';
}
module.exports = new Type('tag:yaml.org,2002:js/undefined', {
kind: 'scalar',
resolve: resolveJavascriptUndefined,
construct: constructJavascriptUndefined,
predicate: isUndefined,
represent: representJavascriptUndefined
});

View File

@ -1,8 +0,0 @@
'use strict';
var Type = require('../type');
module.exports = new Type('tag:yaml.org,2002:map', {
kind: 'mapping',
construct: function (data) { return data !== null ? data : {}; }
});

View File

@ -1,12 +0,0 @@
'use strict';
var Type = require('../type');
function resolveYamlMerge(data) {
return data === '<<' || data === null;
}
module.exports = new Type('tag:yaml.org,2002:merge', {
kind: 'scalar',
resolve: resolveYamlMerge
});

View File

@ -1,34 +0,0 @@
'use strict';
var Type = require('../type');
function resolveYamlNull(data) {
if (data === null) return true;
var max = data.length;
return (max === 1 && data === '~') ||
(max === 4 && (data === 'null' || data === 'Null' || data === 'NULL'));
}
function constructYamlNull() {
return null;
}
function isNull(object) {
return object === null;
}
module.exports = new Type('tag:yaml.org,2002:null', {
kind: 'scalar',
resolve: resolveYamlNull,
construct: constructYamlNull,
predicate: isNull,
represent: {
canonical: function () { return '~'; },
lowercase: function () { return 'null'; },
uppercase: function () { return 'NULL'; },
camelcase: function () { return 'Null'; }
},
defaultStyle: 'lowercase'
});

View File

@ -1,44 +0,0 @@
'use strict';
var Type = require('../type');
var _hasOwnProperty = Object.prototype.hasOwnProperty;
var _toString = Object.prototype.toString;
function resolveYamlOmap(data) {
if (data === null) return true;
var objectKeys = [], index, length, pair, pairKey, pairHasKey,
object = data;
for (index = 0, length = object.length; index < length; index += 1) {
pair = object[index];
pairHasKey = false;
if (_toString.call(pair) !== '[object Object]') return false;
for (pairKey in pair) {
if (_hasOwnProperty.call(pair, pairKey)) {
if (!pairHasKey) pairHasKey = true;
else return false;
}
}
if (!pairHasKey) return false;
if (objectKeys.indexOf(pairKey) === -1) objectKeys.push(pairKey);
else return false;
}
return true;
}
function constructYamlOmap(data) {
return data !== null ? data : [];
}
module.exports = new Type('tag:yaml.org,2002:omap', {
kind: 'sequence',
resolve: resolveYamlOmap,
construct: constructYamlOmap
});

View File

@ -1,53 +0,0 @@
'use strict';
var Type = require('../type');
var _toString = Object.prototype.toString;
function resolveYamlPairs(data) {
if (data === null) return true;
var index, length, pair, keys, result,
object = data;
result = new Array(object.length);
for (index = 0, length = object.length; index < length; index += 1) {
pair = object[index];
if (_toString.call(pair) !== '[object Object]') return false;
keys = Object.keys(pair);
if (keys.length !== 1) return false;
result[index] = [ keys[0], pair[keys[0]] ];
}
return true;
}
function constructYamlPairs(data) {
if (data === null) return [];
var index, length, pair, keys, result,
object = data;
result = new Array(object.length);
for (index = 0, length = object.length; index < length; index += 1) {
pair = object[index];
keys = Object.keys(pair);
result[index] = [ keys[0], pair[keys[0]] ];
}
return result;
}
module.exports = new Type('tag:yaml.org,2002:pairs', {
kind: 'sequence',
resolve: resolveYamlPairs,
construct: constructYamlPairs
});

View File

@ -1,8 +0,0 @@
'use strict';
var Type = require('../type');
module.exports = new Type('tag:yaml.org,2002:seq', {
kind: 'sequence',
construct: function (data) { return data !== null ? data : []; }
});

View File

@ -1,29 +0,0 @@
'use strict';
var Type = require('../type');
var _hasOwnProperty = Object.prototype.hasOwnProperty;
function resolveYamlSet(data) {
if (data === null) return true;
var key, object = data;
for (key in object) {
if (_hasOwnProperty.call(object, key)) {
if (object[key] !== null) return false;
}
}
return true;
}
function constructYamlSet(data) {
return data !== null ? data : {};
}
module.exports = new Type('tag:yaml.org,2002:set', {
kind: 'mapping',
resolve: resolveYamlSet,
construct: constructYamlSet
});

View File

@ -1,8 +0,0 @@
'use strict';
var Type = require('../type');
module.exports = new Type('tag:yaml.org,2002:str', {
kind: 'scalar',
construct: function (data) { return data !== null ? data : ''; }
});

View File

@ -1,88 +0,0 @@
'use strict';
var Type = require('../type');
var YAML_DATE_REGEXP = new RegExp(
'^([0-9][0-9][0-9][0-9])' + // [1] year
'-([0-9][0-9])' + // [2] month
'-([0-9][0-9])$'); // [3] day
var YAML_TIMESTAMP_REGEXP = new RegExp(
'^([0-9][0-9][0-9][0-9])' + // [1] year
'-([0-9][0-9]?)' + // [2] month
'-([0-9][0-9]?)' + // [3] day
'(?:[Tt]|[ \\t]+)' + // ...
'([0-9][0-9]?)' + // [4] hour
':([0-9][0-9])' + // [5] minute
':([0-9][0-9])' + // [6] second
'(?:\\.([0-9]*))?' + // [7] fraction
'(?:[ \\t]*(Z|([-+])([0-9][0-9]?)' + // [8] tz [9] tz_sign [10] tz_hour
'(?::([0-9][0-9]))?))?$'); // [11] tz_minute
function resolveYamlTimestamp(data) {
if (data === null) return false;
if (YAML_DATE_REGEXP.exec(data) !== null) return true;
if (YAML_TIMESTAMP_REGEXP.exec(data) !== null) return true;
return false;
}
function constructYamlTimestamp(data) {
var match, year, month, day, hour, minute, second, fraction = 0,
delta = null, tz_hour, tz_minute, date;
match = YAML_DATE_REGEXP.exec(data);
if (match === null) match = YAML_TIMESTAMP_REGEXP.exec(data);
if (match === null) throw new Error('Date resolve error');
// match: [1] year [2] month [3] day
year = +(match[1]);
month = +(match[2]) - 1; // JS month starts with 0
day = +(match[3]);
if (!match[4]) { // no hour
return new Date(Date.UTC(year, month, day));
}
// match: [4] hour [5] minute [6] second [7] fraction
hour = +(match[4]);
minute = +(match[5]);
second = +(match[6]);
if (match[7]) {
fraction = match[7].slice(0, 3);
while (fraction.length < 3) { // milli-seconds
fraction += '0';
}
fraction = +fraction;
}
// match: [8] tz [9] tz_sign [10] tz_hour [11] tz_minute
if (match[9]) {
tz_hour = +(match[10]);
tz_minute = +(match[11] || 0);
delta = (tz_hour * 60 + tz_minute) * 60000; // delta in mili-seconds
if (match[9] === '-') delta = -delta;
}
date = new Date(Date.UTC(year, month, day, hour, minute, second, fraction));
if (delta) date.setTime(date.getTime() - delta);
return date;
}
function representYamlTimestamp(object /*, style*/) {
return object.toISOString();
}
module.exports = new Type('tag:yaml.org,2002:timestamp', {
kind: 'scalar',
resolve: resolveYamlTimestamp,
construct: constructYamlTimestamp,
instanceOf: Date,
represent: representYamlTimestamp
});

View File

@ -1,38 +0,0 @@
'use strict';
/*global Java, base, module, exports, require, __FILE__*/
var ZipFile = Java.type("java.util.zip.ZipFile");
var fs = require('core/fs');
/**
* 解压文件
* @param zipFile 压缩文件
* @param target 目标目录(不传则为zip文件同级目录)
*/
function unzip(zipFile, target) {
if (!zipFile.exists()) {
console.warn("解压文件 %s 错误 文件不存在!".format(zipFile));
return;
}
if (target === undefined) {
var fname = zipFile.name;
// noinspection JSUnresolvedVariable
target = fs.file(zipFile.parentFile.canonicalPath, fname.substring(0, fname.length() - 4));
}
console.debug("解压文件 %s 到目录 %s".format(zipFile.canonicalPath, target));
var zipObj = new ZipFile(zipFile);
var e = zipObj.entries();
while (e.hasMoreElements()) {
var entry = e.nextElement();
if (entry.isDirectory()) {
continue;
}
var destinationFilePath = fs.file(target, entry.name);
destinationFilePath.parentFile.mkdirs();
fs.copy(zipObj.getInputStream(entry), destinationFilePath, true);
}
zipObj.close();
}
exports.unzip = unzip;

View File

@ -0,0 +1,6 @@
name: ${project.artifactId}
description: ${project.description}
main: ${project.groupId}.${project.artifactId}.${project.artifactId}Nukkit
version: ${project.version}
api: "1.0.0"
author: MiaoWoo

View File

@ -1,26 +1,10 @@
name: ${project.artifactId}
description: ${project.description}
main: ${project.groupId}.${project.artifactId}.${project.artifactId}
version: ${project.version}-git-${env.GIT_COMMIT}
author: 喵♂呜
version: ${project.version}
author: MiaoWoo
website: ${ciManagement.url}
load: STARTUP
softdepend:
- PlaceholderAPI
commands:
${project.artifactId}:
description: ${project.artifactId} - ${project.description}
aliases:
- ms
- mjs
- script
- mscript
usage: §b使用/${project.artifactId} help 查看帮助!
permission: ${project.artifactId}.reload
permission-message: §c你没有 <permission> 的权限来执行此命令!
permissions:
${project.artifactId}.use:
description: ${project.artifactId} 使用!
default: true
${project.artifactId}.reload:
description: 重新载入插件!
default: op
- Vault

View File

@ -1,24 +0,0 @@
'use strict';
/**
* PAPI扩展类
*/
/*global Java, base, module, exports, require, __FILE__*/
var PlaceholderAPI;
var bukkit = require('api/server');
if (bukkit.plugin.load("PlaceholderAPI")) {
PlaceholderAPI = ext.getStatic("me.clip.placeholderapi.PlaceholderAPI");
} else {
log.w("PlaceholderAPI 未找到 变量替换功能失效!");
PlaceholderAPI = {
setPlaceholders: function () {
return arguments[1];
}
}
}
exports.$ = function () {
if (arguments.length > 1) {
return PlaceholderAPI.setPlaceholders(arguments[0], arguments[1]);
} else {
return PlaceholderAPI.setPlaceholders(null, arguments[0]);
}
};

View File

@ -1,114 +0,0 @@
#脚本名称
#xxxxx:
# 脚本表达式
# expression: | [这里写"|"则下方缩进均为一行 请看案例]
# if( x = y ) {
# 省略代码
# }
# expression: "Player.getDisplayName()"
# PS: JS表达式 支持调用Bukkit的内部方法
# 当前支持Bukkit(Server),Player,Event
# Bukkit(或Server): 调用的是服务器数据
# - getOnlinePlayer().size(): 在线玩家数量
# - broadcastMessage('xxx'): 公告xxx
# - getConsoleSender(): 获得控制台
# - dispatchCommand(Bukkit.getConsoleSender(),"xxx"): 控制台执行xxx命令
# - dispatchCommand(Player,"xxx"): 玩家执行xxx命令
# 更多的方法请查询: https://hub.spigotmc.org/javadocs/spigot/org/bukkit/Bukkit.html
#
# Player: 调用玩家对象 常用方法有:
# - getName(): 玩家名称
# - getDisplayName(): 玩家显示名称
# - hasPermission("xxx"): 判断玩家是否有xxx权限
# - sendMessage("xxx"): 向玩家发送xxx消息
# - isOp():是否为OP
# - setFlying(true 或 false): 设置飞行
# - setHealth(20): 设置玩家血量
# 更多的方法请查询: https://hub.spigotmc.org/javadocs/spigot/org/bukkit/entity/Player.html
#
# Event: 调用事件 不同事件有不同的参数 常用方法如下:
# - setCancelled(true): 用于取消事件
# 更多的方法请查询: https://hub.spigotmc.org/javadocs/spigot/org/bukkit/event/player/PlayerEvent.html
#
# Data: 数据库支持
# - get("def") 获得默认数据库配置 详见config.yml
# 例:
# var db = Data.get("def");
# == 创建表 ======================================
# var sql = 'CREATE TABLE IF NOT EXISTS `MiaoScript` ( `id` INTEGER PRIMARY KEY AUTO_INCREMENT, `name` VARCHAR(30), `script` VARCHAR(600)) ENGINE = InnoDB DEFAULT CHARSET=UTF8"';
# db.execute(sql);
#增删改 返回值为数据库改动条数
# == 插入数据 ====================================
# var sql = 'INSERT INTO `MiaoScript` (`name`, `script`) VALUES ("setOp", "Player.setOp(false)")';
# var result = db.update(sql);
# if ( result >1 ){
# Log.info("数据添加成功!");
# }
# == 更新数据 ====================================
# var sql = 'UPDATE `MiaoScript` SET `script` = "Player.setOp(true)" WHERE name = "setOp"';
# var result = db.update(sql);
# == 删除数据 ====================================
# var sql = 'DELETE FROM `MiaoScript` WHERE name = "setOp"';
# var result = db.update(sql);
# ===============================================
# [Config, PlayerConfig(玩家数据)]: 调用数据存储 若崩服数据可能丢失
# - set("key","value"): 保存一条键为key值为value的数据
# - get("key"): 获得键为key的值
# - getStringList("dirChat"): 获得键为dirChat的字符串列表
# - save(): 保存数据到硬盘
# 更多的方法请查询: https://hub.spigotmc.org/javadocs/spigot/org/bukkit/configuration/ConfigurationSection.html
#
# Log: 调用插件日志系统
# - info("xxx"): 输出信息xxx到日志
# - warning("xxx"): 输出警告xxx
# 更多的方法请查询: http://docs.oracle.com/javase/7/docs/api/java/util/logging/Logger.html
#
# type: "boolean" 或 "string" 不写 默认为string
# #下面两个参数 当type为boolean时才有效
# trueResult: '&c管理员' [脚本返回True时的返回值]
# falseResult: '&a玩家' [脚本返回False时的返回值]
#
#脚本名称
welcome:
#脚本表达式
expression: 'file: welcome.js'
#物品丢弃检测
checkDrop:
expression: |
function handle(Event){
if( Event.getItemDrop().getItemStack().getType().name().contains("DIAMOND") ){
Player.sendMessage("&6[&b警告&6] &c您可能丢弃了一件贵重物品!");
}
}
#获得玩家前缀
getPrefix:
expression: Player.isOp()
#脚本返回值
type: boolean
#脚本返回True时的返回值
trueResult: '&c管理员'
#脚本返回False时的返回值
falseResult: '&a玩家'
#获取玩家的显示名称
getDisplayName:
expression: Player.getDisplayName()
type: string
#开启玩家飞行模式
flyon:
expression: 'Player.setAllowFlight(true);Player.sendMessage("&6[&bMiaoScript&6] &a已为您开启飞行模式!")'
#关闭玩家飞行模式
flyoff:
expression: |
Player.setAllowFlight(false);
Player.sendMessage("&6[&bMiaoScript&6] &a已为您关闭飞行模式!");
#top命令
top:
expression: |
Player.teleport(Player.getWorld().getHighestBlockAt(Player.getLocation()).getLocation());
commands: [top]

View File

@ -1,14 +1,5 @@
package pw.yumc.MiaoScript;
import java.io.FileReader;
import javax.script.ScriptEngineManager;
import org.junit.Test;
import pw.yumc.YumCore.bukkit.Log;
import pw.yumc.YumCore.engine.MiaoScriptEngine;
/**
* Created with IntelliJ IDEA
*
@ -16,24 +7,6 @@ import pw.yumc.YumCore.engine.MiaoScriptEngine;
* Created on 2017/9/14 10:08.
*/
public class MiaoScriptTest {
private MiaoScriptEngine engine;
@Test
public void testBoot() {
Thread currentThread = Thread.currentThread();
ClassLoader previousClassLoader = currentThread.getContextClassLoader();
currentThread.setContextClassLoader(getClass().getClassLoader());
try {
ScriptEngineManager manager = new ScriptEngineManager();
this.engine = new MiaoScriptEngine(manager);
this.engine.put("base", new Base());
this.engine.eval(new FileReader("src/main/resources/bios.js"));
engine.invokeFunction("boot", null, engine);
} catch (Exception e) {
Log.w("脚本引擎初始化失败! %s:%s", e.getClass().getName(), e.getMessage());
e.printStackTrace();
} finally {
currentThread.setContextClassLoader(previousClassLoader);
}
}
}