Compare commits
153 Commits
V1.2.1Alph
...
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 | |||
f7b97f3e84 | |||
89cab251c7 | |||
3d3bf20acd | |||
423c7cc844 | |||
8df9ad9ec7 | |||
39d9c67c75 | |||
6f1a103aca | |||
f79acd43c5 | |||
f19e51d8a7 | |||
d5aa98b716 | |||
04a7b99ce5 | |||
a672b85678 | |||
288619ddb7 | |||
3df2625e65 | |||
a041e8e2d2 | |||
320cc0479e | |||
755d4b005d | |||
e290f17771 | |||
be95acd001 | |||
75340fd824 | |||
51499b3b52 | |||
54b5909875 | |||
fe6d0e7250 | |||
bf6d52d8cc |
102
.gitignore
vendored
102
.gitignore
vendored
@ -1,44 +1,58 @@
|
||||
# Eclipse stuff
|
||||
/.settings
|
||||
|
||||
# netbeans
|
||||
/nbproject
|
||||
|
||||
# we use maven!
|
||||
/build.xml
|
||||
|
||||
# maven
|
||||
/target
|
||||
/repo
|
||||
|
||||
# vim
|
||||
.*.sw[a-p]
|
||||
|
||||
# various other potential build files
|
||||
/build
|
||||
/bin
|
||||
/dist
|
||||
/manifest.mf
|
||||
|
||||
/world
|
||||
|
||||
# Mac filesystem dust
|
||||
*.DS_Store
|
||||
|
||||
# intellij
|
||||
*.iml
|
||||
*.ipr
|
||||
*.iws
|
||||
.idea/
|
||||
|
||||
# Project Stuff
|
||||
/src/main/resources/Soulbound
|
||||
|
||||
# Atlassian Stuff
|
||||
/atlassian-ide-plugin.xml
|
||||
|
||||
/src/main/resources/cache/
|
||||
|
||||
# ThinkPHP
|
||||
vendor/
|
||||
composer.lock
|
||||
# Eclipse stuff
|
||||
/.settings
|
||||
|
||||
# netbeans
|
||||
/nbproject
|
||||
|
||||
# we use maven!
|
||||
/build.xml
|
||||
|
||||
# maven
|
||||
/target
|
||||
/repo
|
||||
|
||||
# vim
|
||||
.*.sw[a-p]
|
||||
|
||||
# various other potential build files
|
||||
/build
|
||||
/bin
|
||||
/dist
|
||||
/manifest.mf
|
||||
|
||||
# Mac filesystem dust
|
||||
*.DS_Store
|
||||
|
||||
# intellij
|
||||
*.iml
|
||||
*.ipr
|
||||
*.iws
|
||||
.idea/
|
||||
|
||||
# Project Stuff
|
||||
/src/main/resources/Soulbound
|
||||
|
||||
# Atlassian Stuff
|
||||
/atlassian-ide-plugin.xml
|
||||
|
||||
# Eclipse
|
||||
.project
|
||||
.classpath
|
||||
.factorypath
|
||||
.settings
|
||||
|
||||
# Visual Studio Code
|
||||
.vscode
|
||||
|
||||
# NodeJs PHP LOCK File
|
||||
*.lock
|
||||
|
||||
# PHP Vendor
|
||||
vendor/
|
||||
|
||||
# Minecraft Data
|
||||
/world
|
||||
**/node_modules/
|
||||
|
||||
# Gradle
|
||||
.gradle
|
||||
|
0
CHANGELOG.md
Normal file
0
CHANGELOG.md
Normal file
88
README.md
88
README.md
@ -1,87 +1,11 @@
|
||||
# MiaoScript
|
||||
|
||||
> 排版什么的 不存在的 这辈子都不会有排版的 除非什么时候论坛支持 `MarkDown` 了
|
||||
> 一个兼容 Spigot Sponge Nukkit BungeeCord 的 脚本插件运行时
|
||||
|
||||
### 简介
|
||||
## 简介
|
||||
|
||||
> 这个坑是我自己刨的 但是发现坑太大 需要更多的人一起填
|
||||
## 安装
|
||||
|
||||
#### 起源
|
||||
|
||||
- 诞生于 `2016年08月25日` 这是 Git 上的第一个提交 具体啥时候我也忘了
|
||||
- 起初 `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`
|
||||
|
||||
### 填坑
|
||||
|
||||
- 实际上说了那么多 最终希望的就是 有大佬能一起来填坑 毕竟这个坑太大了
|
||||
- 下载后放入对应服务器目录
|
||||
- Bukkit Nukkit BungeeCord 以及其分支 => `plugins`
|
||||
- Sponge => `mods`
|
||||
|
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"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<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">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>pw.yumc</groupId>
|
||||
<artifactId>MiaoScript</artifactId>
|
||||
<version>1.2.1</version>
|
||||
<version>0.28.0</version>
|
||||
<developers>
|
||||
<developer>
|
||||
<id>502647092</id>
|
||||
<name>喵♂呜</name>
|
||||
<name>MiaoWoo</name>
|
||||
<email>admin@yumc.pw</email>
|
||||
<url>http://www.yumc.pw</url>
|
||||
<url>https://www.yumc.pw</url>
|
||||
</developer>
|
||||
</developers>
|
||||
<build>
|
||||
@ -17,78 +16,141 @@
|
||||
<resources>
|
||||
<resource>
|
||||
<directory>src/main/resources</directory>
|
||||
<excludes>
|
||||
<exclude>plugins/**.js</exclude>
|
||||
</excludes>
|
||||
<filtering>true</filtering>
|
||||
</resource>
|
||||
</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>
|
||||
<ciManagement>
|
||||
<system>Jenkins</system>
|
||||
<url>http://ci.yumc.pw/job/${project.artifactId}/</url>
|
||||
<url>https://ci.yumc.pw/job/Minecraft/job/${project.artifactId}/</url>
|
||||
</ciManagement>
|
||||
<properties>
|
||||
<env.GIT_COMMIT>DEV</env.GIT_COMMIT>
|
||||
<update.changes>
|
||||
§618-01-09 §afeat: 优化加载流程 完善事件注册
|
||||
§618-01-02 §afeat: 新增http网络访问模块
|
||||
§617-12-28 §afeat: 完善Sponge事件注册 新增player封装类
|
||||
§623-10-25 §afeat: 升级 asm 版本;
|
||||
§623-07-30 §afeat: 优化 require 性能;
|
||||
§cfix: 修复 require 加载特殊文件异常;
|
||||
§623-07-22 §afeat: 网络加载 jtar 优化包大小;
|
||||
§aremove: 移除 Spring 相关支持;
|
||||
§adeps: 更新 Nashorn 和 GraalvmJS 引擎版本
|
||||
</update.changes>
|
||||
<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-03 §afeat: 新增抽奖插件;
|
||||
§617-10-16 §cfix: 修复关闭MiaoScript时task异常;
|
||||
@ -97,47 +159,57 @@
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<maven.compiler.source>1.8</maven.compiler.source>
|
||||
<maven.compiler.target>1.8</maven.compiler.target>
|
||||
<repo.url>https://repo.yumc.pw</repo.url>
|
||||
</properties>
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>yumc-repo</id>
|
||||
<url>http://repo.yumc.pw/content/groups/public/</url>
|
||||
</repository>
|
||||
<repository>
|
||||
<id>sponge</id>
|
||||
<url>https://repo.spongepowered.org/maven/</url>
|
||||
<url>${repo.url}/repository/maven-public/</url>
|
||||
</repository>
|
||||
</repositories>
|
||||
<pluginRepositories>
|
||||
<pluginRepository>
|
||||
<id>yumc-repo</id>
|
||||
<url>http://repo.yumc.pw/content/groups/public/</url>
|
||||
<url>${repo.url}/repository/maven-public/</url>
|
||||
</pluginRepository>
|
||||
</pluginRepositories>
|
||||
<distributionManagement>
|
||||
<repository>
|
||||
<id>jtb</id>
|
||||
<name>YUMC</name>
|
||||
<url>http://repo.yumc.pw/content/repositories/yumcenter/</url>
|
||||
<url>${repo.url}/repository/yumcenter/</url>
|
||||
</repository>
|
||||
</distributionManagement>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>pw.yumc</groupId>
|
||||
<artifactId>YumCore</artifactId>
|
||||
<type>jar</type>
|
||||
<version>[1.8,)</version>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>org.bukkit</groupId>
|
||||
<artifactId>craftbukkit</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
<version>1.18.24</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.spigotmc</groupId>
|
||||
<artifactId>spigot-api</artifactId>
|
||||
<version>1.18.2-R0.1-SNAPSHOT</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.spongepowered</groupId>
|
||||
<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>
|
||||
</dependencies>
|
||||
</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;
|
||||
|
||||
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 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
|
||||
@ -28,7 +21,7 @@ import lombok.SneakyThrows;
|
||||
* @author 喵♂呜
|
||||
* 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 {
|
||||
private ScriptEngine engine;
|
||||
@Inject
|
||||
@ -39,77 +32,31 @@ public class MiaoScriptSponge {
|
||||
private File pluginConfigDir;
|
||||
|
||||
@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
|
||||
@SneakyThrows
|
||||
public void onStart(GameStartedServerEvent event) {
|
||||
Sponge.getServer().getConsole();
|
||||
Sponge.getCommandManager().register(this, main(), "ms", "mscript", "MiaoScript");
|
||||
engine = new ScriptEngine(pluginConfigDir.getCanonicalPath(), logger);
|
||||
public void onStarted(GameStartedServerEvent event) {
|
||||
engine.enableEngine();
|
||||
}
|
||||
|
||||
@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();
|
||||
}
|
||||
}
|
||||
|
@ -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,2 +0,0 @@
|
||||
/*global Java, base, module, exports, require*/
|
||||
module.exports = require('./msp.js').command;
|
@ -1,156 +0,0 @@
|
||||
'use strict';
|
||||
/**
|
||||
* Bukkit 事件相关类
|
||||
*/
|
||||
/*global Java, base, module, exports, require, __FILE__*/
|
||||
|
||||
function EventHandlerDefault() {
|
||||
var Thread = Java.type("java.lang.Thread");
|
||||
|
||||
this.plugin = require('./server').plugin.self;
|
||||
this.mapEvent = [];
|
||||
this.listenerMap = [];
|
||||
this.baseEventDir = '';
|
||||
|
||||
/**
|
||||
* 扫描包 org.bukkit.event 下的所有事件
|
||||
* 映射简写名称 org.bukkit.event.player.PlayerLoginEvent => playerloginevent
|
||||
*/
|
||||
this.mapEventName = function mapEventName() {
|
||||
if (this.baseEventDir === "") {
|
||||
throw new Error("事件基础包名为空 无法进行事件映射!");
|
||||
}
|
||||
var count = 0;
|
||||
var dirs = Thread.currentThread().getContextClassLoader().getResources(this.baseEventDir);
|
||||
while (dirs.hasMoreElements()) {
|
||||
var url = dirs.nextElement();
|
||||
var protocol = url.protocol;
|
||||
if (protocol === "jar") {
|
||||
// noinspection JSUnresolvedVariable
|
||||
var jar = url.openConnection().jarFile;
|
||||
var entries = jar.entries();
|
||||
while (entries.hasMoreElements()) {
|
||||
var entry = entries.nextElement();
|
||||
var name = entry.name;
|
||||
// 以 org/bukkit/event 开头 并且以 .class 结尾
|
||||
if (name.startsWith(this.baseEventDir) && name.endsWith(".class")) {
|
||||
var i = name.replaceAll('/', '.');
|
||||
try {
|
||||
var clz = base.getClass(i.substring(0, i.length - 6));
|
||||
// 继承于 org.bukkit.event.Event 访问符为Public
|
||||
if (this.isVaildEvent(clz)) {
|
||||
// noinspection JSUnresolvedVariable
|
||||
var simpleName = this.class2Name(clz);
|
||||
console.debug("Mapping Event [%s] => %s".format(clz.name, simpleName));
|
||||
this.mapEvent[simpleName] = clz;
|
||||
count++;
|
||||
}
|
||||
} catch (ex) {
|
||||
//ignore already loaded class
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
this.class2Name = function class2Name(clazz) {
|
||||
return clazz.simpleName.toLowerCase();
|
||||
}
|
||||
|
||||
this.name2Class = function name2Class(name, event) {
|
||||
var eventCls = this.mapEvent[event] || this.mapEvent[event.toLowerCase()] || this.mapEvent[event + 'Event'] || this.mapEvent[event.toLowerCase() + 'event'];
|
||||
if (!eventCls) {
|
||||
try {
|
||||
eventCls = base.getClass(eventCls);
|
||||
this.mapEvent[event] = eventCls;
|
||||
} catch (ex) {
|
||||
console.console("§6插件 §b%s §6注册事件 §c%s §6失败 §4事件未找到!".format(name, event));
|
||||
console.ex(new Error("插件 %s 注册事件 %s 失败 事件未找到!".format(name, event)))
|
||||
return;
|
||||
}
|
||||
}
|
||||
return eventCls;
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断是否为一个有效的事件类
|
||||
* @param clz
|
||||
* @returns {*|boolean}
|
||||
*/
|
||||
this.isVaildEvent = function isVaildEvent(clz) {
|
||||
throw new Error("当前服务器不支持事件系统!");
|
||||
}
|
||||
|
||||
this.register = function register(eventCls, exec, priority, ignoreCancel) {
|
||||
throw new Error("当前服务器不支持事件系统!");
|
||||
}
|
||||
|
||||
this.unregister = function unregister(event, listener) {
|
||||
throw new Error("当前服务器不支持事件系统!");
|
||||
}
|
||||
|
||||
this.execute = function execute(name, exec, eventCls) {
|
||||
return function execute() {
|
||||
try {
|
||||
exec(arguments[arguments.length - 1]);
|
||||
} catch (ex) {
|
||||
console.console('§6插件 §b%s §6处理 §d%s §6事件时发生异常 §4%s'.format(name, this.class2Name(eventCls), ex));
|
||||
console.ex(ex);
|
||||
}
|
||||
}.bind(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加事件监听
|
||||
* @param jsp
|
||||
* @param event
|
||||
* @param exec {function}
|
||||
* @param priority [LOWEST,LOW,NORMAL,HIGH,HIGHEST,MONITOR]
|
||||
* @param ignoreCancel
|
||||
*/
|
||||
this.listen = function listen(jsp, event, exec, priority, ignoreCancel) {
|
||||
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, eventCls.name.substring(eventCls.name.lastIndexOf(".") + 1)));
|
||||
}.bind(this);
|
||||
var off = {
|
||||
event: eventCls,
|
||||
listener: listener,
|
||||
off: offExec
|
||||
};
|
||||
listenerMap[name].push(off);
|
||||
// noinspection JSUnresolvedVariable
|
||||
console.debug('插件 %s 注册事件 %s => %s'.format(name, eventCls.name.substring(eventCls.name.lastIndexOf(".") + 1), exec.name === '' ? '匿名方法' : exec.name));
|
||||
return off;
|
||||
}
|
||||
}
|
||||
var EventHandler = Object.assign(new EventHandlerDefault(), requireInternal('event'));
|
||||
// 映射事件名称
|
||||
console.info('%s 事件映射完毕 共计 %s 个事件!'.format(DetectServerType, EventHandler.mapEventName().toFixed(0)));
|
||||
module.exports = {
|
||||
on: EventHandler.listen.bind(EventHandler),
|
||||
disable: function (jsp) {
|
||||
var jspl = EventHandler.listenerMap[jsp.description.name];
|
||||
if (jspl) {
|
||||
jspl.forEach(function (t) t.off.call(EventHandler));
|
||||
delete EventHandler.listenerMap[jsp.description.name];
|
||||
}
|
||||
}
|
||||
};
|
@ -1,2 +0,0 @@
|
||||
/*global Java, base, module, exports, require*/
|
||||
module.exports = require('./msp.js').item;
|
@ -1,13 +0,0 @@
|
||||
/*global Java, base, module, exports, require*/
|
||||
function impl(name) {
|
||||
return require('../internal/' + DetectServerType + '/' + name, {warnNotFound: false});
|
||||
}
|
||||
|
||||
exports = module.exports = {
|
||||
command: impl('command'),
|
||||
event: impl('event'),
|
||||
permission: impl('permission'),
|
||||
server: impl('server'),
|
||||
task: impl('task'),
|
||||
item: impl('item')
|
||||
};
|
@ -1,2 +0,0 @@
|
||||
/*global Java, base, module, exports, require*/
|
||||
module.exports = require('./msp.js').permission;
|
@ -1,274 +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) {
|
||||
// // TODO ZIP类型插件加载
|
||||
// files.filter(function (file) {
|
||||
// return file.name.endsWith(".zip");
|
||||
// }).forEach(function (file) {
|
||||
// zip.unzip(fs.file(plugins_dir, file));
|
||||
// var dir = new File(plugins_dir, file.name.split(".")[0]);
|
||||
// // TODO 添加文件夹类型的插件兼容
|
||||
// });
|
||||
}
|
||||
|
||||
/**
|
||||
* JS类型插件预加载
|
||||
*/
|
||||
function loadJsPlugins(files) {
|
||||
files.filter(function (file) {
|
||||
return file.name.endsWith(".js")
|
||||
}).forEach(function (file) {
|
||||
try {
|
||||
loadPlugin(file);
|
||||
} catch (ex) {
|
||||
console.console('§6插件 §b%s §6初始化时发生错误 §4%s'.format(fs.path(file), ex.message));
|
||||
console.ex(ex);
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
function loadPlugin(file) {
|
||||
var update = fs.file(fs.file(file.parentFile, 'update'), file.name);
|
||||
if (update.exists()) {
|
||||
console.info('自动升级插件 %s'.format(file.name));
|
||||
fs.move(update, file, true);
|
||||
}
|
||||
var plugin = require(file, {
|
||||
cache: false,
|
||||
hook: function (origin) {
|
||||
return beforeLoadHook(origin);
|
||||
}
|
||||
})
|
||||
console.debug("插件编译结果: %s".format(JSON.stringify(plugin)));
|
||||
var desc = plugin.description;
|
||||
if (!desc || !desc.name) {
|
||||
console.warn("文件 %s 不存在 description 描述信息 无法加载插件!".format(file));
|
||||
} else {
|
||||
initPlugin(file, plugin);
|
||||
afterLoadHook(plugin);
|
||||
plugins[plugin.description.name] = plugin;
|
||||
console.info('载入插件 %s 版本 %s By %s'.format(desc.name, desc.version || '未知', desc.author || '未知'));
|
||||
}
|
||||
return plugin;
|
||||
}
|
||||
|
||||
function beforeLoadHook(origin) {
|
||||
var result = origin;
|
||||
// 处理 event 为了不影响 正常逻辑 event 还是手动require吧
|
||||
// result = result + 'var event = {}; module.exports.event = event;';
|
||||
// 注入 console 对象 // 给插件注入单独的 console
|
||||
result = result + 'var console = new Console(); module.exports.console = console;';
|
||||
// 插件注入 self 对象
|
||||
result = result + 'var self = {}; module.exports.self = self;';
|
||||
return result;
|
||||
}
|
||||
|
||||
function afterLoadHook(plugin) {
|
||||
// plugin.event.on = event.on.bind(plugin);
|
||||
// 给 console 添加插件名称
|
||||
plugin.console.name = plugin.description.name;
|
||||
// 赋值 self
|
||||
Object.assign(plugin.self, plugin);
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化插件内容(提供config,__DATA__等参数)
|
||||
*/
|
||||
function initPlugin(file, plugin) {
|
||||
// 初始化 __FILE__
|
||||
plugin.__FILE__ = file;
|
||||
// 初始化 __DATA__
|
||||
plugin.__DATA__ = plugin.dataFolder = fs.file(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 () {
|
||||
switch (arguments.length) {
|
||||
case 0:
|
||||
plugin.configFile.parentFile.mkdirs();
|
||||
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.description) {
|
||||
return [name];
|
||||
}
|
||||
if (!exports.plugins[name]) {
|
||||
throw new Error("插件 " + name + " 不存在!");
|
||||
}
|
||||
return [exports.plugins[name]];
|
||||
}
|
||||
|
||||
function checkAndRun(args, name, ext) {
|
||||
var pls = checkAndGet(args);
|
||||
for (var i in pls) {
|
||||
var jsp = pls[i];
|
||||
var exec = jsp[name];
|
||||
try {
|
||||
// 绑定方法的this到插件自身
|
||||
if (typeof exec === "function") exec.call(jsp);
|
||||
if (ext) 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
|
||||
}
|
@ -1,2 +0,0 @@
|
||||
/*global Java, base, module, exports, require*/
|
||||
module.exports = require('./msp.js').server;
|
@ -1,2 +0,0 @@
|
||||
/*global Java, base, module, exports, require*/
|
||||
module.exports = require('./msp.js').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';
|
||||
var log;
|
||||
var boot;
|
||||
var disable;
|
||||
'use strict'
|
||||
var global = this;
|
||||
/**
|
||||
* 初始化框架引擎
|
||||
* Init MiaoScriptEngine Runtime
|
||||
*/
|
||||
/*global base ScriptEngineContextHolder*/
|
||||
(function () {
|
||||
var loader;
|
||||
boot = function (root, logger) {
|
||||
log = logger;
|
||||
// 开发环境下初始化
|
||||
root = root || "src/main/resources";
|
||||
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 Files = Java.type('java.nio.file.Files')
|
||||
var Paths = Java.type('java.nio.file.Paths')
|
||||
var System = Java.type('java.lang.System')
|
||||
var Thread = Java.type('java.lang.Thread')
|
||||
var FutureTask = Java.type('java.util.concurrent.FutureTask')
|
||||
|
||||
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() {
|
||||
var classLoader = java.lang.Thread.currentThread().getContextClassLoader();
|
||||
pluginYml = classLoader.getResource("plugin.yml");
|
||||
if (pluginYml === null) {
|
||||
log.info("==================== ERROR ====================");
|
||||
log.info("异常的类加载器: " + classLoader.class.name);
|
||||
log.info("==================== ERROR ====================");
|
||||
throw Error('MiaoScript核心类库初始化失败 异常的类加载器!');
|
||||
// Check Class Loader, Sometimes Server will can't found plugin.yml file
|
||||
var classLoader = Thread.currentThread().contextClassLoader
|
||||
if (classLoader.getResource("bios.js") === null) {
|
||||
throw Error("Error class loader: " + classLoader.class.name + " Please contact the author MiaoWoo!")
|
||||
}
|
||||
return classLoader;
|
||||
}
|
||||
|
||||
function release(root, regex, replace) {
|
||||
var upath = pluginYml.getFile().substring(pluginYml.getFile().indexOf("/") + 1);
|
||||
var jarPath = java.net.URLDecoder.decode(upath.substring(0, upath.indexOf('!')));
|
||||
if (!java.nio.file.Files.exists(java.nio.file.Paths.get(jarPath))) {
|
||||
jarPath = "/" + jarPath;
|
||||
logger.info("Class loader compatible: " + classLoader.class.name)
|
||||
if (classLoader.parent) {
|
||||
logger.info("Parent class loader: " + classLoader.parent.class.name)
|
||||
}
|
||||
var jar = new java.util.jar.JarFile(jarPath);
|
||||
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();
|
||||
}
|
||||
})
|
||||
return classLoader
|
||||
}
|
||||
})();
|
||||
})()
|
||||
|
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 @@
|
||||
/**
|
||||
* 控制台输出类
|
||||
*/
|
||||
/*global base*/
|
||||
(function (global) {
|
||||
var Arrays = Java.type('java.util.Arrays');
|
||||
var Level = Java.type('java.util.logging.Level');
|
||||
global.ConsoleDefault = function ConsoleDefault(name) {
|
||||
Object.defineProperty(this, 'name', {
|
||||
get: function () {
|
||||
return this._name;
|
||||
}.bind(this),
|
||||
set: function (name) {
|
||||
this._name = name ? '[' + name + '] ' : '';
|
||||
this.prefix = name ? '§6[§cMS§6][§b' + name + '§6]§r ' : '§6[§bMiaoScript§6]§r ';
|
||||
}.bind(this)
|
||||
});
|
||||
this.name = name;
|
||||
this.log = this.info = function () {
|
||||
log.info(this.name + Array.prototype.join.call(arguments, ' '));
|
||||
};
|
||||
this.warn = function () {
|
||||
log.warning(this.name + Array.prototype.join.call(arguments, ' '));
|
||||
};
|
||||
this.error = function () {
|
||||
log.log(Level.SEVERE, this.name + Array.prototype.join.call(arguments, ' '));
|
||||
};
|
||||
this.debug = function () {
|
||||
log.info(this.name + '[DEBUG] ' + Array.prototype.join.call(arguments, ' '));
|
||||
};
|
||||
this.debug = global.debug ? this.debug : global.noop;
|
||||
this.sender = this.info;
|
||||
this.console = this.info;
|
||||
this.object = function (obj) {
|
||||
for (var i in obj) {
|
||||
this.log(i, '=>', obj[i])
|
||||
/// <reference path="./index.d.ts" />
|
||||
// @ts-check
|
||||
(
|
||||
/**
|
||||
* @param {{
|
||||
* info: (arg0: string) => void;
|
||||
* warn: (arg0: string) => void;
|
||||
* debug: (arg0: string) => void;
|
||||
* error: (arg0: string) => void;
|
||||
* warning: (arg0: string) => void;
|
||||
* }} logger
|
||||
*/
|
||||
function (logger) {
|
||||
function log() {
|
||||
logger.info(Array.prototype.join.call(arguments, ' '))
|
||||
}
|
||||
function warn() {
|
||||
logger.warn(Array.prototype.join.call(arguments, ' '))
|
||||
}
|
||||
function debug() {
|
||||
logger.debug(Array.prototype.join.call(arguments, ' '))
|
||||
}
|
||||
function error() {
|
||||
logger.error(Array.prototype.join.call(arguments, ' '))
|
||||
}
|
||||
function warning() {
|
||||
logger.warning(Array.prototype.join.call(arguments, ' '))
|
||||
}
|
||||
/**
|
||||
* @param {string} prefix
|
||||
*/
|
||||
function _proxy(prefix) {
|
||||
return function () {
|
||||
log('[' + prefix + ']', Array.prototype.join.call(arguments, ' '))
|
||||
}
|
||||
}
|
||||
this.ex = function (message, ex) {
|
||||
if (!ex) {
|
||||
this.console('§4' + message);
|
||||
ex = message;
|
||||
} else {
|
||||
this.console('§4' + message + ' ' + ex);
|
||||
}
|
||||
var track = ex.getStackTrace();
|
||||
if (track.class) {
|
||||
track = Arrays.asList(track)
|
||||
}
|
||||
track.forEach(function (stack) {
|
||||
if (stack.className.startsWith('<')) {
|
||||
this.console(' §e位于§c', stack.fileName, '=>§c', stack.methodName, '§4行', stack.lineNumber);
|
||||
} else {// %s.%s(§4%s:%s§c)
|
||||
this.console(' §e位于§c', stack.className + '.' + stack.methodName + '(§4' + stack.fileName + ':' + stack.lineNumber + '§c)');
|
||||
}
|
||||
}.bind(this));
|
||||
};
|
||||
}
|
||||
global.Console = ConsoleDefault;
|
||||
})(global);
|
||||
var logProxy = {
|
||||
log: log,
|
||||
info: log,
|
||||
ex: log,
|
||||
trace: global.ScriptEngineLoggerLevel === "trace" ? _proxy('TRACE') : global.noop,
|
||||
debug: global.debug ? logger.debug ? debug : _proxy('DEBUG') : global.noop,
|
||||
warn: _proxy('WARN'),
|
||||
error: _proxy('ERROR')
|
||||
}
|
||||
if (logger.warn) {
|
||||
logProxy.warn = warn
|
||||
}
|
||||
if (logger.warning) {
|
||||
logProxy.warn = warning
|
||||
}
|
||||
if (logger.error) {
|
||||
logProxy.error = error
|
||||
}
|
||||
return logProxy
|
||||
})
|
||||
|
@ -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,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,50 +0,0 @@
|
||||
/**
|
||||
* 补丁和方法扩展
|
||||
*/
|
||||
|
||||
(function () {
|
||||
// Object.assign Polyfill
|
||||
if (!Object.assign) {
|
||||
Object.defineProperty(Object, "assign", {
|
||||
enumerable: false,
|
||||
configurable: true,
|
||||
writable: true,
|
||||
value: function(target) {
|
||||
"use strict";
|
||||
if (target === undefined || target === null)
|
||||
throw new TypeError("Cannot convert first argument to object");
|
||||
var to = Object(target);
|
||||
for (var i = 1; i < arguments.length; i++) {
|
||||
var nextSource = arguments[i];
|
||||
if (nextSource === undefined || nextSource === null) continue;
|
||||
var keysArray = Object.keys(Object(nextSource));
|
||||
for (var nextIndex = 0, len = keysArray.length; nextIndex < len; nextIndex++) {
|
||||
var nextKey = keysArray[nextIndex];
|
||||
var desc = Object.getOwnPropertyDescriptor(nextSource, nextKey);
|
||||
if (desc !== undefined && desc.enumerable) to[nextKey] = nextSource[nextKey];
|
||||
}
|
||||
}
|
||||
return to;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// // JSON快捷方法
|
||||
if(!Object.toJson){
|
||||
Object.defineProperty(Object.prototype, "toJson", {
|
||||
enumerable: false,
|
||||
value: function() {
|
||||
return JSON.stringify(this);
|
||||
}
|
||||
});
|
||||
}
|
||||
// Object.prototype.toJson = function () {
|
||||
// return JSON.stringify(this);
|
||||
// };
|
||||
|
||||
// // YAML快速生成
|
||||
// var yaml = require('modules/yaml');
|
||||
// Object.prototype.toYaml = function () {
|
||||
// return yaml.safeDump(this);
|
||||
// };
|
||||
})();
|
@ -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))
|
||||
};
|
||||
})();
|
@ -1,152 +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(file) {
|
||||
// noinspection JSUnresolvedVariable
|
||||
file.parentFile.mkdirs();
|
||||
};
|
||||
/**
|
||||
* 创建文件
|
||||
* @param file
|
||||
*/
|
||||
function create(file) {
|
||||
f = file(file);
|
||||
if (!f.exists()) {
|
||||
mkdirs(f);
|
||||
f.createNewFile();
|
||||
}
|
||||
};
|
||||
/**
|
||||
* 获得文件规范路径
|
||||
* @param file
|
||||
* @returns {*}
|
||||
*/
|
||||
function path(file) {
|
||||
// noinspection JSUnresolvedVariable
|
||||
return file.canonicalPath;
|
||||
};
|
||||
/**
|
||||
* 复制文件
|
||||
* @param inputStream 输入流
|
||||
* @param target 目标文件
|
||||
* @param override 是否覆盖
|
||||
*/
|
||||
function copy(inputStream, target, override) {
|
||||
Files.copy(inputStream, target.toPath(), StandardCopyOption[override ? 'REPLACE_EXISTING' : 'ATOMIC_MOVE']);
|
||||
};
|
||||
/**
|
||||
* 读取文件
|
||||
* @param file 文件路径
|
||||
*/
|
||||
function read(f) {
|
||||
var file = exports.file(f);
|
||||
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 = new File(path);
|
||||
file.getParentFile().mkdirs();
|
||||
Files.write(file.toPath(),
|
||||
content.getBytes("UTF-8"),
|
||||
override ? StandardCopyOption['REPLACE_EXISTING'] : StandardCopyOption['ATOMIC_MOVE']);
|
||||
};
|
||||
/**
|
||||
* 列出目录文件
|
||||
* @param path
|
||||
*/
|
||||
function list(path) {
|
||||
var dir = file(path);
|
||||
if (dir.isDirectory()) {
|
||||
return Files.list(dir.toPath());
|
||||
}
|
||||
console.debug('路径', path, '不是一个目录 返回空数组!');
|
||||
return [];
|
||||
};
|
||||
/**
|
||||
* 移动文件
|
||||
* @param src 原始目录
|
||||
* @param des 目标目录
|
||||
* @param override 是否覆盖
|
||||
*/
|
||||
function move(src, des, override) {
|
||||
Files.move(file(src).toPath(), file(des).toPath(),
|
||||
override ? StandardCopyOption['REPLACE_EXISTING'] : StandardCopyOption['ATOMIC_MOVE'])
|
||||
};
|
||||
|
||||
function del(file) {
|
||||
file = exports.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());
|
||||
}
|
||||
|
||||
exports = module.exports = {
|
||||
canonical: path,
|
||||
concat: concat,
|
||||
create: create,
|
||||
mkdirs: mkdirs,
|
||||
file: file,
|
||||
path: path,
|
||||
copy: copy,
|
||||
read: read,
|
||||
save: save,
|
||||
list: list,
|
||||
move: move,
|
||||
del: del
|
||||
}
|
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();
|
||||
loadExt();
|
||||
loadRequire();
|
||||
try {
|
||||
loadServerLib();
|
||||
loadPlugins();
|
||||
} catch (ex) {
|
||||
console.console("§4初始化插件基础系统库错误:§c", ex);
|
||||
console.ex(ex);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 初始化核心
|
||||
*/
|
||||
function loadCore() {
|
||||
// 加载基础模块
|
||||
load(root + '/core/ext.js');
|
||||
// 加载Console
|
||||
load(root + '/core/console.js');
|
||||
// 探测服务器类型
|
||||
load(root + '/core/detect.js');
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化模块
|
||||
*/
|
||||
function loadRequire() {
|
||||
global.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');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 加载补丁
|
||||
*/
|
||||
function loadExt() {
|
||||
java.nio.file.Files.list(new java.io.File(root, 'core/ext').toPath()).forEach(function (path) {
|
||||
console.log('加载扩展类库', path);
|
||||
try {
|
||||
load(path.toFile());
|
||||
} catch (ex) {
|
||||
console.ex(ex);
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 加载系统类库
|
||||
*/
|
||||
function loadServerLib() {
|
||||
var task = require('api/task');
|
||||
global.setTimeout = function 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);
|
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. 如果模块以 `./` `../` 开头
|
||||
* a. 尝试使用 resolveAsFile(dir/xx) 加载文件
|
||||
* b. 尝试使用 resolveAsDirectory(dir/xx) 加载目录
|
||||
* 3. 尝试去 root root/core root/modules => xx 加载模块
|
||||
* 3. 尝试去 root root/node_modules => xx 加载模块
|
||||
* a. 尝试使用 resolveAsFile(xx/xx) 加载文件
|
||||
* b. 尝试使用 resolveAsDirectory(xx/xx) 加载目录
|
||||
* 4. 抛出 not found 异常
|
||||
@ -23,247 +23,749 @@
|
||||
* 2. 如果 xx/index.js 存在 则使用 resolveAsFile(xx/index.js) 加载
|
||||
* 3. 如果 xx/index.json 存在 则使用 `xx/index.json` 解析为对象加载 并停止执行
|
||||
* 暂不支持 4. 如果 xx/index.msm 是一个文件 则使用MScript解析器解析 并停止执行
|
||||
* 注: MiaoScript 暂不支持多层 modules 加载 暂时不需要(估计以后也不会需要)
|
||||
*/
|
||||
/*global Java, base*/
|
||||
(function (parent) {
|
||||
'use strict';
|
||||
var File = Java.type("java.io.File");
|
||||
var separatorChar = File.separatorChar;
|
||||
var cacheDir = parent + separatorChar + "runtime";
|
||||
var paths = [parent, parent + separatorChar + 'core', parent + separatorChar + 'api', parent + separatorChar + 'modules'];
|
||||
|
||||
try{
|
||||
base.delete(cacheDir);
|
||||
} catch (ex) {
|
||||
console.ex(ex);
|
||||
}
|
||||
|
||||
/// <reference path="./index.d.ts" />
|
||||
// @ts-check
|
||||
(
|
||||
/**
|
||||
* 判断是否为一个文件
|
||||
* @param file
|
||||
* @returns {*}
|
||||
* @private
|
||||
* @param {string} root
|
||||
*/
|
||||
function _isFile(file) {
|
||||
return file.isFile && file.isFile();
|
||||
}
|
||||
function (root) {
|
||||
'use strict'
|
||||
var System = Java.type('java.lang.System')
|
||||
|
||||
/**
|
||||
* 获得文件规范路径
|
||||
* @param file
|
||||
* @returns {*}
|
||||
* @private
|
||||
*/
|
||||
function _canonical(file) {
|
||||
// noinspection JSUnresolvedVariable
|
||||
return file.canonicalPath;
|
||||
}
|
||||
var File = Java.type('java.io.File')
|
||||
var Paths = Java.type('java.nio.file.Paths')
|
||||
var Files = Java.type('java.nio.file.Files')
|
||||
var StandardCopyOption = Java.type('java.nio.file.StandardCopyOption')
|
||||
|
||||
/**
|
||||
* 获得缓存的文件名称
|
||||
* @param file
|
||||
* @returns {string}
|
||||
* @private
|
||||
*/
|
||||
function _cacheFile(file) {
|
||||
return _canonical(file).replace(parent, cacheDir);
|
||||
}
|
||||
var TarInputStream = Java.type('org.kamranzafar.jtar.TarInputStream')
|
||||
var GZIPInputStream = Java.type('java.util.zip.GZIPInputStream')
|
||||
var BufferedInputStream = Java.type('java.io.BufferedInputStream')
|
||||
|
||||
/**
|
||||
* 解析模块名称为文件
|
||||
* 按照下列顺序查找
|
||||
* 当前目录 ./
|
||||
* 父目录 ../
|
||||
* 核心目录 /core
|
||||
* 模块目录 /modules
|
||||
* @param name 模块名称
|
||||
* @param parent 父目录
|
||||
*/
|
||||
function resolve(name, parent) {
|
||||
name = _canonical(name) || name;
|
||||
// 解析本地目录
|
||||
if (name.startsWith('./') || name.startsWith('../')) {
|
||||
return resolveAsFile(parent, name) || resolveAsDirectory(parent, name) || undefined;
|
||||
} else {
|
||||
// 查找可能存在的路径
|
||||
for (var i in paths) {
|
||||
var path = paths[i];
|
||||
var result = resolveAsFile(path, name) || resolveAsDirectory(path, name);
|
||||
if (result) {
|
||||
return result;
|
||||
var 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')
|
||||
var Executors = Java.type('java.util.concurrent.Executors')
|
||||
var TimeUnit = Java.type('java.util.concurrent.TimeUnit')
|
||||
var separatorChar = File.separatorChar
|
||||
|
||||
var MS_NODE_PATH = System.getenv("MS_NODE_PATH") || root + separatorChar + 'node_modules'
|
||||
var MS_NODE_REGISTRY = System.getenv("MS_NODE_REGISTRY") || 'https://registry.npmmirror.com'
|
||||
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'
|
||||
var MS_NETWORK_CONNECT_TIMEOUT = System.getenv("MS_NETWORK_CONNECT_TIMEOUT") || 5000
|
||||
var MS_NETWORK_READ_TIMEOUT = System.getenv("MS_NETWORK_TIMEOUT") || 45000
|
||||
var MS_NETWORK_DOWNLOAD_TIMEOUT = System.getenv("MS_NETWORK_DOWNLOAD_TIMEOUT") || 60000
|
||||
var MS_NETWORK_USE_CACHES = System.getenv("MS_NETWORK_USE_CACHES") || true
|
||||
|
||||
var CoreModules = [
|
||||
"assert", "async_hooks", "Buffer", "child_process", "cluster", "crypto",
|
||||
"dgram", "dns", "domain", "events", "fs", "http", "http2", "https",
|
||||
"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;
|
||||
}
|
||||
|
||||
/**
|
||||
* 解析文件
|
||||
* @returns {*}
|
||||
*/
|
||||
function resolveAsFile(dir, file) {
|
||||
file = ext.notNull(dir) ? new File(dir, file) : new File(file);
|
||||
// 直接文件
|
||||
if (file.isFile()) {
|
||||
return file;
|
||||
function __DynamicDisable__() {
|
||||
base.save(cacheModuleIdsFile, JSON.stringify(upgradeMode ? {} : cacheModuleIds))
|
||||
for (var cacheModule in cacheModules) {
|
||||
delete cacheModules[cacheModule]
|
||||
}
|
||||
cacheModules = {}
|
||||
for (var cacheModuleId in cacheModuleIds) {
|
||||
delete cacheModuleIds[cacheModuleId]
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 解析目录
|
||||
* @returns {*}
|
||||
*/
|
||||
function resolveAsDirectory(dir, file) {
|
||||
dir = ext.notNull(dir) ? new File(dir, file) : new File(file);
|
||||
var _package = new File(dir, 'package.json');
|
||||
if (_package.exists()) {
|
||||
var json = JSON.parse(base.read(_package));
|
||||
if (json.main) {
|
||||
return resolveAsFile(dir, json.main);
|
||||
function __setUpgradeMode__(status) {
|
||||
upgradeMode = status
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {any} parent
|
||||
*/
|
||||
function getRequire(parent) {
|
||||
/**
|
||||
* @type {any} require
|
||||
*/
|
||||
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');
|
||||
}
|
||||
|
||||
/**
|
||||
* 后缀检测和添加
|
||||
* @param fileName 文件名称
|
||||
* @param ext 后缀
|
||||
* @returns {*}
|
||||
*/
|
||||
function normalizeName(fileName, ext) {
|
||||
var extension = ext || '.js';
|
||||
if (fileName.endsWith(extension)) {
|
||||
return fileName;
|
||||
}
|
||||
return fileName + extension;
|
||||
}
|
||||
|
||||
/**
|
||||
* 编译模块
|
||||
* @param id 模块ID
|
||||
* @param name 模块名称
|
||||
* @param file 模块文件
|
||||
* @param optional 附加选项
|
||||
* @returns {Object}
|
||||
*/
|
||||
function getCacheModule(id, name, file, optional) {
|
||||
var module = cacheModules[id];
|
||||
if (optional.cache && module) {
|
||||
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);
|
||||
function initVersionLock() {
|
||||
try {
|
||||
var version_lock_url = MS_SCRIPT_PACKAGE_CENTER + '?name=version_lock' + (global.debug ? '-debug' : '')
|
||||
VersionLockModules = JSON.parse(fetchContent(version_lock_url, 5000))
|
||||
try {
|
||||
VersionLockModules = __assign(VersionLockModules, JSON.parse(base.read(localVersionLockFile)))
|
||||
} catch (e) {
|
||||
}
|
||||
} catch (error) {
|
||||
console.warn("无法获取到最新的版本锁定信息 使用默认配置.")
|
||||
console.warn("InitVersionLock Error:", error)
|
||||
console.debug(error)
|
||||
VersionLockModules = {
|
||||
"@babel/standalone": "7.12.18",
|
||||
"crypto-js": "3.3.0",
|
||||
"core-js": "3.33.1"
|
||||
}
|
||||
}
|
||||
if (_canonical(file).endsWith('.json')) {
|
||||
compileJson(module, file, optional);
|
||||
console.info('Lock module version List:')
|
||||
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) {
|
||||
console.console('§4警告! §c模块§a', name, '§c编译失败! §4ERR:', ex);
|
||||
console.ex(ex);
|
||||
require.main = mainRequire = require
|
||||
return require
|
||||
}
|
||||
return module;
|
||||
}
|
||||
|
||||
/**
|
||||
* 预编译JS
|
||||
* @param file JS文件
|
||||
* @param optional 附加选项
|
||||
* @returns {Object}
|
||||
*/
|
||||
function compileJs(module, file, optional) {
|
||||
var cacheFile = _cacheFile(file);
|
||||
var origin = base.read(file);
|
||||
if (optional.hook) {
|
||||
origin = optional.hook(origin);
|
||||
function loadCoreScript(name) {
|
||||
return engineLoad({
|
||||
script: fetchContent(MS_SCRIPT_PACKAGE_CENTER + '?name=' + name, 5000),
|
||||
name: 'core/' + name + '.js'
|
||||
})
|
||||
}
|
||||
base.save(cacheFile, "(function __init__(module, exports, require, __dirname, __filename) {" + origin + "});");
|
||||
// 使用 load 可以保留行号和文件名称
|
||||
var compiledWrapper = engineLoad(cacheFile);
|
||||
try {
|
||||
base.delete(cacheFile);
|
||||
} catch (ex) {
|
||||
cacheFile.deleteOnExit();
|
||||
|
||||
if (typeof parent === 'string') {
|
||||
parent = new File(parent)
|
||||
}
|
||||
compiledWrapper.apply(module.exports, [
|
||||
module, module.exports, module.require, file.parentFile, file
|
||||
]);
|
||||
module.loaded = true;
|
||||
}
|
||||
var mainRequire = undefined
|
||||
/**
|
||||
* require 支持的后缀
|
||||
* @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")
|
||||
})
|
||||
|
||||
/**
|
||||
* 预编译Json
|
||||
* @param file Json 文件
|
||||
* @param optional 附加选项
|
||||
* @returns {Object}
|
||||
*/
|
||||
function compileJson(module, file, optional) {
|
||||
module.exports = JSON.parse(base.read(file));
|
||||
module.loaded = true;
|
||||
}
|
||||
printRequireInfo()
|
||||
initCacheModuleIds()
|
||||
initVersionLock()
|
||||
|
||||
/**
|
||||
* 加载模块
|
||||
* @param name 模块名称
|
||||
* @param path 路径
|
||||
* @param optional 附加选项
|
||||
* @returns {*}
|
||||
* @private
|
||||
*/
|
||||
function _require(name, path, optional) {
|
||||
var file = new File(name);
|
||||
file = _isFile(file) ? file : resolve(name, path);
|
||||
optional = Object.assign({cache: true, warnNotFound: true}, optional);
|
||||
if (file === undefined) {
|
||||
if (optional.warnNotFound) {
|
||||
console.console('§c目录§b', path, '§c下模块§a', name, '§c加载失败! §4未找到该模块!');
|
||||
}
|
||||
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);
|
||||
});
|
||||
return initRequireLoader(getRequire({
|
||||
id: 'main',
|
||||
path: root
|
||||
}))
|
||||
})
|
||||
|
@ -1,99 +0,0 @@
|
||||
'use strict';
|
||||
/**
|
||||
* Bukkit 命令相关类
|
||||
*/
|
||||
|
||||
/*global Java, base, module, exports, require, __FILE__*/
|
||||
var ref = require('modules/reflect');
|
||||
var bukkit = require('./server');
|
||||
var plugin = bukkit.plugin.self;
|
||||
var commandMap = ref.on(bukkit.plugin.manager).get('commandMap').get();
|
||||
var PluginCommand = Java.type('org.bukkit.command.PluginCommand');
|
||||
|
||||
var StringUtil = Java.type('org.bukkit.util.StringUtil');
|
||||
|
||||
var ArrayList = Java.type('java.util.ArrayList');
|
||||
var Arrays = Java.type('java.util.Arrays');
|
||||
|
||||
function enable(jsp) {
|
||||
var commands = jsp.description.commands;
|
||||
if (commands) {
|
||||
var pluginCmds = [];
|
||||
for (var name in commands) {
|
||||
var command = commands[name];
|
||||
if (typeof command !== 'object') continue;
|
||||
var newCmd = create(jsp, name);
|
||||
if (command.description) newCmd.setDescription(command.description);
|
||||
if (command.usage) newCmd.setUsage(command.usage);
|
||||
if (command.aliases) newCmd.setAliases(Arrays.asList(command.aliases));
|
||||
if (command.permission) newCmd.setPermission(command.permission);
|
||||
if (command['permission-message']) newCmd.setPermissionMessage(command['permission-message']);
|
||||
pluginCmds.push(newCmd);
|
||||
console.debug('插件 %s 注册命令 %s ...'.format(jsp.description.name, name));
|
||||
}
|
||||
commandMap.registerAll(jsp.description.name, Arrays.asList(pluginCmds));
|
||||
}
|
||||
}
|
||||
|
||||
function disable(jsp) {
|
||||
var commands = jsp.description.commands;
|
||||
if (commands) {
|
||||
for (var name in commands) {
|
||||
//TODO 删除插件命令
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function get(name) {
|
||||
return commandMap.getCommand(name);
|
||||
}
|
||||
|
||||
function create(jsp, name) {
|
||||
return register(jsp, ref.on(PluginCommand).create(name, plugin).get());
|
||||
}
|
||||
|
||||
function register(jsp, cmd) {
|
||||
commandMap.register(jsp.description.name, cmd);
|
||||
return cmd;
|
||||
}
|
||||
|
||||
function on(jsp, name, exec) {
|
||||
var c = get(name) || create(jsp, name);
|
||||
console.debug('插件 %s 设置命令 %s(%s) 执行器 ...'.format(jsp.description.name, name, c));
|
||||
if (exec.cmd) {
|
||||
// 必须指定需要实现的接口类型 否则MOD服会报错
|
||||
c.setExecutor(new org.bukkit.command.CommandExecutor({
|
||||
onCommand: function (sender, cmd, command, args) {
|
||||
try {
|
||||
return exec.cmd(sender, command, args);
|
||||
} catch (ex) {
|
||||
console.console('§6玩家 §a%s §6执行 §b%s §6插件 §d%s %s §6命令时发生异常 §4%s'.format(sender.name, jsp.description.name, command, Java.from(args).join(' '), ex));
|
||||
console.ex(ex);
|
||||
}
|
||||
}
|
||||
}));
|
||||
}
|
||||
if (exec.tab) {
|
||||
// 必须指定需要实现的接口类型 否则MOD服会报错
|
||||
c.setTabCompleter(new org.bukkit.command.TabCompleter({
|
||||
onTabComplete: function (sender, cmd, command, args) {
|
||||
try {
|
||||
var completions = new ArrayList();
|
||||
var token = args[args.length - 1];
|
||||
StringUtil.copyPartialMatches(token, Arrays.asList(exec.tab(sender, command, args)), completions);
|
||||
return completions;
|
||||
} catch (ex) {
|
||||
console.console('§6玩家 §a%s §6执行 §b%s §6插件 §d%s %s §6补全时发生异常 §4%s'.format(sender.name, jsp.description.name, command, Java.from(args).join(' '), ex));
|
||||
console.ex(ex);
|
||||
}
|
||||
}
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
exports.enable = enable;
|
||||
|
||||
exports.on = on;
|
||||
exports.off = function () {
|
||||
|
||||
};
|
@ -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,112 +0,0 @@
|
||||
'use strict';
|
||||
/**
|
||||
* Bukkit基础操作
|
||||
* Created by 蒋天蓓 on 2017/2/9 0009.
|
||||
*/
|
||||
|
||||
/*global Java, base, module, exports, require, __FILE__*/
|
||||
var Bukkit = MServer;
|
||||
var Server = Bukkit.server;
|
||||
var PluginManager = Server.pluginManager;
|
||||
exports.$ = Bukkit;
|
||||
/**
|
||||
* 获取NMS版本
|
||||
*/
|
||||
exports.nmsVersion = Bukkit.server.class.name.split('.')[3];
|
||||
/**
|
||||
* 获取NMS类
|
||||
*/
|
||||
exports.nmsCls = function (name) {
|
||||
return Java.type(['net.minecraft.server', exports.nmsVersion, name].join('.'));
|
||||
};
|
||||
/**
|
||||
* 获取玩家
|
||||
*/
|
||||
exports.player = function () {
|
||||
switch (arguments.length) {
|
||||
case 0:
|
||||
return undefined;
|
||||
case 1:
|
||||
return Server.getPlayer(arguments[0]);
|
||||
default:
|
||||
return Server.getPlayerExtra(arguments[0]);
|
||||
}
|
||||
};
|
||||
/**
|
||||
* 获取在线玩家
|
||||
*/
|
||||
exports.players = function () {
|
||||
switch (arguments.length) {
|
||||
case 1:
|
||||
return Server.onlinePlayers.forEach(arguments[0]);
|
||||
default:
|
||||
return Server.onlinePlayers;
|
||||
}
|
||||
};
|
||||
/**
|
||||
* 插件管理
|
||||
* @type {{manager: *, get: exports.plugin.get, load: exports.plugin.load}}
|
||||
*/
|
||||
exports.plugin = {
|
||||
/**
|
||||
* 插件管理工具
|
||||
*/
|
||||
manager: PluginManager,
|
||||
/**
|
||||
* 获得插件实例
|
||||
* @param name 插件名称
|
||||
* @returns {*}
|
||||
*/
|
||||
get: function (name) {
|
||||
return PluginManager.getPlugin(name);
|
||||
},
|
||||
/**
|
||||
* 载入插件 并且返回结果
|
||||
* @param name 插件名称
|
||||
* @returns {*}
|
||||
*/
|
||||
load: function (name) {
|
||||
var plugin = this.get(name);
|
||||
if (ext.notNull(plugin) && !plugin.isEnabled()) {
|
||||
PluginManager.enablePlugin(plugin);
|
||||
}
|
||||
return PluginManager.isPluginEnabled(name);
|
||||
},
|
||||
self: PluginManager.getPlugin('MiaoScript')
|
||||
};
|
||||
/**
|
||||
* 公告
|
||||
* @param message 消息
|
||||
*/
|
||||
exports.broadcast = function (message) {
|
||||
Bukkit.broadcastMessage(message);
|
||||
};
|
||||
/**
|
||||
* 执行名称
|
||||
* @param player 玩家
|
||||
* @param command 命令
|
||||
*/
|
||||
exports.command = function (player, command) {
|
||||
Bukkit.dispatchCommand(player, command);
|
||||
};
|
||||
/**
|
||||
* 执行控制台命令
|
||||
* @param command 命令
|
||||
*/
|
||||
exports.console = function (command) {
|
||||
exports.command(Bukkit.getConsoleSender(), command);
|
||||
};
|
||||
/**
|
||||
* 玩家以OP权限执行命令
|
||||
* @param player
|
||||
* @param exper
|
||||
*/
|
||||
exports.opcommand = function (player, exper) {
|
||||
var origin = player.isOp();
|
||||
player.setOp(true);
|
||||
try {
|
||||
exports.command(player, exper);
|
||||
} finally {
|
||||
player.setOp(origin);
|
||||
}
|
||||
};
|
@ -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,130 +0,0 @@
|
||||
'use strict';
|
||||
/**
|
||||
* Sponge 命令相关类
|
||||
*/
|
||||
|
||||
/*global Java, base, module, exports, require, __FILE__*/
|
||||
var Sponge = MServer;
|
||||
var server = require('./server');
|
||||
var plugin = server.plugin.self;
|
||||
|
||||
var CommandManager = server.CommandManager;
|
||||
|
||||
var CommandSpec = Java.type('org.spongepowered.api.command.spec.CommandSpec');
|
||||
var CommandCallable = Java.type('org.spongepowered.api.command.CommandCallable');
|
||||
var CommandResult = Java.type('org.spongepowered.api.command.CommandResult');
|
||||
|
||||
var Text = Java.type('org.spongepowered.api.text.Text');
|
||||
|
||||
var Optional = Java.type('java.util.Optional');
|
||||
|
||||
var ArrayList = Java.type('java.util.ArrayList');
|
||||
var Arrays = Java.type('java.util.Arrays');
|
||||
|
||||
var commandMap=[];
|
||||
|
||||
var SimpleCommandCallable = function (name) {
|
||||
var that = this;
|
||||
this.name = name;
|
||||
this.cmd = noop;
|
||||
this.tab = function() { return new ArrayList(); };
|
||||
this.callable = new CommandCallable({
|
||||
//CommandResult process(CommandSource source, String arguments) throws CommandException;
|
||||
process: function (src, args) {
|
||||
return that.cmd(src, name, args.split(" ")) ? CommandResult.success() : CommandResult.empty();
|
||||
},
|
||||
//List<String> getSuggestions(CommandSource source, String arguments, @Nullable Location<World> targetPosition) throws CommandException;
|
||||
getSuggestions: function (src, args, target) {
|
||||
return that.tab(src, name, args.split(" "));
|
||||
},
|
||||
//boolean testPermission(CommandSource source);
|
||||
testPermission: function () {
|
||||
return true;
|
||||
},
|
||||
//Optional<Text> getShortDescription(CommandSource source);
|
||||
getShortDescription: function () {
|
||||
return Optional.of(Text.of(""));
|
||||
},
|
||||
//Optional<Text> getHelp(CommandSource source);
|
||||
getHelp: function () {
|
||||
return Optional.of(Text.of(""));
|
||||
},
|
||||
//Text getUsage(CommandSource source);
|
||||
getUsage: function () {
|
||||
return Text.of('');
|
||||
}
|
||||
});
|
||||
this.setExecutor = function (exec) {
|
||||
that.cmd = exec;
|
||||
};
|
||||
this.setTabCompleter = function (exec) {
|
||||
that.tab = exec;
|
||||
}
|
||||
}
|
||||
|
||||
function enable(jsp) {
|
||||
var pname = jsp.description.name;
|
||||
var commands = jsp.description.commands;
|
||||
if (commands) {
|
||||
var pluginCmds = [];
|
||||
for (var name in commands) {
|
||||
var command = commands[name];
|
||||
if (typeof command !== 'object') continue;
|
||||
create(jsp, name)
|
||||
console.debug('插件 %s 注册命令 %s ...'.format(jsp.description.name, name));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function get(name) {
|
||||
}
|
||||
|
||||
function create(jsp, name) {
|
||||
var commandKey = jsp.description.name.toLowerCase() + ":" + name;
|
||||
if(!commandMap[commandKey]){
|
||||
commandMap[commandKey] = new SimpleCommandCallable();
|
||||
commandMap[commandKey].name = name;
|
||||
Sponge.getCommandManager().register(plugin, commandMap[commandKey].callable, name, commandKey);
|
||||
}
|
||||
return commandMap[commandKey];
|
||||
}
|
||||
|
||||
function on(jsp, name, exec) {
|
||||
var c = create(jsp, name);
|
||||
console.debug('插件 %s 设置命令 %s 执行器 ...'.format(jsp.description.name, name));
|
||||
if (exec.cmd) {
|
||||
c.setExecutor(function (sender, command, args) {
|
||||
try {
|
||||
return exec.cmd(sender, command, args);
|
||||
} catch (ex) {
|
||||
console.log(args)
|
||||
console.console('§6玩家 §a%s §6执行 §b%s §6插件 §d%s %s §6命令时发生异常 §4%s'.format(sender.name, jsp.description.name, command, args, ex));
|
||||
console.ex(ex);
|
||||
}
|
||||
});
|
||||
}
|
||||
if (exec.tab) {
|
||||
c.setTabCompleter(function (sender, command, args) {
|
||||
try {
|
||||
var token = args[args.length - 1];
|
||||
return Arrays.asList(exec.tab(sender, command, args));
|
||||
} catch (ex) {
|
||||
console.console('§6玩家 §a%s §6执行 §b%s §6插件 §d%s %s §6补全时发生异常 §4%s'.format(sender.name, jsp.description.name, command, args, ex));
|
||||
console.ex(ex);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
var exist = Sponge.getCommandManager().getOwnedBy(plugin);
|
||||
exist.forEach(function(commandMapping) {
|
||||
if (!commandMapping.getAllAliases().contains("ms")) {
|
||||
Sponge.getCommandManager().removeMapping(commandMapping);
|
||||
}
|
||||
});
|
||||
|
||||
exports = module.exports = {
|
||||
enable: enable,
|
||||
on: on,
|
||||
off: noop
|
||||
}
|
@ -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.name.substring(clazz.name.lastIndexOf(".") + 1).replace(/\$/g, '.').toLowerCase();
|
||||
}
|
||||
|
||||
function register(eventCls, exec, priority, ignoreCancel) {
|
||||
var listener = new EventListener({
|
||||
handle: exec
|
||||
});
|
||||
MServer.getEventManager().registerListener(this.plugin, eventCls, Order[priorityMap[priority]], listener);
|
||||
return listener;
|
||||
}
|
||||
|
||||
function unregister(event, listener) {
|
||||
MServer.getEventManager().unregisterListeners(listener);
|
||||
}
|
||||
exports = module.exports = {
|
||||
baseEventDir: 'org/spongepowered/api/event',
|
||||
isVaildEvent: isVaildEvent,
|
||||
class2Name: class2Name,
|
||||
register: register,
|
||||
unregister: unregister
|
||||
};
|
@ -1,66 +0,0 @@
|
||||
'use strict';
|
||||
/**
|
||||
* Sponge基础操作
|
||||
* Created by 蒋天蓓 on 2017/10/27 0009.
|
||||
*/
|
||||
|
||||
/*global Java, base, module, exports, require, __FILE__*/
|
||||
var Sponge = MServer;
|
||||
var Server = Sponge.server;
|
||||
var PluginManager = Sponge.pluginManager;
|
||||
exports.$ = Sponge;
|
||||
/**
|
||||
* 插件管理
|
||||
* @type {{manager: *, get: exports.plugin.get, load: exports.plugin.load}}
|
||||
*/
|
||||
exports.plugin = {
|
||||
/**
|
||||
* 插件管理工具
|
||||
*/
|
||||
manager: PluginManager,
|
||||
/**
|
||||
* 获得插件实例
|
||||
* @param name 插件名称
|
||||
* @returns {*}
|
||||
*/
|
||||
get: function (name) {
|
||||
return PluginManager.getPlugin(name);
|
||||
},
|
||||
/**
|
||||
* 载入插件 并且返回结果
|
||||
* @param name 插件名称
|
||||
* @returns {*}
|
||||
*/
|
||||
load: function (name) {
|
||||
var plugin = this.get(name);
|
||||
if (ext.notNull(plugin) && !plugin.isEnabled()) {
|
||||
PluginManager.enablePlugin(plugin);
|
||||
}
|
||||
return PluginManager.isPluginEnabled(name);
|
||||
},
|
||||
self: PluginManager.getPlugin('miaoscript').get()
|
||||
};
|
||||
/**
|
||||
* 获取玩家
|
||||
*/
|
||||
exports.player = function () {
|
||||
switch (arguments.length) {
|
||||
case 0:
|
||||
return undefined;
|
||||
case 1:
|
||||
return Server.getPlayer(arguments[0]).get();
|
||||
default:
|
||||
return Server.getPlayer(arguments[0]).get();
|
||||
}
|
||||
};
|
||||
/**
|
||||
* 获取在线玩家
|
||||
*/
|
||||
exports.players = function () {
|
||||
switch (arguments.length) {
|
||||
case 1:
|
||||
return Server.onlinePlayers.forEach(arguments[0]);
|
||||
default:
|
||||
return Server.onlinePlayers;
|
||||
}
|
||||
};
|
@ -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,115 +0,0 @@
|
||||
'use strict';
|
||||
/**
|
||||
* HTTP 网络类
|
||||
* Created by 蒋天蓓 on 2017/2/9 0009.
|
||||
*/
|
||||
|
||||
/*global Java, base, module, exports, require, __FILE__*/
|
||||
|
||||
var URL = Java.type("java.net.URL");
|
||||
var Files = Java.type("java.nio.file.Files");
|
||||
var Paths = Java.type("java.nio.file.Paths");
|
||||
var String = Java.type("java.lang.String");
|
||||
|
||||
var HttpURLConnection = Java.type("java.net.HttpURLConnection");
|
||||
var HttpsURLConnection = Java.type("javax.net.ssl.HttpsURLConnection");
|
||||
var SSLContext = Java.type("javax.net.ssl.SSLContext");
|
||||
|
||||
var HostnameVerifier = Java.type("javax.net.ssl.HostnameVerifier");
|
||||
var X509TrustManager = Java.type("javax.net.ssl.X509TrustManager");
|
||||
|
||||
var TrustAnyHostnameVerifier = new HostnameVerifier({
|
||||
verify: function (hostname, session) {
|
||||
return true;
|
||||
}
|
||||
})
|
||||
|
||||
var SSLSocketFactory = function initSSLSocketFactory() {
|
||||
var sslContext = SSLContext.getInstance("TLS");
|
||||
sslContext.init(null, [new X509TrustManager({
|
||||
getAcceptedIssuers: function () {
|
||||
return null;
|
||||
},
|
||||
checkClientTrusted: function (chain, authType) {},
|
||||
checkServerTrusted: function (chain, authType) {}
|
||||
})], new java.security.SecureRandom());
|
||||
return sslContext.getSocketFactory();
|
||||
}();
|
||||
|
||||
var config = {
|
||||
Charset: 'UTF-8',
|
||||
ConnectTimeout: 10000,
|
||||
ReadTimeout: 10000
|
||||
}
|
||||
|
||||
function open(url, method, header) {
|
||||
// conn.setRequestProperty
|
||||
var conn = new URL(url).openConnection();
|
||||
if (conn instanceof HttpsURLConnection) {
|
||||
conn.setHostnameVerifier(TrustAnyHostnameVerifier);
|
||||
conn.setSSLSocketFactory(SSLSocketFactory);
|
||||
}
|
||||
conn.setRequestMethod(method);
|
||||
conn.setDoOutput(true);
|
||||
conn.setDoInput(true);
|
||||
conn.setConnectTimeout(config.ConnectTimeout);
|
||||
conn.setReadTimeout(config.ReadTimeout);
|
||||
for (var key in header) {
|
||||
conn.setRequestProperty(key, header[key]);
|
||||
}
|
||||
return conn;
|
||||
}
|
||||
|
||||
function buildUrl(url, params) {
|
||||
if (params && Object.keys(params).length > 0) {
|
||||
var queryStart = url.indexOf('?');
|
||||
if (queryStart == -1) {
|
||||
url += '?';
|
||||
}
|
||||
for (var key in params) {
|
||||
url += key;
|
||||
url += '=';
|
||||
url += params[key];
|
||||
url += '&';
|
||||
}
|
||||
return url.substr(0, url.length - 1);
|
||||
}
|
||||
return url;
|
||||
}
|
||||
|
||||
function request(url, method, header, params, body) {
|
||||
var conn = open(buildUrl(url, params), method, header);
|
||||
try {
|
||||
conn.connect();
|
||||
if (body) {
|
||||
var out = conn.getOutputStream();
|
||||
out.write(new String(body).getBytes(config.Charset));
|
||||
out.flush();
|
||||
out.close();
|
||||
}
|
||||
return response(conn);
|
||||
} finally {
|
||||
conn.disconnect();
|
||||
}
|
||||
}
|
||||
|
||||
function response (conn) {
|
||||
var temp = Paths.get(java.lang.System.getProperty("java.io.tmpdir"), java.util.UUID.randomUUID().toString());
|
||||
Files.copy(conn.getInputStream(), temp);
|
||||
var result = new String(Files.readAllBytes(temp), config.Charset);
|
||||
var tempFile = temp.toFile();
|
||||
tempFile.delete() || tempFile.deleteOnExit();
|
||||
return result;
|
||||
}
|
||||
|
||||
var http = {
|
||||
config: config
|
||||
};
|
||||
|
||||
['GET', 'POST', 'PUT', 'DELETE', 'HEADER'].forEach(function(method){
|
||||
http[method.toLowerCase()] = function (url, header, params, body) {
|
||||
return request(url, method, header, params, body);
|
||||
}
|
||||
})
|
||||
|
||||
exports = module.exports = http;
|
@ -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,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;
|
6
src/main/resources/nukkit.yml
Normal file
6
src/main/resources/nukkit.yml
Normal file
@ -0,0 +1,6 @@
|
||||
name: ${project.artifactId}
|
||||
description: ${project.description}
|
||||
main: ${project.groupId}.${project.artifactId}.${project.artifactId}Nukkit
|
||||
version: ${project.version}
|
||||
api: "1.0.0"
|
||||
author: MiaoWoo
|
@ -1,26 +1,26 @@
|
||||
name: ${project.artifactId}
|
||||
description: ${project.description}
|
||||
main: ${project.groupId}.${project.artifactId}.${project.artifactId}
|
||||
version: ${project.version}-git-${env.GIT_COMMIT}
|
||||
author: 喵♂呜
|
||||
main: ${project.groupId}.${project.artifactId}.${project.artifactId}Bukkit
|
||||
version: ${project.version}
|
||||
api-version: 1.13
|
||||
author: MiaoWoo
|
||||
website: ${ciManagement.url}
|
||||
softdepend:
|
||||
- PlaceholderAPI
|
||||
commands:
|
||||
${project.artifactId}:
|
||||
description: ${project.artifactId} - ${project.description}
|
||||
aliases:
|
||||
- ms
|
||||
- mjs
|
||||
- script
|
||||
- mscript
|
||||
usage: §b使用/${project.artifactId} help 查看帮助!
|
||||
permission: ${project.artifactId}.reload
|
||||
permission-message: §c你没有 <permission> 的权限来执行此命令!
|
||||
permissions:
|
||||
${project.artifactId}.use:
|
||||
description: ${project.artifactId} 使用!
|
||||
default: true
|
||||
${project.artifactId}.reload:
|
||||
description: 重新载入插件!
|
||||
default: op
|
||||
- OriginAttribute
|
||||
- AttributeSystem
|
||||
- ItemLoreOrigin
|
||||
- PlaceholderAPI
|
||||
- AttributePlus
|
||||
- PlayerPoints
|
||||
- SX-Attribute
|
||||
- CrazyCrates
|
||||
- ProtocolLib
|
||||
- DragonCore
|
||||
- MythicMobs
|
||||
- WorldGuard
|
||||
- Adyeshach
|
||||
- WorldEdit
|
||||
- SkillAPI
|
||||
- TradeMe
|
||||
- Chemdah
|
||||
- Vault
|
||||
|
@ -1,68 +0,0 @@
|
||||
'use strict';
|
||||
/**
|
||||
* Hello Wrold 测试插件
|
||||
*/
|
||||
/*global Java, base, module, exports, require*/
|
||||
|
||||
var event = require('api/event');
|
||||
var wrapper = require('api/wrapper');
|
||||
var command = require('api/command');
|
||||
var server = require('api/server');
|
||||
var fs = require('fs');
|
||||
|
||||
var description = {
|
||||
name: 'HelloWorld',
|
||||
version: '1.0',
|
||||
commands: {
|
||||
'hello': {
|
||||
description: 'HelloWorld主命令'
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
function load() {
|
||||
console.log('载入 Hello Wrold 测试插件!');
|
||||
}
|
||||
|
||||
function enable() {
|
||||
command.on(this, 'hello', {
|
||||
cmd: function (sender, command, args) {
|
||||
engineLoad(fs.file(root, 'test.js'));
|
||||
return true;
|
||||
}
|
||||
});
|
||||
console.log('启用 Hello World 测试插件!');
|
||||
switch (DetectServerType) {
|
||||
case ServerType.Bukkit:
|
||||
event.on(this, 'playerloginevent', function join(event) {
|
||||
send(event, wrapper.player(event.player));
|
||||
});
|
||||
break;
|
||||
case ServerType.Sponge:
|
||||
// clientconnectionevent.join
|
||||
event.on(this, 'clientconnectionevent.join', function join(event) {
|
||||
send(event, wrapper.player(event.targetEntity));
|
||||
});
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
function send(event, player){
|
||||
// noinspection JSUnresolvedVariable
|
||||
console.debug('玩家', player.getName(), "触发事件", event.class.simpleName);
|
||||
setTimeout(function () {
|
||||
// noinspection JSUnresolvedVariable
|
||||
player.sendMessage("§a欢迎来到 §bMiaoScript §a的世界! 当前在线: " + server.players.length)
|
||||
}, 10);
|
||||
}
|
||||
|
||||
function disable() {
|
||||
console.log('卸载 Hello World 测试插件!');
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
description: description,
|
||||
load: load,
|
||||
enable: enable,
|
||||
disable: disable
|
||||
};
|
@ -1,79 +0,0 @@
|
||||
'use strict';
|
||||
/*global Java, base, module, exports, require*/
|
||||
|
||||
var event = require('api/event');
|
||||
var wrapper = require('api/wrapper');
|
||||
var command = require('api/command');
|
||||
var server = require('api/server');
|
||||
var http = require('http');
|
||||
var fs = require('fs');
|
||||
|
||||
var nameMap = [];
|
||||
|
||||
var description = {
|
||||
name: 'ItemTag',
|
||||
version: '1.0',
|
||||
author: '喵♂呜'
|
||||
};
|
||||
|
||||
var itemConfig;
|
||||
|
||||
function load() {
|
||||
var itemFile = self.file('item.yml');
|
||||
if (!itemFile.exists()) {
|
||||
base.save(itemFile, http.get('https://data.yumc.pw/config/Item_zh_CN.yml'));
|
||||
}
|
||||
itemConfig = self.getConfig('item.yml');
|
||||
}
|
||||
|
||||
function enable() {
|
||||
switch (DetectServerType) {
|
||||
case ServerType.Bukkit:
|
||||
event.on(self, 'ItemMergeEvent', function (event) {
|
||||
bukkit(event.target, event.entity.itemStack.amount + event.target.itemStack.amount);
|
||||
})
|
||||
event.on(self, 'ItemSpawnEvent', function (event) {
|
||||
if (event.entity.itemStack) {
|
||||
bukkit(event.entity, event.entity.itemStack.amount);
|
||||
}
|
||||
})
|
||||
break;
|
||||
case ServerType.Sponge:
|
||||
event.on(self, 'itemmergeitemevent', function (event) {
|
||||
// Sponge 暂未实现当前事件
|
||||
})
|
||||
event.on(self, 'spawnentityevent', function (event) {
|
||||
event.entities.forEach(function (entity) {
|
||||
if (entity.type.name === "item") sponge(entity);
|
||||
})
|
||||
})
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
function getItemName(name) {
|
||||
return itemConfig[(name + '').toUpperCase()] || name;
|
||||
}
|
||||
|
||||
function bukkit(item , amount) {
|
||||
var amounts = amount == 1 ? "" : "*" + amount;
|
||||
item.setCustomName('§b' + getItemName(item.itemStack.type) + amounts);
|
||||
item.setCustomNameVisible(true);
|
||||
}
|
||||
|
||||
function sponge(entity) {
|
||||
var itemOptional = entity.get(Keys.REPRESENTED_ITEM);
|
||||
if (itemOptional.isPresent()) {
|
||||
var item = itemOptional.get();
|
||||
var amounts = item.count == 1 ? "" : "*" + item.count;
|
||||
entity.offer(org.spongepowered.api.data.key.Keys.DISPLAY_NAME, org.spongepowered.api.text.Text.of('§b' + getItemName(item.type.name.split(':')[1]) + amounts));
|
||||
entity.offer(org.spongepowered.api.data.key.Keys.CUSTOM_NAME_VISIBLE, true);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
description: description,
|
||||
load: load,
|
||||
enable: enable,
|
||||
disable: disable
|
||||
};
|
@ -1,210 +0,0 @@
|
||||
'use strict';
|
||||
/**
|
||||
* Hello Wrold 测试插件
|
||||
*/
|
||||
/*global Java, base, module, exports, require*/
|
||||
|
||||
var event = require('api/event');
|
||||
var command = require('api/command');
|
||||
var bukkit = require('api/server');
|
||||
var item = require('api/item');
|
||||
|
||||
var Arrays = Java.type('java.util.Arrays');
|
||||
var ItemStackArray = Java.type('org.bukkit.inventory.ItemStack[]');
|
||||
|
||||
var description = {
|
||||
name: 'Lottery',
|
||||
version: '1.0',
|
||||
commands: {
|
||||
'lottery': {
|
||||
description: 'Lottery主命令'
|
||||
}
|
||||
},
|
||||
config: {
|
||||
title: '§m§s§a幸运抽奖',
|
||||
panel: '160:13',
|
||||
list: [
|
||||
{
|
||||
box: {
|
||||
id: 160,
|
||||
damage: 1,
|
||||
name: '§a箱子',
|
||||
lore: [
|
||||
'这是箱子的Lore'
|
||||
]
|
||||
},
|
||||
key: {
|
||||
id: 160,
|
||||
damage: 2,
|
||||
name: '§b钥匙',
|
||||
lore: [
|
||||
'这是钥匙的Lore'
|
||||
]
|
||||
},
|
||||
result: [
|
||||
{
|
||||
percent: 10,
|
||||
command: 'money give %player% 100',
|
||||
item: {
|
||||
id: 160,
|
||||
damage: 3,
|
||||
name: '§c奖品1',
|
||||
lore: [
|
||||
'这是奖品1的Lore'
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
percent: 20,
|
||||
command: 'money give %player% 200',
|
||||
item: {
|
||||
id: 160,
|
||||
damage: 4,
|
||||
name: '§c奖品2',
|
||||
lore: [
|
||||
'这是奖品2的Lore'
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
};
|
||||
|
||||
var panel = item.create(160, 1, 13);
|
||||
var config;
|
||||
var items;
|
||||
|
||||
function load() {
|
||||
config = this.config;
|
||||
if (config.panel) {
|
||||
var arr = config.panel.split(':');
|
||||
if (arr.length === 2) {
|
||||
panel = newItem(arr[0], arr[1]);
|
||||
} else {
|
||||
panel = newItem(arr[0]);
|
||||
}
|
||||
}
|
||||
items = new ItemStackArray(54);
|
||||
item.setName(panel, '');
|
||||
var ok = newItem(160, 14);
|
||||
item.setName(ok, '§a确定抽奖');
|
||||
var no = newItem(160, 15);
|
||||
item.setName(no, '§c取消抽奖');
|
||||
Arrays.fill(items, 0, 10, panel);
|
||||
Arrays.fill(items, 11, 16, panel);
|
||||
Arrays.fill(items, 17, 29, panel);
|
||||
items[29] = no;
|
||||
Arrays.fill(items, 30, 33, panel);
|
||||
items[33] = ok;
|
||||
Arrays.fill(items, 34, 40, panel);
|
||||
Arrays.fill(items, 41, 54, panel);
|
||||
}
|
||||
|
||||
function isTargetItem(item, config) {
|
||||
return item.typeId === config.id &&
|
||||
item.itemMeta &&
|
||||
item.itemMeta.displayName === config.name &&
|
||||
item.itemMeta.lore && Java.from(item.itemMeta.lore).toJson() === config.lore.toJson()
|
||||
}
|
||||
|
||||
function newItem(name, sub) {
|
||||
return item.create(name, 1, sub || 0);
|
||||
}
|
||||
|
||||
function newItemFromConfig(config) {
|
||||
var i = newItem(config.id, config.damage);
|
||||
if (config.name) item.setName(i, config.name);
|
||||
if (config.lore) item.setLore(i, config.lore);
|
||||
return i;
|
||||
}
|
||||
|
||||
function enable() {
|
||||
command.on(this, 'l', {
|
||||
cmd: function (sender, command, args) {
|
||||
if (!sender.openInventory) {
|
||||
console.sender(sender, "§4当前用户无法使用该命令!");
|
||||
}
|
||||
var inv = bukkit.$.createInventory(null, 54, config.title);
|
||||
inv.setContents(items);
|
||||
sender.openInventory(inv);
|
||||
return true;
|
||||
}
|
||||
});
|
||||
event.on(this, 'InventoryClick', function click(event) {
|
||||
var inv = event.inventory;
|
||||
if (inv.title !== config.title) return;
|
||||
var player = event.whoClicked;
|
||||
var slot = event.rawSlot;
|
||||
if (slot > 53 || slot < 0) {
|
||||
return;
|
||||
}
|
||||
event.cancelled = true;
|
||||
switch (slot) {
|
||||
case 10:
|
||||
case 16:
|
||||
case 40:
|
||||
event.cancelled = false;
|
||||
break;
|
||||
case 29:
|
||||
// TODO 关闭界面
|
||||
player.closeInventory();
|
||||
break;
|
||||
case 33:
|
||||
var temp = inv.getItem(40);
|
||||
if (temp && temp.typeId !== 0) {
|
||||
console.sender(player, '§c请先取走奖品!');
|
||||
return;
|
||||
}
|
||||
var litem;
|
||||
var box = inv.getItem(10);
|
||||
var key = inv.getItem(16);
|
||||
if (box && box.typeId !== 0 && key && key.typeId !== 0) {
|
||||
for (var i = 0; i < config.list.length; i++) {
|
||||
var r = config.list[i];
|
||||
if (isTargetItem(box, r.box)) {
|
||||
litem = r;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
// TODO 抽奖
|
||||
if (!litem) {
|
||||
console.sender(player, '§c请先放入抽奖物品和钥匙!');
|
||||
return;
|
||||
}
|
||||
if (!isTargetItem(key, litem.key)) {
|
||||
console.sender(player, '§c抽奖物品和钥匙不匹配!');
|
||||
return;
|
||||
}
|
||||
var resultlist = [];
|
||||
litem.result.forEach(function (t) {
|
||||
for (var i = 0; i < t.percent; i++) {
|
||||
resultlist.push(t);
|
||||
}
|
||||
});
|
||||
var ri = ext.random(resultlist.length);
|
||||
var result = resultlist[ri];
|
||||
box.amount = box.amount - 1;
|
||||
key.amount = key.amount - 1;
|
||||
inv.setItem(10, box);
|
||||
inv.setItem(16, key);
|
||||
inv.setItem(40, newItemFromConfig(result.item));
|
||||
bukkit.console(result.command.replace('%player%', player.name));
|
||||
break;
|
||||
default:
|
||||
event.cancelled = true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function disable() {
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
description: description,
|
||||
load: load,
|
||||
enable: enable,
|
||||
disable: disable
|
||||
};
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user