Compare commits

...

28 Commits

Author SHA1 Message Date
2185b1a2f8 v0.6.5 2020-05-12 14:35:26 +08:00
c14e20e269 feat: optimize framework
Signed-off-by: MiaoWoo <admin@yumc.pw>
2020-05-12 14:22:31 +08:00
45a1c43dd8 feat: complate deploy access check
Signed-off-by: MiaoWoo <admin@yumc.pw>
2020-05-12 00:07:05 +08:00
9226e1ab4f feat: ignore if trace.fileName is empty
Signed-off-by: MiaoWoo <admin@yumc.pw>
2020-05-11 22:13:31 +08:00
287585d8f5 feat: add node shim
Signed-off-by: MiaoWoo <admin@yumc.pw>
2020-05-11 22:13:03 +08:00
b323d16123 v0.6.4 2020-05-11 17:52:13 +08:00
85240608a1 feat: add npmignore
Signed-off-by: MiaoWoo <admin@yumc.pw>
2020-05-11 17:46:57 +08:00
6f9b458e6a v0.6.3 2020-05-11 17:32:02 +08:00
64159b621f feat: support address arg
Signed-off-by: MiaoWoo <admin@yumc.pw>
2020-05-11 17:24:26 +08:00
393ae6ce25 feat: support online load plugin
Signed-off-by: MiaoWoo <admin@yumc.pw>
2020-05-11 17:22:45 +08:00
b9b80ecb83 feat: support blockly online debug
Signed-off-by: MiaoWoo <admin@yumc.pw>
2020-05-11 17:22:15 +08:00
57e2845ad9 feat: compatible blockly plugin
Signed-off-by: MiaoWoo <admin@yumc.pw>
2020-05-11 17:20:50 +08:00
e03a4f9b34 feat: add i18n load tip
Signed-off-by: MiaoWoo <admin@yumc.pw>
2020-05-11 17:19:44 +08:00
72015ec132 feat: ignore jar:file stack info
Signed-off-by: MiaoWoo <admin@yumc.pw>
2020-05-10 16:25:04 +08:00
3e329233ce feat: add incremental compiler config
Signed-off-by: MiaoWoo <admin@yumc.pw>
2020-05-10 16:24:19 +08:00
b53d9e8a4e remove: plugins public file 2020-05-08 18:42:17 +08:00
331357f1a2 feat: support basic plugin... 2020-05-08 18:41:56 +08:00
ec809fb013 feat: update init command... 2020-05-08 10:11:30 +08:00
e38e772b17 feat: update gitpod init command... 2020-05-08 10:05:47 +08:00
2b56b1e573 feat: add gitpod config... 2020-05-08 09:53:18 +08:00
2df09b2472 feat: complate deploy feature 2020-05-08 00:50:30 +08:00
f9303b0e11 v0.6.2 2020-05-07 18:38:28 +08:00
d43f52a2a4 fix: reload & download error
Signed-off-by: MiaoWoo <admin@yumc.pw>
2020-05-07 18:33:10 +08:00
7cf9718a9a v0.6.1 2020-05-07 17:18:38 +08:00
9693dc235f feat: update docs & MSPM
Signed-off-by: MiaoWoo <admin@yumc.pw>
2020-05-07 17:13:48 +08:00
40e9d1db6e feat: support source map & reload
Signed-off-by: MiaoWoo <admin@yumc.pw>
2020-05-07 17:12:15 +08:00
d50506ab9d v0.6.0 2020-05-03 00:15:06 +08:00
c34d3027e4 refactor: rename scope to @ccms
Signed-off-by: MiaoWoo <admin@yumc.pw>
2020-05-03 00:14:47 +08:00
90 changed files with 644 additions and 1194 deletions

10
.gitpod.Dockerfile vendored Normal file
View File

@@ -0,0 +1,10 @@
FROM gitpod/workspace-full
USER gitpod
# Install custom tools, runtime, etc. using apt-get
# For example, the command below would install "bastet" - a command line tetris clone:
#
# RUN sudo apt-get -q update && # sudo apt-get install -yq bastet && # sudo rm -rf /var/lib/apt/lists/*
#
# More information: https://www.gitpod.io/docs/config-docker/

5
.gitpod.yml Normal file
View File

@@ -0,0 +1,5 @@
tasks:
- init: yarn && yarn bs && yarn build
command: yarn watch
# image:
# file: .gitpod.Dockerfile

View File

@@ -1,478 +1,6 @@
- 构建状态 [![Build Status](https://ci.yumc.pw/job/Minecraft/job/MiaoScript/badge/icon?style=flat-square)](https://ci.yumc.pw/job/Minecraft/job/MiaoScript/)
- 当前版本 ![Build Status](https://ci.yumc.pw/job/Minecraft/job/MiaoScript/badge/icon?style=flat-square&subject=version&status=0.1.0beta&color=darkturquoise)
- 下载地址 [![Build Status](https://ci.yumc.pw/job/Minecraft/job/MiaoScript/badge/icon?style=flat-square&subject=download&status=MiaoScript&color=darkgreen)](http://w.yumc.pw/free.html#MiaoScript-download)
- 为了方便阅读 我对帖子进行了分页 请点击目录阅读!
### 更新日志
- 2020-03-03
- 发布 `v0.3.1` 版本
- 2020-03-02
- 杂项 更新文档以及示例插件
- 2020-03-01
- 修复 多个包之间的循环依赖问题
- 优化 `@ms/types` 的引用逻辑
- 2020-02-29
- 更新 `TypeScript` 版本为 `3.8.3`
- 新增 `@ms/common` 的 `http` 下载功能
- 2020-02-27
- 发布 `v0.3.0` 版本
- 新增 `@ms/i18n` 国际化包的支持
- 修复 `@ms/plugin` 对 `servers` 相关处理异常
- 优化 `@ms/api` 的 `Channel` 处理增加 扩展原始数据
- 2020-02-26
- 优化 `@ms/container` 使用 `autoProvide` 自动注入依赖
- 2020-02-25
- 修复 `@ms/api` 对 `evnet` 的类型处理异常
- 2020-02-24
- 发布 `v0.2.1` 版本
- 完善 对 `Nukkit` 端的支持
- 新增 `@ms/api` 通道相关的支持
- 2020-02-23
- 新增 `@ms/nukkit` 包 对 `Nukkit` 端的支持
- 新增 `@ms/type` 的 `nukkit` 类型自动补全
- 2020-02-22
- 发布 `v0.2.0` 版本
- 新增 `@ms/plugin` 的 `@config` 注解 目前支持 `json` `yml` 格式的配置
- 2020-02-15
- 新增 `SourceMap` 的支持 用于跟踪源代码行数
- 2020-02-09
- 新增 `core-js` 用于支持大部分新ES语法
- 2020-01-31
- 优化 `@ms/ployfill` 全局处理
- 2020-01-15
- 新增 `@ms/bungee` 包 对 `BungeeCord` 端的支持
- 2020-01-14
- 新增 `@ms/type` 的 `bungee` 类型自动补全
- 2019-11-10
- 新增 `WebSocket` 的注入支持
- 2019-11-07
- 新增 `@ms/type` 的 `jdk` 类型自动补全
- 2019-09-27
- 新增 `CatServer` MOD端的支持
- 2019-09-25
- 新增 `@ms/type` 的 `sponge` 类型自动补全
- 2019-09-24
- 新增 `@ms/type` 的 `bukkit` 类型自动补全
## 插件简介
- 此插件可以实现跨端使用 `TypeScript` 开发 脚本插件
- 目前已经兼容 `Spigot` `Sponge` `Paper` `CatServer` `BungeeCord` `Nukkit`
- 后续计划兼容 暂无
## 起源 (可以略过)
### 简介
> 这个坑是我自己刨的 但是发现坑太大 需要更多的人一起填
### 起源
- 诞生于 `2016年08月25日` 这是 Git 上的第一个提交 具体啥时候我也忘了
- 起初 `MiaoScript` 只是用于服务器其他插件的变量执行 并且依赖于PAPI(不知道是啥的自己百度)
- 比如 [`MiaoMenu`](http://w.yumc.pw/zc/MiaoMenu.html) 的部分复杂脚本
- 比如 [`MiaoChat`](http://mcbbs.net/thread-631240-1-1.html) 的聊天变量
- 突然有一天 圈内的大佬 `QSB` @qiu1995 过来找我 说能不能用脚本监听玩家的事件
- PS: 这货自从用过 `DeluxeMenu` 之后就喜欢上了用JS写菜单
- 当初感觉没啥问题 就出了第一个简易的 `MiaoScript` 版本 还是用 yml 做的配置文件
- 但是由于设计 BukkitAPI 等内容 对Java要求太高 后来 邱也弃坑了 我也弃坑了
### 刨坑
- 时隔多年(也就一年) 看到了Sponge的兴起 (估摸着是MCPC系列的MOD端都弃坑了)
- 同时 这期间 收到很多腐竹的单子 但是又是非常基础的东西
- 比如 开服给玩家发一条消息啦
- 比如 修改玩家某些数据啦
- 这些东西实际上也就几行代码的事情
- 同时 很多想入坑 插件开发 但是又有一些被卡死在环境搭建上
- 比如 `Bukkit` 需要 `BukkitAPI`
- `Sponge` 需要 `SpongeAPI` 如果涉及 `MOD` 还要 `Forge` 环境
- 再或者 BungeeCord 的插件开发 我也是经常懒得搞
- 当然 最主要的是 某个 咕咕咕的群 天天有人问我 喵系插件能不能支持 Sponge
- 内心当然是拒绝的 现在要上班养老婆孩子(咳咳 不要以为我是大叔 我也才刚毕业而已) 那里还有时间免费给你们写插件
- 于是乎 我又想起了当初的 `MiaoScript`
- 突发奇想 一个插件的雏形出现在我的脑海中
- 可以兼容多种服务器
- 不需要开发环境 有记事本就可以开发
- 语法要简单 比如 JavaScript
- 能够自动搜索安装依赖(毕竟很多人天天问我为何喵系插件跑不起来 都是缺少PAPI)
- 能够不重启更新插件(当然得保证代码安全的前提下)
- 在 2017年9月14号(距离 第一个版本正式版发布(2016-09-21) 相差一年整)
- 一个全新的 `MiaoScript` 诞生了
- Java部分代码 只有一个启动类
- 核心全部由 JS 编写
- 兼容 `CommonJS` 规范
- 实时重载
- 2019年9月14号 emm 咸鱼2年之后
- TypeScript 重构版本横空出世
- 只保留 基础Java启动类 三个环境初始化js
- 完整的服务端Java类自动补全
- 全新的 IOC容器 注入功能
- 注解式 注册命令 注册事件
- 2020年3月2日 发布0.3.0版本
- 支持 Bukkit Nukkit BungeeCord 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`
## 框架设计
### MiaoScript TS 实现
项目具体实现 由 TypeScript 进行编写 然后编译至 `es5` 用于兼容 Java8 的 `Nashorn`
### Project Structure
```txt
└─packages
├─api 全平台兼容的接口
├─core 核心代码 用于引导加载
├─common 公共类库代码 例如 http reflect 模块
├─client NodeJS的Minecraft客户端 用于调试插件
├─container IOC容器 用于注入具体实现
├─ployfill Nashorn 的一些自定义增强
├─nashorn Nashorn 的类型定义
├─bungee BungeeCordAPI内部实现
├─bukkit BukkitAPI内部实现
├─sponge SpongeAPI内部实现
├─nukkit NukkitAPI内部实现
├─ployfill JS环境的相关环境补全
├─plugin 插件管理器
├─websocket Netty的WebSocket注入
├─type Java的类型定义
| ├─bungee BungeeCord类型定义
| ├─bukkit Bukkit类型定义
| ├─sponge Sponge类型定义
| └─nukkit Nukkit类型定义
└─plugins 这里当然是插件啦
├─bungee 只兼容BungeeCord的插件
├─bukkit 只兼容Bukkit的插件
├─sponge 只兼容Sponge的插件
└─nukkit 只兼容Nukkit的插件
```
详细的内容就不逼逼了 自己看代码吧
Github: https://github.com/circlecloud/ms
YUMC: https://git.yumc.pw/circlecloud/ms
## 插件开发基础
### 开发IDE (推荐VSCode或者MiaoScrit在线IDE)
如果只是简单的开发 你可用记事本 (但是没有任何补全和错误提示)
### 开发环境准备(针对高级用户)
- 安装 `NodeJS` 和 `Yarn`
- 拉取代码
- `git clone https://github.com/circlecloud/ms.git`
- 进入目录 `ms`
- 安装 npm 包
- `yarn`
- 建立内部依赖链接
- `yarn bs`
- 编译一次生成对应的类库
- `yarn build`
- 编译插件
- `yarn build:plugins`
### 直接在 MiaoScript Online WebIDE 开发
填坑中...
## 基本插件框架
### HelloWorld 示例插件
先来一个 `HelloWorld.ts` 插件示范!
```ts
/// <reference types="@ms/types" />
import { server } from '@ms/api';
import { inject } from '@ms/container';
import { plugin, interfaces, cmd, listener, tab } from '@ms/plugin'
@plugin({ name: 'HelloWorld', version: '1.0.0', author: 'MiaoWoo', source: __filename })
export class HelloWorld extends interfaces.Plugin {
@inject(server.Server)
private Server: server.Server
@config()
private config = {
version: 1.0.0
}
load() {
this.logger.log('Plugin load from MiaoScript Plugin System...');
}
enable() {
this.logger.log('Plugin enable from MiaoScript Plugin System...');
}
disable() {
this.logger.log('Plugin disable from MiaoScript Plugin System...');
}
bukkitload() {
this.logger.log('Load When ServerType is Bukkit!')
}
bukkitenable() {
this.logger.log('Enable When ServerType is Bukkit!')
}
bukkitdisable() {
this.logger.log('Disable When ServerType is Bukkit!')
}
spongeload() {
this.logger.log('Load When ServerType is Sponge!')
}
spongeenable() {
this.logger.log('Enable When ServerType is Sponge!')
}
spongedisable() {
this.logger.log('Disable When ServerType is Sponge!')
}
bungeeload() {
this.logger.log('Load When ServerType is BungeeCord!')
}
bungeeenable() {
this.logger.log('Enable When ServerType is BungeeCord!')
}
bungeedisable() {
this.logger.log('Disable When ServerType is BungeeCord!')
}
nukkitload() {
this.logger.log('Load When ServerType is Nukkit!')
}
nukkitenable() {
this.logger.log('Enable When ServerType is Nukkit!')
}
nukkitdisable() {
this.logger.log('Disable When ServerType is Nukkit!')
}
@cmd()
hello(sender: any, command: string, args: string[]) {
this.logger.log(sender, command, args);
sender.sendMessage(JSON.stringify({ command, ...args }))
}
@tab()
tabhello(_sender: any, _command: string, _args: string[]) {
return ['world']
}
// bukkit nukkit 大部分API神似 可以直接用
@listener({ servers: ['bukkit', 'nukkit'] })
PlayerJoin(event: org.bukkit.event.player.PlayerJoinEvent) {
let plyaer = event.getPlayer();
this.logger.console(`§cBukkit §aPlayerJoinEvent: §b${plyaer.getName()}`)
setTimeout(() => this.sendWelcome(plyaer), 10);
}
@listener({ servers: ['sponge'] })
ClientConnectionEvent$Join(event: org.spongepowered.api.event.network.ClientConnectionEvent.Join) {
this.logger.console(`§cSponge §aClientConnectionEvent.Join: §b${event.getTargetEntity().getName()}`)
setTimeout(() => this.sendWelcome(event.getTargetEntity()), 10);
}
private sendWelcome(player: any) {
this.logger.sender(player, `§a欢迎来到 §bMiaoScript §a的世界!`)
this.logger.sender(player, `§6当前版本: §c${this.Server.getVersion()}`)
}
@listener({ servers: ['bungee'] })
ServerConnected(e: any) {
let event = e as net.md_5.bungee.api.event.ServerConnectedEvent
this.logger.console(`§cBungeeCord §aServerConnectedEvent: §b${event.getPlayer().getDisplayName()}`)
setTimeout(() => this.logger.sender(event.getPlayer(), `§a欢迎来到 §bMiaoScript §a的世界 §6来自 §cBungeeCord §6的问候!`), 10);
}
}
```
- 进入 `ms`目录
- 执行编译 `yarn build:plugins`
- 从 `packages/plugins/dist` 中复制 `HelloWorld.js` 和 `HelloWorld.js.map`(可选 用于显示插件原有行数) 文件 到对应的插件目录
- Bungee: plugins/MiaoScript/plugins/
- Bukkit: plugins/MiaoScript/plugins/
- Sponge: config/miaoscript/plugins/
- Nukkit: plugins/MiaoScript/plugins/
- 重载 `MiaoScript`
- 打开客户端进入游戏 预览一下效果
- 从 Spigot 服务端进入
![image.png](https://i.loli.net/2019/09/22/2BZuwF65WV1xGnv.png)
![image.png](https://i.loli.net/2019/09/22/m2CftwbalnXsxvg.png)
- 从 Sponge 服务端进入
![image.png](https://i.loli.net/2019/09/22/QD1jrShtJpPXyVl.png)
![image.png](https://i.loli.net/2019/09/22/GzLFVC3sjAJ4obm.png)
## 注册插件
- 从上面的示例可以看到 一个插件 通过注解 `@plugin` 即可启动
- 此注解接受一个 `PluginMetadata` 对象 定义如下
```ts
export interface PluginMetadata {
/**
* 插件名称
*/
name: string;
/**
* 支持的服务器列表 为空则代表所有
*/
servers?: string[];
/**
* 前缀
*/
prefix?: string;
/**
* 插件版本
*/
version: string;
/**
* 插件版本
*/
author: string | string[];
/**
* 插件源文件 必须指定为 __filename
*/
source: string;
/**
* 插件本体
*/
target?: any;
}
```
### 插件生命周期
MiaoScript 的生命周期遵循了 Bukkit 的生命周期
MiaoScript 针对不同的服务端 提供了扩展的周期
以服务端类型开头阶段名结束 例如 `bukkitload` `spongeenbale` `bungeedisable`
扩展的生命周期只会在特定的服务器执行
### load 加载阶段
此阶段通常用于初始化基础配置 数据库链接等
某些对外提供功能的插件 需要在此阶段初始化完成
### enable 启动阶段
此阶段通常用于注册命令 注册事件等
由于命令和事件 MiaoScript 已经托管了 所以开发者可以直接用注解实现
### disable 关闭阶段
此阶段通常用于注销命令 注销事件等
由于命令和事件 MiaoScript 已经托管了 所以开发者可以直接用注解实现
## 注册命令/补全
### cmd 命令
命令 就是玩家在Minecraft中执行命令 下面是一个示例的命令
- 命令是一个 `function` 通过 `@cmd` 注解注册
- 由于不同的服务端有不同的逻辑 所以支持通过 `servers` 指定注册的类型 加上 `!` 代表不注册 不指定 `servers` 则注册所有的类型
- 命令注册时默认使用方法名称为命令名称 当前你可以传入 name 参数指定命令名称 例如 `{name: 'test'}`
- 接受三个参数 `sender: any, command: string, args: string[]`
- 分别代表 命令发送者 命令名称 命令参数
```ts
@cmd({ servers: ["bukkit", "sponge", "!bungee"] })
hello(sender: any, command: string, args: string[]) {
this.logger.log(sender, command, args);
this.logger.sender(sender, JSON.stringify({ command, args }));
}
```
### tab 补全
补全就是 玩家在Minecraft执行命令时 使用 Tab键 补全
- 补全是一个 `function` 一般以 `tab` 开头 需要补全的命令结尾 通过 `@tab` 注解注册
- 补全注册时默认使用方法名称为补全名称 当前你可以传入 name 参数指定命令名称 例如 `{name: 'test'}`
- 接受三个参数 `sender: any, command: string, args: string[]`
- 分别代表 命令发送者 命令名称 命令参数
_注意: 当补全命令未注册时 补全无效! 且补全和命令必须在同一个Class内!_
```ts
@tab()
tabhello(_sender: any, _command: string, _args: string[]) {
return ['world']
}
```
## 监听事件
事件是指 Minecraft 中发生的各种事情
- 监听事件是一个 `function` 通过 `@listener` 注册
- 由于不同的服务端有不同的逻辑 所以支持通过 `servers` 指定注册的类型 加上 `!` 代表不注册 不指定 `servers` 则注册所有的类型
- 事件名称默认为方法名称
- 所有类型服务端的事件 MiaoScript 都会进行一次映射 方便使用
- 例如 `PlayerJoinEvent` 会映射为 `PlayerJoinEvent, playerjoinevent, playerjoin` 等
- 一般规则就是 类名直接小写 如果遇到子类 则保留 `$`
- 例如 `ClientConnectionEvent.Join` 会映射为 `clientconnectionevent$join`
- 事件的注可以传入 `servertype` 来指定这个事件类型的服务端加载 默认是所有服务端都加载
- 事件监听方法的第一个参数就是本次事件的具体内容 (这里就需要自己去查询对应的JavaDoc了)
```ts
// bukkit nukkit 大部分API神似 可以直接用
@listener({ servers: ['bukkit', 'nukkit'] })
PlayerJoin(event: org.bukkit.event.player.PlayerJoinEvent) {
let plyaer = event.getPlayer();
this.logger.console(`§cBukkit §aPlayerJoinEvent: §b${plyaer.getName()}`)
setTimeout(() => this.sendWelcome(plyaer), 10);
}
@listener({ servers: ['sponge'] })
ClientConnectionEvent$Join(event: org.spongepowered.api.event.network.ClientConnectionEvent.Join) {
this.logger.console(`§cSponge §aClientConnectionEvent.Join: §b${event.getTargetEntity().getName()}`)
setTimeout(() => this.sendWelcome(event.getTargetEntity()), 10);
}
private sendWelcome(player: any) {
this.logger.sender(player, `§a欢迎来到 §bMiaoScript §a的世界!`)
this.logger.sender(player, `§6当前版本: §c${this.Server.getVersion()}`)
}
@listener({ servers: ['bungee'] })
ServerConnected(e: any) {
let event = e as net.md_5.bungee.api.event.ServerConnectedEvent
this.logger.console(`§cBungeeCord §aServerConnectedEvent: §b${event.getPlayer().getDisplayName()}`)
setTimeout(() => this.logger.sender(event.getPlayer(), `§a欢迎来到 §bMiaoScript §a的世界 §6来自 §cBungeeCord §6的问候!`), 10);
}
```
## 配置文件
配置文件 默认读取的是 `MiaoScript根目录/plugins/插件名称/配置名称.配置格式`
例如下面文件 默认处理的是 `plugins/MiaoScript/plugins/HelloWorld/config.yml`
```ts
@config()
private config = {
version: 1.0.0
}
```
## 插件列表
暂无
> 注意: 一楼的列表是老版本的 新版本无法加载!
- 当前版本 ![Build Status](https://ci.yumc.pw/job/Minecraft/job/MiaoScript/badge/icon?style=flat-square&subject=VERSION&status=0.1.0beta&color=darkturquoise)
- 下载地址 [![Build Status](https://ci.yumc.pw/job/Minecraft/job/MiaoScript/badge/icon?style=flat-square&subject=MiaoScript&status=DOWNLOAD&color=darkgreen)](http://w.yumc.pw/free.html#MiaoScript-download)
- 更新日志 [![Build Status](https://ci.yumc.pw/job/Minecraft/job/MiaoScript/badge/icon?style=flat-square&subject=MiaoScript&status=CHANGELOG&color=green)](https://docs.yumc.pw/MiaoScript/CHANGELOG.html)
- 安装文档 [![Build Status](https://ci.yumc.pw/job/Minecraft/job/MiaoScript/badge/icon?style=flat-square&subject=MiaoScript&status=MiaoDoc%20USER&color=red)](https://docs.yumc.pw/MiaoScript/1-user/1.1-check-env.html)
- 开发文档 [![Build Status](https://ci.yumc.pw/job/Minecraft/job/MiaoScript/badge/icon?style=flat-square&subject=MiaoScript&status=MiaoDoc%20DEVELOP&color=darkred)](https://docs.yumc.pw/MiaoScript/2-develop/1.1-check-env.html)

View File

@@ -1,5 +1,5 @@
{
"version": "0.5.0",
"version": "0.6.5",
"useWorkspaces": true,
"npmClient": "yarn",
"packages": [

View File

@@ -9,8 +9,8 @@
"bs": "lerna bootstrap",
"clean": "lerna run clean",
"watch": "lerna run watch --parallel",
"build": "lerna run build --scope=\"@ms/!(plugins)\"",
"build:plugins": "lerna run build --scope=\"@ms/plugins\"",
"build": "lerna run build --scope=\"@ccms/!(plugins)\"",
"build:plugins": "lerna run build --scope=\"@ccms/plugins\"",
"ug": "yarn upgrade-interactive --latest",
"lp": "lerna publish"
},

View File

@@ -1,6 +1,6 @@
{
"name": "@ms/api",
"version": "0.5.0",
"name": "@ccms/api",
"version": "0.6.5",
"description": "MiaoScript api package",
"keywords": [
"miaoscript",
@@ -12,9 +12,6 @@
"homepage": "https://github.com/circlecloud/ms.git",
"license": "ISC",
"main": "dist/index.js",
"publishConfig": {
"registry": "https://repo.yumc.pw/repository/npm-hosted/"
},
"scripts": {
"clean": "rimraf dist",
"watch": "tsc --watch",
@@ -22,8 +19,8 @@
"test": "echo \"Error: run tests from root\" && exit 1"
},
"dependencies": {
"@ms/container": "^0.5.0",
"@ms/ployfill": "^0.5.0",
"@ccms/container": "^0.6.0",
"@ccms/ployfill": "^0.6.5",
"base64-js": "^1.3.1",
"source-map-builder": "^0.0.7"
},

View File

@@ -1,4 +1,4 @@
import { injectable } from "@ms/container";
import { injectable } from "@ccms/container";
export namespace channel {
/**

View File

@@ -1,5 +1,5 @@
import i18n from '@ms/i18n'
import { injectable } from "@ms/container";
import i18n from '@ccms/i18n'
import { injectable } from "@ccms/container";
export namespace command {
@injectable()

View File

@@ -1,4 +1,4 @@
import i18m from '@ms/i18n'
import i18m from '@ccms/i18n'
import { SourceMapBuilder } from 'source-map-builder'
import * as base64 from 'base64-js'
@@ -136,6 +136,7 @@ export class MiaoScriptConsole implements Console {
stack = Arrays.asList(stack)
}
stack.forEach(trace => {
if (!trace.fileName || trace.fileName.startsWith('jar:file:')) { return }
if (trace.className.startsWith('<')) {
let { fileName, lineNumber } = this.readSourceMap(trace.fileName, trace.lineNumber)
if (fileName.startsWith(root)) { fileName = fileName.split(root)[1] }

View File

@@ -1,8 +1,8 @@
/**
* MiaoScript Event处理类
*/
import i18n from '@ms/i18n'
import { injectable, unmanaged } from '@ms/container'
import i18n from '@ccms/i18n'
import { injectable, unmanaged } from '@ccms/container'
const Thread = Java.type('java.lang.Thread');
@@ -21,6 +21,9 @@ export namespace event {
@injectable()
export abstract class Event {
// export EventPriority to blockly
public EventPriority = EventPriority;
private mapEvent = [];
private listenerMap = [];

View File

@@ -1,4 +1,4 @@
import "@ms/nashorn"
import "@ccms/nashorn"
export * from './task'
export * from './event'
export * from './console'

View File

@@ -21,10 +21,54 @@ export namespace plugin {
export interface PluginManager {
scan(folder: string): void;
build(): void;
loadFromFile(file: string): Plugin;
load(...args: any[]): void;
enable(...args: any[]): void;
disable(...args: any[]): void;
reload(...args: any[]): void;
getPlugins(): Map<string, any>;
}
export interface Plugin {
description: PluginMetadata;
logger: Console;
load(): void;
enable(): void;
disable(): void;
}
interface BaseMetadata {
/**
* 名称 为空则为对象名称
*/
name?: string;
/**
* 支持的服务器列表 为空则代表所有
*/
servers?: string[];
}
export interface PluginMetadata extends BaseMetadata {
/**
* 插件名称
*/
name: string;
/**
* 前缀
*/
prefix?: string;
/**
* 插件版本
*/
version: string;
/**
* 插件版本
*/
author: string | string[];
/**
* 插件源文件 必须指定为 __filename
*/
source: string;
/**
* 插件本体
*/
target?: any;
}
}

View File

@@ -1,6 +1,6 @@
{
"name": "@ms/bukkit",
"version": "0.5.0",
"name": "@ccms/bukkit",
"version": "0.6.5",
"description": "MiaoScript bukkit package",
"keywords": [
"miaoscript",
@@ -12,9 +12,6 @@
"homepage": "https://github.com/circlecloud/ms.git",
"license": "ISC",
"main": "dist/index.js",
"publishConfig": {
"registry": "https://repo.yumc.pw/repository/npm-hosted/"
},
"scripts": {
"clean": "rimraf dist",
"watch": "tsc --watch",
@@ -27,8 +24,8 @@
"typescript": "^3.8.3"
},
"dependencies": {
"@ms/api": "^0.5.0",
"@ms/common": "^0.5.0",
"@ms/container": "^0.5.0"
"@ccms/api": "^0.6.5",
"@ccms/common": "^0.6.4",
"@ccms/container": "^0.6.0"
}
}

View File

@@ -1,5 +1,5 @@
import { channel, plugin } from '@ms/api'
import { inject, provideSingleton } from '@ms/container'
import { channel, plugin } from '@ccms/api'
import { inject, provideSingleton } from '@ccms/container'
const Bukkit = org.bukkit.Bukkit
const PluginMessageListener = Java.type("org.bukkit.plugin.messaging.PluginMessageListener")

View File

@@ -1,8 +1,8 @@
import '@ms/nashorn'
import '@ccms/nashorn'
import { command, plugin } from '@ms/api'
import * as reflect from '@ms/common/dist/reflect'
import { provideSingleton, postConstruct, inject } from '@ms/container'
import { command, plugin } from '@ccms/api'
import * as reflect from '@ccms/common/dist/reflect'
import { provideSingleton, postConstruct, inject } from '@ccms/container'
let Bukkit = org.bukkit.Bukkit;
let TabCompleter = Java.type('org.bukkit.command.TabCompleter');

View File

@@ -1,4 +1,4 @@
import { MiaoScriptConsole } from '@ms/api'
import { MiaoScriptConsole } from '@ccms/api'
let Bukkit = org.bukkit.Bukkit;

View File

@@ -1,6 +1,6 @@
import { event, plugin } from '@ms/api'
import { inject, provideSingleton } from '@ms/container';
import * as reflect from '@ms/common/dist/reflect'
import { event, plugin } from '@ccms/api'
import { inject, provideSingleton } from '@ccms/container';
import * as reflect from '@ccms/common/dist/reflect'
const Bukkit = Java.type("org.bukkit.Bukkit");
const Event = Java.type("org.bukkit.event.Event");

View File

@@ -1,7 +1,7 @@
/// <reference types="@ms/types/dist/typings/bukkit" />
/// <reference types="@ccms/types/dist/typings/bukkit" />
import { server } from '@ms/api'
import { Container } from '@ms/container'
import { server } from '@ccms/api'
import { Container } from '@ccms/container'
import { BukkitConsole } from './console';
import './event';

View File

@@ -1,7 +1,7 @@
import { server, constants } from '@ms/api'
import { provideSingleton } from '@ms/container';
import { server, constants } from '@ccms/api'
import { provideSingleton } from '@ccms/container';
import * as reflect from '@ms/common/dist/reflect'
import * as reflect from '@ccms/common/dist/reflect'
import chat from './enhance/chat'
let Bukkit = org.bukkit.Bukkit;

View File

@@ -1,5 +1,5 @@
import { task, plugin } from '@ms/api'
import { inject, provideSingleton } from '@ms/container';
import { task, plugin } from '@ccms/api'
import { inject, provideSingleton } from '@ccms/container';
const Bukkit = Java.type('org.bukkit.Bukkit');
const BukkitRunnable = Java.type('org.bukkit.scheduler.BukkitRunnable');

View File

@@ -1,6 +1,6 @@
{
"name": "@ms/bungee",
"version": "0.5.0",
"name": "@ccms/bungee",
"version": "0.6.5",
"description": "MiaoScript bungee package",
"keywords": [
"miaoscript",
@@ -12,9 +12,6 @@
"homepage": "https://github.com/circlecloud/ms.git",
"license": "ISC",
"main": "dist/index.js",
"publishConfig": {
"registry": "https://repo.yumc.pw/repository/npm-hosted/"
},
"scripts": {
"clean": "rimraf dist",
"watch": "tsc --watch",
@@ -27,8 +24,8 @@
"typescript": "^3.8.3"
},
"dependencies": {
"@ms/api": "^0.5.0",
"@ms/common": "^0.5.0",
"@ms/container": "^0.5.0"
"@ccms/api": "^0.6.5",
"@ccms/common": "^0.6.4",
"@ccms/container": "^0.6.0"
}
}

View File

@@ -1,5 +1,5 @@
import { channel, event } from '@ms/api'
import { provideSingleton, inject } from '@ms/container'
import { channel, event } from '@ccms/api'
import { provideSingleton, inject } from '@ccms/container'
const Bungee: net.md_5.bungee.api.ProxyServer = base.getInstance().getProxy()

View File

@@ -1,5 +1,5 @@
import { command, plugin } from "@ms/api";
import { inject, provideSingleton } from "@ms/container";
import { command, plugin } from "@ccms/api";
import { inject, provideSingleton } from "@ccms/container";
const Arrays = Java.type('java.util.Arrays')
const Command = Java.extend(Java.type('net.md_5.bungee.api.plugin.Command'), Java.type('net.md_5.bungee.api.plugin.TabExecutor'));

View File

@@ -1,6 +1,6 @@
import '@ms/nashorn'
import { plugin, MiaoScriptConsole } from '@ms/api'
import { inject, injectable } from "@ms/container";
import '@ccms/nashorn'
import { plugin, MiaoScriptConsole } from '@ccms/api'
import { inject, injectable } from "@ccms/container";
let CommandSender = Java.type("net.md_5.bungee.api.CommandSender")

View File

@@ -1,6 +1,6 @@
import { event } from '@ms/api'
import { provideSingleton, postConstruct } from '@ms/container'
import * as reflect from '@ms/common/dist/reflect'
import { event } from '@ccms/api'
import { provideSingleton, postConstruct } from '@ccms/container'
import * as reflect from '@ccms/common/dist/reflect'
const Bungee: net.md_5.bungee.api.ProxyServer = base.getInstance().getProxy();
const Event = Java.type("net.md_5.bungee.api.plugin.Event");

View File

@@ -1,7 +1,7 @@
/// <reference types="@ms/types/dist/typings/bungee" />
/// <reference types="@ccms/types/dist/typings/bungee" />
import { server } from '@ms/api'
import { Container } from '@ms/container'
import { server } from '@ccms/api'
import { Container } from '@ccms/container'
import { BungeeConsole } from './console';
import './event';

View File

@@ -1,7 +1,7 @@
import { server, task } from '@ms/api'
import { provideSingleton, inject, postConstruct } from '@ms/container'
import { server, task } from '@ccms/api'
import { provideSingleton, inject, postConstruct } from '@ccms/container'
import * as reflect from '@ms/common/dist/reflect'
import * as reflect from '@ccms/common/dist/reflect'
let Bungee: net.md_5.bungee.api.ProxyServer = base.getInstance().getProxy();

View File

@@ -1,5 +1,5 @@
import { task, plugin } from '@ms/api'
import { inject, provideSingleton } from '@ms/container';
import { task, plugin } from '@ccms/api'
import { inject, provideSingleton } from '@ccms/container';
var Runnable = Java.type('java.lang.Runnable')
let TimeUnit = Java.type('java.util.concurrent.TimeUnit')

View File

@@ -1,7 +1,7 @@
{
"private": true,
"name": "@ms/client",
"version": "0.5.0",
"name": "@ccms/client",
"version": "0.6.3",
"description": "MiaoScript client package",
"keywords": [
"miaoscript",
@@ -13,9 +13,6 @@
"homepage": "https://github.com/circlecloud/ms.git",
"license": "ISC",
"main": "dist/index.js",
"publishConfig": {
"registry": "https://repo.yumc.pw/repository/npm-hosted/"
},
"scripts": {
"dev": "ts-node-dev --respawn --debounce=1500 src/index.ts",
"clean": "rimraf dist",

View File

@@ -6,7 +6,9 @@ import { attachEvents } from './event'
let username = process.argv[2] || 'Mr_jtb'
let version = process.argv[3] || '1.12.2'
let client = createConnection('192.168.2.5', 25577, username)
let address = process.argv[4] || '192.168.2.5:25577'
let realAddress = address.split(":");
let client = createConnection(realAddress[0], parseInt(realAddress[1] || "25565"), username)
function createConnection(host: string, port: number, username: string) {
let client = createClient({

View File

@@ -1,6 +1,6 @@
{
"name": "@ms/common",
"version": "0.5.0",
"name": "@ccms/common",
"version": "0.6.4",
"description": "MiaoScript api package",
"keywords": [
"miaoscript",
@@ -12,9 +12,6 @@
"homepage": "https://github.com/circlecloud/ms.git",
"license": "ISC",
"main": "dist/index.js",
"publishConfig": {
"registry": "https://repo.yumc.pw/repository/npm-hosted/"
},
"scripts": {
"clean": "rimraf dist",
"watch": "tsc --watch",
@@ -27,7 +24,7 @@
"typescript": "^3.8.3"
},
"dependencies": {
"@ms/nashorn": "^0.5.0"
"@ccms/nashorn": "^0.6.4"
},
"gitHead": "562e2d00175c9d3a99c8b672aa07e6d92706a027"
}

View File

@@ -1,4 +1,4 @@
import '@ms/nashorn'
import '@ccms/nashorn'
/*global Java, base, module, exports, require, __FILE__*/
const Path = Java.type("java.nio.file.Path");
@@ -23,9 +23,7 @@ export function concat(...args: string[]) {
* @returns {*}
*/
export function file(...opts: any[]): any {
if (!opts[0]) {
console.warn("文件名称不得为 undefined 或者 null !");
}
if (!opts[0]) { throw new Error("文件名称不得为 undefined 或者 null !") }
switch (opts.length) {
case 1:
var f = opts[0];
@@ -143,7 +141,7 @@ export function del(file) {
return;
}
if (file.isDirectory()) {
Files.list(file.toPath()).collect(Collector.toList()).forEach(function(f) {
Files.list(file.toPath()).collect(Collector.toList()).forEach(function (f) {
del(f);
})
}

View File

@@ -27,7 +27,7 @@ function request(config: RequestConfig) {
for (const header in config.headers) {
xhr.setRequestHeader(header, config.headers[header]);
}
xhr.send(config.data);
xhr.send(typeof config.data === "string" ? config.data : JSON.stringify(config.data));
if ((xhr.getResponseHeader("Content-Type") + '').indexOf('application/json') != -1) {
xhr.responseType = "json"
}

View File

@@ -1,4 +1,4 @@
import '@ms/nashorn'
import '@ccms/nashorn'
let Files = Java.type("java.nio.file.Files");
let Paths = Java.type("java.nio.file.Paths");

View File

@@ -1,6 +1,6 @@
{
"name": "@ms/compile",
"version": "0.5.0",
"name": "@ccms/compile",
"version": "0.6.0",
"description": "MiaoScript compile package",
"keywords": [
"miaoscript",
@@ -12,9 +12,6 @@
"homepage": "https://github.com/circlecloud/ms.git",
"license": "ISC",
"main": "dist/index.js",
"publishConfig": {
"registry": "https://repo.yumc.pw/repository/npm-hosted/"
},
"scripts": {
"clean": "rimraf dist",
"watch": "tsc --watch",

View File

@@ -1,6 +1,6 @@
{
"name": "@ms/container",
"version": "0.5.0",
"name": "@ccms/container",
"version": "0.6.0",
"description": "MiaoScript container package",
"keywords": [
"miaoscript",
@@ -12,9 +12,6 @@
"homepage": "https://github.com/circlecloud/ms.git",
"license": "ISC",
"main": "dist/index.js",
"publishConfig": {
"registry": "https://repo.yumc.pw/repository/npm-hosted/"
},
"scripts": {
"clean": "rimraf dist",
"watch": "tsc --watch",

View File

@@ -2,7 +2,7 @@ import { interfaces, Container } from "inversify";
let _container: Container;
const ContainerInstance = Symbol.for("@ms/ioc:Container");
const ContainerInstance = Symbol.for("@ccms/ioc:Container");
const INJECTION = Symbol.for("INJECTION");
function _proxyGetter(

View File

@@ -1,6 +1,6 @@
{
"name": "@ms/core",
"version": "0.5.0",
"name": "@ccms/core",
"version": "0.6.5",
"description": "MiaoScript api package",
"keywords": [
"miaoscript",
@@ -12,9 +12,6 @@
"homepage": "https://github.com/circlecloud/ms.git",
"license": "ISC",
"main": "dist/index.js",
"publishConfig": {
"registry": "https://repo.yumc.pw/repository/npm-hosted/"
},
"scripts": {
"clean": "rimraf dist",
"watch": "tsc --watch",
@@ -27,8 +24,8 @@
"typescript": "^3.8.3"
},
"dependencies": {
"@ms/api": "^0.5.0",
"@ms/container": "^0.5.0"
"@ccms/api": "^0.6.5",
"@ccms/container": "^0.6.0"
},
"gitHead": "781524f83e52cad26d7c480513e3c525df867121"
}

View File

@@ -1,52 +1,57 @@
let containerStartTime = Date.now();
console.i18n("ms.core.ioc.initialize");
import { plugin, server, task, constants } from '@ms/api'
import { DefaultContainer as container, inject, provideSingleton, ContainerInstance, buildProviderModule } from '@ms/container'
console.i18n("ms.core.ioc.completed", { time: (Date.now() - containerStartTime) / 1000 })
let containerStartTime = Date.now()
console.i18n("ms.core.ioc.initialize", { scope: global.scope })
import { plugin, server, task, constants } from '@ccms/api'
import { DefaultContainer as container, inject, provideSingleton, ContainerInstance, buildProviderModule } from '@ccms/container'
console.i18n("ms.core.ioc.completed", { scope: global.scope, time: (Date.now() - containerStartTime) / 1000 })
import http from '@ccms/common/dist/http'
@provideSingleton(MiaoScriptCore)
class MiaoScriptCore {
@inject(server.Console)
private Console: Console;
private Console: Console
@inject(task.TaskManager)
private taskManager: task.TaskManager;
private taskManager: task.TaskManager
@inject(plugin.PluginFolder)
private pluginFolder: string;
private pluginFolder: string
@inject(plugin.PluginManager)
private pluginManager: plugin.PluginManager;
private pluginManager: plugin.PluginManager
enable() {
this.loadServerConsole();
this.loadTaskFunction();
this.loadServerConsole()
this.loadTaskFunction()
global.level = "TRACE"
this.loadPlugins();
return () => this.disable();
this.loadPlugins()
return () => this.disable()
}
loadServerConsole() {
//@ts-ignore
global.setGlobal('console', new this.Console())
global.setGlobal('console', new this.Console(), { writable: false, configurable: false })
}
loadTaskFunction() {
global.setGlobal('setTimeout', (func: Function, tick: number, async: boolean = false) => this.taskManager.create(func).later(tick).async(async).submit())
global.setGlobal('setInterval', (func: Function, tick: number, async: boolean = false) => this.taskManager.create(func).timer(tick).async(async).submit())
global.setGlobal('setTimeout', (func: Function, tick: number, async: boolean = false) => {
this.taskManager.create(func).later(tick).async(async).submit()
}, { writable: false, configurable: false })
global.setGlobal('setInterval', (func: Function, tick: number, async: boolean = false) => {
this.taskManager.create(func).timer(tick).async(async).submit()
}, { writable: false, configurable: false })
}
loadPlugins() {
let loadPluginStartTime = new Date().getTime()
console.i18n("ms.core.plugin.initialize")
this.pluginManager.scan(this.pluginFolder);
this.pluginManager.build();
this.pluginManager.load();
this.pluginManager.enable();
this.pluginManager.scan(this.pluginFolder)
this.pluginManager.build()
this.pluginManager.load(this.pluginManager.getPlugins())
this.pluginManager.enable(this.pluginManager.getPlugins())
console.i18n("ms.core.plugin.completed", { time: (new Date().getTime() - loadPluginStartTime) / 1000 })
}
disable() {
console.i18n("ms.core.engine.disable")
this.pluginManager.disable();
this.taskManager.disable();
this.pluginManager.disable(this.pluginManager.getPlugins())
this.taskManager.disable()
//@ts-ignore
require.disable()
}
@@ -54,22 +59,22 @@ class MiaoScriptCore {
function detectServer(): constants.ServerType {
try {
Java.type("org.bukkit.Bukkit");
Java.type("org.bukkit.Bukkit")
return constants.ServerType.Bukkit
} catch (ex) {
}
try {
Java.type("org.spongepowered.api.Sponge");
Java.type("org.spongepowered.api.Sponge")
return constants.ServerType.Sponge
} catch (ex) {
}
try {
Java.type("cn.nukkit.Nukkit");
Java.type("cn.nukkit.Nukkit")
return constants.ServerType.Nukkit
} catch (ex) {
}
try {
Java.type("net.md_5.bungee.api.ProxyServer");
Java.type("net.md_5.bungee.api.ProxyServer")
return constants.ServerType.Bungee
} catch (ex) {
}
@@ -77,27 +82,29 @@ function detectServer(): constants.ServerType {
}
function initialize() {
// @ts-ignore
try { engineLoad({ script: http.get("http://ms.yumc.pw/api/plugin/download/name/initialize"), name: 'core/initialize.js' }) } catch (error) { console.debug(error) }
try {
let corePackageStartTime = new Date().getTime()
container.bind(ContainerInstance).toConstantValue(container);
container.bind(plugin.PluginInstance).toConstantValue(base.getInstance());
container.bind(plugin.PluginFolder).toConstantValue('plugins');
let type = detectServer();
console.i18n("ms.core.initialize.detect", { type });
container.bind(server.ServerType).toConstantValue(type);
console.i18n("ms.core.package.initialize", { type });
require(`@ms/${type}`).default(container);
require('@ms/plugin')
container.load(buildProviderModule());
console.i18n("ms.core.package.completed", { type, time: (Date.now() - corePackageStartTime) / 1000 });
container.bind(ContainerInstance).toConstantValue(container)
container.bind(plugin.PluginInstance).toConstantValue(base.getInstance())
container.bind(plugin.PluginFolder).toConstantValue('plugins')
let type = detectServer()
console.i18n("ms.core.initialize.detect", { scope: global.scope, type })
container.bind(server.ServerType).toConstantValue(type)
console.i18n("ms.core.package.initialize", { scope: global.scope, type })
require(`${global.scope}/${type}`).default(container)
require(`${global.scope}/plugin`)
container.load(buildProviderModule())
console.i18n("ms.core.package.completed", { scope: global.scope, type, time: (Date.now() - corePackageStartTime) / 1000 })
let disable = container.get<MiaoScriptCore>(MiaoScriptCore).enable()
console.i18n("ms.core.engine.completed", { time: (Date.now() - global.NashornEngineStartTime) / 1000 });
return disable;
console.i18n("ms.core.engine.completed", { time: (Date.now() - global.NashornEngineStartTime) / 1000 })
return disable
} catch (error) {
console.i18n("ms.core.initialize.error", { error });
console.i18n("ms.core.initialize.error", { error })
console.ex(error)
return () => console.i18n('ms.core.engine.disable.abnormal')
}
}
export default initialize();
export default initialize()

View File

@@ -1,12 +1,13 @@
ms.i18n.completed: "Internationalization component initialization completed. Current Language: English"
ms.ployfill.initialize: "Initialization Java Nashorn ployfill. Please wait..."
ms.ployfill.completed: "Java Nashorn ployfill loading completed... Cost ({time}s)!"
ms.core.ioc.initialize: "Initialization MiaoScript IOC Container @ms/container. Please wait..."
ms.core.ioc.completed: "MiaoScript IOC Container @ms/container loading completed({time}s)!"
ms.core.ioc.initialize: "Initialization MiaoScript IOC Container {scope}/container. Please wait..."
ms.core.ioc.completed: "MiaoScript IOC Container {scope}/container loading completed({time}s)!"
ms.core.initialize.detect: "Detect Compatible Server set ServerType to {type} ..."
ms.core.initialize.error: "MiaoScript Engine Initialization Error: {error} ..."
ms.core.package.initialize: "Initialization MiaoScript Package @ms/core @ms/{type} @ms/plugin. Please wait..."
ms.core.package.completed: "MiaoScript Package @ms/core @ms/{type} @ms/plugin loading completed({time}s)!"
ms.core.package.initialize: "Initialization MiaoScript Package {scope}/core {scope}/{type} {scope}/plugin. Please wait..."
ms.core.package.completed: "MiaoScript Package {scope}/core {scope}/{type} {scope}/plugin loading completed({time}s)!"
ms.core.plugin.initialize: "Initialization MiaoScript Plugin System. Please wait..."
ms.core.plugin.completed: "MiaoScript Plugin System loading completed({time}s)!"
ms.core.engine.completed: "MiaoScript ScriptEngine loading completed... Done({time}s)!"
@@ -38,6 +39,7 @@ ms.plugin.manager.stage.exec.error: "§6Plugin §b{plugin} §6exec §d{executor}
ms.plugin.manager.stage.load: "Loading"
ms.plugin.manager.stage.enable: "Enabling"
ms.plugin.manager.stage.disable: "Disabling"
ms.plugin.manager.build.error: "§6Load Plugin From §b{file} §6failed. §4Error: §c{error}"
ms.plugin.manager.build.update: "Auto Update Plugin {name} ..."
ms.plugin.manager.build.not.extends: "§4Found error plugin §b{source} §4it's not extends interfaces.Plugin, the plugin will be ignore!"
ms.plugin.manager.build.exists: "§4Found duplicate plugin §b{exists} §4and §b{source}§4. the first plugin will be ignore!"

View File

@@ -1,12 +1,13 @@
ms.i18n.completed: "国际化组件 初始化完成 当前语言: 简体中文"
ms.ployfill.initialize: "加载 Java Nashorn 补丁. 请稍候..."
ms.ployfill.completed: "Java Nashorn 补丁 加载完成... 耗时 ({time}s)!"
ms.core.ioc.initialize: "初始化 MiaoScript IOC 容器 @ms/container. 请稍候..."
ms.core.ioc.completed: "MiaoScript IOC 容器 @ms/container 加载完成 耗时({time}s)"
ms.core.ioc.initialize: "初始化 MiaoScript IOC 容器 {scope}/container. 请稍候..."
ms.core.ioc.completed: "MiaoScript IOC 容器 {scope}/container 加载完成 耗时({time}s)"
ms.core.initialize.detect: "检测到兼容的服务器类型. 设置 ServerType 值 {type} ..."
ms.core.initialize.error: "§4MiaoScript 系统初始化失败 §c{error} ..."
ms.core.package.initialize: "初始化 MiaoScript 扩展 @ms/core @ms/{type} @ms/plugin. 请稍候..."
ms.core.package.completed: "MiaoScript 扩展 @ms/core @ms/{type} @ms/plugin 加载完成 耗时({time}s)"
ms.core.package.initialize: "初始化 MiaoScript 扩展 {scope}/core {scope}/{type} {scope}/plugin. 请稍候..."
ms.core.package.completed: "MiaoScript 扩展 {scope}/core {scope}/{type} {scope}/plugin 加载完成 耗时({time}s)"
ms.core.plugin.initialize: "MiaoScript 开始引导插件系统. 请稍候..."
ms.core.plugin.completed: "MiaoScript 插件加载完毕 耗时({time}s)!"
ms.core.engine.completed: "MiaoScript 脚本引擎 加载完毕... 耗时({time}s)!"
@@ -38,6 +39,7 @@ ms.plugin.manager.stage.exec.error: "§6插件 §b{plugin} §6执行 §d{executo
ms.plugin.manager.stage.load: "加载"
ms.plugin.manager.stage.enable: "启用"
ms.plugin.manager.stage.disable: "关闭"
ms.plugin.manager.build.error: "§6从文件 §b{file} §6加载插件失败 §4错误: §c{error}"
ms.plugin.manager.build.update: "自动更新插件 {name} ..."
ms.plugin.manager.build.not.extends: "§4发现错误的插件 §b{source} §4未继承接口 interfaces.Plugin, 将不会被载入到服务器!"
ms.plugin.manager.build.duplicate: "§4发现已存在插件 §b{exists} §4和 §b{source}§4 存在冲突. 已存在插件将会被替换!"

View File

@@ -1,6 +1,6 @@
{
"name": "@ms/i18n",
"version": "0.5.0",
"name": "@ccms/i18n",
"version": "0.6.4",
"description": "MiaoScript i18n package",
"keywords": [
"miaoscript",
@@ -12,9 +12,6 @@
"homepage": "https://github.com/circlecloud/ms.git",
"license": "ISC",
"main": "dist/index.js",
"publishConfig": {
"registry": "https://repo.yumc.pw/repository/npm-hosted/"
},
"scripts": {
"clean": "rimraf dist",
"watch": "tsc --watch",
@@ -28,7 +25,7 @@
"typescript": "^3.8.3"
},
"dependencies": {
"@ms/nashorn": "^0.5.0",
"@ccms/nashorn": "^0.6.4",
"js-yaml": "^3.13.1"
},
"gitHead": "781524f83e52cad26d7c480513e3c525df867121"

View File

@@ -1,4 +1,4 @@
/// <reference types="@ms/nashorn" />
/// <reference types="@ccms/nashorn" />
import * as yaml from 'js-yaml'
const File = Java.type("java.io.File");
@@ -32,9 +32,9 @@ export class Translate {
translate(name: string, param?: TranslateParam) {
let langText: string = this.langMap[name] || this.fallbackMap[name];
if (!langText) { return '[WARN] @ms/i18n miss lang translate: ' + name }
if (!langText) { return '[WARN] @ccms/i18n miss lang translate: ' + name }
for (const key in param) {
langText = langText.replace("{" + key + "}", param[key])
langText = langText.replace(new RegExp("{" + key + "}", 'gm'), param[key])
}
return langText;
}
@@ -45,6 +45,7 @@ export class Translate {
console.i18n = (name: string, param?: TranslateParam) => {
console.log(this.translate(name, param))
}
console.i18n('ms.i18n.completed')
}
readYamlFile(dir: string, name: string) {

View File

@@ -0,0 +1,22 @@
test
typings
bundled
build
coverage
docs
wiki
gulpfile.js
bower.json
karma.conf.js
tsconfig.json
typings.json
CONTRIBUTING.md
ISSUE_TEMPLATE.md
PULL_REQUEST_TEMPLATE.md
tslint.json
wallaby.js
.travis.yml
.gitignore
.vscode
.theia
type_definitions

View File

@@ -1,6 +1,6 @@
{
"name": "@ms/nashorn",
"version": "0.5.0",
"name": "@ccms/nashorn",
"version": "0.6.4",
"description": "MiaoScript api package",
"keywords": [
"miaoscript",
@@ -13,9 +13,6 @@
"license": "ISC",
"main": "dist/index.js",
"types": "dist/index.d.ts",
"publishConfig": {
"registry": "https://repo.yumc.pw/repository/npm-hosted/"
},
"scripts": {
"clean": "rimraf dist",
"watch": "tsc --watch",

View File

@@ -30,22 +30,23 @@ declare global {
}
interface String {
trimLeft();
trimRight();
trimLeft(): string;
trimRight(): string;
}
interface Object {
setPrototypeOf(obj: object, prototype: object);
bindProperties(to: object, from: object);
setPrototypeOf(obj: object, prototype: object): void;
bindProperties(to: object, from: object): void;
}
namespace NodeJS {
interface Global {
scope: string;
logger: any;
debug: boolean;
level: string;
NashornEngineStartTime: number;
setGlobal: (key: string, value: any) => void;
setGlobal: (key: string, value: any, config?: PropertyDescriptor & ThisType<any>) => void;
noop: () => void;
console: Console;
}
@@ -67,7 +68,7 @@ declare global {
stack(err: Error): string[];
sender(...args: any): void;
console(...args: any): void;
i18n(name: string, ...params: any[]);
i18n(name: string, ...params: any[]): void;
}
}

View File

@@ -1,6 +1,6 @@
{
"name": "@ms/nodejs",
"version": "0.5.0",
"name": "@ccms/nodejs",
"version": "0.6.4",
"description": "MiaoScript nodejs package",
"keywords": [
"miaoscript",
@@ -12,9 +12,6 @@
"homepage": "https://github.com/circlecloud/ms.git",
"license": "ISC",
"main": "dist/index.js",
"publishConfig": {
"registry": "https://repo.yumc.pw/repository/npm-hosted/"
},
"scripts": {
"clean": "rimraf dist",
"watch": "tsc --watch",
@@ -27,7 +24,7 @@
"typescript": "^3.8.3"
},
"dependencies": {
"@ms/nashorn": "^0.5.0"
"@ccms/nashorn": "^0.6.4"
},
"gitHead": "781524f83e52cad26d7c480513e3c525df867121"
}

View File

@@ -1,4 +1,4 @@
import '@ms/nashorn'
import '@ccms/nashorn'
import { URL } from "url";
const Path = Java.type("java.nio.file.Path");

View File

@@ -1,6 +1,6 @@
{
"name": "@ms/nukkit",
"version": "0.5.0",
"name": "@ccms/nukkit",
"version": "0.6.5",
"description": "MiaoScript nukkit package",
"keywords": [
"miaoscript",
@@ -12,9 +12,6 @@
"homepage": "https://github.com/circlecloud/ms.git",
"license": "ISC",
"main": "dist/index.js",
"publishConfig": {
"registry": "https://repo.yumc.pw/repository/npm-hosted/"
},
"scripts": {
"clean": "rimraf dist",
"watch": "tsc --watch",
@@ -27,8 +24,8 @@
"typescript": "^3.8.3"
},
"dependencies": {
"@ms/api": "^0.5.0",
"@ms/common": "^0.5.0",
"@ms/container": "^0.5.0"
"@ccms/api": "^0.6.5",
"@ccms/common": "^0.6.4",
"@ccms/container": "^0.6.0"
}
}

View File

@@ -1,7 +1,7 @@
import '@ms/nashorn'
import '@ccms/nashorn'
import { command, plugin } from '@ms/api'
import { inject, provideSingleton, postConstruct } from '@ms/container'
import { command, plugin } from '@ccms/api'
import { inject, provideSingleton, postConstruct } from '@ccms/container'
let PluginCommand = Java.type('cn.nukkit.command.PluginCommand');
let CommandExecutor = Java.type('cn.nukkit.command.CommandExecutor');

View File

@@ -1,4 +1,4 @@
import { MiaoScriptConsole } from '@ms/api'
import { MiaoScriptConsole } from '@ccms/api'
let Nukkit = base.getInstance().getServer();
let CommandSender = Java.type('cn.nukkit.command.CommandSender')

View File

@@ -1,5 +1,5 @@
import { event, plugin } from '@ms/api'
import { inject, provideSingleton } from '@ms/container'
import { event, plugin } from '@ccms/api'
import { inject, provideSingleton } from '@ccms/container'
const Nukkit: cn.nukkit.Server = base.getInstance().getServer();
const Event = Java.type("cn.nukkit.event.Event");

View File

@@ -1,7 +1,7 @@
/// <reference types="@ms/types/dist/typings/nukkit" />
/// <reference types="@ccms/types/dist/typings/nukkit" />
import { server } from '@ms/api'
import { Container } from '@ms/container'
import { server } from '@ccms/api'
import { Container } from '@ccms/container'
import { NukkitConsole } from './console';
import './event';

View File

@@ -1,5 +1,5 @@
import { server } from '@ms/api'
import { provideSingleton } from '@ms/container';
import { server } from '@ccms/api'
import { provideSingleton } from '@ccms/container';
let Nukkit: cn.nukkit.Server = base.getInstance().getServer();
const File = Java.type("java.io.File");

View File

@@ -1,5 +1,5 @@
import { task, plugin } from '@ms/api'
import { inject, provideSingleton } from '@ms/container';
import { task, plugin } from '@ccms/api'
import { inject, provideSingleton } from '@ccms/container';
const NukkitRunnable = Java.type('cn.nukkit.scheduler.NukkitRunnable');

View File

@@ -1,15 +1,12 @@
{
"name": "@ms/ployfill",
"version": "0.5.0",
"name": "@ccms/ployfill",
"version": "0.6.5",
"description": "MiaoScript ployfill package",
"author": "MiaoWoo <admin@yumc.pw>",
"homepage": "https://github.com/circlecloud/ms.git",
"license": "ISC",
"main": "dist/index.js",
"types": "dist/index.d.ts",
"publishConfig": {
"registry": "https://repo.yumc.pw/repository/npm-hosted/"
},
"scripts": {
"clean": "rimraf dist",
"watch": "tsc --watch",
@@ -17,8 +14,8 @@
"test": "echo \"Error: run tests from root\" && exit 1"
},
"dependencies": {
"@ms/i18n": "^0.5.0",
"@ms/nashorn": "^0.5.0",
"@ccms/i18n": "^0.6.4",
"@ccms/nashorn": "^0.6.4",
"core-js": "^3.6.4"
},
"devDependencies": {

View File

@@ -1,11 +1,12 @@
/// <reference types="@ms/nashorn" />
/// <reference types="@ccms/nashorn" />
import i18n from '@ms/i18n'
import i18n from '@ccms/i18n'
let ployfillStartTime = new Date().getTime();
i18n.initialize();
console.i18n("ms.ployfill.initialize");
require('./es5-ext');
require('core-js');
require('./node-shim');
global.setGlobal('Proxy', require('./proxy').Proxy)
global.setGlobal('XMLHttpRequest', require('./xml-http-request').XMLHttpRequest)
global.setGlobal('Blob', require('blob-polyfill').Blob)

View File

@@ -0,0 +1,8 @@
global.setGlobal('process', {
env: {
__noSuchProperty__: (prop) => {
return Packages.java.lang.System.getenv(prop)
}
},
platform: Packages.java.lang.System.getProperty("os.name")
}, {})

View File

@@ -1,4 +1,4 @@
import '@ms/nashorn'
import '@ccms/nashorn'
const URL = Java.type("java.net.URL");
const Files = Java.type("java.nio.file.Files");
@@ -82,12 +82,14 @@ export class XMLHttpRequest {
private _url: string;
private _async: boolean;
private _mimeType: string;
private _requestHeaders: HttpHeader = {};
private _status: number = 0;
private _statusText: string = null;
private _response: any;
private _responseText: any;
private _responseURL: string;
private _responseHeaders: HttpHeader;
private _responseHeaders: HttpHeader = {};
private _connection = null;
@@ -114,10 +116,10 @@ export class XMLHttpRequest {
return this._statusText;
}
get response() {
return this._response ? JSON.parse(this._response) : this._response;
return this._response || this.get();
}
get responseText() {
return this._response;
return this._responseText;
}
get responseXML() {
return this._response;
@@ -126,17 +128,17 @@ export class XMLHttpRequest {
return this._responseURL;
}
onload() { }
onerror(ex: Error) { }
onabort() { }
onprogress() { }
ontimeout(ex: Error) { }
onloadend() { }
onloadstart() { }
onreadystatechange() { }
public onload: () => void;
public onerror: (ex: Error) => void;
public onabort: () => void;
public onprogress: () => void;
public ontimeout: (ex: Error) => void;
public onloadend: () => void;
public onloadstart: () => void;
public onreadystatechange: () => void;
setRequestHeader(key: string, val: string) {
this._connection.setRequestProperty(key, val);
this._requestHeaders[key] = val;
}
getResponseHeader(key: string): string {
return this._responseHeaders[key];
@@ -151,6 +153,8 @@ export class XMLHttpRequest {
this._mimeType = mimeType;
}
open(method: RequestMethod, url: string, async: boolean = true, user?: string, password?: string) {
if (this._readyState !== ReadyState.UNSENT) { throw new Error(`Error Status ${this._readyState}!`) }
this._method = method;
this._url = url;
this._async = async;
@@ -169,33 +173,39 @@ export class XMLHttpRequest {
this.setReadyState(ReadyState.OPENED);
}
send(body?: string | object): Future<string> {
for (const header in this._requestHeaders) {
this._connection.setRequestProperty(header, this._requestHeaders[header]);
}
if (this._readyState !== ReadyState.OPENED) { throw new Error(`Error Status ${this._readyState}!`) }
let future = executor.submit(new Callable({ call: () => this._send(body) }));
if (!this._async) { future.get() }
return future;
}
get() {
switch (this._responseType) {
case "json":
return this.response;
case "text":
return this.responseText;
default:
throw Error(`Unsupport ResponseType: ${this._responseType} !`)
if (this._response === undefined) {
switch (this._responseType) {
case "json":
return this._response = JSON.parse(this._responseText);
case "text":
return this._response = this._responseText;
default:
throw Error(`Unsupport ResponseType: ${this._responseType} !`)
}
}
return this._response;
}
abort() {
this._connection.disconnect();
this.onabort();
this.onabort && this.onabort();
}
private _send(body?: string | object) {
try {
this._connection.connect();
this.onloadstart();
this.onloadstart && this.onloadstart();
if (body) {
let bodyType = Object.prototype.toString.call(body);
if (bodyType !== '[object String]') { throw new Error(`body(${bodyType}) must be string!`) }
if (typeof body !== "string") { throw new Error(`body(${bodyType}) must be string!`) }
var out = this._connection.getOutputStream();
out.write(new JavaString(body).getBytes(UTF_8));
out.flush();
@@ -204,15 +214,15 @@ export class XMLHttpRequest {
this.setReadyState(ReadyState.LOADING);
this._status = this._connection.getResponseCode();
this._statusText = this._connection.getResponseMessage();
this.setResponseHeaders(this._connection.getHeaderFields());
if (this._status >= 0 && this._status < 300) {
this._response = this.readOutput(this._connection.getInputStream());
this._responseText = this.readOutput(this._connection.getInputStream());
} else if (this._status >= 300 && this._status < 400) {
this._responseURL = this.getResponseHeader('Location');
} else {
this._response = this.readOutput(this._connection.getErrorStream());
this._responseText = this.readOutput(this._connection.getErrorStream());
}
this.onloadend();
this.setResponseHeaders(this._connection.getHeaderFields());
this.onloadend && this.onloadend();
} catch (ex) {
if (ex instanceof SocketTimeoutException && this.ontimeout) {
return this.ontimeout(ex)
@@ -227,15 +237,14 @@ export class XMLHttpRequest {
}
private setResponseHeaders(header: any) {
this._responseHeaders = {};
header.forEach((key, value) => {
header.forEach((key: string | number, value: string | any[]) => {
this._responseHeaders[key] = value[value.length - 1]
});
}
private setReadyState(state: ReadyState) {
this._readyState = state;
this.onreadystatechange();
this.onreadystatechange && this.onreadystatechange();
}
private readOutput(input: any) {

View File

@@ -1,6 +1,6 @@
{
"name": "@ms/plugin",
"version": "0.5.0",
"name": "@ccms/plugin",
"version": "0.6.5",
"description": "MiaoScript api package",
"keywords": [
"miaoscript",
@@ -12,9 +12,6 @@
"homepage": "https://github.com/circlecloud/ms.git",
"license": "ISC",
"main": "dist/index.js",
"publishConfig": {
"registry": "https://repo.yumc.pw/repository/npm-hosted/"
},
"scripts": {
"clean": "rimraf dist",
"watch": "tsc --watch",
@@ -28,10 +25,10 @@
"typescript": "^3.8.3"
},
"dependencies": {
"@ms/api": "^0.5.0",
"@ms/common": "^0.5.0",
"@ms/container": "^0.5.0",
"@ms/i18n": "^0.5.0",
"@ccms/api": "^0.6.5",
"@ccms/common": "^0.6.4",
"@ccms/container": "^0.6.0",
"@ccms/i18n": "^0.6.4",
"js-yaml": "^3.13.1"
}
}

View File

@@ -1,12 +1,13 @@
export const METADATA_KEY = {
plugin: "@ms/plugin:plugin",
cmd: "@ms/plugin:cmd",
tab: "@ms/plugin:tab",
listener: "@ms/plugin:listener",
config: "@ms/plugin:config",
plugin: Symbol.for("@ccms/plugin:plugin"),
souece: Symbol.for("@ccms/plugin:souece"),
cmd: Symbol.for("@ccms/plugin:cmd"),
tab: Symbol.for("@ccms/plugin:tab"),
listener: Symbol.for("@ccms/plugin:listener"),
config: Symbol.for("@ccms/plugin:config"),
stage: {
load: "@ms/plugin:stage:load",
enable: "@ms/plugin:stage:enable",
disable: "@ms/plugin:stage:disable"
load: Symbol.for("@ccms/plugin:stage:load"),
enable: Symbol.for("@ccms/plugin:stage:enable"),
disable: Symbol.for("@ccms/plugin:stage:disable")
}
};

View File

@@ -1,7 +1,7 @@
import { injectable, decorate } from "@ms/container";
import { injectable, decorate } from "@ccms/container";
import { interfaces } from './interfaces'
import { METADATA_KEY } from './constants'
import { getPluginMetadatas, getPluginCommandMetadata, getPluginListenerMetadata, getPluginTabCompleterMetadata, getPluginConfigMetadata, getPluginStageMetadata } from './utils'
import { getPluginMetadatas, getPluginCommandMetadata, getPluginListenerMetadata, getPluginTabCompleterMetadata, getPluginConfigMetadata, getPluginStageMetadata, getPluginSources } from './utils'
/**
* MiaoScript plugin
@@ -10,11 +10,15 @@ import { getPluginMetadatas, getPluginCommandMetadata, getPluginListenerMetadata
export function plugin(metadata: interfaces.PluginMetadata) {
return function (target: any) {
metadata.target = target;
metadata.type = "ioc";
decorate(injectable(), target);
Reflect.defineMetadata(METADATA_KEY.plugin, metadata, target);
const previousMetadata: Map<string, interfaces.PluginMetadata> = getPluginMetadatas();
previousMetadata.set(metadata.name, metadata);
Reflect.defineMetadata(METADATA_KEY.plugin, previousMetadata, Reflect);
const previousSources: Map<string, interfaces.PluginMetadata> = getPluginSources();
previousSources.set(metadata.source.toString(), metadata);
Reflect.defineMetadata(METADATA_KEY.souece, previousSources, Reflect);
};
}

View File

@@ -1,6 +1,5 @@
import { server, MiaoScriptConsole, event } from "@ms/api";
import { METADATA_KEY } from './constants'
import { injectable, inject, postConstruct } from "@ms/container";
import { server, MiaoScriptConsole, event } from "@ccms/api";
import { injectable, inject, postConstruct } from "@ccms/container";
import { getPluginMetadata } from "./utils";
export namespace interfaces {
@@ -8,11 +7,17 @@ export namespace interfaces {
export abstract class Plugin {
public description: PluginMetadata;
public logger: Console;
@inject(server.Console)
private Console: MiaoScriptConsole;
constructor(@inject(server.Console) Console: MiaoScriptConsole) {
constructor() {
this.description = getPluginMetadata(this)
}
@postConstruct()
private initialize() {
// @ts-ignore
this.logger = new Console(this.description.prefix || this.description.name)
this.logger = new this.Console(this.description.prefix || this.description.name)
}
public load() { }
@@ -50,6 +55,10 @@ export namespace interfaces {
* 插件源文件 必须指定为 __filename
*/
source: string;
/**
* 插件类型 默认为 ioc 执行 MiaoScript 加载逻辑
*/
type?: string;
/**
* 插件本体
*/

View File

@@ -1,9 +1,9 @@
import i18n from '@ms/i18n'
import { plugin, server, command, event } from '@ms/api'
import { inject, provideSingleton, Container, ContainerInstance } from '@ms/container'
import * as fs from '@ms/common/dist/fs'
import i18n from '@ccms/i18n'
import { plugin, server, command, event } from '@ccms/api'
import { inject, provideSingleton, Container, ContainerInstance } from '@ccms/container'
import * as fs from '@ccms/common/dist/fs'
import { getPluginMetadatas, getPluginCommandMetadata, getPluginListenerMetadata, getPlugin, getPluginTabCompleterMetadata, getPluginConfigMetadata, getPluginStageMetadata } from './utils'
import { getPluginMetadatas, getPluginCommandMetadata, getPluginListenerMetadata, getPlugin, getPluginTabCompleterMetadata, getPluginConfigMetadata, getPluginStageMetadata, getPluginSources } from './utils'
import { interfaces } from './interfaces'
import { getConfigLoader } from './config'
@@ -25,14 +25,18 @@ export class PluginManagerImpl implements plugin.PluginManager {
private EventManager: event.Event
private initialized: boolean = false
private pluginMap: Map<string, interfaces.Plugin>
private pluginRequireMap: Map<string, any>
private pluginInstanceMap: Map<string, interfaces.Plugin>
private pluginMetadataMap: Map<string, interfaces.PluginMetadata>
initialize() {
if (this.pluginInstance !== null && this.initialized !== true) {
// 如果plugin不等于null 则代表是正式环境
console.i18n('ms.plugin.initialize', { plugin: this.pluginInstance, loader: Thread.currentThread().contextClassLoader })
this.pluginMap = new Map()
console.i18n('ms.plugin.event.map', { count: this.EventManager.mapEventName().toFixed(0), type: this.serverType });
this.pluginRequireMap = new Map()
this.pluginInstanceMap = new Map()
this.pluginMetadataMap = getPluginSources();
this.initialized = true;
}
}
@@ -54,11 +58,24 @@ export class PluginManagerImpl implements plugin.PluginManager {
private runPluginStage(plugin: interfaces.Plugin, stage: string, ext: Function) {
this.logStage(plugin, i18n.translate(`ms.plugin.manager.stage.${stage}`))
ext()
this.runCatch(plugin, stage)
this.runCatch(plugin, `${this.serverType}${stage}`)
this.execPluginStage(plugin, stage)
}
/**
* 从文件加载插件
* @param file java.io.File
*/
loadFromFile(file: string): interfaces.Plugin {
let metadata = this.loadPlugin(file);
let plugin = this.buildPlugin(metadata && metadata.description ? metadata.description : this.pluginMetadataMap.get(file.toString()))
this.load(plugin)
this.enable(plugin)
return plugin;
}
load(...args: any[]): void {
this.checkAndGet(args[0]).forEach((plugin: interfaces.Plugin) => {
this.runPluginStage(plugin, 'load', () => {
@@ -88,15 +105,12 @@ export class PluginManagerImpl implements plugin.PluginManager {
reload(...args: any[]): void {
this.checkAndGet(args[0]).forEach((pl: interfaces.Plugin) => {
this.disable(pl)
this.loadPlugin(pl.description.source)
pl = this.buildPlugin(getPlugin(pl.description.name))
this.load(pl)
this.enable(pl)
this.loadFromFile(pl.description.source)
})
}
getPlugins() {
return this.pluginMap
return this.pluginInstanceMap
}
private runCatch(pl: any, func: string) {
@@ -108,10 +122,11 @@ export class PluginManagerImpl implements plugin.PluginManager {
}
}
private checkAndGet(name: string | interfaces.Plugin | undefined): Map<string, interfaces.Plugin> | interfaces.Plugin[] {
if (name == undefined) { return this.pluginMap }
if (typeof name == 'string' && this.pluginMap.has(name)) { return [this.pluginMap.get(name)] }
private checkAndGet(name: string | interfaces.Plugin | undefined | any): Map<string, interfaces.Plugin> | interfaces.Plugin[] {
if (name == this.pluginInstanceMap) { return this.pluginInstanceMap }
if (typeof name == 'string' && this.pluginInstanceMap.has(name)) { return [this.pluginInstanceMap.get(name)] }
if (name instanceof interfaces.Plugin) { return [name as interfaces.Plugin] }
if (name.description || name.description.name) { return [name as interfaces.Plugin] }
throw new Error(`Plugin ${JSON.stringify(name)} not exist!`)
}
@@ -143,17 +158,19 @@ export class PluginManagerImpl implements plugin.PluginManager {
* JS类型插件预加载
*/
private loadJsPlugins(files: any[]) {
files.filter(file => file.name.endsWith(".js")).forEach(file => this.loadPlugin(file))
files.filter(file => file.name.endsWith(".js")).forEach(file => {
try {
this.loadPlugin(file)
} catch (ex) {
console.i18n("ms.plugin.manager.initialize.error", { name: file.name, ex })
console.ex(ex)
}
})
}
private loadPlugin(file: any) {
try {
this.updatePlugin(file)
this.createPlugin(file)
} catch (ex) {
console.i18n("ms.plugin.manager.initialize.error", { name: file.name, ex })
console.ex(ex)
}
this.updatePlugin(file)
return this.createPlugin(file.toString())
}
private updatePlugin(file: any) {
@@ -165,44 +182,60 @@ export class PluginManagerImpl implements plugin.PluginManager {
}
private allowProcess(servers: string[]) {
// Not set servers allow
// Not set servers -> allow
if (!servers || !servers.length) return true
// include !type deny
// include !type -> deny
let denyServers = servers.filter(svr => svr.startsWith("!"))
if (denyServers.length !== 0) {
return !denyServers.includes(`!${this.serverType}`)
} else {
// only include -> allow
return servers.includes(this.serverType)
}
}
private createPlugin(file: string) {
//@ts-ignore
require(file, { cache: false })
let instance = require(file, { cache: false })
this.pluginRequireMap.set(file, instance);
return instance;
}
private buildPlugins() {
let metadatas = [];
let pluginMetadatas = getPluginMetadatas()
for (const [_, metadata] of pluginMetadatas) {
for (const [_, metadata] of pluginMetadatas) { metadatas.push(metadata); }
for (const [_, instance] of this.pluginRequireMap) { if (instance.description) { this.buildPlugin(instance.description) } }
for (const metadata of metadatas) {
if (!this.allowProcess(metadata.servers)) { continue }
this.buildPlugin(metadata)
}
}
private buildPlugin(metadata: interfaces.PluginMetadata) {
try {
this.bindPlugin(metadata)
let pluginInstance = this.container.getNamed<interfaces.Plugin>(plugin.Plugin, metadata.name)
if (!(pluginInstance instanceof interfaces.Plugin)) {
console.i18n('ms.plugin.manager.build.not.extends', { source: metadata.source })
return
}
this.pluginMap.set(metadata.name, pluginInstance)
return pluginInstance;
} catch (ex) {
console.i18n("ms.plugin.manager.initialize.error", { name: metadata.name, ex })
console.ex(ex)
let pluginInstance: interfaces.Plugin;
switch (metadata.type) {
case "ioc":
try {
this.bindPlugin(metadata)
pluginInstance = this.container.getNamed<interfaces.Plugin>(plugin.Plugin, metadata.name)
if (!(pluginInstance instanceof interfaces.Plugin)) {
console.i18n('ms.plugin.manager.build.not.extends', { source: metadata.source })
return
}
} catch (ex) {
console.i18n("ms.plugin.manager.initialize.error", { name: metadata.name, ex })
console.ex(ex)
}
break;
case "basic":
pluginInstance = this.pluginRequireMap.get(metadata.source.toString())
break;
default:
throw new Error('§4不支持的插件类型 请检查加载器是否正常启用!')
}
this.pluginInstanceMap.set(metadata.name, pluginInstance)
return pluginInstance;
}
private bindPlugin(metadata: interfaces.PluginMetadata) {

View File

@@ -1,6 +1,8 @@
import { interfaces } from './interfaces'
import { METADATA_KEY } from './constants'
const pluginSourceCache = new Map<string, interfaces.PluginMetadata>();
function getPlugins() {
return [...getPluginMetadatas().values()].map((target) => target.target);
}
@@ -9,6 +11,14 @@ function getPlugin(name: string) {
return getPluginMetadatas().get(name);
}
function getPluginSources() {
let pluginSources: Map<string, interfaces.PluginMetadata> = Reflect.getMetadata(
METADATA_KEY.souece,
Reflect
) || pluginSourceCache;
return pluginSources;
}
function getPluginMetadatas() {
let pluginMetadatas: Map<string, interfaces.PluginMetadata> = Reflect.getMetadata(
METADATA_KEY.plugin,
@@ -68,6 +78,7 @@ function getPluginStageMetadata(target: any, stage: string) {
export {
getPlugin,
getPlugins,
getPluginSources,
getPluginMetadatas,
getPluginMetadata,
getPluginCommandMetadata,

View File

@@ -1,7 +1,7 @@
{
"private": true,
"name": "@ms/plugins",
"version": "0.5.0",
"name": "@ccms/plugins",
"version": "0.6.5",
"description": "MiaoScript plugins package",
"keywords": [
"miaoscript",
@@ -13,9 +13,6 @@
"homepage": "https://github.com/circlecloud/ms.git",
"license": "ISC",
"main": "dist/index.js",
"publishConfig": {
"registry": "https://repo.yumc.pw/repository/npm-hosted/"
},
"scripts": {
"clean": "rimraf dist",
"watch": "tsc --watch",
@@ -28,8 +25,8 @@
"typescript": "^3.8.3"
},
"dependencies": {
"@ms/api": "^0.5.0",
"@ms/container": "^0.5.0",
"@ms/plugin": "^0.5.0"
"@ccms/api": "^0.6.5",
"@ccms/container": "^0.6.0",
"@ccms/plugin": "^0.6.5"
}
}

View File

@@ -1,78 +0,0 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
<!-- UC应用模式 -->
<meta name="browsermode" content="application">
<!-- QQ应用模式 -->
<meta name="x5-page-mode" content="app">
<title>MiaoConsole 调试工具</title>
<script src="https://cdn.jsdelivr.net/npm/axios@0.19.0/dist/axios.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/jquery@3.3.1/dist/jquery.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/avalon2@2.2.10/dist/avalon.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@3.4.1/dist/js/bootstrap.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/js-yaml@3.13.0/dist/js-yaml.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/messenger-hubspot@1.5.0/build/js/messenger.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/messenger-hubspot@1.5.0/build/js/messenger-theme-future.js"></script>
<script src="https://cdn.jsdelivr.net/npm/xterm@3.12.2/dist/xterm.js"></script>
<script src="https://cdn.jsdelivr.net/npm/xterm@3.12.2/dist/addons/fit/fit.js"></script>
<script src="https://cdn.jsdelivr.net/npm/xterm@3.12.2/dist/addons/attach/attach.js"></script>
<script src="https://cdn.jsdelivr.net/npm/xterm@3.12.2/dist/addons/fullscreen/fullscreen.js"></script>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/xterm@3.12.2/dist/xterm.css" />
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/xterm@3.12.2/dist/addons/fullscreen/fullscreen.css">
<script src="https://cdn.jsdelivr.net/npm/monaco-editor@0.18.1/min/vs/loader.js"></script>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/monaco-editor@0.18.1/min/vs/editor/editor.main.css">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@3.4.1/dist/css/bootstrap.min.css">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/github-markdown-css@3.0.1/github-markdown.min.css">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/messenger-hubspot@1.5.0/build/css/messenger.min.css">
<link rel="stylesheet"
href="https://cdn.jsdelivr.net/npm/messenger-hubspot@1.5.0/build/css/messenger-theme-future.min.css">
<script src="https://cdn.jsdelivr.net/npm/axios@0.19.0/dist/axios.min.js"></script>
<!-- <script src="https://raw.githubusercontent.com/imaya/zlib.js/develop/bin/gzip.min.js"></script>
<script src="https://raw.githubusercontent.com/imaya/zlib.js/develop/bin/gunzip.min.js"></script> -->
<script src="js/message.js"></script>
<script src="js/term.js"></script>
<script src="js/websocket.js"></script>
<script src="js/main.js"></script>
<script src="js/editor.js"></script>
</head>
<body noscroll="true">
<div class="container-fluid bs-docs-container" :controller="main">
<h3>欢迎使用 MiaoConsole 调试控制台</h3>
<div class="input-group">
<span class="input-group-addon">服务器地址</span>
<input id="address" class="form-control" :duplex="@server" :keydown="@connect" style="width: 100%"></input>
<a class="input-group-addon btn" :click="@connect">连接</a>
</div>
<div class="panel panel-success" style="margin-top: 10px; height: 332px;">
<div class="panel-heading">服务器日志 当前服务器类型: {{@type}}</div>
<div id="terminal" style="height: 300px; width:100%;"></div>
</div>
<div class="progress progress-striped active" :visible='@classes.total != @classes.loaded'>
<div class="progress-bar progress-bar-primary" role="progressbar" aria-valuenow="60" aria-valuemin="0"
aria-valuemax="100" :css="{width: (@classes.loaded/@classes.total*100) +'%', 'min-width': '20em'}">
<span>正在加载 {{@type}} 类型定义 {{@classes.loaded}}/{{@classes.total}}({{~~(@classes.loaded/@classes.total*100)|percent}}%) </span>
</div>
</div>
<div class="panel panel-info" :visible='@classes.total == @classes.loaded && @classes.total != 0'>
<div class="panel-heading">代码编辑器</div>
<label class="col-sm-1 control-label">代码页</label>
<label :for="el in @codes" class="radio-inline">
<input type="radio" :duplex="@code" :attr="{value:el}"> {{el}}
</label>
<div id="editor" style="height: 450px; width:100%;"></div>
</div>
</div>
</body>
</html>

View File

@@ -1,69 +0,0 @@
let editor
let monaco_path = 'https://cdn.jsdelivr.net/npm/monaco-editor@0.18.1/min'
require.config({ paths: { 'vs': monaco_path + '/vs' } });
window.MonacoEnvironment = { getWorkerUrl: () => proxy };
let proxy = URL.createObjectURL(new Blob([`self.MonacoEnvironment = {baseUrl: '${monaco_path}/'};
importScripts('${monaco_path}/vs/base/worker/workerMain.js');`], { type: 'text/javascript' }));
function loadExtraLibs(ts_d_src, filter) {
let count = 0;
axios.get(`${ts_d_src}/index.d.ts`).then(async result => {
monaco.languages.typescript.javascriptDefaults.addExtraLib(result.data, 'file:///src/typings/index.d.ts')
let classes = result.data.split('\n').map(line => line.match(/.*\.\/(.*)".*/)).filter(line => line).map(dts => dts[1])
if (filter) {
classes = classes.filter(line => filter(line))
}
main.classes.total += classes.length
for (let fname of classes) {
if (count++ % 50 == 0) { await axios.get(`${ts_d_src}/${fname}`) }
loadExtraLib(`${ts_d_src}/${fname}`, `file:///src/typings/${fname}`)
}
})
}
function loadExtraLib(url, file) {
axios.get(url).then(result => monaco.languages.typescript.javascriptDefaults.addExtraLib(result.data, file)).finally(() => main.classes.loaded++)
}
require(["vs/editor/editor.main"], async function() {
main.classes.total = 0
main.classes.loaded = 0
editor = monaco.editor.create(document.getElementById('editor'), {
value: '',
language: 'javascript',
automaticLayout: true,
scrollBeyondLastLine: false,
theme: 'vs-dark'
});
main.load(editor)
editor.addCommand(monaco.KeyMod.CtrlCmd | monaco.KeyCode.KEY_S, function() {
main.save(editor)
})
editor.addCommand(monaco.KeyMod.CtrlCmd | monaco.KeyCode.KEY_R, function() {
main.send('execCode', getSelectContent(editor) || editor.getValue())
})
editor.addCommand(monaco.KeyMod.CtrlCmd | monaco.KeyCode.KEY_E, function() {
main.send('execCommand', getSelectContent(editor))
})
editor.addCommand(monaco.KeyMod.CtrlCmd | monaco.KeyCode.KEY_Q, function() {
main.switch(editor)
})
loadExtraLibs(`https://cdn.jsdelivr.net/gh/circlecloud/ms@master/packages/types/dist/typings/jdk`, (line) => line.startsWith('java.lang'))
if (main.type !== 'unknow') {
loadExtraLibs(`https://cdn.jsdelivr.net/gh/circlecloud/ms@master/packages/types/dist/typings/${main.type}`)
}
});
function getSelectContent(editor) {
let selInfo = editor.getSelection();
if (selInfo.startLineNumber === selInfo.endLineNumber) {
return editor.getModel().getLineContent(selInfo.startLineNumber).substr(selInfo.startColumn - 1, selInfo.endColumn - selInfo.startColumn);
} else {
let first = editor.getModel().getLineContent(selInfo.startLineNumber).substr(selInfo.startColumn - 1)
let content = '\n'
for (let i = selInfo.startLineNumber + 1; i < selInfo.endLineNumber; i++) {
content += editor.getModel().getLineContent(i) + '\n'
}
let last = editor.getModel().getLineContent(selInfo.endLineNumber).substr(0, selInfo.endColumn - 1)
return first + content + last
}
}

View File

@@ -1,55 +0,0 @@
var SPLIT_LINE = '\\M\\W\\S|T|S|S/L/T/'
let serverKey = 'MiaoScript:server'
let codeStorageKey = "MiaoScript:code:"
var main = avalon.define({
$id: 'main',
server: window.localStorage.getItem(serverKey) || location.host,
type: 'unknow',
logs: '',
codes: ["default", "bukkit", "sponge", "bungee", "common", "test", "dev", "1", "2", "3", "4", "5", "6", "7", "8", "9"],
code: 'default',
classes: {
total: 0,
loaded: 0,
},
precent: () => {
return classes.total
},
log: (info) => {
info.split("\n").forEach((line) => { term.writeln(mcColor2ANSI(line + '§r')) })
},
send: (type, content) => {
if (!ws || ws.readyState != 1) { term.writeln('Please Connect to Server first!'); return; }
ws.send(`${type}${SPLIT_LINE}${content}`);
},
connect: (event = { key: 'Enter' }) => {
if (event.key !== "Enter") {
return;
}
connectWebSocket()
},
init: () => {
if (main.server) {
main.connect()
}
},
load: (editor) => {
editor.setValue(window.localStorage.getItem(codeStorageKey + main.code) || '')
},
save: (editor) => {
window.localStorage.setItem(codeStorageKey + main.code, editor.getValue())
showMessenger('代码页 ' + main.code + ' 保存成功!')
},
switch: (editor) => {
let index = main.codes.indexOf(main.code) + 1
main.code = main.codes[index == main.codes.length ? 0 : index]
}
});
main.$watch('code', (now, old, name) => {
window.localStorage.setItem(codeStorageKey + old, editor.getValue())
showMessenger('代码页 ' + old + ' 保存成功!')
editor.setValue(window.localStorage.getItem(codeStorageKey + now) || '// empty code page ' + now)
})
main.init()

View File

@@ -1,10 +0,0 @@
$._messengerDefaults = {
extraClasses: 'messenger-fixed messenger-theme-future messenger-on-top messenger-on-right'
};
var showMessenger = function(message, type) {
return Messenger().post({
message: message,
type: type || 'info',
showClo6seButton: true
});
};

View File

@@ -1,54 +0,0 @@
Terminal.applyAddon(fit);
var term = new Terminal();
avalon.ready(() => {
term.open(document.getElementById('terminal'));
window.onresize = () => {
term.fit();
}
window.onresize()
})
term.on('data', (data) => {
if (data == '\r') {
term.writeln(data)
}
});
term.attachCustomKeyEventHandler(e => {
if (e.ctrlKey && e.key == 'c' && term.hasSelection()) {
showMessenger('内容已复制到粘贴板')
return false;
}
if (e.ctrlKey && e.key == 'v') {
return false;
}
return true;
})
var colorMap = []
colorMap['0'] = '38;5;0'
colorMap['1'] = '38;5;4'
colorMap['2'] = '38;5;2'
colorMap['3'] = '38;5;6'
colorMap['4'] = '38;5;1'
colorMap['5'] = '38;5;5'
colorMap['6'] = '38;5;3'
colorMap['7'] = '38;5;7'
colorMap['8'] = '38;5;8'
colorMap['9'] = '38;5;12'
colorMap['a'] = '38;5;10'
colorMap['b'] = '38;5;14'
colorMap['c'] = '38;5;9'
colorMap['d'] = '38;5;13'
colorMap['e'] = '38;5;11'
colorMap['f'] = '38;5;15'
colorMap['r'] = '0'
colorMap['l'] = '1'
colorMap['n'] = '4'
var regexMap = []
for (const c in colorMap) {
regexMap[colorMap[c]] = new RegExp(`§${c}`, "g")
}
function mcColor2ANSI(str) {
for (const regex in regexMap) {
str = str.replace(regexMap[regex], `\u001b[${regex}m`)
}
return str;
}

View File

@@ -1,30 +0,0 @@
var ws;
function connectWebSocket() {
if (ws && ws.readyState == 1) {
ws.close()
}
window.localStorage.setItem(serverKey, main.server)
ws = new WebSocket(`${location.protocol == 'http:' ? 'ws' : 'wss'}://${main.server}/ws`)
ws.onmessage = (event) => {
const [type, obj] = event.data.split(SPLIT_LINE)
switch (type) {
case "log":
main.log(obj)
break;
case "type":
main.type = obj;
break;
}
}
ws.onopen = () => {
main.send("execDetect", "type");
}
ws.onclose = (ev) => {
main.log(`Remote Server Close Connection... ${ev.code}`)
if (ev.code == 1006) {
setTimeout(() => {
main.connect()
}, 1000)
}
}
}

View File

@@ -1,11 +1,11 @@
/// <reference types="@ms/types/dist/typings/bukkit" />
/// <reference types="@ms/types/dist/typings/sponge" />
/// <reference types="@ms/types/dist/typings/bungee" />
/// <reference types="@ms/types/dist/typings/nukkit" />
/// <reference types="@ccms/types/dist/typings/bukkit" />
/// <reference types="@ccms/types/dist/typings/sponge" />
/// <reference types="@ccms/types/dist/typings/bungee" />
/// <reference types="@ccms/types/dist/typings/nukkit" />
import { server } from '@ms/api';
import { inject } from '@ms/container';
import { plugin, interfaces, cmd, listener, tab } from '@ms/plugin'
import { server } from '@ccms/api';
import { inject } from '@ccms/container';
import { plugin, interfaces, cmd, listener, tab } from '@ccms/plugin'
@plugin({ name: 'HelloWorld', version: '1.0.0', author: 'MiaoWoo', source: __filename })
export class HelloWorld extends interfaces.Plugin {

View File

@@ -1,11 +1,11 @@
/// <reference types="@ms/types/dist/typings/bukkit" />
/// <reference types="@ms/types/dist/typings/sponge" />
/// <reference types="@ms/types/dist/typings/bungee" />
/// <reference types="@ccms/types/dist/typings/bukkit" />
/// <reference types="@ccms/types/dist/typings/sponge" />
/// <reference types="@ccms/types/dist/typings/bungee" />
import { server, plugin as pluginApi, channel, constants } from '@ms/api'
import { inject, optional } from '@ms/container';
import { plugin, interfaces, cmd, listener, tab, config, enable } from '@ms/plugin'
import Tellraw from '@ms/common/dist/tellraw'
import { server, plugin as pluginApi, channel, constants } from '@ccms/api'
import { inject, optional } from '@ccms/container';
import { plugin, interfaces, cmd, listener, tab, config, enable } from '@ccms/plugin'
import Tellraw from '@ccms/common/dist/tellraw'
const ByteArrayInputStream = Java.type("java.io.ByteArrayInputStream");
const ByteArrayOutputStream = Java.type("java.io.ByteArrayOutputStream");

View File

@@ -1,11 +1,12 @@
/// <reference types="@ms/types/dist/typings/bukkit" />
/// <reference types="@ms/types/dist/typings/sponge" />
/// <reference types="@ms/types/dist/typings/bungee" />
/// <reference types="@ccms/types/dist/typings/bukkit" />
/// <reference types="@ccms/types/dist/typings/sponge" />
/// <reference types="@ccms/types/dist/typings/bungee" />
import { plugin as pluginApi, server, task } from '@ms/api'
import { plugin, interfaces, cmd } from '@ms/plugin'
import { inject, ContainerInstance, Container } from '@ms/container'
import io, { Server as SocketIOServer, Socket as SocketIOSocket } from '@ms/websocket'
import { plugin as pluginApi, server, task } from '@ccms/api'
import { plugin, interfaces, cmd } from '@ccms/plugin'
import { inject, ContainerInstance, Container } from '@ccms/container'
import io, { Server as SocketIOServer, Socket as SocketIOSocket } from '@ccms/websocket'
import * as fs from '@ccms/common/dist/fs'
const suffixMap = {
ts: 'typescript',
@@ -25,6 +26,8 @@ export class MiaoConsole extends interfaces.Plugin {
private task: task.TaskManager
@inject(pluginApi.PluginManager)
private pluginManager: pluginApi.PluginManager
@inject(pluginApi.PluginFolder)
private pluginFolder: string;
private pipeline: any;
private socketIOServer: SocketIOServer;
@@ -92,6 +95,24 @@ export class MiaoConsole extends interfaces.Plugin {
client.on('edit', (file: string, fn) => {
fn && fn(base.read(file), suffixMap[file.split('.', 2)[1]])
})
client.on('save', (name: string, content: string, fn) => {
this.logger.console(`§6客户端 §b${client.id} §6请求更新插件 §a${name} §6...`)
let file = fs.concat(root, this.pluginFolder, name + '.js')
if (!fs.exists(file)) { return fn('§6插件 §a' + name + ' §6尚未安装 §c请先创建空文件 或安装插件!') }
try {
base.save(file, content)
this.pluginManager.reload(name);
fn('§6插件 §a' + name + ' §6更新成功!')
} catch (error) {
this.logger.error(error)
fn('§6插件 §a' + name + ' §4更新异常 错误: ' + error)
}
})
client.on('error', (error) => {
this.logger.console(`§6客户端 §b${client.id} §c触发异常: ${error}`)
this.logger.error(error)
})
client.on('disconnect', () => {
this.logger.console(`§6客户端 §b${client.id} §c断开连接...`)
})
@@ -101,7 +122,7 @@ export class MiaoConsole extends interfaces.Plugin {
private runCode(code: string, namespace: any, client: any) {
let tfunc = new Function('namespace', 'client', `
var reflect = require('@ms/common/dist/reflect');
var reflect = require('@ccms/common/dist/reflect');
var tempconcent = '';
function print(text) {
tempconcent += text + "\\n"

View File

@@ -1,11 +1,11 @@
/// <reference types="@ms/types" />
/// <reference types="@ccms/types" />
import { task, server } from "@ms/api";
import { inject } from "@ms/container";
import { plugin, interfaces, cmd } from "@ms/plugin";
import { task, server } from "@ccms/api";
import { inject } from "@ccms/container";
import { plugin, interfaces, cmd } from "@ccms/plugin";
import http from '@ms/common/dist/http'
import * as fs from '@ms/common/dist/fs'
import http from '@ccms/common/dist/http'
import * as fs from '@ccms/common/dist/fs'
@plugin({ name: 'MiaoPluginManager', prefix: 'MPM', version: '1.0.0', author: 'MiaoWoo', source: __filename })
export class MiaoPluginManager extends interfaces.Plugin {

View File

@@ -1,35 +1,50 @@
import { plugin as pluginApi, task, server } from '@ms/api'
import { plugin as pluginApi, task, server } from '@ccms/api'
import { Translate } from '@ms/i18n'
import { inject } from '@ms/container';
import { interfaces, plugin, cmd, tab } from '@ms/plugin'
import { Translate } from '@ccms/i18n'
import { inject } from '@ccms/container';
import { interfaces, plugin, cmd, tab } from '@ccms/plugin'
import * as fs from '@ms/common/dist/fs'
import http from '@ms/common/dist/http'
import * as fs from '@ccms/common/dist/fs'
import http from '@ccms/common/dist/http'
let help = [
'§6========= §6[§aMiaoScriptPackageManager§6] 帮助 §aBy §b喵♂呜 §6=========',
'§6/mpm §ainstall §e<插件名称> §6- §3安装插件',
'§6/mpm §auninstall §e<插件名称> §6- §3卸载插件',
'§6/mpm §alist [install]§6- §3列出仓库插件[已安装插件]',
'§6/mpm §aupdate §e<插件名称> §6- §3更新插件(无插件名称则更新源)',
'§6/mpm §aupgrade §e<插件名称> §6- §3及时更新插件(update需要重启生效)',
'§6/mpm §areload §e<插件名称> §6- §3重载插件(无插件名称则重载自身)',
'§6/mpm §arun §e<JS代码> §6- §3运行JS代码',
'§6/mpm §acreate §e<插件名称> [作者] [版本] [主命令] §6- §3通过模板创建名称',
'§6/mpm §crestart §6- §4重启MiaoScript脚本引擎'
'§6========= §6[§aMiaoScriptPackageManager§6] 帮助 §aBy §bMiaoWoo §6=========',
'§6/mpm §ainstall §e<插件名称> §6- §3安装仓库插件',
'§6/mpm §aload §e<插件名称> §6- §3安装本地插件',
'§6/mpm §aunload §e<插件名称> §6- §3卸载已安装插件',
'§6/mpm §areload §e<插件名称> §6- §3重载已安装插件(无名称则重载自身)',
'§6/mpm §alist [i] §6- §3列出仓库插件[已安装的插件]',
'§6/mpm §aupdate §e[插件名称] §6- §3更新插件(无名称则更新源)',
'§6/mpm §aupgrade §e[插件名称] §6- §3升级插件/框架(§4无名称则升级框架§3)',
'§6/mpm §arun §e<JS代码> §6- §3运行JS代码',
'§6/mpm §adeploy §e<插件名称> §6- §3发布插件',
'§6/mpm §crestart §6- §4重启MiaoScript脚本引擎'
];
let langMap = {
'list.header.install': '§6当前 §bMiaoScript §6已安装下列插件:',
'main.command.not.exists': '§4未知的子命令: §c{command}',
'main.command.help.tip': '§6请执行 §b/{command} §ahelp §6查看帮助!',
'list.install.header': '§6当前 §bMiaoScript §6已安装下列插件:',
'list.install.body': '§6插件名称: §b{name} §6版本: §a{version} §6作者: §3{author}',
'list.header': '§6当前 §bMiaoScriptPackageCenter §6中存在下列插件:',
'list.body': '§6插件名称: §b{name} §6版本: §a{version} §6作者: §3{author}',
'list.body': '§6插件名称: §b{name} §6版本: §a{version} §6作者: §3{author} §6更新时间: §9{updated_at}',
'plugin.not.exists': '§6插件 §b{name} §c不存在!',
'plugin.unload.finish': '§6插件 §b{name} §a已卸载!',
'plugin.reload.finish': '§6插件 §b{name} §a重载完成!',
'plugin.name.empty': '§c请输入插件名称!',
'cloud.update.finish': '§6成功从 §aMiaoScriptPackageCenter §6获取到 §a{length} §6个插件!',
'cloud.not.exists': '§6当前 §aMiaoScriptPackageCenter §c不存在 §a{name} §c插件!'
'cloud.not.exists': '§6当前 §aMiaoScriptPackageCenter §c不存在 §a{name} §c插件!',
'download.start': '§6开始下载插件: §b{name}',
'download.url': '§6插件下载地址: §b{url}',
'download.finish': '§6插件 §b{name} §a下载完毕 开始加载 ...',
'install.finish': '§6插件 §b{name} §a安装成功!',
'update.finish': '§6插件 §b{name} §a更新成功!',
'deploy.token.not.exists': '§4请先配置发布Token!',
'deploy.success': '§6插件 §b{name} §a发布成功! §6服务器返回: §a{msg}',
'deploy.fail': '§6插件 §b{name} §c发布失败! §6服务器返回: §c{msg}',
'run.script': '§b运行脚本:§r {script}',
'run.result': '§a返回结果:§r {result}',
'run.noresult': '§4没有返回结果!',
}
let fallbackMap = langMap
@@ -44,6 +59,8 @@ export class MiaoScriptPackageManager extends interfaces.Plugin {
private serverType: string;
@inject(server.Server)
private server: server.Server
@inject(pluginApi.PluginFolder)
private pluginFolder: string;
private packageCache: any[] = [];
private packageNameCache: string[] = [];
@@ -69,19 +86,33 @@ export class MiaoScriptPackageManager extends interfaces.Plugin {
main(sender: any, command: string, args: string[]) {
let cmdKey = 'cmd' + args[0]
if (!this[cmdKey] || args[0] === 'help') {
this.logger.sender(sender, help);
if (!this[cmdKey]) {
this.i18n(sender, 'main.command.not.exists', { command: args[0] })
this.i18n(sender, 'main.command.help.tip', { command })
return;
}
args.shift()
this[cmdKey](sender, ...args);
}
cmdlist(sender, type: string = 'cloud') {
cmdhelp(sender: any) {
this.logger.sender(sender, help);
}
cmdload(sender: any, name: string) {
let pluginFile = fs.concat(__dirname + '', name);
if (!fs.exists(pluginFile)) {
this.i18n(sender, 'plugin.not.exists', { name: `${name}(${pluginFile})` })
return;
}
this.pluginManager.loadFromFile(fs.file(pluginFile));
}
cmdlist(sender: any, type: string = 'cloud') {
if (type == "install") {
this.i18n(sender, 'list.header.install')
this.i18n(sender, 'list.install.header')
this.pluginManager.getPlugins().forEach((plugin) => {
this.i18n(sender, 'list.body', plugin.description);
this.i18n(sender, 'list.install.body', plugin.description);
})
} else {
this.i18n(sender, 'list.header')
@@ -104,6 +135,20 @@ export class MiaoScriptPackageManager extends interfaces.Plugin {
}
}
cmdupgrade(sender: any, name: string) {
if (name == "system") {
let enginePath = fs.path(fs.file(fs.concat(root, 'node_modules', '@ccms')))
if (enginePath.startsWith(root)) {
base.delete(enginePath);
this.cmdrestart(sender);
}
}
if (this.checkPlugin(sender, name)) {
this.update(sender, name);
this.pluginManager.reload(name);
}
}
cmdunload(sender: any, name: string) {
if (this.checkPlugin(sender, name)) {
this.pluginManager.disable(name)
@@ -112,6 +157,7 @@ export class MiaoScriptPackageManager extends interfaces.Plugin {
}
cmdreload(sender: any, name: string) {
name = name || this.description.name
if (this.checkPlugin(sender, name)) {
this.pluginManager.reload(name);
this.i18n(sender, 'plugin.reload.finish', { name })
@@ -124,6 +170,12 @@ export class MiaoScriptPackageManager extends interfaces.Plugin {
return false
}
checkCloudPlugin(sender: any, name: string) {
if (name && this.packageNameCache.includes(name)) { return true }
this.i18n(sender, 'cloud.not.exists', { name })
return false
}
cmdrestart(sender: any) {
if (this.serverType === "sponge") {
setTimeout(() => this.server.dispatchConsoleCommand('sponge plugins reload'), 0)
@@ -132,6 +184,7 @@ export class MiaoScriptPackageManager extends interfaces.Plugin {
try {
this.logger.sender(sender, '§6Reloading §3MiaoScript Engine...');
ScriptEngineContextHolder.disableEngine();
Packages.java.lang.System.gc();
ScriptEngineContextHolder.enableEngine();
this.logger.sender(sender, '§3MiaoScript Engine §6Reload §aSuccessful...');
} catch (ex) {
@@ -140,25 +193,41 @@ export class MiaoScriptPackageManager extends interfaces.Plugin {
}
}
cmdrun(sender, ...args: any[]) {
cmdrun(sender: any, ...args: any[]) {
try {
var script = args.join(' ');
this.logger.sender(sender, '§b运行脚本:§r', script);
this.logger.sender(sender, '§a返回结果:§r', eval(script) || '§4没有返回结果!');
this.i18n(sender, 'run.script', { script })
this.i18n(sender, 'run.result', { result: eval(script) || this.translate.translate('run.noresult') })
} catch (ex) {
this.logger.sender(sender, this.logger.stack(ex));
}
}
cmddeploy(sender: any, name: any) {
if (!process.env.AccessToken) { return this.i18n(sender, 'deploy.token.not.exists') }
this.taskManager.create(() => {
if (this.checkPlugin(sender, name)) {
let plugin: interfaces.Plugin = this.pluginManager.getPlugins().get(name);
let result = http.post("http://ms.yumc.pw/api/plugin/deploy?access_token=" + process.env.AccessToken, {
name,
author: plugin.description.author,
version: plugin.description.version,
source: base.read(plugin.description.source.toString())
})
this.i18n(sender, result.code == 200 ? 'deploy.success' : 'deploy.fail', { name, msg: result.msg })
}
}).async().submit()
}
update(sender: any, name: string) {
if (!this.packageNameCache.includes(name)) {
this.i18n(sender, 'cloud.not.exists', { name })
if (this.checkCloudPlugin(sender, name)) {
this.download(sender, name, true);
}
}
@tab()
tabmpm(sender, command, args) {
if (args.length === 1) return ['list', 'install', 'update', 'upgrade', 'reload', 'restart', 'run', 'help', 'create'];
tabmpm(sender: any, command: any, args: string | any[]) {
if (args.length === 1) { return ['list', 'install', 'update', 'upgrade', 'reload', 'restart', 'run', 'help', 'create', 'deploy'] }
if (args.length > 1) {
switch (args[0]) {
case "list":
@@ -170,6 +239,7 @@ export class MiaoScriptPackageManager extends interfaces.Plugin {
case "load":
case "unload":
case "reload":
case "deploy":
return [...this.pluginManager.getPlugins().keys()];
}
}
@@ -177,16 +247,22 @@ export class MiaoScriptPackageManager extends interfaces.Plugin {
updateRepo(sender: any) {
this.taskManager.create(() => {
let result = http.get('http://ms.yumc.pw/api/plugin');
for (const pl of result.data) {
this.packageCache[pl.name] = pl;
}
let result = http.get('http://ms.yumc.pw/api/plugin/list');
for (const pl of result.data) { this.packageCache[pl.name] = pl; }
this.packageNameCache = Object.keys(this.packageCache);
this.i18n(sender, 'cloud.update.finish', { length: this.packageNameCache.length })
}).async().submit();
}
download(sender, name) {
download(sender: any, name: string, update: boolean = false) {
this.taskManager.create(() => {
this.i18n(sender, 'download.start', { name })
this.i18n(sender, 'download.url', { url: this.packageCache[name].url })
let pluginFile = update ? fs.concat(this.pluginFolder, 'update', name + '.js') : fs.concat(this.pluginFolder, name + '.js')
http.download(this.packageCache[name].url, pluginFile)
this.i18n(sender, 'download.finish', { name })
this.pluginManager.loadFromFile(pluginFile)
this.i18n(sender, update ? 'update.finish' : 'install.finish', { name })
}).async().submit()
}
}

View File

@@ -1,9 +1,9 @@
import { plugin as pluginApi } from '@ms/api'
import { plugin, interfaces, cmd, listener, tab } from '@ms/plugin'
import { inject } from '@ms/container';
import { plugin as pluginApi } from '@ccms/api'
import { plugin, interfaces, cmd, listener, tab } from '@ccms/plugin'
import { inject } from '@ccms/container';
import * as reflect from '@ms/common/dist/reflect';
import http from '@ms/common/dist/http';
import * as reflect from '@ccms/common/dist/reflect';
import http from '@ccms/common/dist/http';
@plugin({ name: 'Test', version: '1.0.0', author: 'MiaoWoo', source: __filename })
export class Test extends interfaces.Plugin {

View File

@@ -1,6 +1,6 @@
{
"name": "@ms/sponge",
"version": "0.5.0",
"name": "@ccms/sponge",
"version": "0.6.5",
"description": "MiaoScript api package",
"keywords": [
"miaoscript",
@@ -12,9 +12,6 @@
"homepage": "https://github.com/circlecloud/ms.git",
"license": "ISC",
"main": "dist/index.js",
"publishConfig": {
"registry": "https://repo.yumc.pw/repository/npm-hosted/"
},
"scripts": {
"clean": "rimraf dist",
"watch": "tsc --watch",
@@ -27,8 +24,8 @@
"typescript": "^3.8.3"
},
"dependencies": {
"@ms/api": "^0.5.0",
"@ms/common": "^0.5.0",
"@ms/container": "^0.5.0"
"@ccms/api": "^0.6.5",
"@ccms/common": "^0.6.4",
"@ccms/container": "^0.6.0"
}
}

View File

@@ -1,5 +1,5 @@
import { channel, plugin } from '@ms/api'
import { inject, provideSingleton } from '@ms/container'
import { channel, plugin } from '@ccms/api'
import { inject, provideSingleton } from '@ccms/container'
const Sponge = org.spongepowered.api.Sponge
const RawDataListener = Java.type("org.spongepowered.api.network.RawDataListener")

View File

@@ -1,5 +1,5 @@
import { command, plugin } from "@ms/api";
import { inject, provideSingleton } from "@ms/container";
import { command, plugin } from "@ccms/api";
import { inject, provideSingleton } from "@ccms/container";
let Sponge = Java.type('org.spongepowered.api.Sponge');
let Text = Java.type('org.spongepowered.api.text.Text');

View File

@@ -1,5 +1,5 @@
import '@ms/nashorn'
import { MiaoScriptConsole } from '@ms/api'
import '@ccms/nashorn'
import { MiaoScriptConsole } from '@ccms/api'
let Sponge = Java.type('org.spongepowered.api.Sponge');
var Text = Java.type('org.spongepowered.api.text.Text');

View File

@@ -1,5 +1,5 @@
import { event, plugin } from '@ms/api'
import { inject, provideSingleton } from '@ms/container';
import { event, plugin } from '@ccms/api'
import { inject, provideSingleton } from '@ccms/container';
let Modifier = Java.type("java.lang.reflect.Modifier");
let Order = Java.type("org.spongepowered.api.event.Order");

View File

@@ -1,7 +1,7 @@
/// <reference types="@ms/types/dist/typings/sponge" />
/// <reference types="@ccms/types/dist/typings/sponge" />
import { server } from '@ms/api'
import { Container } from '@ms/container'
import { server } from '@ccms/api'
import { Container } from '@ccms/container'
import { SpongeConsole } from './console';
import './event';

View File

@@ -1,7 +1,7 @@
import { server, constants } from '@ms/api'
import { provideSingleton } from '@ms/container';
import { server, constants } from '@ccms/api'
import { provideSingleton } from '@ccms/container';
import * as reflect from '@ms/common/dist/reflect'
import * as reflect from '@ccms/common/dist/reflect'
const Sponge = org.spongepowered.api.Sponge;
const TextSerializers = org.spongepowered.api.text.serializer.TextSerializers;

View File

@@ -1,5 +1,5 @@
import { task, plugin } from '@ms/api'
import { inject, provideSingleton, postConstruct } from '@ms/container';
import { task, plugin } from '@ccms/api'
import { inject, provideSingleton, postConstruct } from '@ccms/container';
const Sponge = Java.type("org.spongepowered.api.Sponge");
const Task = Java.type("org.spongepowered.api.scheduler.Task");

View File

@@ -1,6 +1,6 @@
{
"name": "@ms/types",
"version": "0.5.0",
"name": "@ccms/types",
"version": "0.6.0",
"description": "MiaoScript types package",
"keywords": [
"miaoscript",
@@ -12,8 +12,5 @@
"homepage": "https://github.com/circlecloud/ms.git",
"license": "ISC",
"main": "dist/index.js",
"types": "dist/index.d.ts",
"publishConfig": {
"registry": "https://repo.yumc.pw/repository/npm-hosted/"
}
"types": "dist/index.d.ts"
}

View File

@@ -1,6 +1,6 @@
{
"name": "@ms/websocket",
"version": "0.5.0",
"name": "@ccms/websocket",
"version": "0.6.4",
"description": "MiaoScript websocket package",
"keywords": [
"miaoscript",
@@ -12,9 +12,6 @@
"homepage": "https://github.com/circlecloud/ms.git",
"license": "ISC",
"main": "dist/index.js",
"publishConfig": {
"registry": "https://repo.yumc.pw/repository/npm-hosted/"
},
"scripts": {
"clean": "rimraf dist",
"watch": "tsc --watch",
@@ -27,6 +24,6 @@
"typescript": "^3.8.3"
},
"dependencies": {
"@ms/nashorn": "^0.5.0"
"@ccms/nashorn": "^0.6.4"
}
}

View File

@@ -1,4 +1,4 @@
/// <reference types="@ms/nashorn" />
/// <reference types="@ccms/nashorn" />
import { Server, ServerOptions } from './socket-io'
@@ -41,6 +41,6 @@ type SocketStatic = SocketIOStatic & { Instance?: symbol }
let io: SocketStatic = function (pipeline: any, options: ServerOptions) {
return new Server(pipeline, options)
}
io.Instance = Symbol("@ms/websocket")
io.Instance = Symbol("@ccms/websocket")
export default io
export * from './socket-io'

View File

@@ -1,5 +1,6 @@
{
"compilerOptions": {
"incremental": true,
"baseUrl": "src",
"outDir": "dist",
"target": "es5",