129 Commits

Author SHA1 Message Date
6b34566489 feat: optimize require module & update asm version 2024-01-08 15:43:21 +08:00
074e6e8a10 feat: remove spring support & optimize require 2023-07-30 17:32:59 +08:00
14cc05e923 feat: support BungeeCord at JDK17
Signed-off-by: MiaoWoo <admin@yumc.pw>
2022-06-21 17:28:17 +08:00
ebc03b6164 feat: release 0.23.0
Signed-off-by: MiaoWoo <admin@yumc.pw>
2022-06-02 10:23:17 +08:00
9268ce9fee feat: 调整引擎初始化逻辑
Signed-off-by: MiaoWoo <admin@yumc.pw>
2022-06-01 17:52:55 +08:00
3e4453a197 feat: v0.22.0
Signed-off-by: MiaoWoo <admin@yumc.pw>
2022-05-21 15:53:03 +08:00
dc66290f97 feat: use system classloader load jar
Signed-off-by: MiaoWoo <admin@yumc.pw>
2022-05-15 02:55:57 +08:00
56152657c8 feat: add MavenDependLoader
Signed-off-by: MiaoWoo <admin@yumc.pw>
2022-05-14 18:44:24 +08:00
e2f9bbf587 feat: update to 0.20.0
Signed-off-by: MiaoWoo <admin@yumc.pw>
2022-04-19 17:20:43 +08:00
a9003025ee feat: support mjs.json js compile & add API
Signed-off-by: MiaoWoo <admin@yumc.pw>
2022-04-01 18:47:28 +08:00
91a87ab20e feat: release 0.18.0 version
1. optimize load logic
2. add root change detach
3. add common softdepends

Signed-off-by: MiaoWoo <admin@yumc.pw>
2022-02-16 14:36:22 +08:00
ce92ae9ec6 feat: optimize upgrade logic
Signed-off-by: MiaoWoo <admin@yumc.pw>
2021-11-04 11:29:37 +08:00
cfd44a6289 feat: optimize network request
Signed-off-by: MiaoWoo <admin@yumc.pw>
2021-07-10 18:29:44 +08:00
fc7fb67023 feat: 调整启动逻辑 兼容 Arclight
Signed-off-by: MiaoWoo <admin@yumc.pw>
2021-06-25 02:44:19 +00:00
7b171f1546 feat: add local version lock
Signed-off-by: MiaoWoo <admin@yumc.pw>
2021-06-22 15:05:27 +08:00
389bfd7137 feat: support java15+
Signed-off-by: MiaoWoo <admin@yumc.pw>
2021-06-22 06:03:16 +00:00
f8ba885b8c fix: require error
Signed-off-by: MiaoWoo <admin@yumc.pw>
2021-03-27 09:08:17 +08:00
48306b64c4 fix: windows load error
Signed-off-by: MiaoWoo <admin@yumc.pw>
2021-03-26 18:40:57 +08:00
1cb4c05efd feat: 异步加载 polyfill 并且同步加载 @ccms/core
Signed-off-by: MiaoWoo <admin@yumc.pw>
2021-03-26 15:54:26 +08:00
54e40b6768 fix: cache module load error
Signed-off-by: MiaoWoo <admin@yumc.pw>
2020-12-17 18:34:57 +08:00
51fc4549da feat: 优化路径寻找逻辑
Signed-off-by: MiaoWoo <admin@yumc.pw>
2020-12-17 16:17:16 +08:00
824c440f63 fix: window restart error
Signed-off-by: MiaoWoo <admin@yumc.pw>
2020-12-07 13:49:27 +08:00
7f32062dca feat: add JavaScriptTask class
Signed-off-by: MiaoWoo <admin@yumc.pw>
2020-11-20 10:30:05 +08:00
12d07bf552 feat: add package version lock logic
Signed-off-by: MiaoWoo <admin@yumc.pw>
2020-11-11 17:27:43 +08:00
0506c9e3e6 feat: update version to 0.9.4
Signed-off-by: MiaoWoo <admin@yumc.pw>
2020-09-24 14:18:39 +08:00
40760713ff fix: engineDisable override
Signed-off-by: MiaoWoo <admin@yumc.pw>
2020-09-22 16:48:44 +08:00
7e36b6109d refactor: rename EngineStartTime
Signed-off-by: MiaoWoo <admin@yumc.pw>
2020-09-21 17:09:23 +08:00
7f85295eb1 release: update to 0.9.3
Signed-off-by: MiaoWoo <admin@yumc.pw>
2020-09-21 16:06:37 +08:00
427aa262f0 feat: update to 0.9.1
Signed-off-by: MiaoWoo <admin@yumc.pw>
2020-08-27 17:30:59 +08:00
e71bd2a0cb feat: add createEngine method
Signed-off-by: MiaoWoo <admin@yumc.pw>
2020-07-08 11:11:18 +08:00
9bb67410ac feat: support custom NODE env
Signed-off-by: MiaoWoo <admin@yumc.pw>
2020-06-23 13:39:00 +08:00
eba0e18285 feat: add web filter proxy
Signed-off-by: MiaoWoo <admin@yumc.pw>
2020-06-15 09:30:57 +08:00
219eb6b919 feat: add web proxy support
Signed-off-by: MiaoWoo <admin@yumc.pw>
2020-05-30 10:21:17 +08:00
17d07d6cef feat: add spring full support
Signed-off-by: MiaoWoo <admin@yumc.pw>
2020-05-28 17:05:47 +08:00
f2b8f6ff26 feat: support more core module
Signed-off-by: MiaoWoo <admin@yumc.pw>
2020-05-14 19:12:03 +08:00
9a15a0ab1f feat: 新增defineProperty全局变量
Signed-off-by: MiaoWoo <admin@yumc.pw>
2020-05-11 10:20:28 +08:00
d0de120867 feat: update to 0.6.0 rename scope to ccms
Signed-off-by: MiaoWoo <admin@yumc.pw>
2020-05-03 00:31:59 +08:00
351183ab3c feat: use classpath load core js
Signed-off-by: MiaoWoo <admin@yumc.pw>
2020-04-22 09:23:21 +08:00
87c78f7c6f feat: default require nodejs module
Signed-off-by: MiaoWoo <admin@yumc.pw>
2020-04-07 22:20:53 +08:00
28db77333e feat: clean engine after disable
Signed-off-by: MiaoWoo <admin@yumc.pw>
2020-04-03 15:07:05 +08:00
ac83acd4c8 feat: add internal node moudle punycode
Signed-off-by: MiaoWoo <admin@yumc.pw>
2020-04-01 14:41:07 +08:00
876c9b77f7 feat: add nodejs internal module support
Signed-off-by: MiaoWoo <admin@yumc.pw>
2020-03-31 16:55:18 +08:00
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
111 changed files with 2161 additions and 8612 deletions

5
.gitignore vendored
View File

@ -38,6 +38,7 @@
# Eclipse # Eclipse
.project .project
.classpath .classpath
.factorypath
.settings .settings
# Visual Studio Code # Visual Studio Code
@ -51,3 +52,7 @@ vendor/
# Minecraft Data # Minecraft Data
/world /world
**/node_modules/
# Gradle
.gradle

0
CHANGELOG.md Normal file
View File

View File

@ -1,87 +1,11 @@
# MiaoScript # MiaoScript
> 排版什么的 不存在的 这辈子都不会有排版的 除非什么时候论坛支持 `MarkDown` 了 > 一个兼容 Spigot Sponge Nukkit BungeeCord 的 脚本插件运行时
### 简介 ## 简介
> 这个坑是我自己刨的 但是发现坑太大 需要更多的人一起填 ## 安装
#### 起源 - 下载后放入对应服务器目录
- Bukkit Nukkit BungeeCord 以及其分支 => `plugins`
- 诞生于 `2016年08月25日` 这是 Git 上的第一个提交 具体啥时候我也忘了 - Sponge => `mods`
- 起初 `MiaoScript` 只是用于服务器其他插件的变量执行 并且依赖于PAPI(不知道是啥的自己百度)
- 比如 [`MiaoMenu`](http://w.yumc.pw/zc/MiaoMenu.html) 的部分复杂脚本
- 比如 [`MiaoChat`](http://mcbbs.tvt.im/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 @@
™™
▄™
▒™
░™
▓™
™▄
▄▄
▒▄
░▄
▓▄
™▒
▄▒
▒▒
░▒
▓▒
™░
▄░
▒░
░░
▓░
™▓
▄▓
▒▓
░▓
▓▓
™▄
™▒
™░
™▓
▄™
▄▄
▄▒
▄░
▄▓
▒™
▒▄
▒░
▒▓
░™
░▄
░▒
░▓
▓™
▓▄
▓▒
▓░
™™™
▄™▄
▒™▒
░™░
▓™▓
™▄™
▄▄▄
▒▄▒
░▄░
▓▄▓
™▒™
▄▒▄
▒▒▒
░▒░
▓▒▓
™░™
▄░▄
▒░▒
░░░
▓░▓
™▓™
▄▓▄
▒▓▒
░▓░
▓▓▓
™ ™
™▄™
™▒™
™░™
™▓™
▄™▄
▄ ▄
▄▒▄
▄░▄
▄▓▄
▒™▒
▒▄▒
▒ ▒
▒░▒
▒▓▒
░™░
░▄░
░▒░
░ ░
░▓░
▓™▓
▓▄▓
▓▒▓
▓░▓
▓ ▓

238
pom.xml
View File

@ -1,15 +1,14 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<groupId>pw.yumc</groupId> <groupId>pw.yumc</groupId>
<artifactId>MiaoScript</artifactId> <artifactId>MiaoScript</artifactId>
<version>1.2.1</version> <version>0.28.0</version>
<developers> <developers>
<developer> <developer>
<id>502647092</id> <id>502647092</id>
<name>喵♂呜</name> <name>MiaoWoo</name>
<email>admin@yumc.pw</email> <email>admin@yumc.pw</email>
<url>http://www.yumc.pw</url> <url>https://www.yumc.pw</url>
</developer> </developer>
</developers> </developers>
<build> <build>
@ -17,78 +16,141 @@
<resources> <resources>
<resource> <resource>
<directory>src/main/resources</directory> <directory>src/main/resources</directory>
<excludes>
<exclude>plugins/**.js</exclude>
</excludes>
<filtering>true</filtering> <filtering>true</filtering>
</resource> </resource>
</resources> </resources>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>2.4.3</version>
<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>
</plugins>
</build> </build>
<ciManagement> <ciManagement>
<system>Jenkins</system> <system>Jenkins</system>
<url>http://ci.yumc.pw/job/${project.artifactId}/</url> <url>https://ci.yumc.pw/job/Minecraft/job/${project.artifactId}/</url>
</ciManagement> </ciManagement>
<properties> <properties>
<env.GIT_COMMIT>DEV</env.GIT_COMMIT> <env.GIT_COMMIT>DEV</env.GIT_COMMIT>
<update.changes> <update.changes>
§618-01-09 §afeat: 优化加载流程 完善事件注册 §623-10-25 §afeat: 升级 asm 版本;
§618-01-02 §afeat: 新增http网络访问模块 §623-07-30 §afeat: 优化 require 性能;
§617-12-28 §afeat: 完善Sponge事件注册 新增player封装类       §cfix: 修复 require 加载特殊文件异常;
§623-07-22 §afeat: 网络加载 jtar 优化包大小;
      §aremove: 移除 Spring 相关支持;
      §adeps: 更新 Nashorn 和 GraalvmJS 引擎版本
</update.changes> </update.changes>
<update.changelog> <update.changelog>
§622-11-22 §afeat: 兼容 1.7.10-1.19.2 版本;
      §afeat: 新增 MiaoScriptAPI 相关方法;
§622-06-21 §afeat: 兼容 1.7.10-1.19 版本;
      §afeat: 兼容 JDK17 BungeeCord;
§622-05-25 §afeat: 兼容 1.7.10-1.18.2 版本;
§622-05-21 §afeat: 优化 框架加载逻辑;
§622-05-20 §afeat: 调整 require 主包逻辑;
§622-04-09 §afeat: 优化 引擎初始化逻辑;
      §afeat: 优化 require 网络加载;
      §afeat: 新增 JS 类型定义文件;
      §afeat: 新增 自定义类型加载逻辑;
§622-02-16 §afeat: 新增 MiaoScriptAPI;
      §afeat: 新增 ScriptEvent;
      §afeat: 新增 .mjs .json 类型加载;
§622-02-16 §afeat: 优化 初始化逻辑 加快引擎加载速度;
      §afeat: 新增 root 目录变更检测 变更后重新生成缓存;
      §afeat: 添加常用库的软依赖;
§622-01-01 §afeat: 兼容JDK17 更新Nashorn;
§621-11-04 §afeat: 优化系统模块升级逻辑;
§621-07-10 §afeat: 优化网络相关功能;
§621-06-25 §afeat: 调整启动逻辑 兼容 Arclight;
§621-06-22 §afeat: 新增本地版本锁定功能;
§621-06-19 §afeat: 兼容JDK16 反射异常;
§621-05-15 §afeat: 兼容JDK15+ 自动下载Nashorn类库;
§621-03-25 §afeat: 异步加载 polyfill 并且同步加载 @ccms/core;
§621-03-25 §cfix: 修改 ployfill 为 polyfill;
§620-12-22 §cfix: 增加 require 效验;
§620-12-17 §afeat: JavaScriptTask 新增任务ID 并通过 ID 比较优先级;
§620-12-16 §afeat: 新增 require 缓存 优化路径寻找速度;
§620-12-15 §cfix: 修复 非主线程重载时发生的异常;
§620-12-07 §cfix: 修复 Windows 环境 重载异常;
§620-11-19 §afeat: 新增 JavaScriptTask 类;
§620-11-11 §afeat: 新增 package 版本锁定逻辑;
§620-09-21 §afeat: 完善 upgrade 逻辑;
§620-08-27 §afeat: 新增 ProtocolLib 依赖;
§620-07-28 §afeat: 新增框架升级功能;
§620-06-23 §afeat: 支持自定义参数;
§620-06-22 §afeat: 优化 require 加载逻辑;
§620-05-28 §afeat: 新增 Spring 的支持;
§620-05-02 §afeat: 调整 scope 为 @ccms;
§620-04-10 §afeat: 默认从 classpath 加载内建的 js 模块;
§620-04-07 §afeat: 默认初始化 内建 nodejs 模块;
§620-04-03 §afeat: 优化 框架卸载逻辑;
§620-03-31 §afeat: require 新增 内建 nodejs 模块;
§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 实例获取;
§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-30 §afeat: 新增Sponge的兼容;
§617-11-03 §afeat: 新增抽奖插件; §617-11-03 §afeat: 新增抽奖插件;
§617-10-16 §cfix: 修复关闭MiaoScript时task异常; §617-10-16 §cfix: 修复关闭MiaoScript时task异常;
@ -97,47 +159,57 @@
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source> <maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target> <maven.compiler.target>1.8</maven.compiler.target>
<repo.url>https://repo.yumc.pw</repo.url>
</properties> </properties>
<repositories> <repositories>
<repository> <repository>
<id>yumc-repo</id> <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>
<url>https://repo.spongepowered.org/maven/</url>
</repository> </repository>
</repositories> </repositories>
<pluginRepositories> <pluginRepositories>
<pluginRepository> <pluginRepository>
<id>yumc-repo</id> <id>yumc-repo</id>
<url>http://repo.yumc.pw/content/groups/public/</url> <url>${repo.url}/repository/maven-public/</url>
</pluginRepository> </pluginRepository>
</pluginRepositories> </pluginRepositories>
<distributionManagement> <distributionManagement>
<repository> <repository>
<id>jtb</id> <id>jtb</id>
<name>YUMC</name> <name>YUMC</name>
<url>http://repo.yumc.pw/content/repositories/yumcenter/</url> <url>${repo.url}/repository/yumcenter/</url>
</repository> </repository>
</distributionManagement> </distributionManagement>
<dependencies> <dependencies>
<dependency> <dependency>
<groupId>pw.yumc</groupId> <groupId>org.projectlombok</groupId>
<artifactId>YumCore</artifactId> <artifactId>lombok</artifactId>
<type>jar</type> <version>1.18.24</version>
<version>[1.8,)</version> <scope>compile</scope>
<exclusions> </dependency>
<exclusion> <dependency>
<groupId>org.bukkit</groupId> <groupId>org.spigotmc</groupId>
<artifactId>craftbukkit</artifactId> <artifactId>spigot-api</artifactId>
</exclusion> <version>1.18.2-R0.1-SNAPSHOT</version>
</exclusions> <scope>compile</scope>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.spongepowered</groupId> <groupId>org.spongepowered</groupId>
<artifactId>spongeapi</artifactId> <artifactId>spongeapi</artifactId>
<version>6.0.0</version> <version>7.3.0</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>net.md-5</groupId>
<artifactId>bungeecord-api</artifactId>
<version>1.16-R0.4</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>cn.nukkit</groupId>
<artifactId>nukkit</artifactId>
<version>1.0-SNAPSHOT</version>
<scope>compile</scope>
</dependency> </dependency>
</dependencies> </dependencies>
</project> </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

@ -1,53 +0,0 @@
package pw.yumc.MiaoScript;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.stream.Collectors;
import lombok.val;
import pw.yumc.YumCore.annotation.NotProguard;
import pw.yumc.YumCore.mc.MinecraftTools;
/**
* Created with IntelliJ IDEA
*
* @author 喵♂呜
* Created on 2017/10/9 12:40.
*/
@NotProguard
public class Base {
public Class getClass(String name) throws ClassNotFoundException {
return Class.forName(name);
}
public String read(String path) throws IOException {
return new String(Files.readAllBytes(new File(path).toPath()), "UTF-8");
}
public void save(String path, String content) throws IOException {
File file = new File(path);
file.getParentFile().mkdirs();
Files.write(file.toPath(), content.getBytes("UTF-8"));
}
public void delete(String path) throws IOException {
delete(new File(path).toPath());
}
public void delete(Path path) throws IOException {
val file = path.toFile();
if (!file.exists()) { return; }
if (file.isDirectory()) {
for (Path f : Files.list(file.toPath()).collect(Collectors.toList())) {
delete(f);
}
}
Files.delete(path);
}
public Class getTools() {
return MinecraftTools.class;
}
}

View File

@ -1,86 +0,0 @@
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;
/**
* 喵式脚本
*
* @author 喵♂呜
* @since 2016年8月29日 上午7:50:39
*/
public class MiaoScript extends JavaPlugin implements Executor {
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.enableEngine();
Thread.currentThread().setContextClassLoader(origin);
}
@Override
public void onDisable() {
engine.disableEngine();
}
}

View File

@ -0,0 +1,40 @@
package pw.yumc.MiaoScript;
import lombok.SneakyThrows;
import org.bukkit.plugin.java.JavaPlugin;
import pw.yumc.MiaoScript.api.MiaoScriptAPI;
import pw.yumc.MiaoScript.api.ScriptEngine;
/**
* 喵式脚本
*
* @author 喵♂呜
* @since 2016年8月29日 上午7:50:39
*/
public class MiaoScriptBukkit extends JavaPlugin {
private ScriptEngine engine;
@SneakyThrows
public MiaoScriptBukkit() {
ClassLoader origin = Thread.currentThread().getContextClassLoader();
Thread.currentThread().setContextClassLoader(getClassLoader());
engine = MiaoScriptAPI.createEngine(getDataFolder().getCanonicalPath(), getLogger(), this);
Thread.currentThread().setContextClassLoader(origin);
engine.loadEngine();
}
@Override
public void onLoad() {
}
@Override
public void onEnable() {
engine.enableEngine();
}
@Override
public void onDisable() {
engine.disableEngine();
engine = null;
}
}

View File

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

View File

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

View File

@ -1,26 +1,19 @@
package pw.yumc.MiaoScript; 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.state.GameStartedServerEvent;
import org.spongepowered.api.plugin.Plugin;
import org.spongepowered.api.text.Text;
import com.google.inject.Inject; import com.google.inject.Inject;
import lombok.SneakyThrows; import lombok.SneakyThrows;
import org.slf4j.Logger;
import org.spongepowered.api.config.ConfigDir;
import org.spongepowered.api.event.Listener;
import org.spongepowered.api.event.game.GameReloadEvent;
import org.spongepowered.api.event.game.state.GamePreInitializationEvent;
import org.spongepowered.api.event.game.state.GameStartedServerEvent;
import org.spongepowered.api.event.game.state.GameStoppingServerEvent;
import org.spongepowered.api.plugin.Plugin;
import pw.yumc.MiaoScript.api.MiaoScriptAPI;
import pw.yumc.MiaoScript.api.ScriptEngine;
import java.io.File;
/** /**
* Created with IntelliJ IDEA * Created with IntelliJ IDEA
@ -28,7 +21,7 @@ import lombok.SneakyThrows;
* @author 喵♂呜 * @author 喵♂呜
* Created on 2017/10/25 20:35. * Created on 2017/10/25 20:35.
*/ */
@Plugin(id = "miaoscript", name = "MiaoScript", version = "1.0", authors = "喵♂呜") @Plugin(id = "miaoscript", name = "MiaoScript", description = "MiaoScript runtime in Sponge", version = MiaoScriptAPI.VERSION, authors = "MiaoWoo")
public class MiaoScriptSponge { public class MiaoScriptSponge {
private ScriptEngine engine; private ScriptEngine engine;
@Inject @Inject
@ -39,77 +32,31 @@ public class MiaoScriptSponge {
private File pluginConfigDir; private File pluginConfigDir;
@Listener @Listener
public void onInit(GameInitializationEvent event) { @SneakyThrows
public void onPreInitialization(GamePreInitializationEvent event) {
} engine = MiaoScriptAPI.createEngine(pluginConfigDir.getCanonicalPath(), logger, this);
engine.loadEngine();
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 @Listener
@SneakyThrows @SneakyThrows
public void onStart(GameStartedServerEvent event) { public void onStarted(GameStartedServerEvent event) {
Sponge.getServer().getConsole(); engine.enableEngine();
Sponge.getCommandManager().register(this, main(), "ms", "mscript", "MiaoScript"); }
engine = new ScriptEngine(pluginConfigDir.getCanonicalPath(), logger);
@Listener
@SneakyThrows
public void onStop(GameStoppingServerEvent event) {
engine.disableEngine();
engine = null;
}
@Listener
@SneakyThrows
public void reload(GameReloadEvent event) {
engine.disableEngine();
System.gc();
engine.loadEngine();
engine.enableEngine(); engine.enableEngine();
} }
} }

View File

@ -1,52 +0,0 @@
package pw.yumc.MiaoScript;
import java.io.InputStreamReader;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import javax.script.ScriptEngineManager;
import lombok.SneakyThrows;
import pw.yumc.YumCore.engine.MiaoScriptEngine;
/**
* Created with IntelliJ IDEA
*
* @author 喵♂呜
* Created on 2017/10/25 21:01.
*/
public class ScriptEngine {
private String root;
private Object logger;
private MiaoScriptEngine engine;
public ScriptEngine(String root, Object logger) {
this.root = root;
this.logger = logger;
}
@SneakyThrows
public void enableEngine() {
ScriptEngineManager manager = new ScriptEngineManager();
this.engine = new MiaoScriptEngine(manager, "nashorn");
this.engine.put("base", new Base());
Path bios = Paths.get(root, "bios.js");
// 如果存在自定义bios就加载自定义的
if (Files.exists(bios)) {
this.engine.eval("load('" + bios.toFile().getCanonicalPath() + "')");
} else {
this.engine.eval(new InputStreamReader(Thread.currentThread().getContextClassLoader().getResourceAsStream("bios.js")));
}
engine.invokeFunction("boot", root, logger);
}
@SneakyThrows
public void disableEngine() {
engine.invokeFunction("engineDisable");
}
public MiaoScriptEngine getEngine() {
return engine;
}
}

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

@ -0,0 +1,128 @@
package pw.yumc.MiaoScript.api;
import lombok.Getter;
import java.io.File;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
/**
* Created with IntelliJ IDEA
*
* @author 喵♂呜
* Created on 2017/10/9 12:40.
*/
@Getter
public class Base {
private final Object instance;
Base(Object instance) {
this.instance = instance;
}
public String getVersion() {
return MiaoScriptAPI.VERSION;
}
public Class<?> getClass(String name) throws ClassNotFoundException {
try {
return Class.forName(name);
} catch (Throwable ignored) {
}
try {
return Class.forName(name, true, instance.getClass().getClassLoader());
} catch (Throwable ex) {
return Class.forName(name, true, instance.getClass().getClassLoader().getParent());
}
}
public Class<?> getProxyClass() {
return ProxyClass.class;
}
public Class<?> getJavaScriptTaskClass() {
return JavaScriptTask.class;
}
public File[] loadMavenDepend(String groupId, String artifactId, String version) {
return MiaoScriptAPI.loadMavenDepend(groupId, artifactId, version);
}
public File[] loadMavenDepend(String groupId, String artifactId, String version, ClassLoader classLoader) {
return MiaoScriptAPI.loadMavenDepend(groupId, artifactId, version, classLoader);
}
public File[] parentLoadMavenDepend(String groupId, String artifactId, String version) {
return MiaoScriptAPI.parentLoadMavenDepend(groupId, artifactId, version);
}
public String read(String path) throws IOException {
return read(Paths.get(path));
}
public String read(File file) throws IOException {
return read(file.toPath());
}
public String read(Path path) throws IOException {
return new String(Files.readAllBytes(path), StandardCharsets.UTF_8);
}
public Path save(String path, String content) throws IOException {
return save(Paths.get(path), content);
}
public Path save(File file, String content) throws IOException {
return save(file.toPath(), content);
}
public Path save(Path path, String content) throws IOException {
path.getParent().toFile().mkdirs();
return Files.write(path, content.getBytes(StandardCharsets.UTF_8));
}
public boolean move(String source, String target) {
return move(new File(source), new File(target));
}
public boolean move(File source, File target) {
return source.renameTo(target);
}
public boolean delete(String path) throws IOException {
return delete(new File(path));
}
public boolean delete(Path path) throws IOException {
return delete(path.toFile());
}
public boolean delete(File file) throws IOException {
if (!file.exists()) {
return false;
}
if (file.isFile()) {
return file.delete();
}
File[] files = file.listFiles();
if (files != null) {
for (File f : files) {
if (f.isFile()) {
if (!f.delete()) {
f.deleteOnExit();
}
} else {
this.delete(f);
}
}
}
boolean result = file.delete();
if (!result) {
file.deleteOnExit();
}
return result;
}
}

View File

@ -0,0 +1,41 @@
package pw.yumc.MiaoScript.api;
import lombok.Getter;
import java.util.concurrent.Delayed;
import java.util.concurrent.TimeUnit;
@Getter
public class JavaScriptTask implements Delayed {
private final long id;
private final Object task;
private final long startTime;
private final long executeTime;
public JavaScriptTask(Object task, long ms) {
this(0, task, ms);
}
public JavaScriptTask(long id, Object task, long ms) {
this.id = id;
this.task = task;
this.startTime = System.currentTimeMillis();
this.executeTime = ms;
}
@Override
public long getDelay(TimeUnit unit) {
return unit.convert((this.startTime + this.executeTime) - System.currentTimeMillis(), TimeUnit.MILLISECONDS);
}
@Override
public int compareTo(Delayed delayed) {
JavaScriptTask task = (JavaScriptTask) delayed;
int delay = (int) ((this.startTime + this.executeTime) - (task.getStartTime() + task.getExecuteTime()));
if (delay != 0) {
return delay;
} else {
return (int) (this.id - task.getId());
}
}
}

View File

@ -0,0 +1,62 @@
package pw.yumc.MiaoScript.api;
import lombok.Getter;
import pw.yumc.MiaoScript.api.loader.MavenDependLoader;
import pw.yumc.MiaoScript.api.plugin.PluginManager;
import pw.yumc.MiaoScript.engine.MiaoScriptEngine;
import java.io.File;
import java.nio.file.Paths;
public class MiaoScriptAPI {
public static final String VERSION = "0.28.0";
@Getter
private static String root;
private static String libPath;
private static ScriptEngine scriptEngine;
@Getter
private static PluginManager pluginManager;
public static ScriptEngine createEngine(String root, Object logger, Object instance) {
MiaoScriptAPI.scriptEngine = new ScriptEngine(root, logger, instance);
return MiaoScriptAPI.scriptEngine;
}
static void setRoot(String root) {
MiaoScriptAPI.root = root;
MiaoScriptAPI.libPath = Paths.get(root, "libs").toString();
}
public static MiaoScriptEngine getEngine() {
return MiaoScriptAPI.scriptEngine.getEngine();
}
static void setEngine(ScriptEngine scriptEngine) {
MiaoScriptAPI.scriptEngine = scriptEngine;
}
public static void setPluginManager(Object pluginManager) {
MiaoScriptAPI.pluginManager = getEngine().getInterface(pluginManager, PluginManager.class);
}
public static File[] loadMavenDepend(String groupId, String artifactId, String version) {
if (root == null || scriptEngine == null) {
throw new IllegalStateException("root can't be null before loadMavenDepend.");
}
return MavenDependLoader.load(MiaoScriptAPI.libPath, groupId, artifactId, version);
}
public static File[] loadMavenDepend(String groupId, String artifactId, String version, ClassLoader classLoader) {
if (root == null || scriptEngine == null) {
throw new IllegalStateException("root can't be null before loadMavenDepend.");
}
return MavenDependLoader.load(MiaoScriptAPI.libPath, groupId, artifactId, version, classLoader);
}
public static File[] parentLoadMavenDepend(String groupId, String artifactId, String version) {
if (root == null || scriptEngine == null) {
throw new IllegalStateException("root can't be null before loadMavenDepend.");
}
return MavenDependLoader.parentLoad(MiaoScriptAPI.libPath, groupId, artifactId, version);
}
}

View File

@ -0,0 +1,51 @@
package pw.yumc.MiaoScript.api;
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

@ -0,0 +1,76 @@
package pw.yumc.MiaoScript.api;
import lombok.Getter;
import lombok.SneakyThrows;
import pw.yumc.MiaoScript.engine.MiaoScriptEngine;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
/**
* Created with IntelliJ IDEA
*
* @author 喵♂呜 Created on 2017/10/25 21:01.
*/
public class ScriptEngine {
private final ClassLoader loader;
private final Object logger;
private final String root;
private final Base base;
@Getter
private MiaoScriptEngine engine;
private Object future;
ScriptEngine(String root, Object logger, Object instance) {
this.loader = Thread.currentThread().getContextClassLoader();
this.root = root;
this.logger = logger;
this.base = new Base(instance);
MiaoScriptAPI.setRoot(root);
MiaoScriptAPI.setEngine(this);
}
public void createEngine() {
synchronized (logger) {
if (this.engine == null) {
this.engine = new MiaoScriptEngine(root);
this.engine.put("base", this.base);
this.engine.put("ScriptEngineContextHolder", this);
}
}
}
@SneakyThrows
public void loadEngine() {
ClassLoader originLoader = Thread.currentThread().getContextClassLoader();
Thread.currentThread().setContextClassLoader(this.loader);
createEngine();
Path bios = Paths.get(root, "bios.js");
// 如果存在自定义bios就加载自定义的
if (Files.exists(bios)) {
this.engine.eval("load('" + bios.toFile().getCanonicalPath() + "')");
} else {
this.engine.eval("load('classpath:bios.js')");
}
future = engine.invokeFunction("boot", root, logger);
Thread.currentThread().setContextClassLoader(originLoader);
}
@SneakyThrows
public void enableEngine() {
if (this.engine != null) {
engine.invokeFunction("enable", future);
}
}
@SneakyThrows
public void disableEngine() {
synchronized (logger) {
if (this.engine != null) {
this.engine.invokeFunction("disable");
this.engine = null;
}
}
}
}

View File

@ -0,0 +1,39 @@
package pw.yumc.MiaoScript.api.bukkit;
import lombok.Getter;
import org.bukkit.event.Cancellable;
import org.bukkit.event.Event;
import org.bukkit.event.HandlerList;
import javax.script.Bindings;
@Getter
public class EngineEvent extends Event implements Cancellable {
private final String event;
private final Bindings data;
private boolean cancelled = false;
public EngineEvent(String event, Bindings data) {
this.event = event;
this.data = data;
}
@Override
public boolean isCancelled() {
return this.cancelled;
}
@Override
public void setCancelled(boolean b) {
this.cancelled = b;
}
@Getter
private static final HandlerList handlerList = new HandlerList();
@Override
public HandlerList getHandlers() {
return handlerList;
}
}

View File

@ -0,0 +1,41 @@
package pw.yumc.MiaoScript.api.bukkit;
import lombok.Getter;
import org.bukkit.event.Cancellable;
import org.bukkit.event.Event;
import org.bukkit.event.HandlerList;
import javax.script.Bindings;
@Getter
public class ScriptEvent extends Event implements Cancellable {
private final Bindings plugin;
private final String event;
private final Bindings data;
private boolean cancelled = false;
public ScriptEvent(Bindings plugin, String event, Bindings data) {
this.plugin = plugin;
this.event = event;
this.data = data;
}
@Override
public boolean isCancelled() {
return this.cancelled;
}
@Override
public void setCancelled(boolean b) {
this.cancelled = b;
}
@Getter
private static final HandlerList handlerList = new HandlerList();
@Override
public HandlerList getHandlers() {
return handlerList;
}
}

View File

@ -0,0 +1,67 @@
package pw.yumc.MiaoScript.api.loader;
import lombok.SneakyThrows;
import java.io.File;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.net.URL;
public class JarLoader {
private static sun.misc.Unsafe unsafe;
private static long offset;
private static Object parentUcp;
private static Object ucp;
private static MethodHandle addURLMethodHandle;
static {
initReflect();
}
@SneakyThrows
public static File load(File file) {
addURLMethodHandle.invoke(ucp, file.toURI().toURL());
return file;
}
@SneakyThrows
public static File parentLoad(File file) {
if (parentUcp == null)
throw new IllegalStateException("parentUcp is null.");
addURLMethodHandle.invoke(parentUcp, file.toURI().toURL());
return file;
}
@SneakyThrows
public static File load(File file, ClassLoader loader) {
addURLMethodHandle.invoke(unsafe.getObject(loader, offset), file.toURI().toURL());
return file;
}
private static void initReflect() {
try {
ClassLoader loader = JarLoader.class.getClassLoader();
Field theUnsafe = sun.misc.Unsafe.class.getDeclaredField("theUnsafe");
theUnsafe.setAccessible(true);
unsafe = (sun.misc.Unsafe) theUnsafe.get(null);
Field field = MethodHandles.Lookup.class.getDeclaredField("IMPL_LOOKUP");
MethodHandles.Lookup lookup = (MethodHandles.Lookup) unsafe.getObject(unsafe.staticFieldBase(field), unsafe.staticFieldOffset(field));
Field ucpField;
try {
ucpField = loader.getClass().getDeclaredField("ucp");
} catch (NoSuchFieldException e) {
ucpField = loader.getClass().getSuperclass().getDeclaredField("ucp");
}
offset = unsafe.objectFieldOffset(ucpField);
ucp = unsafe.getObject(loader, offset);
Method method = ucp.getClass().getDeclaredMethod("addURL", URL.class);
addURLMethodHandle = lookup.unreflect(method);
if (loader.getParent() != null)
parentUcp = unsafe.getObject(loader.getParent(), offset);
} catch (Throwable e) {
throw new RuntimeException(e);
}
}
}

View File

@ -0,0 +1,98 @@
package pw.yumc.MiaoScript.api.loader;
import lombok.SneakyThrows;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.net.URL;
import java.net.URLConnection;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.security.MessageDigest;
public class MavenDependLoader {
public static final String MavenRepo = "https://maven.aliyun.com/repository/public";
public static File[] load(String libPath, String groupId, String artifactId, String version) {
return new File[]{
downloadAndCheckSha1(libPath, groupId, artifactId, version, "pom"),
JarLoader.load(downloadAndCheckSha1(libPath, groupId, artifactId, version, "jar"))
};
}
public static File[] parentLoad(String libPath, String groupId, String artifactId, String version) {
return new File[]{
downloadAndCheckSha1(libPath, groupId, artifactId, version, "pom"),
JarLoader.parentLoad(downloadAndCheckSha1(libPath, groupId, artifactId, version, "jar"))
};
}
public static File[] load(String libPath, String groupId, String artifactId, String version, ClassLoader loader) {
return new File[]{
downloadAndCheckSha1(libPath, groupId, artifactId, version, "pom"),
JarLoader.load(downloadAndCheckSha1(libPath, groupId, artifactId, version, "jar"), loader)
};
}
@SneakyThrows
public static File downloadAndCheckSha1(String libPath, String groupId, String artifactId, String version, String ext) {
File sha1 = getMavenFile(libPath, groupId, artifactId, version, ext + ".sha1");
if (!sha1.exists()) {
downloadFile(sha1, groupId, artifactId, version, ext + ".sha1");
}
File file = getMavenFile(libPath, groupId, artifactId, version, ext);
if (!file.exists()) {
downloadFile(file, groupId, artifactId, version, ext);
}
if (!new String(Files.readAllBytes(sha1.toPath())).equals(getSha1(file))) {
sha1.delete();
file.delete();
throw new IllegalStateException("file " + file.getName() + " sha1 not match.");
}
return file;
}
public static File getMavenFile(String libPath, String groupId, String artifactId, String version, String ext) {
return Paths.get(libPath, groupId.replace(".", File.separator), artifactId, version, String.format("%s-%s.%s", artifactId, version, ext)).toFile();
}
@SneakyThrows
public static void downloadFile(File target, String groupId, String artifactId, String version, String ext) {
target.getParentFile().mkdirs();
URLConnection connection = new URL(MavenRepo +
String.format("/%1$s/%2$s/%3$s/%2$s-%3$s.%4$s",
groupId.replace(".", "/"),
artifactId,
version,
ext)
).openConnection();
connection.setConnectTimeout(5000);
connection.setReadTimeout(120000);
connection.setUseCaches(true);
try (InputStream inputStream = connection.getInputStream()) {
Files.copy(inputStream, target.toPath(), StandardCopyOption.REPLACE_EXISTING);
}
}
@SneakyThrows
private static String getSha1(File file) {
MessageDigest digest = MessageDigest.getInstance("SHA-1");
try (FileInputStream in = new FileInputStream(file)) {
MappedByteBuffer byteBuffer = in.getChannel().map(FileChannel.MapMode.READ_ONLY, 0, file.length());
digest.update(byteBuffer);
return getHash(digest.digest());
}
}
private static String getHash(byte[] bytes) {
StringBuilder result = new StringBuilder();
for (byte b : bytes) {
result.append(String.format("%02x", b));
}
return result.toString();
}
}

View File

@ -0,0 +1,22 @@
package pw.yumc.MiaoScript.api.plugin;
import javax.script.Bindings;
import java.util.Map;
public interface PluginManager {
Map<String, Bindings> getPlugins();
Bindings getPlugin(String name);
boolean has(String name);
Bindings get(String name);
boolean enable(String name);
boolean disable(String name);
boolean install(String name);
boolean uninstall(String name);
}

View File

@ -0,0 +1,268 @@
package pw.yumc.MiaoScript.engine;
import lombok.Getter;
import lombok.SneakyThrows;
import pw.yumc.MiaoScript.api.loader.JarLoader;
import pw.yumc.MiaoScript.api.loader.MavenDependLoader;
import javax.script.*;
import java.io.File;
import java.io.Reader;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
/**
* 喵式脚本引擎
*
* @author 喵♂呜
* @since 2016年8月29日 上午7:51:43
*/
public class MiaoScriptEngine implements ScriptEngine, Invocable {
private final String libsRoot;
@Getter
private ScriptEngine engine;
@SneakyThrows
public MiaoScriptEngine(String engineRoot) {
File libRootFile = new File(engineRoot, "libs");
libRootFile.mkdirs();
this.libsRoot = libRootFile.getCanonicalPath();
if (new File(engineRoot, "debug").exists()) {
System.setProperty("nashorn.debug", "true");
}
MavenDependLoader.load(this.libsRoot, "org.kamranzafar", "jtar", "2.3");
this.loadScriptEngine(engineRoot);
if (this.engine == null)
throw new UnsupportedOperationException("当前环境不支持 Nashorn 或 GraalJS 脚本引擎.");
}
private void loadScriptEngine(String engineRoot) {
if (new File(engineRoot, "graal").exists()) {
this.engine = this.loadNetworkGraalJS();
return;
}
if (getJavaVersion() > 15) {
this.loadGraalJS();
} else {
this.loadNashorn();
}
}
private void loadGraalJS() {
try {
this.engine = this.parentLoadNetworkNashorn();
} catch (Throwable ex) {
this.engine = this.loadNetworkNashorn();
}
if (this.engine == null) {
this.engine = this.loadNetworkGraalJS();
}
}
private void loadNashorn() {
try {
this.createEngineByName();
} catch (final Throwable ex) {
ex.printStackTrace();
}
try {
String extDirs = System.getProperty("java.ext.dirs");
if (this.engine == null && extDirs != null) {
this.engine = this.loadLocalNashorn(extDirs);
}
} catch (final Throwable ex) {
ex.printStackTrace();
}
try {
if (this.engine == null) {
this.engine = this.loadNetworkNashorn();
}
} catch (final Throwable ex) {
ex.printStackTrace();
}
if (this.engine == null)
throw new UnsupportedOperationException("当前环境不支持 Nashorn 脚本引擎.");
}
private int getJavaVersion() {
String version = System.getProperty("java.version");
if (version.startsWith("1.")) {
version = version.substring(2, 3);
} else {
int dot = version.indexOf(".");
if (dot != -1) {
version = version.substring(0, dot);
}
}
return Integer.parseInt(version);
}
private ScriptEngine loadLocalNashorn(String extDirs) {
String[] dirs = extDirs.split(File.pathSeparator);
for (String dir : dirs) {
File nashorn = new File(dir, "nashorn.jar");
if (nashorn.exists()) {
JarLoader.load(nashorn);
return this.createEngineByName();
}
}
return null;
}
private String nashornVersion = "15.4";
private String asmVersion = "9.6";
private ScriptEngine loadNetworkNashorn() {
MavenDependLoader.load(this.libsRoot, "org.openjdk.nashorn", "nashorn-core", this.nashornVersion);
MavenDependLoader.load(this.libsRoot, "org.ow2.asm", "asm", this.asmVersion);
MavenDependLoader.load(this.libsRoot, "org.ow2.asm", "asm-commons", this.asmVersion);
MavenDependLoader.load(this.libsRoot, "org.ow2.asm", "asm-tree", this.asmVersion);
MavenDependLoader.load(this.libsRoot, "org.ow2.asm", "asm-util", this.asmVersion);
return createEngineByFactoryClassName("org.openjdk.nashorn.api.scripting.NashornScriptEngineFactory", false);
}
private ScriptEngine parentLoadNetworkNashorn() {
MavenDependLoader.parentLoad(this.libsRoot, "org.openjdk.nashorn", "nashorn-core", this.nashornVersion);
MavenDependLoader.parentLoad(this.libsRoot, "org.ow2.asm", "asm", this.asmVersion);
MavenDependLoader.parentLoad(this.libsRoot, "org.ow2.asm", "asm-commons", this.asmVersion);
MavenDependLoader.parentLoad(this.libsRoot, "org.ow2.asm", "asm-tree", this.asmVersion);
MavenDependLoader.parentLoad(this.libsRoot, "org.ow2.asm", "asm-util", this.asmVersion);
return createEngineByFactoryClassName("org.openjdk.nashorn.api.scripting.NashornScriptEngineFactory", false);
}
private String graalVersion = "23.0.2";
private String icu4jVersion = "72.1";
@SneakyThrows
private ScriptEngine loadNetworkGraalJS() {
MavenDependLoader.load(this.libsRoot, "org.graalvm.js", "js", this.graalVersion);
MavenDependLoader.load(this.libsRoot, "com.ibm.icu", "icu4j", this.icu4jVersion);
MavenDependLoader.load(this.libsRoot, "org.graalvm.js", "js-scriptengine", this.graalVersion);
MavenDependLoader.load(this.libsRoot, "org.graalvm.regex", "regex", this.graalVersion);
MavenDependLoader.load(this.libsRoot, "org.graalvm.sdk", "graal-sdk", this.graalVersion);
MavenDependLoader.load(this.libsRoot, "org.graalvm.truffle", "truffle-api", this.graalVersion);
System.setProperty("polyglot.engine.AllowExperimentalOptions", "true");
System.setProperty("polyglot.engine.WarnInterpreterOnly", "false");
System.setProperty("polyglot.js.nashorn-compat", "true");
System.setProperty("polyglot.js.scripting", "true");
System.setProperty("polyglot.js.ecmascript-version", "5");
Class<?> NashornScriptEngineFactory = Class.forName("com.oracle.truffle.js.scriptengine.GraalJSEngineFactory");
Method getScriptEngine = NashornScriptEngineFactory.getMethod("getScriptEngine");
Object factory = NashornScriptEngineFactory.newInstance();
ScriptEngine engine = (ScriptEngine) getScriptEngine.invoke(factory);
Bindings bind = engine.getBindings(ScriptContext.ENGINE_SCOPE);
bind.put("polyglot.js.allowAllAccess", true);
return engine;
}
@SneakyThrows
private ScriptEngine createEngineByName() {
return createEngineByFactoryClassName("jdk.nashorn.api.scripting.NashornScriptEngineFactory", true);
}
@SneakyThrows
private ScriptEngine createEngineByFactoryClassName(String factoryClassName, boolean jdk) {
Class<?> NashornScriptEngineFactory = Class.forName(factoryClassName);
Method getScriptEngine = NashornScriptEngineFactory.getMethod("getScriptEngine", String[].class);
Object factory = NashornScriptEngineFactory.newInstance();
List<String> engineArgs = new ArrayList<>();
engineArgs.add("--language=es5");
engineArgs.add("--optimistic-types=false");
if (getJavaVersion() >= 11 && jdk) {
engineArgs.add("--no-deprecation-warning");
}
return (ScriptEngine) getScriptEngine.invoke(factory, (Object) engineArgs.toArray(new String[] {}));
}
@Override
public Bindings createBindings() {
return engine.createBindings();
}
@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> cls) {
return ((Invocable) engine).getInterface(cls);
}
@Override
public <T> T getInterface(final Object thiz, final Class<T> cls) {
return ((Invocable) engine).getInterface(thiz, cls);
}
@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

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

View File

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

View File

@ -1,158 +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 = '';
var self = this;
/**
* 扫描包 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).toLowerCase();
console.debug("Mapping Event [%s] => %s".format(clz.canonicalName, simpleName));
this.mapEvent[simpleName] = clz;
count++;
}
} catch (ex) {
//ignore already loaded class
}
}
}
}
}
return count;
}
this.class2Name = function class2Name(clazz) {
return clazz.simpleName;
}
this.name2Class = function name2Class(name, event) {
var eventCls = this.mapEvent[event.toLowerCase()] || 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) {
if (!jsp || !jsp.description || !jsp.description.name) throw new TypeError('插件名称为空 请检查传入参数!');
var name = jsp.description.name;
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, this.class2Name(eventCls), 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 eventCache = EventHandler.listenerMap[jsp.description.name];
if (eventCache) {
eventCache.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 = requireInternal('item');

View File

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

View File

@ -1,290 +0,0 @@
'use strict';
/**
* MiaoScript脚本插件加载类
*/
/*global Java, 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) {
files.filter(function (file) {
return file.name.endsWith(".zip");
}).forEach(function (file) {
// console.log(file);
// console.log(fs.file(file,"!package.json"))
// zip.unzip(fs.file(plugins_dir, file));
// var dir = new File(plugins_dir, file.name.split(".")[0]);
// TODO 添加文件夹类型的插件兼容
});
}
/**
* JS类型插件预加载
*/
function loadJsPlugins(files) {
files.filter(function (file) {
return file.name.endsWith(".js")
}).forEach(function (file) {
loadPlugin(file)
})
}
function loadPlugin(file) {
try {
var plugin = readPlugin(file);
initPlugin(plugin);
plugins[plugin.description.name] = plugin;
return plugin
} catch (ex) {
console.console('§6插件 §b%s §6初始化时发生错误 §4%s'.format(file.name, ex.message));
console.ex(ex);
}
}
function readPlugin(file) {
var update = fs.file(fs.file(file.parentFile, 'update'), file.name);
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)));
plugin.__FILE__ = file;
return plugin;
}
function initPlugin(plugin) {
var desc = plugin.description;
if (!desc || !desc.name) {
throw new Error("文件 %s 不存在 description 描述信息 无法加载插件!".format(plugin.__FILE__));
} else {
internalInitPlugin(plugin);
afterLoadHook(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 += '\nvar console = new Console(); module.exports.console = console;';
// 插件注入 self 对象
result += '\nvar 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 internalInitPlugin(plugin) {
// 初始化 __DATA__
plugin.__DATA__ = plugin.dataFolder = fs.file(plugin.__FILE__.parentFile, plugin.description.name);
// 初始化 getDataFolder()
plugin.getDataFolder = function getDataFolder() {
return plugin.__DATA__;
}
// 初始化 getFile()
plugin.getFile = plugin.file = function getFile(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(fs.read(file), { json: true });
}
}
/**
* 重载配置文件
* @constructor
* @constructor (file|string)
*/
plugin.reloadConfig = function () {
plugin.config = plugin.getConfig(plugin.configFile);
}
/**
* 保存配置文件
* @constructor
* @constructor (file, content)
*/
plugin.saveConfig = function () {
// 判断插件目录是否存在 并且不为文件 否则删除重建
if (!plugin.configFile.parentFile.isDirectory()) {
fs.del(plugin.configFile.parentFile);
}
plugin.configFile.parentFile.mkdirs();
switch (arguments.length) {
case 0:
fs.save(plugin.configFile, yaml.safeDump(plugin.config));
break;
case 2:
fs.save(fs.file(plugin.__DATA__, 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 checkAndGet(args) {
if (args.length === 0) {
return plugins;
}
var name = args[0];
// 如果是插件 则直接返回
if (name && name.description) {
return [name];
}
var plugin = exports.plugins[name];
if (!plugin) {
throw new Error("插件 " + name + " 不存在!");
}
return [plugin];
}
function checkAndRun(args, name, ext) {
var pls = checkAndGet(args);
for (var i in pls) {
var jsp = pls[i];
var exec = jsp[name];
try {
// 绑定方法的this到插件自身
if (typeof exec === "function") exec.call(jsp);
if (typeof ext === "function") ext.call(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() {
checkAndGet(arguments).forEach(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,
loadPlugin: loadPlugin
}

View File

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

View File

@ -1,2 +0,0 @@
/*global Java, base, module, exports, require*/
module.exports = requireInternal('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,74 +1,97 @@
'use strict'; 'use strict'
var log;
var boot;
var disable;
var global = this; var global = this;
/** /**
* 初始化框架引擎 * Init MiaoScriptEngine Runtime
*/ */
/*global base ScriptEngineContextHolder*/
(function () { (function () {
var loader; var Files = Java.type('java.nio.file.Files')
boot = function (root, logger) { var Paths = Java.type('java.nio.file.Paths')
log = logger; var System = Java.type('java.lang.System')
// 开发环境下初始化 var Thread = Java.type('java.lang.Thread')
root = root || "src/main/resources"; var FutureTask = Java.type('java.util.concurrent.FutureTask')
if (__FILE__ !== "<eval>") {
logger.info('载入自定义 BIOS 文件 ' + __FILE__);
global.debug = true;
}
if (java.nio.file.Files.exists(java.nio.file.Paths.get(root, "debug"))) {
logger.info('已开启调试模式!');
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();
}
};
var pluginYml; global.boot = function (root, logger) {
global.scope = System.getenv("MS_NODE_CORE_SCOPE") || "@ccms"
global.logger = logger
// Development Env Detect
global.root = root || "src/main/resources"
readEnvironment()
if (!global.debug) { checkUpgrade() }
return bootEngineThread(checkClassLoader())
}
function bootEngineThread(loader) {
logger.info("ScriptEngine: " + ScriptEngineContextHolder.getEngine().getEngine().class.name)
var future = new FutureTask(function () {
Thread.currentThread().contextClassLoader = loader
load(System.getenv("MS_NODE_CORE_POLYFILL") || 'classpath:core/polyfill.js')(root, logger)
var core = require(System.getenv("MS_NODE_CORE_MODULE") || (global.scope + '/core'))
return core.default || core
})
// Async Loading MiaoScript Engine
new Thread(future, "MiaoScript thread").start()
return future
}
global.enable = function (future) {
// await polyfill loading
if (!future.isDone()) { logger.info("MiaoScript booting...") }
// faster load core
var core = future.get()
logger.info("MiaoScript starting...")
global.engineDisableImpl = core.enable()
}
global.disable = function () {
(global.engineDisableImpl || function () {
logger.info('Error: abnormal Initialization MiaoScript Engine. Skip disable step...')
})()
}
function readEnvironment() {
if (__FILE__.indexOf('!') === -1) {
logger.info('loading custom BIOS file ' + __FILE__)
global.debug = true
}
if (Files.exists(Paths.get(root, "debug"))) {
logger.info('running in debug mode...')
global.debug = true
}
if (Files.exists(Paths.get(root, "level"))) {
global.ScriptEngineLoggerLevel = base.read(Paths.get(root, "level"))
logger.info('found level set ScriptEngineLoggerLevel to ' + global.ScriptEngineLoggerLevel + '.')
}
if (Files.exists(Paths.get(root, "channel"))) {
global.ScriptEngineChannel = base.read(Paths.get(root, "channel"))
logger.info('found channel set ScriptEngineChannel to ' + global.ScriptEngineChannel + '.')
}
}
function checkUpgrade() {
if (Files.exists(Paths.get(root, "upgrade"))) {
logger.info('found upgrade file starting upgrade...')
base.move(Paths.get(root, "node_modules"), Paths.get(root, "old_node_modules"))
base.delete(Paths.get(root, "upgrade"))
}
new Thread(function () {
try {
base.delete(Paths.get(root, "old_node_modules"))
} catch (ex) {
}
}, "MiaoScript node_modules clean thread").start()
}
function checkClassLoader() { function checkClassLoader() {
var classLoader = java.lang.Thread.currentThread().contextClassLoader; // Check Class Loader, Sometimes Server will can't found plugin.yml file
pluginYml = classLoader.getResource("plugin.yml"); var classLoader = Thread.currentThread().contextClassLoader
if (pluginYml === null) { if (classLoader.getResource("bios.js") === null) {
log.info("==================== ERROR ===================="); throw Error("Error class loader: " + classLoader.class.name + " Please contact the author MiaoWoo!")
log.info("异常的类加载器: " + classLoader.class.name);
log.info("==================== ERROR ====================");
throw Error('MiaoScript核心类库初始化失败 异常的类加载器!');
} }
return classLoader; logger.info("Class loader compatible: " + classLoader.class.name)
} if (classLoader.parent) {
logger.info("Parent class loader: " + classLoader.parent.class.name)
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('!')));
if (!java.nio.file.Files.exists(java.nio.file.Paths.get(jarPath))) {
jarPath = "/" + jarPath;
} }
var jar = new java.util.jar.JarFile(jarPath); return classLoader
var r = new RegExp(regex);// "[core|modules]/.*"
jar.stream().forEach(function (entry) {
try {
if (!entry.isDirectory()) {
if (r.test(entry.name)) {
var path = java.nio.file.Paths.get(root, entry.name);
var parentFile = path.toFile().parentFile;
if (!parentFile.exists()) { parentFile.mkdirs(); }
if (!java.nio.file.Files.exists(path) || replace) {
java.nio.file.Files.copy(loader.getResourceAsStream(entry.name), path, java.nio.file.StandardCopyOption['REPLACE_EXISTING']);
}
}
}
} catch (ex) {
ex.printStackTrace();
}
})
} }
})(); })()

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,56 @@
/** /// <reference path="./index.d.ts" />
* 控制台输出类 // @ts-check
*/ (
/*global base*/ /**
(function (global) { * @param {{
var Arrays = Java.type('java.util.Arrays'); * info: (arg0: string) => void;
var Level = Java.type('java.util.logging.Level'); * warn: (arg0: string) => void;
global.ConsoleDefault = function ConsoleDefault(name) { * debug: (arg0: string) => void;
Object.defineProperty(this, 'name', { * error: (arg0: string) => void;
get: function () { * warning: (arg0: string) => void;
return this._name; * }} logger
}.bind(this), */
set: function (name) { function (logger) {
this._name = name ? '[' + name + '] ' : ''; function log() {
this.prefix = name ? '§6[§cMS§6][§b' + name + '§6]§r ' : '§6[§bMiaoScript§6]§r '; logger.info(Array.prototype.join.call(arguments, ' '))
}.bind(this) }
}); function warn() {
this.name = name; logger.warn(Array.prototype.join.call(arguments, ' '))
this.log = this.info = function () { }
log.info(this.name + Array.prototype.join.call(arguments, ' ')); function debug() {
}; logger.debug(Array.prototype.join.call(arguments, ' '))
this.warn = function () { }
log.warning(this.name + Array.prototype.join.call(arguments, ' ')); function error() {
}; logger.error(Array.prototype.join.call(arguments, ' '))
this.error = function () { }
log.log(Level.SEVERE, this.name + Array.prototype.join.call(arguments, ' ')); function warning() {
}; logger.warning(Array.prototype.join.call(arguments, ' '))
this.debug = function () { }
log.info(this.name + '[DEBUG] ' + Array.prototype.join.call(arguments, ' ')); /**
}; * @param {string} prefix
this.debug = global.debug ? this.debug : global.noop; */
this.sender = this.info; function _proxy(prefix) {
this.console = this.info; return function () {
this.object = function (obj) { log('[' + prefix + ']', Array.prototype.join.call(arguments, ' '))
for (var i in obj) {
this.log(i, '=>', obj[i])
} }
} }
this.ex = function (message, ex) { var logProxy = {
if (!ex) { log: log,
this.console('§4' + message); info: log,
ex = message; ex: log,
} else { trace: global.ScriptEngineLoggerLevel === "trace" ? _proxy('TRACE') : global.noop,
this.console('§4' + message + ' ' + ex); debug: global.debug ? logger.debug ? debug : _proxy('DEBUG') : global.noop,
} warn: _proxy('WARN'),
var track = ex.getStackTrace(); error: _proxy('ERROR')
if (track.class) { }
track = Arrays.asList(track) if (logger.warn) {
} logProxy.warn = warn
track.forEach(function (stack) { }
if (stack.className.startsWith('<')) { if (logger.warning) {
this.console(' §e位于§c', stack.fileName, '=>§c', stack.methodName, '§4行', stack.lineNumber); logProxy.warn = warning
} else {// %s.%s(§4%s:%s§c) }
this.console(' §e位于§c', stack.className + '.' + stack.methodName + '(§4' + stack.fileName + ':' + stack.lineNumber + '§c)'); if (logger.error) {
} logProxy.error = error
}.bind(this)); }
}; return logProxy
} })
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,158 +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");
var _toString = function (obj) {
return Object.prototype.toString.call(obj);
}
/**
* 用文件分割符合并路径
*/
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:
var f = arguments[0]
if (f instanceof File) {
return f;
}
if (typeof f === "string") {
return new File(f);
}
if (f instanceof Path) {
return f.toFile();
}
case 2:
return new File(exports.file(arguments[0]), arguments[1]);
}
};
/**
* 创建目录
* @param file
*/
function mkdirs(path) {
// noinspection JSUnresolvedVariable
fs.file(path).parentFile.mkdirs();
};
/**
* 创建文件
* @param file
*/
function create(path) {
var file = fs.file(path)
if (!file.exists()) {
mkdirs(file);
file.createNewFile();
}
};
/**
* 获得文件规范路径
* @param file
* @returns {*}
*/
function path(file) {
// noinspection JSUnresolvedVariable
return fs.file(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 path 文件路径
*/
function read(path) {
var file = fs.file(path);
if (!file.exists()) {
console.warn('读取文件', file, '错误 文件不存在!');
return;
}
// noinspection JSPrimitiveTypeWrapperUsage
return new java.lang.String(Files.readAllBytes(file.toPath()), "UTF-8");
};
/**
* 保存内容文件
* @param path 路径
* @param content 内容
* @param override 是否覆盖
*/
function save(path, content, override) {
var file = fs.file(path);
file.getParentFile().mkdirs();
Files.write(file.toPath(), new java.lang.String(content).getBytes("UTF-8"));
};
/**
* 列出目录文件
* @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(fs.file(src).toPath(), fs.file(des).toPath(),
override ? StandardCopyOption['REPLACE_EXISTING'] : StandardCopyOption['ATOMIC_MOVE'])
};
function del(file) {
file = fs.file(file);
if (!file.exists()) { return; }
if (file.isDirectory()) {
Files.list(file.toPath()).collect(Collectors.toList()).forEach(function (f) { del(f); })
}
Files.delete(file.toPath());
}
function exists(file) {
return fs.file(file).exists()
}
var fs = {};
fs.path = fs.canonical = fs.realpath = path
fs.write = fs.save = save
fs.readdir = fs.list = list
fs.rename = fs.move = move
fs.delete = fs.del = del
Object.assign(fs, {
concat: concat,
create: create,
mkdirs: mkdirs,
file: file,
copy: copy,
read: read
})
exports = module.exports = fs

25
src/main/resources/core/index.d.ts vendored Normal file
View File

@ -0,0 +1,25 @@
declare const global: any
declare const root: string
declare const base: Core
declare function engineLoad(str: string | { script: string, name: string }): any
interface Core {
version: string
getClass(name: String): any
getProxyClass(): any
getJavaScriptTaskClass(): any
getInstance(): any
read(path: string): string
save(path: string, content: string): void
delete(path: string): void
}
namespace Java {
function type<T = any>(clazz: string): T
function from<T = any>(javaObj: T[]): T[]
function to<T = any>(array: T[], type?: T): T[]
function extend(...parentTypes: any[]): any
function synchronized(func: () => void, lock: any): Function
function isJavaObject(obj: any): boolean
function asJSONCompatible<T = any>(obj: T): T
//@ts-ignore
// function super(type: any);
}

View File

@ -1,107 +0,0 @@
'use strict';
/*global base*/
(function (global) {
// noinspection JSUnusedLocalSymbols
global.init = function init(root) {
global.root = root;
global.noop = function () {
};
loadCore();
loadPatch();
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.engineLoad = load;
global.load = function __denyGlobalLoad__() {
throw new Error('系统内部不许允许使用 load 如需执行脚本 请使用 engineLoad !');
}
// 初始化加载器
global.require = engineLoad(root + '/core/require.js')(root);
global.requireInternal = function requireInternal(name) {
return require(root + '/internal/' + DetectServerType + '/' + name + '.js', arguments[1]);
}
}
/**
* 加载补丁
*/
function loadPatch() {
java.nio.file.Files.list(new java.io.File(root, 'core/patch').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 setTimeout(func, time, _async) {
return _async ? task.laterAsync(func, time) : task.later(func, time);
};
global.clearTimeout = function clearTimeout(task) {
task.cancel();
};
global.setInterval = function setInterval(func, time, _async) {
return _async ? task.timerAsync(func, time) : task.timer(func, time);
};
global.clearInterval = function clearInterval(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.engineDisable = function disable() {
if (global.manager && global.manager.$) {
global.manager.disable();
}
}
})(global);

View File

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

View File

@ -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,71 +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;
}
});
}
if (!Object.values) {
Object.defineProperty(Object, "values", {
enumerable: false,
configurable: true,
writable: true,
value: function(target) {
"use strict";
var vals = [];
for (var key in target) {
var desc = Object.getOwnPropertyDescriptor(target, key);
if (desc !== undefined && desc.enumerable) vals.push(target[key]);
}
return vals;
}
});
}
// JSON快捷方法
if(!Object.toJson){
Object.defineProperty(Object.prototype, "toJson", {
enumerable: false,
configurable: true,
writable: true,
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

@ -0,0 +1,32 @@
/// <reference path="./index.d.ts" />
(
/**
* @param {string} root
* @param {any} logger
*/
function (root, logger) {
var System = Java.type('java.lang.System')
var Thread = Java.type('java.lang.Thread')
// Init Global Value
global.root = root
global.logger = logger
global.ScriptEngineStartTime = new Date().getTime()
global.engineLoad = load
global.noop = function () { }
global.load = load = function __PreventGlobalLoadFunction__() { throw new Error('Internal engine system not allow use `load` function!') }
global.setGlobal = function (key, value, config) {
if (config) {
config.value = value
Object.defineProperty(global, key, config)
} else {
global[key] = value
}
}
// Init console and require
global.console = engineLoad(System.getenv("MS_NODE_CORE_CONSOLE") || 'classpath:core/console.js')(logger)
console.log("Loading Engine at Thread", Thread.currentThread().name)
global.require = engineLoad(System.getenv("MS_NODE_CORE_REQUIRE") || 'classpath:core/require.js')(root)
return require(global.scope + '/polyfill')
}
)

View File

@ -9,7 +9,7 @@
* 2. 如果模块以 `./` `../` 开头 * 2. 如果模块以 `./` `../` 开头
* a. 尝试使用 resolveAsFile(dir/xx) 加载文件 * a. 尝试使用 resolveAsFile(dir/xx) 加载文件
* b. 尝试使用 resolveAsDirectory(dir/xx) 加载目录 * b. 尝试使用 resolveAsDirectory(dir/xx) 加载目录
* 3. 尝试去 root root/core root/modules => xx 加载模块 * 3. 尝试去 root root/node_modules => xx 加载模块
* a. 尝试使用 resolveAsFile(xx/xx) 加载文件 * a. 尝试使用 resolveAsFile(xx/xx) 加载文件
* b. 尝试使用 resolveAsDirectory(xx/xx) 加载目录 * b. 尝试使用 resolveAsDirectory(xx/xx) 加载目录
* 4. 抛出 not found 异常 * 4. 抛出 not found 异常
@ -23,247 +23,749 @@
* 2. 如果 xx/index.js 存在 则使用 resolveAsFile(xx/index.js) 加载 * 2. 如果 xx/index.js 存在 则使用 resolveAsFile(xx/index.js) 加载
* 3. 如果 xx/index.json 存在 则使用 `xx/index.json` 解析为对象加载 并停止执行 * 3. 如果 xx/index.json 存在 则使用 `xx/index.json` 解析为对象加载 并停止执行
* 暂不支持 4. 如果 xx/index.msm 是一个文件 则使用MScript解析器解析 并停止执行 * 暂不支持 4. 如果 xx/index.msm 是一个文件 则使用MScript解析器解析 并停止执行
* 注: MiaoScript 暂不支持多层 modules 加载 暂时不需要(估计以后也不会需要)
*/ */
/*global Java, base*/ /// <reference path="./index.d.ts" />
(function (parent) { // @ts-check
'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 + 'api', parent + separatorChar + 'modules'];
try{
base.delete(cacheDir);
} catch (ex) {
console.ex(ex);
}
/** /**
* 判断是否为一个文件 * @param {string} root
* @param file
* @returns {*}
* @private
*/ */
function _isFile(file) { function (root) {
return file.isFile && file.isFile(); 'use strict'
} var System = Java.type('java.lang.System')
/** var File = Java.type('java.io.File')
* 获得文件规范路径 var Paths = Java.type('java.nio.file.Paths')
* @param file var Files = Java.type('java.nio.file.Files')
* @returns {*} var StandardCopyOption = Java.type('java.nio.file.StandardCopyOption')
* @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')
* @param file var BufferedInputStream = Java.type('java.io.BufferedInputStream')
* @returns {string}
* @private
*/
function _cacheFile(file) {
return _canonical(file).replace(parent, cacheDir);
}
/** var URL = Java.type('java.net.URL')
* 解析模块名称为文件 var ByteArrayOutputStream = Java.type("java.io.ByteArrayOutputStream")
* 按照下列顺序查找 var ByteArray = Java.type("byte[]")
* 当前目录 ./ var Thread = Java.type('java.lang.Thread')
* 父目录 ../ var Callable = Java.type('java.util.concurrent.Callable')
* 核心目录 /core var Executors = Java.type('java.util.concurrent.Executors')
* 模块目录 /modules var TimeUnit = Java.type('java.util.concurrent.TimeUnit')
* @param name 模块名称 var separatorChar = File.separatorChar
* @param parent 父目录
*/ var MS_NODE_PATH = System.getenv("MS_NODE_PATH") || root + separatorChar + 'node_modules'
function resolve(name, parent) { var MS_NODE_REGISTRY = System.getenv("MS_NODE_REGISTRY") || 'https://registry.npmmirror.com'
name = _canonical(name) || name; var MS_FALLBACK_NODE_REGISTRY = System.getenv("MS_FALLBACK_NODE_REGISTRY") || 'https://repo.yumc.pw/repository/npm'
// 解析本地目录 var MS_SCRIPT_PACKAGE_CENTER = System.getenv("MS_SCRIPT_PACKAGE_CENTER") || 'https://mscript.yumc.pw/api/plugin/download'
if (name.startsWith('./') || name.startsWith('../')) { var MS_NETWORK_CONNECT_TIMEOUT = System.getenv("MS_NETWORK_CONNECT_TIMEOUT") || 5000
return resolveAsFile(parent, name) || resolveAsDirectory(parent, name) || undefined; var MS_NETWORK_READ_TIMEOUT = System.getenv("MS_NETWORK_TIMEOUT") || 45000
} else { var MS_NETWORK_DOWNLOAD_TIMEOUT = System.getenv("MS_NETWORK_DOWNLOAD_TIMEOUT") || 60000
// 查找可能存在的路径 var MS_NETWORK_USE_CACHES = System.getenv("MS_NETWORK_USE_CACHES") || true
for (var i in paths) {
var path = paths[i]; var CoreModules = [
var result = resolveAsFile(path, name) || resolveAsDirectory(path, name); "assert", "async_hooks", "Buffer", "child_process", "cluster", "crypto",
if (result) { "dgram", "dns", "domain", "events", "fs", "http", "http2", "https",
return result; "inspector", "net", "os", "path", "perf_hooks", "process", "punycode",
"querystring", "readline", "repl", "stream", "string_decoder",
"timer", "tls", "trace_events", "tty", "url", "util",
"v8", "vm", "wasi", "worker_threads", "zlib"
]
var VersionLockModules = {}
/**
* @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
}
// noinspection JSValidateJSDoc
/**
* 判断是否为一个文件
* @param {any} file
* @returns {*}
*/
function _isFile(file) {
return file && file.isFile && file.isFile()
}
/**
* 获得文件规范路径
* @param {any} file
* @returns {*}
*/
function _canonical(file) {
return file.canonicalPath
}
function __error(message, name) {
var error = new Error(message)
if (name) { error.name = name }
console.error(message)
return error
}
/**
* 解析模块名称为文件
* 按照下列顺序查找
* 当前目录 ./
* 父目录 ../
* 递归模块目录 ../node_modules 到root
* 寻找 ${NODE_PATH}
* @param {string} name 模块名称
* @param {string} parent 父目录
* @param {any} optional 附加参数
*/
function resolve(name, parent, optional) {
name = _canonical(name) || name
// 解析本地目录
if (optional.local) {
return resolveAsFile(name, parent) || resolveAsDirectory(name, parent) || undefined
} else {
// 解析 root 模块目录
var rootModule = resolveAsFile(name, MS_NODE_PATH) || resolveAsDirectory(name, MS_NODE_PATH)
if (rootModule) { return rootModule }
// 解析Node目录
var dir = [parent, 'node_modules'].join(separatorChar)
return resolveAsFile(name, dir) || resolveAsDirectory(name, dir) ||
(parent && parent.toString().startsWith(root) ?
resolve(name, new File(parent).getParent(), optional) : undefined)
}
}
/**
* 解析文件
* @param {any} file 文件
* @param {string | undefined} dir 目录
* @returns {*}
*/
function resolveAsFile(file, dir) {
file = dir !== undefined ? new File(dir, file) : new File(file)
// 直接文件
// 只解析带后缀的文件 其他文件视为非法文件
if (file.isFile() && file.name.lastIndexOf('.') != -1) {
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
}
}
/**
* 解析目录
* @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()) {
try {
var json = JSON.parse(base.read(_package))
if (json.main) {
return resolveAsFile(json.main, dir) || resolveAsFile('index.js', new File(dir, json.main))
}
} catch (error) {
throw __error('resolveAsDirectory ' + dir + ' package.json error ' + error)
}
}
// if no package or package.main exists, look for index.js
return resolveAsFile('index.js', dir)
}
/**
* 后缀检测和添加
* @param {string} fileName 文件名称
* @param {string} ext 后缀
* @returns {*}
*/
function normalizeName(fileName, ext) {
var extension = ext || '.js'
if (fileName.endsWith(extension)) {
return fileName
}
return fileName + extension
}
/**
* 检查模块缓存
* @param {string} id 模块ID
* @param {any} file 模块文件
* @param {any} optional 附加选项
* @returns {Object}
*/
function getCacheModule(id, file, optional) {
var module = cacheModules[id]
if (optional.cache && module) {
return module
}
return createModule(id, file, optional)
}
/**
* 编译模块
* @param {string} id 模块ID
* @param {any} file 模块文件
* @param {any} optional 附加选项
* @returns {Object}
*/
function createModule(id, file, optional) {
var filename = file.name
var lastDotIndexOf = filename.lastIndexOf('.')
if (lastDotIndexOf == -1) {
throw __error("can't require file " + file + '. error: module must include file ext.')
}
var name = filename.substring(0, lastDotIndexOf)
var ext = filename.substring(lastDotIndexOf + 1)
var loader = requireLoaders[ext]
if (!loader) {
throw __error('Unsupported module ' + filename + '. require loader not found.')
}
/**
* @type any
*/
var module = {
id: id,
name: name,
ext: ext,
parent: optional.parent,
exports: {},
loaded: false,
loader: loader,
path: _canonical(file.parentFile),
filename: _canonical(file),
children: []
}
module.require = getRequire(module)
if (module.parent && module.parent.children && module.parent.children.indexOf(module) == -1) {
module.parent.children.push(module)
}
console.trace('Loading module', name + '(' + id + ')', 'Optional', JSON.stringify(__assign(optional, { parent: undefined })))
cacheModules[id] = module
return loader(module, file, __assign(optional, { id: id }))
}
/**
* 预编译JS
* @param {any} module JS模块
* @param {any} file JS文件
* @param {any} optional 附加选项
* @returns {any}
*/
function compileJsFile(module, file, optional) {
return compileJs(module, base.read(file), optional)
}
/**
* 预编译JS
* @param {any} module JS模块
* @param {any} script JS脚本
* @param {any} optional 附加选项
* @returns {any}
*/
function compileJs(module, script, optional) {
if (optional.beforeCompile) {
script = optional.beforeCompile(script)
}
// 2019-09-19 使用 扩展函数直接 load 无需保存/删除文件
// 2020-02-16 结尾新增换行 防止有注释导致加载失败
var wrapperScript = '(function (module, exports, require, __dirname, __filename) {' + script + '\n});'
var compiledWrapper = engineLoad({
script: wrapperScript,
name: optional.id
})
compiledWrapper.apply(module.exports, [
module, module.exports, module.require, module.path, module.filename
])
module.loaded = true
if (optional.afterCompile) {
module = optional.afterCompile(module) || module
}
return module
}
/**
* 预编译Json
* @param {{ id?: string | null; exports?: {}; loaded: any; require?: any; }} module Json模块
* @param {any} file Json 文件
* @returns {any}
*/
function compileJson(module, file) {
module.exports = JSON.parse(base.read(file))
module.loaded = true
return module
}
/**
* 获得网络链接
* @param {string} url 网址
*/
function getConnection(url) {
var connection = new URL(url).openConnection()
connection.setConnectTimeout(MS_NETWORK_CONNECT_TIMEOUT)
connection.setReadTimeout(MS_NETWORK_READ_TIMEOUT)
connection.setUseCaches(MS_NETWORK_USE_CACHES)
return connection
}
/**
* 获得网络流
* @param {string} url 网址
*/
function getConnectionStream(url) {
var connection = getConnection(url)
return connection.getInputStream()
}
function splitVersionFromName(name) {
// process package name
// es6-map/implement => [es6-map/implement, undefined]
// @ccms/common/dist/reflect => [@ccms/common, undefined]
var name_arr = name.split('/')
var module_name = ''
var module_version = ''
if (name.startsWith('@')) {
var module_version_arr = name_arr[1].split('@')
module_name = name_arr[0] + '/' + module_version_arr[0]
} else {
var module_version_arr = name_arr[0].split('@')
module_name = module_version_arr[0]
}
// handle internal package version
if (name.startsWith(global.scope) && global.ScriptEngineChannel) {
module_version = global.ScriptEngineChannel
} else {
module_version = module_version_arr[1]
}
return [module_name, module_version]
}
/**
* 尝试从网络下载依赖包
* @param {string} name 包名称
* @param {string} optional 附加选项
* @param {number} retry 重试次数
*/
function download(name, optional, retry) {
var name_arr = splitVersionFromName(name)
var module_name = name_arr[0]
var module_version = name_arr[1]
try {
var target = MS_NODE_PATH + separatorChar + module_name
if (new File(target, 'package.json').exists()) { return name }
var info = fetchPackageInfo(module_name)
if (!module_version) {
// if not special version get from lock or tag
module_version = VersionLockModules[module_name]
} else if (!/\d+\.\d+\.\w+/.test(module_version)) {
// maybe module_version = latest if special version not exist then fallback latest
console.log('try get node_module ' + module_name + ' version from ' + module_version + ' tag waiting...')
module_version = info['dist-tags'][module_version]
}
if (!module_version) {
console.log('try get node_module ' + module_name + ' version from latest tag waiting...')
module_version = info['dist-tags']['latest']
}
if (!module_version) { throw __error('fetch node_module ' + module_name + " failed. can't found version from " + name + ".", 'ModuleNotFoundError') }
var _version = info.versions[module_version]
if (!_version) { throw __error('fetch node_module ' + module_name + ' version ' + module_version + " failed. can't found tarball from versions.", 'ModuleNotFoundError') }
var url = _version.dist.tarball
console.log('fetch node_module ' + module_name + ' version ' + module_version + ' waiting...')
return executor.submit(new Callable(function () {
var tis = new TarInputStream(new BufferedInputStream(new GZIPInputStream(getConnectionStream(url))))
var entry
while ((entry = tis.getNextEntry()) != null) {
var targetPath = Paths.get(target + separatorChar + entry.getName().substring(8))
var parentFile = targetPath.toFile().getParentFile()
if (!parentFile.isDirectory()) {
parentFile.delete()
parentFile.mkdirs()
}
Files.copy(tis, targetPath, StandardCopyOption.REPLACE_EXISTING)
}
return name
})).get(MS_NETWORK_DOWNLOAD_TIMEOUT, TimeUnit.MILLISECONDS)
} catch (error) {
if (error.name == 'ModuleNotFoundError') { throw error }
if (retry > 3) { throw __error('fetch node_module ' + module_name + ' version ' + module_version + ' failed. greater than 3 times stop retry.') }
console.log('fetch node_module ' + module_name + ' version ' + module_version + ' failed retrying...')
return download(name, optional, ++retry)
}
}
/**
* 获取包信息
* @param {string} module_name
*/
function fetchPackageInfo(module_name) {
var content = ''
try {
content = fetchContent(MS_NODE_REGISTRY + '/' + module_name)
} catch (ex) {
console.warn("can't fetch package " + module_name + ' from ' + MS_NODE_REGISTRY + ' registry. try fetch from ' + MS_FALLBACK_NODE_REGISTRY + ' registry...')
content = fetchContent(MS_FALLBACK_NODE_REGISTRY + '/' + module_name)
}
return JSON.parse(content)
}
/**
* 获取网络内容
* @param {string} url 网址
* @param {number} [timeout] 超时时间
*/
function fetchContent(url, timeout) {
return executor.submit(new Callable(function fetchContent() {
var input = getConnectionStream(url)
var output = new ByteArrayOutputStream()
var buffer = new ByteArray(1024)
try {
var n
while ((n = input.read(buffer)) !== -1) {
output.write(buffer, 0, n)
}
return output.toString("UTF-8")
} finally {
input.close()
output.close()
}
})).get(timeout || MS_NETWORK_READ_TIMEOUT, TimeUnit.MILLISECONDS)
}
var lastModule = ''
/**
* 检查核心模块
* @param {string} name
* @param {string} path
*/
function checkCoreModule(name, path, optional) {
if (name.startsWith('@ms') && lastModule.endsWith('.js')) {
console.warn(lastModule + ' load deprecated module ' + name + ' auto replace to ' + (name = name.replace('@ms', global.scope)) + '...')
return name
} else {
lastModule = name
}
if (CoreModules.indexOf(name) !== -1) {
var newName = global.scope + '/nodejs/dist/' + name
if (resolve(newName, path, optional) !== undefined) {
return newName
}
throw __error("can't load nodejs core module " + name + " . maybe later will auto replace to " + global.scope + "/nodejs/" + name + ' to compatible...')
}
return name
}
/**
* 检查缓存模块
*/
function checkCacheModule(optional) {
return optional.local ? cacheModuleIds[optional.parent.id] && cacheModuleIds[optional.parent.id][optional.path] : cacheModuleIds[optional.path]
}
/**
* 加载模块
* @param {string} name 模块名称
* @param {string} path 路径
* @param {any} optional 附加选项
* @returns {*}
*/
function _require(name, path, optional) {
// require direct file
var file = _isFile(name) ? name : new File(name)
if (_isFile(file) && file.name.lastIndexOf('.') != -1) {
return _requireFile(file, optional)
}
// require cache module
var cachePath = checkCacheModule(optional)
var cacheFile = new File(cachePath)
if (cachePath && cacheFile.exists()) {
return _requireFile(cacheFile, optional)
}
// check core module
name = checkCoreModule(name, path, optional)
var file = resolve(name, path, optional)
// search module
if (file === undefined) {
// excloud local dir, prevent too many recursive call and cache not found module
if (optional.local || optional.recursive || notFoundModules[name]) {
delete optional.parent
throw __error("can't found module " + name + '(' + JSON.stringify(optional) + ') at local ' + path + ' or network!')
}
optional.recursive = true
return _require(download(name, optional, 1), path, optional)
}
setCacheModule(file, optional)
return _requireFile(file, optional)
}
/**
* 设置模块缓存
* @param {any} file
* @param {any} optional
*/
function setCacheModule(file, optional) {
if (optional.local) {
var parent = cacheModuleIds[optional.parent.id]
if (!parent) {
cacheModuleIds[optional.parent.id] = {}
}
return cacheModuleIds[optional.parent.id][optional.path] = _canonical(file)
}
return cacheModuleIds[optional.path] = _canonical(file)
}
function _requireFile(file, optional) {
// 重定向文件名称和类型
return getCacheModule(_canonical(file), file, optional)
}
/**
* 闭包方法
* @param {any} parent 父模块
* @returns {Function}
*/
function exports(parent) {
/**
* @param {string} path
* @param {any} optional
*/
var require = function __DynamicRequire__(path, optional) {
if (!path) {
throw __error("require path can't be undefined or empty!")
}
var optional = __assign({
cache: true,
parent: parent,
path: path,
local: path.startsWith('.') || path.startsWith('/')
}, optional)
return _require(path, parent.path, optional).exports
}
require.resolve = function __DynamicResolve__(path, optional) {
return _canonical(new File(resolve(path, root, __assign({
parent: parent,
cache: true,
local: path.startsWith('.') || path.startsWith('/')
}, optional))))
}
return require
}
/**
* @param {string} name
*/
function __DynamicClear__(name) {
for (var cacheModule in cacheModules) {
if (cacheModule.indexOf(name) !== -1) {
console.trace('clear module ' + cacheModule + ' ...')
delete cacheModules[cacheModule]
} }
} }
} }
return undefined;
}
/** function __DynamicDisable__() {
* 解析文件 base.save(cacheModuleIdsFile, JSON.stringify(upgradeMode ? {} : cacheModuleIds))
* @returns {*} for (var cacheModule in cacheModules) {
*/ delete cacheModules[cacheModule]
function resolveAsFile(dir, file) { }
file = ext.notNull(dir) ? new File(dir, file) : new File(file); cacheModules = {}
// 直接文件 for (var cacheModuleId in cacheModuleIds) {
if (file.isFile()) { delete cacheModuleIds[cacheModuleId]
return file; }
cacheModuleIds = {}
notFoundModules = {}
} }
// 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;
}
}
/** function __setUpgradeMode__(status) {
* 解析目录 upgradeMode = status
* @returns {*} }
*/
function resolveAsDirectory(dir, file) { /**
dir = ext.notNull(dir) ? new File(dir, file) : new File(file); * @param {any} parent
var _package = new File(dir, 'package.json'); */
if (_package.exists()) { function getRequire(parent) {
var json = JSON.parse(base.read(_package)); /**
if (json.main) { * @type {any} require
return resolveAsFile(dir, json.main); */
var require = exports(parent)
require.main = mainRequire
require.cache = cacheModules
require.clear = __DynamicClear__
require.disable = __DynamicDisable__
require.setUpgradeMode = __setUpgradeMode__
require.loader = {
register: registerLoader,
get: getLoader,
unregister: unregisterLoader,
}
require.loaders = requireLoaders
require.internal = {
coreModules: CoreModules,
cacheModules: cacheModules,
cacheModuleIds: cacheModuleIds,
notFoundModules: notFoundModules,
versionLockModules: VersionLockModules
}
require.loadCoreScript = loadCoreScript
return require
}
/**
* @param {string} ext
* @param {any} loader
*/
function registerLoader(ext, loader) {
if (requireLoaders[ext]) {
return console.error('require loader ' + ext + ' already register ignore. if you want override loader please unregister before register.')
}
requireExts.push(ext)
requireLoaders[ext] = loader
console.info('register require loader ' + ext + ' => ' + (loader.name || '<anonymous>') + '.')
}
/**
* @param {*} ext
*/
function getLoader(ext) {
return requireLoaders[ext]
}
/**
* @param {*} ext
*/
function unregisterLoader(ext) {
requireExts.splice(requireExts.indexOf(ext), 1);
delete requireLoaders[ext]
console.info('unregister require loader ' + ext + '.')
}
function printRequireInfo() {
console.info('Initialization require module.')
console.info('ParentDir:', root)
console.info('Require module env list:')
console.info('- JAVA_VERSION:', System.getProperty("java.version"))
console.info('- PLUGIN_VERSION:', base.version)
console.info('- MS_NODE_PATH:', MS_NODE_PATH.startsWith(root) ? MS_NODE_PATH.split(root)[1] : MS_NODE_PATH)
console.info('- MS_NODE_REGISTRY:', MS_NODE_REGISTRY)
console.info('- MS_FALLBACK_NODE_REGISTRY:', MS_FALLBACK_NODE_REGISTRY)
}
function initCacheModuleIds() {
try {
cacheModuleIds = JSON.parse(base.read(cacheModuleIdsFile))
if (cacheModuleIds['@ccms-cache-module-root'] != MS_NODE_PATH) {
throw __error('canonicalRoot Change ' + cacheModuleIds['@ccms-cache-module-root'] + ' to ' + MS_NODE_PATH + ' Clear Cache!')
}
console.log('Read cacheModuleIds from file', cacheModuleIdsFile.startsWith(root) ? cacheModuleIdsFile.split(root)[1] : cacheModuleIdsFile)
} catch (error) {
cacheModuleIds = {}
cacheModuleIds['@ccms-cache-module-root'] = MS_NODE_PATH
console.log('Initialization new cacheModuleIds: ' + error)
} }
} }
// if no package or package.main exists, look for index.js
return resolveAsFile(dir, 'index.js');
}
/** function initVersionLock() {
* 后缀检测和添加 try {
* @param fileName 文件名称 var version_lock_url = MS_SCRIPT_PACKAGE_CENTER + '?name=version_lock' + (global.debug ? '-debug' : '')
* @param ext 后缀 VersionLockModules = JSON.parse(fetchContent(version_lock_url, 5000))
* @returns {*} try {
*/ VersionLockModules = __assign(VersionLockModules, JSON.parse(base.read(localVersionLockFile)))
function normalizeName(fileName, ext) { } catch (e) {
var extension = ext || '.js'; }
if (fileName.endsWith(extension)) { } catch (error) {
return fileName; console.warn("无法获取到最新的版本锁定信息 使用默认配置.")
} console.warn("InitVersionLock Error:", error)
return fileName + extension; console.debug(error)
} VersionLockModules = {
"@babel/standalone": "7.12.18",
/** "crypto-js": "3.3.0",
* 编译模块 "core-js": "3.33.1"
* @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) {
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);
} }
if (_canonical(file).endsWith('.json')) { console.info('Lock module version List:')
compileJson(module, file, optional); for (var key in VersionLockModules) {
console.info('- ' + key + ': ' + VersionLockModules[key])
} }
if (_canonical(file).endsWith('.msm')) { }
throw Error("暂不支持解析 MiaoScript 模块");
function initRequireLoader(require) {
registerLoader('js', compileJsFile)
registerLoader('json', compileJson)
try {
loadCoreScript('require_loader')(require)
} catch (error) {
console.warn("无法获取到最新的加载器信息 使用默认配置.")
console.warn("InitRequireLoader Error:", error)
console.debug(error)
registerLoader('ms', compileJsFile)
} }
} catch (ex) { require.main = mainRequire = require
console.console('§4警告! §c模块§a', name, '§c编译失败! §4ERR:', ex); return require
console.ex(ex);
} }
return module;
}
/** function loadCoreScript(name) {
* 预编译JS return engineLoad({
* @param file JS文件 script: fetchContent(MS_SCRIPT_PACKAGE_CENTER + '?name=' + name, 5000),
* @param optional 附加选项 name: 'core/' + name + '.js'
* @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 可以保留行号和文件名称 if (typeof parent === 'string') {
var compiledWrapper = engineLoad(cacheFile); parent = new File(parent)
try {
base.delete(cacheFile);
} catch (ex) {
cacheFile.deleteOnExit();
} }
compiledWrapper.apply(module.exports, [ var mainRequire = undefined
module, module.exports, module.require, file.parentFile, file /**
]); * require 支持的后缀
module.loaded = true; * @type {string[]} requireExts
} */
var requireExts = []
/**
* require加载器
* @type {{[key:string]:(module:any, file:string, optional?:any)=>any}} requireLoader
*/
var requireLoaders = {}
/**
* 已缓存的模块
* @type {{[key:string]:any}} [cacheModules]
*/
var cacheModules = {}
var cacheModuleIdsFile = _canonical(new File(MS_NODE_PATH, 'cacheModuleIds.json'))
var localVersionLockFile = _canonical(new File(MS_NODE_PATH, 'moduleVersionLock.json'))
/**
* 已缓存的模块ID
* @type {{[key:string]:{[key:string]:string}|string}} [cacheModuleIds]
*/
var cacheModuleIds = {}
/**
* 未找到的模块
* @type {{[key:string]:boolean}}
*/
var notFoundModules = {}
var upgradeMode = false
var executor = Executors.newSingleThreadExecutor(function (r) {
return new Thread(r, "MiaoScript require thread")
})
/** printRequireInfo()
* 预编译Json initCacheModuleIds()
* @param file Json 文件 initVersionLock()
* @param optional 附加选项
* @returns {Object}
*/
function compileJson(module, file, optional) {
module.exports = JSON.parse(base.read(file));
module.loaded = true;
}
/** return initRequireLoader(getRequire({
* 加载模块 id: 'main',
* @param name 模块名称 path: root
* @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未找到该模块!');
}
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;
};
}
if (typeof parent === "string") {
parent = new File(parent);
}
var cacheModules = [];
console.debug("初始化 require 模块组件 父目录 ", _canonical(parent));
return exports(parent);
});

View File

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

View File

@ -1,100 +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 token = args[args.length - 1];
var complate = exec.tab(sender, command, args) || []
return Arrays.asList(complate.copyPartialMatches(token, []));
} 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,118 +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('.'));
};
/**
* 获取OBC类
*/
exports.obcCls = function (name) {
return Java.type(['org.bukkit.craftbukkit', 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,9 +0,0 @@
/*global Java, base, module, exports, require*/
var TextSerializers = Java.type('org.spongepowered.api.text.serializer.TextSerializers');
function json(sender, json) {
sender.sendMessage(TextSerializers.JSON.deserialize(json));
}
exports = module.exports = {
json: json
};

View File

@ -1,132 +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 (command) {
var that = this;
this.name = command.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, that.name, args.length === 0 ? [] : 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, that.name, args.length === 0 ? [] : args.split(" "));
},
//boolean testPermission(CommandSource source);
testPermission: function () {
return true;
},
//Optional<Text> getShortDescription(CommandSource source);
getShortDescription: function () {
return Optional.of(Text.of(command.description || '暂无描述!'));
},
//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;
command.name = name
create(jsp, command)
console.debug('插件 %s 注册命令 %s ...'.format(jsp.description.name, name));
}
}
}
function get(name) {
}
function create(jsp, command) {
var commandKey = jsp.description.name.toLowerCase() + ":" + command.name;
if(!commandMap[commandKey]){
commandMap[commandKey] = new SimpleCommandCallable(command);
Sponge.getCommandManager().register(plugin, commandMap[commandKey].callable, command.name, commandKey);
}
return commandMap[commandKey];
}
function on(jsp, name, exec) {
var c = create(jsp, {name: name});
console.debug('插件 %s 设置命令 %s 执行器 ...'.format(jsp.description.name, name));
if (exec.cmd) {
c.setExecutor(function execCmd(sender, command, args) {
try {
return exec.cmd(sender, command, args);
} catch (ex) {
console.console('§6玩家 §a%s §6执行 §b%s §6插件 §d%s %s §6命令时发生异常'
.format(sender.name, jsp.description.name, command, args.join(' ')));
console.ex(ex);
}
});
}
if (exec.tab) {
c.setTabCompleter(function execTab(sender, command, args) {
try {
var token = args[args.length - 1];
var complate = exec.tab(sender, command, args) || []
return Arrays.asList(complate.copyPartialMatches(token, []));
} catch (ex) {
console.console('§6玩家 §a%s §6执行 §b%s §6插件 §d%s %s §6补全时发生异常'
.format(sender.name, jsp.description.name, command, args.join(' ')));
console.ex(ex);
}
});
}
}
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.canonicalName.substring(clazz.name.lastIndexOf(".") + 1);
}
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,68 +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).orElse(undefined);
},
/**
* 载入插件 并且返回结果
* @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').orElse(undefined)
};
/**
* 获取玩家
*/
exports.player = function () {
switch (arguments.length) {
case 0:
return undefined;
case 1:
return Server.getPlayer(arguments[0]).orElse(undefined);
default:
return Server.getPlayer(arguments[0]).orElse(undefined);
}
};
/**
* 获取在线玩家
*/
exports.players = function () {
switch (arguments.length) {
case 1:
// 此处的forEach是Collection接口的
return Server.onlinePlayers.forEach(arguments[0]);
default:
// 此处会转换为JS原生的Array
return Java.from(Server.onlinePlayers.toArray());
}
};

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,145 +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,
Debug: false
}
function open(url, method, header) {
// conn.setRequestProperty
var conn = new URL(url).openConnection();
if (conn instanceof HttpsURLConnection) {
conn.setHostnameVerifier(TrustAnyHostnameVerifier);
conn.setSSLSocketFactory(SSLSocketFactory);
}
conn.setRequestMethod(method);
conn.setDoOutput(true);
conn.setDoInput(true);
conn.setConnectTimeout(config.ConnectTimeout);
conn.setReadTimeout(config.ReadTimeout);
if (header) {
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 += '?';
}
return url += object2URLSearchParams(params);
}
return url;
}
function request(config) {
var conn = open(buildUrl(config.url, config.query), config.method, config.header);
try {
conn.connect();
var data = config.data;
if (data) {
var out = conn.getOutputStream();
if (typeof data === "object") {
var type = config.header['Content-Type'];
switch (type) {
case "application/x-www-form-urlencoded":
data = object2URLSearchParams(params);
default:
data = JSON.stringify(data)
}
}
out.write(new String(data).getBytes(config.Charset));
out.flush();
out.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;
}
function object2URLSearchParams (params) {
var temp = []
for (var key in params) {
temp.push('%s=%s'.format(encodeURIComponent(key), encodeURIComponent(params[key])))
}
return temp.join('&')
}
var http = {
config: config,
request: request
};
['GET', 'DELETE', 'HEAD', 'OPTIONS'].forEach(function (method) {
http[method.toLowerCase()] = function __likeGet__(url, data, config) {
return this.request(Object.assign(config || {}, {
url: url,
method: method,
query: data
}));
}
});
['POST', 'PUT', 'PATCH'].forEach(function (method) {
http[method.toLowerCase()] = function __likePost__(url, data, config) {
return this.request(Object.assign(config || {}, {
url: url,
method: method,
data: data
}));
}
});
exports = module.exports = http;

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

View File

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

View File

@ -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;

Some files were not shown because too many files have changed in this diff Show More