Compare commits
129 Commits
1.3.0.bate
...
master
Author | SHA1 | Date | |
---|---|---|---|
6b34566489 | |||
074e6e8a10 | |||
14cc05e923 | |||
ebc03b6164 | |||
9268ce9fee | |||
3e4453a197 | |||
dc66290f97 | |||
56152657c8 | |||
e2f9bbf587 | |||
a9003025ee | |||
91a87ab20e | |||
ce92ae9ec6 | |||
cfd44a6289 | |||
fc7fb67023 | |||
7b171f1546 | |||
389bfd7137 | |||
f8ba885b8c | |||
48306b64c4 | |||
1cb4c05efd | |||
54e40b6768 | |||
51fc4549da | |||
824c440f63 | |||
7f32062dca | |||
12d07bf552 | |||
0506c9e3e6 | |||
40760713ff | |||
7e36b6109d | |||
7f85295eb1 | |||
427aa262f0 | |||
e71bd2a0cb | |||
9bb67410ac | |||
eba0e18285 | |||
219eb6b919 | |||
17d07d6cef | |||
f2b8f6ff26 | |||
9a15a0ab1f | |||
d0de120867 | |||
351183ab3c | |||
87c78f7c6f | |||
28db77333e | |||
ac83acd4c8 | |||
876c9b77f7 | |||
ebf218e534 | |||
fd5c2aa087 | |||
ea8e62b696 | |||
367b732f7c | |||
9bcd4cd748 | |||
2ed9614bc4 | |||
00287ff80a | |||
2a891c1117 | |||
46925f9b52 | |||
57926ba788 | |||
8933afeb71 | |||
0b0cea9e50 | |||
1c21792572 | |||
31351fc393 | |||
c859605738 | |||
388e1e9135 | |||
996a63ba2d | |||
548c76f154 | |||
8be38800b0 | |||
0dfe04040e | |||
7dad0e7abc | |||
96639d0978 | |||
0df2d2b71f | |||
de18b0f628 | |||
bbf08816ba | |||
160e7f4118 | |||
2d4bc3dd24 | |||
c5b7a45605 | |||
4653bbc091 | |||
565419a292 | |||
a28386401c | |||
a78e6482e8 | |||
03129b8797 | |||
c2d0c05bcf | |||
b611da5e27 | |||
93d7389047 | |||
a875a6ca8e | |||
135d0f2b90 | |||
8cf8dccbe4 | |||
478bff9599 | |||
2013b3b07c | |||
2dff086a01 | |||
8d5902600f | |||
e455cbf996 | |||
8d40a69ac7 | |||
f98814bf2d | |||
72ae1b4b29 | |||
ee4072526b | |||
2cd6e019c6 | |||
6766c3b0ce | |||
150c18957c | |||
bdc0a62e36 | |||
ccdbd8b683 | |||
c2c17a46d4 | |||
997820d117 | |||
d67f2843b0 | |||
7822803376 | |||
ee496c5bda | |||
324fbee2e5 | |||
c955670658 | |||
33fecc7372 | |||
b33826bbe9 | |||
8e2e2bca82 | |||
5ea78a60e5 | |||
c873031cc2 | |||
9504ec8b12 | |||
abdfbce125 | |||
e6af7b1828 | |||
8f5bae006a | |||
f94fa71f36 | |||
fcc1f18336 | |||
823ff1c70b | |||
2360dd9b0e | |||
f94653249d | |||
c095593c41 | |||
202dc9f00c | |||
88d71abb2a | |||
967e7d1beb | |||
e97de1f8d0 | |||
bc6e07cfc8 | |||
4dec6bca98 | |||
f8ec9b9f6e | |||
1735417887 | |||
9819a82265 | |||
d2ebd8fa7e | |||
0492275eb2 | |||
3fe1feccff |
5
.gitignore
vendored
5
.gitignore
vendored
@ -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
0
CHANGELOG.md
Normal file
88
README.md
88
README.md
@ -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
105
obf.dict
@ -1,105 +0,0 @@
|
|||||||
™
|
|
||||||
▄
|
|
||||||
▒
|
|
||||||
░
|
|
||||||
▓
|
|
||||||
™™
|
|
||||||
▄™
|
|
||||||
▒™
|
|
||||||
░™
|
|
||||||
▓™
|
|
||||||
™▄
|
|
||||||
▄▄
|
|
||||||
▒▄
|
|
||||||
░▄
|
|
||||||
▓▄
|
|
||||||
™▒
|
|
||||||
▄▒
|
|
||||||
▒▒
|
|
||||||
░▒
|
|
||||||
▓▒
|
|
||||||
™░
|
|
||||||
▄░
|
|
||||||
▒░
|
|
||||||
░░
|
|
||||||
▓░
|
|
||||||
™▓
|
|
||||||
▄▓
|
|
||||||
▒▓
|
|
||||||
░▓
|
|
||||||
▓▓
|
|
||||||
™
|
|
||||||
™▄
|
|
||||||
™▒
|
|
||||||
™░
|
|
||||||
™▓
|
|
||||||
▄™
|
|
||||||
▄▄
|
|
||||||
▄▒
|
|
||||||
▄░
|
|
||||||
▄▓
|
|
||||||
▒™
|
|
||||||
▒▄
|
|
||||||
▒
|
|
||||||
▒░
|
|
||||||
▒▓
|
|
||||||
░™
|
|
||||||
░▄
|
|
||||||
░▒
|
|
||||||
░
|
|
||||||
░▓
|
|
||||||
▓™
|
|
||||||
▓▄
|
|
||||||
▓▒
|
|
||||||
▓░
|
|
||||||
▓
|
|
||||||
™™™
|
|
||||||
▄™▄
|
|
||||||
▒™▒
|
|
||||||
░™░
|
|
||||||
▓™▓
|
|
||||||
™▄™
|
|
||||||
▄▄▄
|
|
||||||
▒▄▒
|
|
||||||
░▄░
|
|
||||||
▓▄▓
|
|
||||||
™▒™
|
|
||||||
▄▒▄
|
|
||||||
▒▒▒
|
|
||||||
░▒░
|
|
||||||
▓▒▓
|
|
||||||
™░™
|
|
||||||
▄░▄
|
|
||||||
▒░▒
|
|
||||||
░░░
|
|
||||||
▓░▓
|
|
||||||
™▓™
|
|
||||||
▄▓▄
|
|
||||||
▒▓▒
|
|
||||||
░▓░
|
|
||||||
▓▓▓
|
|
||||||
™ ™
|
|
||||||
™▄™
|
|
||||||
™▒™
|
|
||||||
™░™
|
|
||||||
™▓™
|
|
||||||
▄™▄
|
|
||||||
▄ ▄
|
|
||||||
▄▒▄
|
|
||||||
▄░▄
|
|
||||||
▄▓▄
|
|
||||||
▒™▒
|
|
||||||
▒▄▒
|
|
||||||
▒ ▒
|
|
||||||
▒░▒
|
|
||||||
▒▓▒
|
|
||||||
░™░
|
|
||||||
░▄░
|
|
||||||
░▒░
|
|
||||||
░ ░
|
|
||||||
░▓░
|
|
||||||
▓™▓
|
|
||||||
▓▄▓
|
|
||||||
▓▒▓
|
|
||||||
▓░▓
|
|
||||||
▓ ▓
|
|
238
pom.xml
238
pom.xml
@ -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>
|
@ -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>;
|
|
||||||
}
|
|
@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
@ -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();
|
|
||||||
}
|
|
||||||
}
|
|
40
src/main/java/pw/yumc/MiaoScript/MiaoScriptBukkit.java
Normal file
40
src/main/java/pw/yumc/MiaoScript/MiaoScriptBukkit.java
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
38
src/main/java/pw/yumc/MiaoScript/MiaoScriptBungee.java
Normal file
38
src/main/java/pw/yumc/MiaoScript/MiaoScriptBungee.java
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
35
src/main/java/pw/yumc/MiaoScript/MiaoScriptNukkit.java
Normal file
35
src/main/java/pw/yumc/MiaoScript/MiaoScriptNukkit.java
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
@ -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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
128
src/main/java/pw/yumc/MiaoScript/api/Base.java
Normal file
128
src/main/java/pw/yumc/MiaoScript/api/Base.java
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
41
src/main/java/pw/yumc/MiaoScript/api/JavaScriptTask.java
Normal file
41
src/main/java/pw/yumc/MiaoScript/api/JavaScriptTask.java
Normal 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());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
62
src/main/java/pw/yumc/MiaoScript/api/MiaoScriptAPI.java
Normal file
62
src/main/java/pw/yumc/MiaoScript/api/MiaoScriptAPI.java
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
51
src/main/java/pw/yumc/MiaoScript/api/ProxyClass.java
Normal file
51
src/main/java/pw/yumc/MiaoScript/api/ProxyClass.java
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
76
src/main/java/pw/yumc/MiaoScript/api/ScriptEngine.java
Normal file
76
src/main/java/pw/yumc/MiaoScript/api/ScriptEngine.java
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
39
src/main/java/pw/yumc/MiaoScript/api/bukkit/EngineEvent.java
Normal file
39
src/main/java/pw/yumc/MiaoScript/api/bukkit/EngineEvent.java
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
41
src/main/java/pw/yumc/MiaoScript/api/bukkit/ScriptEvent.java
Normal file
41
src/main/java/pw/yumc/MiaoScript/api/bukkit/ScriptEvent.java
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
67
src/main/java/pw/yumc/MiaoScript/api/loader/JarLoader.java
Normal file
67
src/main/java/pw/yumc/MiaoScript/api/loader/JarLoader.java
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -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();
|
||||||
|
}
|
||||||
|
}
|
@ -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);
|
||||||
|
}
|
268
src/main/java/pw/yumc/MiaoScript/engine/MiaoScriptEngine.java
Normal file
268
src/main/java/pw/yumc/MiaoScript/engine/MiaoScriptEngine.java
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
@ -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;
|
|
@ -1,2 +0,0 @@
|
|||||||
/*global Java, base, module, exports, require*/
|
|
||||||
module.exports = requireInternal('command');
|
|
@ -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];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
@ -1,2 +0,0 @@
|
|||||||
/*global Java, base, module, exports, require*/
|
|
||||||
module.exports = requireInternal('item');
|
|
@ -1,2 +0,0 @@
|
|||||||
/*global Java, base, module, exports, require*/
|
|
||||||
module.exports = requireInternal('permission', {warnNotFound: false});
|
|
@ -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
|
|
||||||
}
|
|
@ -1,2 +0,0 @@
|
|||||||
/*global Java, base, module, exports, require*/
|
|
||||||
module.exports = requireInternal('server');
|
|
@ -1,2 +0,0 @@
|
|||||||
/*global Java, base, module, exports, require*/
|
|
||||||
module.exports = requireInternal('task');
|
|
@ -1,5 +0,0 @@
|
|||||||
/*global Java, base, module, exports, require*/
|
|
||||||
var player = requireInternal('wrapper/player');
|
|
||||||
module.exports = {
|
|
||||||
player: player.$
|
|
||||||
}
|
|
@ -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();
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
})();
|
})()
|
||||||
|
5
src/main/resources/bungee.yml
Normal file
5
src/main/resources/bungee.yml
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
name: ${project.artifactId}
|
||||||
|
description: ${project.description}
|
||||||
|
main: ${project.groupId}.${project.artifactId}.${project.artifactId}Bungee
|
||||||
|
version: ${project.version}
|
||||||
|
author: MiaoWoo
|
@ -1,10 +0,0 @@
|
|||||||
#MySQL数据库配置
|
|
||||||
DataBase:
|
|
||||||
#默认数据库
|
|
||||||
def:
|
|
||||||
#数据库需要自行建立
|
|
||||||
database: minecraft
|
|
||||||
username: root
|
|
||||||
password: root
|
|
||||||
ip: 127.0.0.1
|
|
||||||
port: 3306
|
|
@ -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);
|
|
||||||
|
@ -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();
|
|
@ -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;
|
|
||||||
};
|
|
@ -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
25
src/main/resources/core/index.d.ts
vendored
Normal 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);
|
||||||
|
}
|
@ -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);
|
|
@ -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
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
})();
|
|
@ -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;
|
|
||||||
};
|
|
||||||
})();
|
|
@ -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);
|
|
||||||
// };
|
|
||||||
})();
|
|
@ -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))
|
|
||||||
};
|
|
||||||
})();
|
|
32
src/main/resources/core/polyfill.js
Normal file
32
src/main/resources/core/polyfill.js
Normal 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')
|
||||||
|
}
|
||||||
|
)
|
@ -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);
|
|
||||||
});
|
|
||||||
|
@ -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
|
|
||||||
};
|
|
@ -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 () {
|
|
||||||
|
|
||||||
};
|
|
@ -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);
|
|
@ -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
|
|
||||||
};
|
|
@ -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;
|
|
@ -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;
|
|
@ -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);
|
|
||||||
}
|
|
||||||
};
|
|
@ -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]);
|
|
||||||
}
|
|
||||||
};
|
|
@ -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;
|
|
@ -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
|
|
||||||
};
|
|
@ -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
|
|
||||||
}
|
|
@ -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);
|
|
@ -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
|
|
||||||
};
|
|
@ -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());
|
|
||||||
}
|
|
||||||
};
|
|
@ -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);
|
|
||||||
}
|
|
||||||
};
|
|
@ -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;
|
|
@ -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
|
|
||||||
);
|
|
@ -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;
|
|
@ -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
|
|
||||||
}
|
|
@ -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;
|
|
@ -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
|
|
||||||
}
|
|
@ -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');
|
|
@ -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;
|
|
@ -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 isn’t 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;
|
|
@ -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
@ -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;
|
|
@ -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;
|
|
@ -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')
|
|
||||||
]
|
|
||||||
});
|
|
@ -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')
|
|
||||||
]
|
|
||||||
});
|
|
@ -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')
|
|
||||||
]
|
|
||||||
});
|
|
@ -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')
|
|
||||||
]
|
|
||||||
});
|
|
@ -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')
|
|
||||||
]
|
|
||||||
});
|
|
@ -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;
|
|
@ -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
|
|
||||||
});
|
|
@ -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'
|
|
||||||
});
|
|
@ -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'
|
|
||||||
});
|
|
@ -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' ]
|
|
||||||
}
|
|
||||||
});
|
|
@ -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
|
|
||||||
});
|
|
@ -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
|
|
||||||
});
|
|
@ -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
|
|
||||||
});
|
|
@ -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 : {}; }
|
|
||||||
});
|
|
@ -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
|
|
||||||
});
|
|
@ -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'
|
|
||||||
});
|
|
@ -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
|
|
||||||
});
|
|
@ -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
|
|
||||||
});
|
|
@ -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 : []; }
|
|
||||||
});
|
|
@ -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
|
|
||||||
});
|
|
@ -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 : ''; }
|
|
||||||
});
|
|
@ -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
|
|
||||||
});
|
|
@ -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
Reference in New Issue
Block a user