Compare commits
14 Commits
v0.28.0-be
...
v0.20.0-al
| Author | SHA1 | Date | |
|---|---|---|---|
| bddf28b4ad | |||
| daa28dcfd6 | |||
| 14d30a7b3e | |||
| 16502ecc01 | |||
| 9d891b5596 | |||
| 87b7c66282 | |||
| c8df79a072 | |||
| 2aef84604b | |||
| dbecad996a | |||
| c4aded50f1 | |||
| 93b361a2ac | |||
| 923bf102de | |||
| 4a90455131 | |||
| 2ff57d1c0b |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -1,4 +1,3 @@
|
|||||||
.yarn*
|
|
||||||
.vscode
|
.vscode
|
||||||
.theia
|
.theia
|
||||||
node_modules
|
node_modules
|
||||||
|
|||||||
47
README.MD
47
README.MD
@@ -8,28 +8,27 @@
|
|||||||
|
|
||||||
```txt
|
```txt
|
||||||
└─packages
|
└─packages
|
||||||
├─api 全平台兼容的接口
|
├─api 全平台兼容的接口
|
||||||
├─core 核心代码 用于引导加载
|
├─core 核心代码 用于引导加载
|
||||||
├─common 公共类库代码 例如 http reflect 模块
|
├─common 公共类库代码 例如 http reflect 模块
|
||||||
├─compile 编译器相关功能
|
├─client NodeJS的Minecraft客户端 用于调试插件
|
||||||
├─client NodeJS 的 Minecraft 客户端 已迁移至 ms-client
|
├─container IOC容器 用于注入具体实现
|
||||||
├─container IOC容器 用于注入具体实现
|
├─ployfill Nashorn 的一些自定义增强
|
||||||
├─database 数据库相关功能
|
├─nashorn Nashorn 的类型定义
|
||||||
├─protocol 协议处理相关功能
|
├─bungee BungeeCordAPI内部实现
|
||||||
├─service 服务相关功能
|
├─bukkit BukkitAPI内部实现
|
||||||
├─i18n 多语言环境相关支持
|
├─sponge SpongeAPI内部实现
|
||||||
├─polyfill Nashorn 的一些自定义增强
|
├─nukkit NukkitAPI内部实现
|
||||||
├─nashorn Nashorn 的类型定义
|
├─plugin 插件管理器
|
||||||
├─nodejs NodeJS 的部分 Java 实现
|
├─websocket Netty的WebSocket注入
|
||||||
├─bungee BungeeCordAPI 内部实现
|
├─type Java的类型定义
|
||||||
├─bukkit BukkitAPI 内部实现
|
| ├─bungee BungeeCord类型定义
|
||||||
├─sponge SpongeAPI 内部实现
|
| ├─bukkit Bukkit类型定义
|
||||||
├─nukkit NukkitAPI 内部实现
|
| ├─sponge Sponge类型定义
|
||||||
├─molang MoLang 解析库
|
| └─nukkit Nukkit类型定义
|
||||||
├─qrcode 二维码相关类库
|
└─plugins 这里当然是插件啦
|
||||||
├─plugin 插件管理器
|
├─bungee 只兼容BungeeCord的插件
|
||||||
├─websocket WebSocket 相关实现
|
├─bukkit 只兼容Bukkit的插件
|
||||||
| ├─client 基于 Netty 的 WebSocket 客户端
|
├─sponge 只兼容Sponge的插件
|
||||||
| └─server 基于 Netty 的 WebSocket 服务端
|
└─nukkit 只兼容Nukkit的插件
|
||||||
└─type 类型定义 已迁移到 @javatypes
|
|
||||||
```
|
```
|
||||||
|
|||||||
26
lerna.json
26
lerna.json
@@ -1,15 +1,17 @@
|
|||||||
{
|
{
|
||||||
"version": "0.28.0-beta.4",
|
"version": "0.20.0-alpha.0",
|
||||||
"npmClient": "pnpm",
|
"useWorkspaces": true,
|
||||||
"packages": [
|
"npmClient": "yarn",
|
||||||
"packages/*"
|
"packages": [
|
||||||
],
|
"packages/*"
|
||||||
"command": {
|
],
|
||||||
"run": {
|
"command": {
|
||||||
"stream": true
|
"run": {
|
||||||
|
"stream": true
|
||||||
|
},
|
||||||
|
"publish": {
|
||||||
|
"access": "public",
|
||||||
|
"registry": "https://repo.yumc.pw/repository/npm-hosted/"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
|
||||||
"publishConfig": {
|
|
||||||
"access": "public"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
19
package.json
19
package.json
@@ -10,26 +10,15 @@
|
|||||||
"clean": "lerna run clean",
|
"clean": "lerna run clean",
|
||||||
"watch": "lerna run watch --parallel",
|
"watch": "lerna run watch --parallel",
|
||||||
"build": "lerna run build",
|
"build": "lerna run build",
|
||||||
"ug": "pnpm up -r -i",
|
"ug": "yarn upgrade-interactive --latest",
|
||||||
"np": "./script/push.sh",
|
"np": "./script/push.sh",
|
||||||
"lsp": "npm login -scope=@ccms",
|
"lsp": "npm login --registry=https://registry.npmjs.org --scope=@ccms",
|
||||||
"lp": "lerna publish --force-publish",
|
"lp": "lerna publish --registry https://registry.npmjs.org"
|
||||||
"lpb": "lerna publish --preid beta --dist-tag beta --force-publish",
|
|
||||||
"lpc": "lerna publish --canary --preid beta --pre-dist-tag beta --force-publish",
|
|
||||||
"lpf": "lerna publish from-package --yes",
|
|
||||||
"sync": "./script/sync.sh"
|
|
||||||
},
|
},
|
||||||
"workspaces": [
|
"workspaces": [
|
||||||
"packages/*"
|
"packages/*"
|
||||||
],
|
],
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"lerna": "^7.2.0",
|
"lerna": "^4.0.0"
|
||||||
"reflect-metadata": "^0.1.13",
|
|
||||||
"rimraf": "^5.0.5",
|
|
||||||
"typescript": "^5.2.2",
|
|
||||||
"tslib": "^2.6.2",
|
|
||||||
"@types/node": "^20.8.8",
|
|
||||||
"@ccms/nashorn": "^0.28.0-beta.3",
|
|
||||||
"@javatypes/jdk": "^0.0.3"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
35
packages/amqp/package.json
Normal file
35
packages/amqp/package.json
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
{
|
||||||
|
"name": "@ccms/amqp",
|
||||||
|
"version": "0.20.0-alpha.0",
|
||||||
|
"description": "MiaoScript amqp package",
|
||||||
|
"keywords": [
|
||||||
|
"miaoscript",
|
||||||
|
"minecraft",
|
||||||
|
"bukkit",
|
||||||
|
"sponge"
|
||||||
|
],
|
||||||
|
"author": "MiaoWoo <admin@yumc.pw>",
|
||||||
|
"homepage": "https://github.com/circlecloud/ms.git",
|
||||||
|
"license": "ISC",
|
||||||
|
"main": "dist/index.js",
|
||||||
|
"scripts": {
|
||||||
|
"clean": "rimraf dist",
|
||||||
|
"watch": "tsc --watch",
|
||||||
|
"build": "yarn clean && tsc",
|
||||||
|
"test": "echo \"Error: run tests from root\" && exit 1"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@ccms/api": "^0.20.0-alpha.0",
|
||||||
|
"@ccms/common": "^0.19.0",
|
||||||
|
"@ccms/container": "^0.19.0"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@ccms/nashorn": "^0.19.0",
|
||||||
|
"@javatypes/amqp-client": "^0.0.3",
|
||||||
|
"@javatypes/spring-amqp": "^0.0.3",
|
||||||
|
"@javatypes/spring-rabbit": "^0.0.3",
|
||||||
|
"reflect-metadata": "^0.1.13",
|
||||||
|
"rimraf": "^3.0.2",
|
||||||
|
"typescript": "^4.5.5"
|
||||||
|
}
|
||||||
|
}
|
||||||
17
packages/amqp/src/adapter/admin.ts
Normal file
17
packages/amqp/src/adapter/admin.ts
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
import { ConnectionFactoryAdapter } from "./connection"
|
||||||
|
import { RabbitTemplateAdapter } from "./template"
|
||||||
|
import { JSClass } from "@ccms/container"
|
||||||
|
|
||||||
|
export const RabbitAdmin = Java.type('org.springframework.amqp.rabbit.core.RabbitAdmin')
|
||||||
|
|
||||||
|
export class RabbitAdminAdapter {
|
||||||
|
@JSClass('org.springframework.amqp.rabbit.core.RabbitAdmin')
|
||||||
|
private RabbitAdmin: org.springframework.amqp.rabbit.core.RabbitAdmin
|
||||||
|
private _Handler: org.springframework.amqp.rabbit.core.RabbitAdmin
|
||||||
|
constructor(config: RabbitTemplateAdapter | org.springframework.amqp.rabbit.core.RabbitTemplate | ConnectionFactoryAdapter | org.springframework.amqp.rabbit.connection.ConnectionFactory) {
|
||||||
|
this._Handler = new RabbitAdmin((config instanceof RabbitTemplateAdapter || config instanceof ConnectionFactoryAdapter) ? config.getHandler() : config)
|
||||||
|
}
|
||||||
|
getHandler(): org.springframework.amqp.rabbit.core.RabbitAdmin {
|
||||||
|
return this._Handler
|
||||||
|
}
|
||||||
|
}
|
||||||
30
packages/amqp/src/adapter/callback.ts
Normal file
30
packages/amqp/src/adapter/callback.ts
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
export const ConfirmCallback = Java.type('org.springframework.amqp.rabbit.core.RabbitTemplate.ConfirmCallback')
|
||||||
|
export const ReturnCallback = Java.type('org.springframework.amqp.rabbit.core.RabbitTemplate.ReturnCallback')
|
||||||
|
|
||||||
|
export abstract class ConfirmCallbackAdapter {
|
||||||
|
private _Handler: org.springframework.amqp.rabbit.core.RabbitTemplate.ConfirmCallback
|
||||||
|
constructor() {
|
||||||
|
let ConfirmCallbackImpl = Java.extend(ReturnCallback, {
|
||||||
|
confirm: (correlationData: org.springframework.amqp.rabbit.connection.CorrelationData, ack: boolean, cause: string) => this.confirm(correlationData, ack, cause)
|
||||||
|
})
|
||||||
|
this._Handler = new ConfirmCallbackImpl()
|
||||||
|
}
|
||||||
|
abstract confirm(correlationData: org.springframework.amqp.rabbit.connection.CorrelationData, ack: boolean, cause: string)
|
||||||
|
getHandler() {
|
||||||
|
return this._Handler
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export abstract class ReturnCallbackAdapter {
|
||||||
|
private _Handler: org.springframework.amqp.rabbit.core.RabbitTemplate.ReturnCallback
|
||||||
|
constructor() {
|
||||||
|
let ReturnCallbackImpl = Java.extend(ReturnCallback, {
|
||||||
|
returnedMessage: (message: org.springframework.amqp.core.Message, replyCode: number, replyText: string, exchange: string, routingKey: string) => this.returnedMessage(message, replyCode, replyText, exchange, routingKey)
|
||||||
|
})
|
||||||
|
this._Handler = new ReturnCallbackImpl()
|
||||||
|
}
|
||||||
|
abstract returnedMessage(message: org.springframework.amqp.core.Message, replyCode: number, replyText: string, exchange: string, routingKey: string)
|
||||||
|
getHandler() {
|
||||||
|
return this._Handler
|
||||||
|
}
|
||||||
|
}
|
||||||
31
packages/amqp/src/adapter/connection.ts
Normal file
31
packages/amqp/src/adapter/connection.ts
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
import threadPool from '@ccms/common/dist/thread-pool'
|
||||||
|
|
||||||
|
export const ConnectionFactory = Java.type('org.springframework.amqp.rabbit.connection.ConnectionFactory')
|
||||||
|
const CachingConnectionFactory = Java.type('org.springframework.amqp.rabbit.connection.CachingConnectionFactory')
|
||||||
|
interface ConnectionConfig {
|
||||||
|
url: string,
|
||||||
|
username?: string,
|
||||||
|
password?: string,
|
||||||
|
publisherConfirms?: boolean
|
||||||
|
cacheSize?: number
|
||||||
|
}
|
||||||
|
|
||||||
|
export class ConnectionFactoryAdapter {
|
||||||
|
private _Handler: org.springframework.amqp.rabbit.connection.CachingConnectionFactory
|
||||||
|
|
||||||
|
constructor(config: ConnectionConfig) {
|
||||||
|
if (!config.url) { throw new Error('Connection UrI Can\'t be undefiend!') }
|
||||||
|
config = { publisherConfirms: true, cacheSize: 50, ...config }
|
||||||
|
this._Handler = new CachingConnectionFactory(new java.net.URI(config.url))
|
||||||
|
config.username && this._Handler.setUsername(config.username)
|
||||||
|
config.password && this._Handler.setPassword(config.password)
|
||||||
|
this._Handler.setPublisherConfirms(config.publisherConfirms)
|
||||||
|
this._Handler.setExecutor(threadPool.create({
|
||||||
|
groupName: '@ccms/amqp-rabbit'
|
||||||
|
}))
|
||||||
|
this._Handler.setChannelCacheSize(config.cacheSize)
|
||||||
|
}
|
||||||
|
getHandler() {
|
||||||
|
return this._Handler
|
||||||
|
}
|
||||||
|
}
|
||||||
30
packages/amqp/src/adapter/container.ts
Normal file
30
packages/amqp/src/adapter/container.ts
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
import { ConnectionFactoryAdapter, ConnectionFactory } from "./connection"
|
||||||
|
import { ChannelAwareMessageListenerAdapter, ChannelAwareMessageListener } from "./listener"
|
||||||
|
|
||||||
|
export const SimpleMessageListenerContainer = org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer
|
||||||
|
export const AcknowledgeMode = org.springframework.amqp.core.AcknowledgeMode
|
||||||
|
interface ContainerConfig {
|
||||||
|
connectionFactory: ConnectionFactoryAdapter | typeof ConnectionFactory
|
||||||
|
queueNames: string[]
|
||||||
|
messageListener: ChannelAwareMessageListenerAdapter | typeof ChannelAwareMessageListener
|
||||||
|
maxConcurrentConsumers?: number
|
||||||
|
concurrentConsumers?: number
|
||||||
|
acknowledgeMode?: org.springframework.amqp.core.AcknowledgeMode
|
||||||
|
}
|
||||||
|
|
||||||
|
export class MessageListenerContainerAdapter {
|
||||||
|
private _Handler: org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer
|
||||||
|
constructor(config: ContainerConfig) {
|
||||||
|
config = { concurrentConsumers: 5, maxConcurrentConsumers: 10, acknowledgeMode: AcknowledgeMode.AUTO, ...config }
|
||||||
|
this._Handler = new SimpleMessageListenerContainer(config.connectionFactory instanceof ConnectionFactoryAdapter ? config.connectionFactory.getHandler() : config.connectionFactory)
|
||||||
|
//@ts-ignore
|
||||||
|
this._Handler.setQueueNames(config.queueNames)
|
||||||
|
this._Handler.setMaxConcurrentConsumers(config.maxConcurrentConsumers)
|
||||||
|
this._Handler.setConcurrentConsumers(config.concurrentConsumers)
|
||||||
|
this._Handler.setAcknowledgeMode(config.acknowledgeMode)
|
||||||
|
this._Handler.setMessageListener(config.messageListener instanceof ChannelAwareMessageListenerAdapter ? config.messageListener.getHandler() : config.messageListener)
|
||||||
|
}
|
||||||
|
getHandler() {
|
||||||
|
return this._Handler
|
||||||
|
}
|
||||||
|
}
|
||||||
37
packages/amqp/src/adapter/converter.ts
Normal file
37
packages/amqp/src/adapter/converter.ts
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
const JavaString = Java.type('java.lang.String')
|
||||||
|
const MessageProperties = org.springframework.amqp.core.MessageProperties
|
||||||
|
const Message = org.springframework.amqp.core.Message
|
||||||
|
|
||||||
|
export const MessageConverter = Java.type('org.springframework.amqp.support.converter.MessageConverter')
|
||||||
|
|
||||||
|
export class MessageConverterAdapter {
|
||||||
|
private _Handler: org.springframework.amqp.support.converter.MessageConverter
|
||||||
|
constructor() {
|
||||||
|
var MessageConverterImpl = Java.extend(MessageConverter, {
|
||||||
|
toMessage: (object: any, messageProperties: org.springframework.amqp.core.MessageProperties) => this.toMessage(object, messageProperties),
|
||||||
|
fromMessage: (message: org.springframework.amqp.core.Message) => this.fromMessage(message)
|
||||||
|
})
|
||||||
|
this._Handler = new MessageConverterImpl()
|
||||||
|
}
|
||||||
|
toMessage(object: any, messageProperties: org.springframework.amqp.core.MessageProperties) {
|
||||||
|
if (typeof object == "string") {
|
||||||
|
messageProperties.setContentType(MessageProperties.CONTENT_TYPE_TEXT_PLAIN)
|
||||||
|
return new Message(new JavaString(object).getBytes(), messageProperties)
|
||||||
|
} else {
|
||||||
|
messageProperties.setContentType(MessageProperties.CONTENT_TYPE_JSON)
|
||||||
|
return new Message(new JavaString(JSON.stringify(object)).getBytes(), messageProperties)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fromMessage(message: org.springframework.amqp.core.Message) {
|
||||||
|
if (message.getMessageProperties().getContentType() == MessageProperties.CONTENT_TYPE_TEXT_PLAIN) {
|
||||||
|
return new JavaString(message.getBody(), message.getMessageProperties().getContentEncoding())
|
||||||
|
}
|
||||||
|
if (message.getMessageProperties().getContentType() == MessageProperties.CONTENT_TYPE_JSON) {
|
||||||
|
return JSON.parse(new JavaString(message.getBody(), message.getMessageProperties().getContentEncoding()))
|
||||||
|
}
|
||||||
|
return message
|
||||||
|
}
|
||||||
|
getHandler() {
|
||||||
|
return this._Handler
|
||||||
|
}
|
||||||
|
}
|
||||||
7
packages/amqp/src/adapter/index.ts
Normal file
7
packages/amqp/src/adapter/index.ts
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
export * from './admin'
|
||||||
|
export * from './callback'
|
||||||
|
export * from './connection'
|
||||||
|
export * from './container'
|
||||||
|
export * from './converter'
|
||||||
|
export * from './listener'
|
||||||
|
export * from './template'
|
||||||
49
packages/amqp/src/adapter/listener.ts
Normal file
49
packages/amqp/src/adapter/listener.ts
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
const JavaString = Java.type('java.lang.String')
|
||||||
|
export const MessageProperties = org.springframework.amqp.core.MessageProperties
|
||||||
|
export const ChannelAwareMessageListener = Java.type('org.springframework.amqp.rabbit.listener.api.ChannelAwareMessageListener')
|
||||||
|
export const AmqpRejectAndDontRequeueException = org.springframework.amqp.AmqpRejectAndDontRequeueException
|
||||||
|
export const Channel: com.rabbitmq.client.Channel = Java.type('com.rabbitmq.client.Channel')
|
||||||
|
export const Message = org.springframework.amqp.core.Message
|
||||||
|
export type MessageHandler<T> = (content: T, message: org.springframework.amqp.core.Message, channel: com.rabbitmq.client.Channel) => any
|
||||||
|
export abstract class ChannelAwareMessageListenerAdapter<T = any> {
|
||||||
|
private _Handler: org.springframework.amqp.rabbit.listener.api.ChannelAwareMessageListener
|
||||||
|
constructor(manual: boolean = false) {
|
||||||
|
let ChannelAwareMessageListenerImpl = Java.extend(ChannelAwareMessageListener, {
|
||||||
|
onMessage: (message: org.springframework.amqp.core.Message, channel: com.rabbitmq.client.Channel) => {
|
||||||
|
let content = new JavaString(message.getBody(), message.getMessageProperties().getContentEncoding() || "UTF-8")
|
||||||
|
try {
|
||||||
|
if (message.getMessageProperties().getContentType() == MessageProperties.CONTENT_TYPE_JSON) {
|
||||||
|
content = JSON.parse(content)
|
||||||
|
}
|
||||||
|
} catch (error: any) {
|
||||||
|
if (manual) {
|
||||||
|
channel.basicReject(message.getMessageProperties().getDeliveryTag(), true)
|
||||||
|
} else {
|
||||||
|
throw new AmqpRejectAndDontRequeueException(`${error}`, error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
manual ? this.manualOnMessage(content, message, channel) : this.onMessage(content, message, channel)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
this._Handler = new ChannelAwareMessageListenerImpl()
|
||||||
|
}
|
||||||
|
abstract onMessage(content: T, message: org.springframework.amqp.core.Message, channel: com.rabbitmq.client.Channel): any
|
||||||
|
onError(error: Error, message: org.springframework.amqp.core.Message, channel: com.rabbitmq.client.Channel): any { }
|
||||||
|
getHandler() {
|
||||||
|
return this._Handler
|
||||||
|
}
|
||||||
|
private manualOnMessage(content: T, message: org.springframework.amqp.core.Message, channel: com.rabbitmq.client.Channel) {
|
||||||
|
let deliveryTag = message.getMessageProperties().getDeliveryTag()
|
||||||
|
try {
|
||||||
|
if (this.onMessage(content, message, channel)) {
|
||||||
|
channel.basicAck(deliveryTag, false)
|
||||||
|
} else if (message.getMessageProperties().getRedelivered()) {
|
||||||
|
channel.basicReject(deliveryTag, true)
|
||||||
|
} else {
|
||||||
|
channel.basicNack(deliveryTag, false, true)
|
||||||
|
}
|
||||||
|
} catch (error: any) {
|
||||||
|
channel.basicReject(deliveryTag, this.onError(error, message, channel))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
27
packages/amqp/src/adapter/template.ts
Normal file
27
packages/amqp/src/adapter/template.ts
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
import { MessageConverterAdapter } from "./converter"
|
||||||
|
import { ConnectionFactoryAdapter } from "./connection"
|
||||||
|
import { ConfirmCallbackAdapter, ReturnCallbackAdapter } from "./callback"
|
||||||
|
|
||||||
|
export const RabbitTemplate = Java.type('org.springframework.amqp.rabbit.core.RabbitTemplate')
|
||||||
|
|
||||||
|
interface TemplateConfig {
|
||||||
|
connectionFactory: ConnectionFactoryAdapter | org.springframework.amqp.rabbit.connection.ConnectionFactory
|
||||||
|
confirmCallback?: ConfirmCallbackAdapter
|
||||||
|
returnCallback?: ReturnCallbackAdapter
|
||||||
|
messageConverter?: MessageConverterAdapter
|
||||||
|
}
|
||||||
|
export class RabbitTemplateAdapter {
|
||||||
|
private _Handler: org.springframework.amqp.rabbit.core.RabbitTemplate
|
||||||
|
constructor(config: TemplateConfig) {
|
||||||
|
config = { messageConverter: new MessageConverterAdapter(), ...config }
|
||||||
|
console.debug(JSON.stringify(config))
|
||||||
|
this._Handler = new RabbitTemplate(config.connectionFactory instanceof ConnectionFactoryAdapter ? config.connectionFactory.getHandler() : config.connectionFactory)
|
||||||
|
config.returnCallback && this._Handler.setReturnCallback(config.returnCallback.getHandler())
|
||||||
|
config.confirmCallback && this._Handler.setConfirmCallback(config.confirmCallback.getHandler())
|
||||||
|
config.messageConverter && this._Handler.setMessageConverter(config.messageConverter.getHandler())
|
||||||
|
}
|
||||||
|
|
||||||
|
getHandler() {
|
||||||
|
return this._Handler
|
||||||
|
}
|
||||||
|
}
|
||||||
89
packages/amqp/src/admin.ts
Normal file
89
packages/amqp/src/admin.ts
Normal file
@@ -0,0 +1,89 @@
|
|||||||
|
import { JSClass } from "@ccms/container"
|
||||||
|
import { RabbitAdminAdapter, MessageListenerContainerAdapter, AcknowledgeMode, MessageHandler, ChannelAwareMessageListenerAdapter } from "./adapter"
|
||||||
|
|
||||||
|
export class AmqpAdmin {
|
||||||
|
@JSClass('org.springframework.amqp.core.TopicExchange')
|
||||||
|
private TopicExchange: typeof org.springframework.amqp.core.TopicExchange
|
||||||
|
@JSClass('org.springframework.amqp.core.Queue')
|
||||||
|
private Queue: typeof org.springframework.amqp.core.Queue
|
||||||
|
@JSClass('org.springframework.amqp.core.Binding')
|
||||||
|
private Binding: typeof org.springframework.amqp.core.Binding
|
||||||
|
@JSClass('org.springframework.amqp.rabbit.core.RabbitAdmin')
|
||||||
|
private RabbitAdmin: typeof org.springframework.amqp.rabbit.core.RabbitAdmin
|
||||||
|
@JSClass('org.springframework.amqp.core.Binding.DestinationType')
|
||||||
|
private DestinationType: org.springframework.amqp.core.Binding.DestinationType
|
||||||
|
|
||||||
|
private amqpAdmin: org.springframework.amqp.rabbit.core.RabbitAdmin
|
||||||
|
|
||||||
|
constructor(amqpAdmin: org.springframework.amqp.rabbit.core.RabbitAdmin | any) {
|
||||||
|
if (amqpAdmin instanceof this.RabbitAdmin) {
|
||||||
|
this.amqpAdmin = amqpAdmin
|
||||||
|
} else if (amqpAdmin instanceof RabbitAdminAdapter) {
|
||||||
|
this.amqpAdmin = amqpAdmin.getHandler()
|
||||||
|
} else {
|
||||||
|
this.amqpAdmin = new RabbitAdminAdapter(amqpAdmin).getHandler()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
getHandler() {
|
||||||
|
return this.amqpAdmin
|
||||||
|
}
|
||||||
|
|
||||||
|
getQueueProperties(name: string) {
|
||||||
|
return this.amqpAdmin.getQueueProperties(name)
|
||||||
|
}
|
||||||
|
|
||||||
|
declareExchange(name: string) {
|
||||||
|
let exchange = new this.TopicExchange(name, true, false)
|
||||||
|
this.amqpAdmin.declareExchange(exchange)
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
declareQueue(name: string) {
|
||||||
|
let queue = new this.Queue(name, true)
|
||||||
|
this.amqpAdmin.declareQueue(queue)
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
declareBinding(queue: string, exchange: string, routerKey: string, argument: any = null) {
|
||||||
|
let binding = new this.Binding(queue, org.springframework.amqp.core.Binding.DestinationType.QUEUE, exchange, routerKey, argument)
|
||||||
|
this.amqpAdmin.declareBinding(binding)
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
declareQueueAndBindExchange(queue: string, exchange: string, routerKey: string) {
|
||||||
|
return this.declareQueue(queue).declareExchange(exchange).declareBinding(queue, exchange, routerKey)
|
||||||
|
}
|
||||||
|
|
||||||
|
createContainer<T>(queue: string, listener: MessageHandler<T>, acknowledgeMode = AcknowledgeMode.AUTO) {
|
||||||
|
let connection = this.amqpAdmin.getRabbitTemplate().getConnectionFactory()
|
||||||
|
return new MessageListenerContainerAdapter({
|
||||||
|
connectionFactory: connection,
|
||||||
|
queueNames: [queue],
|
||||||
|
messageListener: new SimpleMessageHandler(listener),
|
||||||
|
acknowledgeMode: acknowledgeMode
|
||||||
|
}).getHandler()
|
||||||
|
}
|
||||||
|
|
||||||
|
send()
|
||||||
|
send() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
getTemplate() {
|
||||||
|
return this.amqpAdmin.getRabbitTemplate()
|
||||||
|
}
|
||||||
|
|
||||||
|
close() {
|
||||||
|
this.getTemplate().stop()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class SimpleMessageHandler extends ChannelAwareMessageListenerAdapter {
|
||||||
|
constructor(private handler: MessageHandler<any>) {
|
||||||
|
super()
|
||||||
|
}
|
||||||
|
onMessage(content: any, message: org.springframework.amqp.core.Message, channel: com.rabbitmq.client.Channel) {
|
||||||
|
return this.handler(content, message, channel)
|
||||||
|
}
|
||||||
|
}
|
||||||
3
packages/amqp/src/constants.ts
Normal file
3
packages/amqp/src/constants.ts
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
export const METADATA_KEY = {
|
||||||
|
|
||||||
|
}
|
||||||
34
packages/amqp/src/index.ts
Normal file
34
packages/amqp/src/index.ts
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
/// <reference types="@ccms/nashorn" />
|
||||||
|
/// <reference types="@javatypes/jdk" />
|
||||||
|
/// <reference types="@javatypes/spring-amqp" />
|
||||||
|
/// <reference types="@javatypes/spring-rabbit" />
|
||||||
|
/// <reference types="@javatypes/amqp-client" />
|
||||||
|
|
||||||
|
import { amqp } from '@ccms/api'
|
||||||
|
import { getContainer, reduceMetadata } from '@ccms/container'
|
||||||
|
|
||||||
|
function init() {
|
||||||
|
const beanFactory = base.getInstance().getAutowireCapableBeanFactory()
|
||||||
|
getContainer().bind(amqp.rabbit.Template).toDynamicValue((ctx) => {
|
||||||
|
let metadata = reduceMetadata(ctx)
|
||||||
|
if (!metadata.named) {
|
||||||
|
return beanFactory.getBean('rabbitTemplate')
|
||||||
|
} else {
|
||||||
|
return beanFactory.getBean(`${metadata.named}-rabbitTemplate`)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
getContainer().bind(amqp.rabbit.Admin).toDynamicValue((ctx) => {
|
||||||
|
let metadata = reduceMetadata(ctx)
|
||||||
|
if (!metadata.named) {
|
||||||
|
return beanFactory.getBean('rabbitAdmin')
|
||||||
|
} else {
|
||||||
|
return beanFactory.getBean(`${metadata.named}-rabbitAdmin`)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
init()
|
||||||
|
|
||||||
|
export * from './admin'
|
||||||
|
export * from './adapter'
|
||||||
|
export * from './manager'
|
||||||
|
export * from './constants'
|
||||||
5
packages/amqp/src/listener.ts
Normal file
5
packages/amqp/src/listener.ts
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
export class AmqpListener {
|
||||||
|
constructor() {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
18
packages/amqp/src/manager.ts
Normal file
18
packages/amqp/src/manager.ts
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
import { amqp } from "@ccms/api"
|
||||||
|
import { provideSingleton } from "@ccms/container"
|
||||||
|
|
||||||
|
import { ConnectionFactoryAdapter, RabbitTemplateAdapter, RabbitAdminAdapter } from "./adapter"
|
||||||
|
import { AmqpAdmin } from "./admin"
|
||||||
|
|
||||||
|
@provideSingleton(amqp.Manager)
|
||||||
|
export class AmqpManager {
|
||||||
|
createConnection(url: string, username: string, password: string) {
|
||||||
|
return new ConnectionFactoryAdapter({ url, username, password })
|
||||||
|
}
|
||||||
|
createTemplate(adapter: ConnectionFactoryAdapter) {
|
||||||
|
return new RabbitTemplateAdapter({ connectionFactory: adapter })
|
||||||
|
}
|
||||||
|
createAdmin(adapter: RabbitTemplateAdapter | ConnectionFactoryAdapter) {
|
||||||
|
return new AmqpAdmin(new RabbitAdminAdapter(adapter))
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@ccms/api",
|
"name": "@ccms/api",
|
||||||
"version": "0.28.0-beta.4",
|
"version": "0.20.0-alpha.0",
|
||||||
"description": "MiaoScript api package",
|
"description": "MiaoScript api package",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"miaoscript",
|
"miaoscript",
|
||||||
@@ -12,24 +12,23 @@
|
|||||||
"homepage": "https://github.com/circlecloud/ms.git",
|
"homepage": "https://github.com/circlecloud/ms.git",
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"main": "dist/index.js",
|
"main": "dist/index.js",
|
||||||
"files": [
|
|
||||||
"dist"
|
|
||||||
],
|
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"clean": "rimraf dist",
|
"clean": "rimraf dist",
|
||||||
"watch": "tsc --watch",
|
"watch": "tsc --watch",
|
||||||
"build": "pnpm clean && tsc",
|
"build": "yarn clean && tsc",
|
||||||
"test": "echo \"Error: run tests from root\" && exit 1"
|
"test": "echo \"Error: run tests from root\" && exit 1"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@ccms/common": "^0.28.0-beta.4",
|
"@ccms/common": "^0.19.0",
|
||||||
"@ccms/container": "^0.28.0-beta.4",
|
"@ccms/container": "^0.19.0",
|
||||||
"@ccms/i18n": "^0.28.0-beta.4",
|
"@ccms/polyfill": "^0.20.0-alpha.0",
|
||||||
"@ccms/polyfill": "^0.28.0-beta.4",
|
|
||||||
"base64-js": "^1.5.1",
|
"base64-js": "^1.5.1",
|
||||||
"source-map-builder": "^0.0.7"
|
"source-map-builder": "^0.0.7"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/base64-js": "^1.3.0"
|
"@types/base64-js": "^1.3.0",
|
||||||
|
"reflect-metadata": "^0.1.13",
|
||||||
|
"rimraf": "^3.0.2",
|
||||||
|
"typescript": "^4.5.5"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
7
packages/api/src/amqp.ts
Normal file
7
packages/api/src/amqp.ts
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
export namespace amqp {
|
||||||
|
export const Manager = Symbol('AmqpManager')
|
||||||
|
export namespace rabbit {
|
||||||
|
export const Admin = Symbol('RabbitAdmin')
|
||||||
|
export const Template = Symbol('RabbitTemplate')
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -5,12 +5,6 @@ import { plugin } from './plugin'
|
|||||||
export namespace command {
|
export namespace command {
|
||||||
@injectable()
|
@injectable()
|
||||||
export abstract class Command {
|
export abstract class Command {
|
||||||
/**
|
|
||||||
* first time script engine need optimize jit code
|
|
||||||
* so ignore first slow exec notify
|
|
||||||
*/
|
|
||||||
private cacheSlowKeys = {};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 注册插件命令
|
* 注册插件命令
|
||||||
* @param plugin 插件
|
* @param plugin 插件
|
||||||
@@ -52,13 +46,36 @@ export namespace command {
|
|||||||
try {
|
try {
|
||||||
let time = Date.now()
|
let time = Date.now()
|
||||||
let result = executor(sender, command, Java.from(args))
|
let result = executor(sender, command, Java.from(args))
|
||||||
this.checkSlow(Date.now() - time,
|
let cost = Date.now() - time
|
||||||
"ms.api.command.execute.slow",
|
if (cost > global.ScriptSlowExecuteTime) {
|
||||||
plugin, command, sender, args)
|
console.i18n("ms.api.command.execute.slow", {
|
||||||
|
player: sender.name,
|
||||||
|
plugin: plugin.description.name,
|
||||||
|
command,
|
||||||
|
args: Java.from(args).join(' '),
|
||||||
|
cost
|
||||||
|
})
|
||||||
|
}
|
||||||
return result
|
return result
|
||||||
} catch (ex: any) {
|
} catch (ex: any) {
|
||||||
this.printError(ex, "ms.api.command.execute.error",
|
console.i18n("ms.api.command.execute.error", {
|
||||||
plugin, command, sender, args)
|
player: sender.name,
|
||||||
|
plugin: plugin.description.name,
|
||||||
|
command,
|
||||||
|
args: Java.from(args).join(' '),
|
||||||
|
ex
|
||||||
|
})
|
||||||
|
console.ex(ex)
|
||||||
|
if (sender.name != 'CONSOLE') {
|
||||||
|
console.sender(sender, [i18n.translate("ms.api.command.execute.error", {
|
||||||
|
player: sender.name,
|
||||||
|
plugin: plugin.description.name,
|
||||||
|
command,
|
||||||
|
args: Java.from(args).join(' '),
|
||||||
|
ex
|
||||||
|
}),
|
||||||
|
...console.stack(ex)])
|
||||||
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -70,18 +87,42 @@ export namespace command {
|
|||||||
var token = args[args.length - 1]
|
var token = args[args.length - 1]
|
||||||
var complete = tabCompleter(sender, command, Java.from(args)) || []
|
var complete = tabCompleter(sender, command, Java.from(args)) || []
|
||||||
let result = this.copyPartialMatches(complete, token)
|
let result = this.copyPartialMatches(complete, token)
|
||||||
this.checkSlow(Date.now() - time,
|
let cost = Date.now() - time
|
||||||
"ms.api.command.tab.completer.slow",
|
if (cost > global.ScriptSlowExecuteTime) {
|
||||||
plugin, command, sender, args)
|
console.i18n("ms.api.command.tab.completer.slow", {
|
||||||
|
player: sender.name,
|
||||||
|
plugin: plugin.description.name,
|
||||||
|
command,
|
||||||
|
args: Java.from(args).join(' '),
|
||||||
|
cost
|
||||||
|
})
|
||||||
|
}
|
||||||
return result
|
return result
|
||||||
} catch (ex: any) {
|
} catch (ex: any) {
|
||||||
this.printError(ex, "ms.api.command.tab.completer.error",
|
console.i18n("ms.api.command.tab.completer.error", {
|
||||||
plugin, command, sender, args)
|
player: sender.name,
|
||||||
|
plugin: plugin.description.name,
|
||||||
|
command,
|
||||||
|
args: Java.from(args).join(' '),
|
||||||
|
ex
|
||||||
|
})
|
||||||
|
console.ex(ex)
|
||||||
|
if (sender.name != 'CONSOLE') {
|
||||||
|
console.sender(sender, [
|
||||||
|
i18n.translate("ms.api.command.tab.completer.error", {
|
||||||
|
player: sender.name,
|
||||||
|
plugin: plugin.description.name,
|
||||||
|
command,
|
||||||
|
args: Java.from(args).join(' '),
|
||||||
|
ex
|
||||||
|
}),
|
||||||
|
...console.stack(ex)
|
||||||
|
])
|
||||||
|
}
|
||||||
return []
|
return []
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected copyPartialMatches(complete: string[], token: string, array: string[] = []): string[] {
|
protected copyPartialMatches(complete: string[], token: string, array: string[] = []): string[] {
|
||||||
if (!token) { return complete }
|
if (!token) { return complete }
|
||||||
complete.forEach(function (e) {
|
complete.forEach(function (e) {
|
||||||
@@ -91,35 +132,5 @@ export namespace command {
|
|||||||
})
|
})
|
||||||
return array
|
return array
|
||||||
}
|
}
|
||||||
|
|
||||||
private checkSlow(cost: number, key: string, plugin: plugin.Plugin, command: string, sender: any, args: any[]) {
|
|
||||||
if (cost > global.ScriptSlowExecuteTime) {
|
|
||||||
let completerKey = `${plugin.description.name}-${key}-${command}-${sender.name}`
|
|
||||||
if (!this.cacheSlowKeys[completerKey]) {
|
|
||||||
return this.cacheSlowKeys[completerKey] = cost
|
|
||||||
}
|
|
||||||
console.i18n(key, {
|
|
||||||
player: sender.name,
|
|
||||||
plugin: plugin.description.name,
|
|
||||||
command,
|
|
||||||
args: Java.from(args).join(' '),
|
|
||||||
cost
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
private printError(error: Error, key: string, plugin: plugin.Plugin, command: string, sender: any, args: any[]) {
|
|
||||||
let message = i18n.translate(key, {
|
|
||||||
player: sender.name,
|
|
||||||
plugin: plugin.description.name,
|
|
||||||
command,
|
|
||||||
args: Java.from(args).join(' '),
|
|
||||||
error
|
|
||||||
})
|
|
||||||
console.console(message)
|
|
||||||
console.ex(error)
|
|
||||||
if (sender.name != 'CONSOLE') {
|
|
||||||
console.sender(sender, [message, ...console.stack(error)])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import * as base64 from 'base64-js'
|
|||||||
const Arrays = Java.type('java.util.Arrays')
|
const Arrays = Java.type('java.util.Arrays')
|
||||||
const Level = Java.type('java.util.logging.Level')
|
const Level = Java.type('java.util.logging.Level')
|
||||||
const Paths = Java.type('java.nio.file.Paths')
|
const Paths = Java.type('java.nio.file.Paths')
|
||||||
const ignoreLogPrefix = ['java.', 'javax.', 'sun.', 'net.minecraft.', 'org.bukkit.', 'jdk.internal.dynalink.', 'jdk.nashorn.', 'org.openjdk.nashorn', 'io.netty.', 'org.spongepowered.', 'org.apache', 'org.springframework']
|
const ignoreLogPrefix = ['java.', 'javax.', 'sun.', 'net.minecraft.', 'org.bukkit.', 'jdk.nashorn.', 'org.openjdk.nashorn', 'io.netty.', 'org.spongepowered.', 'org.apache', 'org.springframework']
|
||||||
|
|
||||||
enum LogLevel {
|
enum LogLevel {
|
||||||
ALL,
|
ALL,
|
||||||
@@ -18,114 +18,12 @@ enum LogLevel {
|
|||||||
OFF
|
OFF
|
||||||
}
|
}
|
||||||
|
|
||||||
const sourceMaps: { [key: string]: SourceMapBuilder } = {}
|
|
||||||
const sourceFileMaps: { [key: string]: string } = {}
|
|
||||||
|
|
||||||
global.setGlobal('MiaoScriptSourceMaps', sourceMaps)
|
|
||||||
global.setGlobal('MiaoScriptSourceFileMaps', sourceFileMaps)
|
|
||||||
|
|
||||||
export namespace jsconsole {
|
|
||||||
export function readSourceMap(fileName: string, lineNumber: any) {
|
|
||||||
try {
|
|
||||||
if (fileName.endsWith('js') || fileName.endsWith('ms')) {
|
|
||||||
if (sourceMaps[fileName] === undefined) {
|
|
||||||
sourceMaps[fileName] = null
|
|
||||||
let sourceLine = base.read(fileName).split('\n')
|
|
||||||
let lastLine = sourceLine[sourceLine.length - 1] || sourceLine[sourceLine.length - 2]
|
|
||||||
// lastLine is similar //# sourceMappingURL=data:application/json;base64,
|
|
||||||
if (lastLine.startsWith('//# sourceMappingURL=')) {
|
|
||||||
let sourceContent = null
|
|
||||||
let sourceMappingURL = lastLine.split('sourceMappingURL=', 2)[1]
|
|
||||||
if (sourceMappingURL.startsWith('data:application/json;base64,')) {
|
|
||||||
sourceContent = String.fromCharCode(...Array.from(base64.toByteArray(sourceMappingURL.split(',', 2)[1])))
|
|
||||||
} else if (sourceMappingURL.startsWith('http://') || sourceMappingURL.startsWith('https://')) {
|
|
||||||
// TODO
|
|
||||||
} else {
|
|
||||||
let file = Paths.get(Paths.get(fileName, '..', sourceMappingURL).toFile().getCanonicalPath()).toFile()
|
|
||||||
if (file.exists()) {
|
|
||||||
sourceContent = base.read(file)
|
|
||||||
sourceFileMaps[fileName] = file.getCanonicalPath()
|
|
||||||
} else if (global.debug) {
|
|
||||||
console.debug('readSourceMap can\'t found', fileName, 'source map file', sourceMappingURL)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (sourceContent) {
|
|
||||||
sourceMaps[fileName] = new SourceMapBuilder(JSON.parse(sourceContent))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (sourceMaps[fileName]) {
|
|
||||||
let sourceMapping = sourceMaps[fileName].getSource(lineNumber, 25, true, true)
|
|
||||||
if (sourceMapping) {
|
|
||||||
fileName = Paths.get(fileName, '..', sourceMapping.sourcePath).toFile().getCanonicalPath()
|
|
||||||
lineNumber = sourceMapping.mapping.sourceLine
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (error: any) {
|
|
||||||
console.debug('search source map', fileName, 'line', lineNumber, 'error:', error)
|
|
||||||
if (global.debug) {
|
|
||||||
console.ex(error)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return {
|
|
||||||
fileName,
|
|
||||||
lineNumber
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export function getStackTrace(ex: Error, color: boolean = true): string[] {
|
|
||||||
if (!ex) return []
|
|
||||||
let stack = ex.getStackTrace()
|
|
||||||
let cache = [(color ? '§c' : '') + ex]
|
|
||||||
//@ts-ignore
|
|
||||||
if (stack.class) {
|
|
||||||
stack = Arrays.asList(stack)
|
|
||||||
}
|
|
||||||
stack.forEach(trace => {
|
|
||||||
if (!trace.fileName || trace.fileName.startsWith('jar:file:') || trace.fileName.startsWith('file:')) { return }
|
|
||||||
if (trace.className.startsWith('<')) {
|
|
||||||
let { fileName, lineNumber } = readSourceMap(trace.fileName, trace.lineNumber)
|
|
||||||
if (fileName.startsWith(root)) { fileName = fileName.split(root)[1] }
|
|
||||||
if (color) {
|
|
||||||
cache.push(` §e->§c ${fileName}:${lineNumber}(${trace.lineNumber}) => §4${trace.methodName}`)
|
|
||||||
} else {
|
|
||||||
cache.push(` -> ${fileName}:${lineNumber}(${trace.lineNumber}) => ${trace.methodName}`)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
let className = trace.className
|
|
||||||
var fileName = trace.fileName as string
|
|
||||||
var lineNumber = trace.lineNumber
|
|
||||||
if (className.startsWith('jdk.nashorn.internal.scripts') || className.startsWith('org.openjdk.nashorn.internal.scripts')) {
|
|
||||||
className = className.substr(className.lastIndexOf('$') + 1)
|
|
||||||
var { fileName, lineNumber } = readSourceMap(fileName, lineNumber)
|
|
||||||
if (fileName.startsWith(root)) { fileName = fileName.split(root)[1] }
|
|
||||||
} else {
|
|
||||||
if (!global.debug) {
|
|
||||||
for (let prefix in ignoreLogPrefix) {
|
|
||||||
if (className.startsWith(ignoreLogPrefix[prefix])) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (className.startsWith('jdk.nashorn.internal.') || className.startsWith('org.openjdk.nashorn.internal.')) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (color) {
|
|
||||||
cache.push(` §e->§c ${className}.${trace.methodName}(§4${fileName}:${lineNumber}§c)`)
|
|
||||||
} else {
|
|
||||||
cache.push(` -> ${className}.${trace.methodName}(${fileName}:${lineNumber})`)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
return cache
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export class MiaoScriptConsole implements Console {
|
export class MiaoScriptConsole implements Console {
|
||||||
Console: any
|
Console: any
|
||||||
memory: any
|
memory: any
|
||||||
|
|
||||||
|
private static sourceMaps: { [key: string]: SourceMapBuilder } = {}
|
||||||
|
private static sourceFileMaps: { [key: string]: string } = {}
|
||||||
private _name: string = ''
|
private _name: string = ''
|
||||||
private _level: LogLevel = LogLevel.INFO
|
private _level: LogLevel = LogLevel.INFO
|
||||||
|
|
||||||
@@ -194,8 +92,91 @@ export class MiaoScriptConsole implements Console {
|
|||||||
ex(ex: Error) {
|
ex(ex: Error) {
|
||||||
this.stack(ex).forEach(line => this.console(line))
|
this.stack(ex).forEach(line => this.console(line))
|
||||||
}
|
}
|
||||||
|
readSourceMap(fileName: string, lineNumber: any) {
|
||||||
|
try {
|
||||||
|
if (fileName.endsWith('js')) {
|
||||||
|
if (MiaoScriptConsole.sourceMaps[fileName] === undefined) {
|
||||||
|
MiaoScriptConsole.sourceMaps[fileName] = null
|
||||||
|
let sourceLine = base.read(fileName).split('\n')
|
||||||
|
let lastLine = sourceLine[sourceLine.length - 1]
|
||||||
|
// lastLine is similar //# sourceMappingURL=data:application/json;base64,
|
||||||
|
if (lastLine.startsWith('//# sourceMappingURL=')) {
|
||||||
|
let sourceContent = null
|
||||||
|
let sourceMappingURL = lastLine.split('sourceMappingURL=', 2)[1]
|
||||||
|
if (sourceMappingURL.startsWith('data:application/json;base64,')) {
|
||||||
|
sourceContent = String.fromCharCode(...Array.from(base64.toByteArray(sourceMappingURL.split(',', 2)[1])))
|
||||||
|
} else if (sourceMappingURL.startsWith('http://') || sourceMappingURL.startsWith('https://')) {
|
||||||
|
// TODO
|
||||||
|
} else {
|
||||||
|
let file = Paths.get(Paths.get(fileName, '..', sourceMappingURL).toFile().getCanonicalPath()).toFile()
|
||||||
|
if (file.exists()) { sourceContent = base.read(file) }
|
||||||
|
}
|
||||||
|
if (sourceContent) {
|
||||||
|
MiaoScriptConsole.sourceMaps[fileName] = new SourceMapBuilder(JSON.parse(sourceContent))
|
||||||
|
MiaoScriptConsole.sourceFileMaps[fileName] = Paths.get(fileName, '..', MiaoScriptConsole.sourceMaps[fileName].sources[0]).toFile().getCanonicalPath()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (MiaoScriptConsole.sourceMaps[fileName]) {
|
||||||
|
let sourceMapping = MiaoScriptConsole.sourceMaps[fileName].getSource(lineNumber, 25, true, true)
|
||||||
|
fileName = MiaoScriptConsole.sourceFileMaps[fileName]
|
||||||
|
if (sourceMapping && lineNumber != sourceMapping.mapping.sourceLine) { lineNumber = sourceMapping.mapping.sourceLine }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (error: any) {
|
||||||
|
console.debug('search source map', fileName, 'line', lineNumber, 'error:', error)
|
||||||
|
if (global.debug) {
|
||||||
|
console.ex(error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
fileName,
|
||||||
|
lineNumber
|
||||||
|
}
|
||||||
|
}
|
||||||
stack(ex: Error, color: boolean = true): string[] {
|
stack(ex: Error, color: boolean = true): string[] {
|
||||||
return jsconsole.getStackTrace(ex, color)
|
if (!ex) return []
|
||||||
|
let stack = ex.getStackTrace()
|
||||||
|
let cache = [(color ? '§c' : '') + ex]
|
||||||
|
//@ts-ignore
|
||||||
|
if (stack.class) {
|
||||||
|
stack = Arrays.asList(stack)
|
||||||
|
}
|
||||||
|
stack.forEach(trace => {
|
||||||
|
if (!trace.fileName || trace.fileName.startsWith('jar:file:') || trace.fileName.startsWith('file:')) { return }
|
||||||
|
if (trace.className.startsWith('<')) {
|
||||||
|
let { fileName, lineNumber } = this.readSourceMap(trace.fileName, trace.lineNumber)
|
||||||
|
if (fileName.startsWith(root)) { fileName = fileName.split(root)[1] }
|
||||||
|
if (color) {
|
||||||
|
cache.push(` §e->§c ${fileName}:${lineNumber} => §4${trace.methodName}`)
|
||||||
|
} else {
|
||||||
|
cache.push(` -> ${fileName}:${lineNumber} => ${trace.methodName}`)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
let className = trace.className
|
||||||
|
var fileName = trace.fileName as string
|
||||||
|
var lineNumber = trace.lineNumber
|
||||||
|
if (className.startsWith('jdk.nashorn.internal.scripts') || className.startsWith('org.openjdk.nashorn.internal.scripts')) {
|
||||||
|
className = className.substr(className.lastIndexOf('$') + 1)
|
||||||
|
var { fileName, lineNumber } = this.readSourceMap(fileName, lineNumber)
|
||||||
|
if (fileName.startsWith(root)) { fileName = fileName.split(root)[1] }
|
||||||
|
} else {
|
||||||
|
if (!global.debug) {
|
||||||
|
for (let prefix in ignoreLogPrefix) {
|
||||||
|
if (className.startsWith(ignoreLogPrefix[prefix])) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (color) {
|
||||||
|
cache.push(` §e->§c ${className}.${trace.methodName}(§4${fileName}:${lineNumber}§c)`)
|
||||||
|
} else {
|
||||||
|
cache.push(` -> ${className}.${trace.methodName}(${fileName}:${lineNumber})`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return cache
|
||||||
}
|
}
|
||||||
assert(value: any, message?: string, ...optionalParams: any[]): void {
|
assert(value: any, message?: string, ...optionalParams: any[]): void {
|
||||||
throw new Error("Method not implemented.")
|
throw new Error("Method not implemented.")
|
||||||
|
|||||||
@@ -11,21 +11,10 @@ export namespace constants {
|
|||||||
}
|
}
|
||||||
export namespace Reflect {
|
export namespace Reflect {
|
||||||
export const Method = {
|
export const Method = {
|
||||||
getServerConnection: [
|
getServerConnection: [/*spigot 1.8.8*/'aq',/*spigot 1.12.2*/ 'an', /*spigot 1.14.4+*/'getServerConnection', /*catserver 1.12.2*/'func_147137_ag']
|
||||||
/*spigot 1.8.8*/'aq',
|
|
||||||
/*spigot 1.12.2*/ 'an',
|
|
||||||
/*spigot 1.14.4+*/'getServerConnection',
|
|
||||||
/*spigot 1.19+*/'ad',
|
|
||||||
/*catserver 1.12.2*/'func_147137_ag'
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
export const Field = {
|
export const Field = {
|
||||||
listeningChannels: [
|
listeningChannels: [/*spigot 1.8.8-1.12.2*/'g', /*spigot 1.14.4*/'f', /*spigot 1.15.2+*/'listeningChannels', /*catserver 1.12.2*/'field_151274_e']
|
||||||
/*spigot 1.8.8-1.12.2*/'g',
|
|
||||||
/*spigot 1.14.4*/'f',
|
|
||||||
/*spigot 1.15.2+*/'listeningChannels',
|
|
||||||
/*catserver 1.12.2*/'field_151274_e'
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
export enum ServerType {
|
export enum ServerType {
|
||||||
|
|||||||
@@ -1,56 +1,5 @@
|
|||||||
import { injectable } from "@ccms/container"
|
|
||||||
|
|
||||||
export namespace database {
|
export namespace database {
|
||||||
export const DataSource = Symbol("DataSource")
|
export const DataBaseManager = Symbol("DataBaseManager");
|
||||||
/**
|
export const DataSource = Symbol("DataSource");
|
||||||
* 数据库配置
|
export const DataBase = Symbol("DataBase");
|
||||||
*/
|
|
||||||
export interface DataBaseConfig {
|
|
||||||
/**
|
|
||||||
* 数据库类型
|
|
||||||
*/
|
|
||||||
type: 'h2' | 'mysql' | 'mongodb' | 'sqlite' | 'postgres' | 'redis'
|
|
||||||
/**
|
|
||||||
* 数据库连接串
|
|
||||||
*/
|
|
||||||
url: string | javax.sql.DataSource
|
|
||||||
/**
|
|
||||||
* 数据库驱动
|
|
||||||
*/
|
|
||||||
driverClassName?: string
|
|
||||||
/**
|
|
||||||
* 用户名
|
|
||||||
*/
|
|
||||||
username?: string
|
|
||||||
/**
|
|
||||||
* 密码
|
|
||||||
*/
|
|
||||||
password?: string
|
|
||||||
/**
|
|
||||||
* 链接属性
|
|
||||||
*/
|
|
||||||
properties?: { [key: string]: any }
|
|
||||||
/**
|
|
||||||
* 调试模式
|
|
||||||
*/
|
|
||||||
debug?: boolean
|
|
||||||
}
|
|
||||||
|
|
||||||
@injectable()
|
|
||||||
export abstract class DataBaseManager {
|
|
||||||
abstract setMainDatabase(mainDatabase: DataBase): void
|
|
||||||
abstract getMainDatabase(): DataBase
|
|
||||||
abstract createDatabase(name: string, config: DataBaseConfig): DataBase
|
|
||||||
abstract removeDatabase(name: string): boolean
|
|
||||||
abstract getDatabase(name: string): DataBase
|
|
||||||
abstract startWebManager(...args: string[])
|
|
||||||
abstract stopWebManager()
|
|
||||||
abstract shutdown()
|
|
||||||
}
|
|
||||||
@injectable()
|
|
||||||
export abstract class DataBase {
|
|
||||||
abstract query<T>(sql: string, ...args: any[]): Array<T>
|
|
||||||
abstract update(sql: string, ...args: any[]): number
|
|
||||||
abstract execute(sql: string): void
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,8 +25,7 @@ export namespace event {
|
|||||||
public EventPriority = EventPriority;
|
public EventPriority = EventPriority;
|
||||||
|
|
||||||
private mapEvent = [];
|
private mapEvent = [];
|
||||||
private pluginEventMap = [];
|
private listenerMap = [];
|
||||||
private cacheSlowEventKey = {};
|
|
||||||
|
|
||||||
protected baseEventDir = '';
|
protected baseEventDir = '';
|
||||||
|
|
||||||
@@ -93,23 +92,17 @@ export namespace event {
|
|||||||
return eventCls
|
return eventCls
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
execute(name, exec, eventCls) {
|
||||||
* 创建命令执行器
|
|
||||||
* @param name 插件名称
|
|
||||||
* @param exec 执行方法
|
|
||||||
* @param eventCls 事件类
|
|
||||||
* @returns
|
|
||||||
*/
|
|
||||||
createExecute(name, exec, eventCls) {
|
|
||||||
return (...args: any[]) => {
|
return (...args: any[]) => {
|
||||||
let event = args[args.length - 1]
|
|
||||||
try {
|
try {
|
||||||
if (!eventCls.isAssignableFrom(event.getClass())) { return }
|
let event = args[args.length - 1]
|
||||||
let time = Date.now(); exec(event); let cost = Date.now() - time
|
if (eventCls.isAssignableFrom(event.getClass())) {
|
||||||
if (cost > global.ScriptSlowExecuteTime && !event.async) {
|
let time = Date.now()
|
||||||
let eventKey = `${name}-${this.class2Name(eventCls)}`
|
exec(event)
|
||||||
if (!this.cacheSlowEventKey[eventKey]) { return this.cacheSlowEventKey[eventKey] = cost }
|
let cost = Date.now() - time
|
||||||
console.i18n("ms.api.event.execute.slow", { name, event: this.class2Name(eventCls), cost })
|
if (cost > global.ScriptSlowExecuteTime) {
|
||||||
|
console.i18n("ms.api.event.execute.slow", { name, event: this.class2Name(eventCls), cost })
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} catch (ex: any) {
|
} catch (ex: any) {
|
||||||
console.i18n("ms.api.event.execute.error", { name, event: this.class2Name(eventCls), ex })
|
console.i18n("ms.api.event.execute.error", { name, event: this.class2Name(eventCls), ex })
|
||||||
@@ -120,17 +113,17 @@ export namespace event {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 添加事件监听
|
* 添加事件监听
|
||||||
* @param plugin {any} 插件
|
* @param plugin {any}
|
||||||
* @param event {string} 事件名称
|
* @param event {string}
|
||||||
* @param exec {function} 事件执行器
|
* @param exec {function}
|
||||||
* @param priority {string} [LOWEST,LOW,NORMAL,HIGH,HIGHEST,MONITOR] 优先级
|
* @param priority {string} [LOWEST,LOW,NORMAL,HIGH,HIGHEST,MONITOR]
|
||||||
* @param ignoreCancel 是否忽略已取消事件
|
* @param ignoreCancel
|
||||||
*/
|
*/
|
||||||
listen(plugin: any, event: string, exec: (event: any) => void, priority: EventPriority = EventPriority.NORMAL, ignoreCancel = false) {
|
listen(plugin: any, event: string, exec: (event: any) => void, priority: EventPriority = EventPriority.NORMAL, ignoreCancel = false) {
|
||||||
if (!plugin || !plugin.description || !plugin.description.name) throw new TypeError(i18n.translate("ms.api.event.listen.plugin.name.empty"))
|
if (!plugin || !plugin.description || !plugin.description.name) throw new TypeError(i18n.translate("ms.api.event.listen.plugin.name.empty"))
|
||||||
var name = plugin.description.name
|
var name = plugin.description.name
|
||||||
var eventCls = this.name2Class(name, event)
|
var eventCls = this.name2Class(name, event)
|
||||||
if (!eventCls) { return () => { console.warn('event ' + event + ' not found ignore off listener.') } }
|
if (!eventCls) { return }
|
||||||
if (typeof priority === 'boolean') {
|
if (typeof priority === 'boolean') {
|
||||||
ignoreCancel = priority
|
ignoreCancel = priority
|
||||||
priority = EventPriority.NORMAL
|
priority = EventPriority.NORMAL
|
||||||
@@ -140,15 +133,16 @@ export namespace event {
|
|||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
let executor = exec.name || exec.executor || '[anonymous]'
|
let executor = exec.name || exec.executor || '[anonymous]'
|
||||||
// noinspection JSUnusedGlobalSymbols
|
// noinspection JSUnusedGlobalSymbols
|
||||||
let listener = this.register(
|
var listener = this.register(
|
||||||
eventCls,
|
eventCls,
|
||||||
this.createExecute(name, exec, eventCls),
|
this.execute(name, exec, eventCls),
|
||||||
priority,
|
priority,
|
||||||
ignoreCancel
|
ignoreCancel
|
||||||
)
|
)
|
||||||
|
var listenerMap = this.listenerMap
|
||||||
// add to cache Be used for close plugin to close event
|
// add to cache Be used for close plugin to close event
|
||||||
if (!this.pluginEventMap[name]) this.pluginEventMap[name] = []
|
if (!listenerMap[name]) listenerMap[name] = []
|
||||||
let off = () => {
|
var off = () => {
|
||||||
if (off['offed']) return
|
if (off['offed']) return
|
||||||
off['offed'] = true
|
off['offed'] = true
|
||||||
this.unregister(eventCls, listener)
|
this.unregister(eventCls, listener)
|
||||||
@@ -158,7 +152,7 @@ export namespace event {
|
|||||||
exec: executor
|
exec: executor
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
this.pluginEventMap[name].push(off)
|
listenerMap[name].push(off)
|
||||||
// noinspection JSUnresolvedVariable
|
// noinspection JSUnresolvedVariable
|
||||||
console.debug(i18n.translate("ms.api.event.register", {
|
console.debug(i18n.translate("ms.api.event.register", {
|
||||||
name,
|
name,
|
||||||
@@ -175,10 +169,10 @@ export namespace event {
|
|||||||
* @param plugin 插件
|
* @param plugin 插件
|
||||||
*/
|
*/
|
||||||
disable(plugin: any) {
|
disable(plugin: any) {
|
||||||
var eventCache = this.pluginEventMap[plugin.description.name]
|
var eventCache = this.listenerMap[plugin.description.name]
|
||||||
if (eventCache) {
|
if (eventCache) {
|
||||||
eventCache.forEach((off: () => any) => off())
|
eventCache.forEach(off => off())
|
||||||
delete this.pluginEventMap[plugin.description.name]
|
delete this.listenerMap[plugin.description.name]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,14 +1,14 @@
|
|||||||
import "@ccms/nashorn"
|
import "@ccms/nashorn"
|
||||||
|
|
||||||
|
export * from './web'
|
||||||
|
export * from './amqp'
|
||||||
export * from './chat'
|
export * from './chat'
|
||||||
export * from './task'
|
export * from './task'
|
||||||
export * from './item'
|
|
||||||
export * from './event'
|
export * from './event'
|
||||||
export * from './proxy'
|
export * from './proxy'
|
||||||
export * from './plugin'
|
export * from './plugin'
|
||||||
export * from './server'
|
export * from './server'
|
||||||
export * from './console'
|
export * from './console'
|
||||||
export { jsconsole as console } from './console'
|
|
||||||
export * from './channel'
|
export * from './channel'
|
||||||
export * from './command'
|
export * from './command'
|
||||||
export * from './database'
|
export * from './database'
|
||||||
|
|||||||
@@ -1,20 +0,0 @@
|
|||||||
import { injectable } from '@ccms/container'
|
|
||||||
|
|
||||||
export namespace item {
|
|
||||||
@injectable()
|
|
||||||
export abstract class Item {
|
|
||||||
abstract builder(): ItemBuilder
|
|
||||||
abstract toJson(item: any): string
|
|
||||||
abstract fromJson(json: string): any
|
|
||||||
}
|
|
||||||
export interface ItemBuilder {
|
|
||||||
from(item: any): ItemBuilder
|
|
||||||
create(type: string | number): ItemBuilder
|
|
||||||
name(name: string): ItemBuilder
|
|
||||||
lore(...lores: string[]): ItemBuilder
|
|
||||||
amount(amount: number): ItemBuilder
|
|
||||||
durability(durability: number): ItemBuilder
|
|
||||||
clone(): any
|
|
||||||
build(): any
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -6,12 +6,6 @@ const UUID = Java.type('java.util.UUID')
|
|||||||
const Math = Java.type('java.lang.Math')
|
const Math = Java.type('java.lang.Math')
|
||||||
|
|
||||||
export namespace particle {
|
export namespace particle {
|
||||||
@injectable()
|
|
||||||
export abstract class ParticleSpawner {
|
|
||||||
abstract spawn(location: any, particle: Particle)
|
|
||||||
abstract spawnToPlayer(player: any, location: any, particle: Particle)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 表示一个特效对象
|
* 表示一个特效对象
|
||||||
*
|
*
|
||||||
@@ -29,11 +23,6 @@ export namespace particle {
|
|||||||
private extra: number = 0;
|
private extra: number = 0;
|
||||||
private data: Object = null;
|
private data: Object = null;
|
||||||
|
|
||||||
/**
|
|
||||||
* Only Show To Player
|
|
||||||
*/
|
|
||||||
private player: any
|
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
this.uuid = UUID.randomUUID().toString()
|
this.uuid = UUID.randomUUID().toString()
|
||||||
}
|
}
|
||||||
@@ -116,15 +105,6 @@ export namespace particle {
|
|||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
getPlayer() {
|
|
||||||
return this.player
|
|
||||||
}
|
|
||||||
|
|
||||||
setPlayer(player) {
|
|
||||||
this.player = player
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 通过给定一个坐标就可以使用已经指定的参数来播放粒子
|
* 通过给定一个坐标就可以使用已经指定的参数来播放粒子
|
||||||
*
|
*
|
||||||
@@ -132,14 +112,9 @@ export namespace particle {
|
|||||||
*/
|
*/
|
||||||
spawn(location: any) {
|
spawn(location: any) {
|
||||||
if (!this.spawner) throw new Error(`particle ${this.uuid} not set spawner can't spawn!`)
|
if (!this.spawner) throw new Error(`particle ${this.uuid} not set spawner can't spawn!`)
|
||||||
if (this.player) {
|
this.spawner.spawn(location, this)
|
||||||
this.spawner.spawnToPlayer(this.player, location, this)
|
|
||||||
} else {
|
|
||||||
this.spawner.spawn(location, this)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 表示一条线
|
* 表示一条线
|
||||||
*
|
*
|
||||||
@@ -183,7 +158,8 @@ export namespace particle {
|
|||||||
|
|
||||||
show() {
|
show() {
|
||||||
for (let i = 0; i < this.length; i += this.step) {
|
for (let i = 0; i < this.length; i += this.step) {
|
||||||
this.spawn(this.start.clone().add(this.vector.clone().multiply(i)))
|
let vectorTemp = this.vector.clone().multiply(i)
|
||||||
|
this.spawn(this.start.clone().add(vectorTemp))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -258,6 +234,15 @@ export namespace particle {
|
|||||||
this.length = this.vector.length()
|
this.length = this.vector.length()
|
||||||
this.vector.normalize()
|
this.vector.normalize()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static buildLine(locA: any, locB: any, step: number, particle: any) {
|
||||||
|
let vectorAB = locB.clone().subtract(locA).toVector()
|
||||||
|
let vectorLength = vectorAB.length()
|
||||||
|
vectorAB.normalize()
|
||||||
|
for (let i = 0; i < vectorLength; i += step) {
|
||||||
|
ParticleManager.globalSpawner.spawn(locA.clone().add(vectorAB.clone().multiply(i)), particle)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* 表示一个弧
|
* 表示一个弧
|
||||||
@@ -346,10 +331,9 @@ export namespace particle {
|
|||||||
|
|
||||||
@injectable()
|
@injectable()
|
||||||
export abstract class ParticleManager {
|
export abstract class ParticleManager {
|
||||||
|
public static globalSpawner: ParticleSpawner = undefined
|
||||||
@Autowired()
|
@Autowired()
|
||||||
private taskManager: task.TaskManager
|
private taskManager: task.TaskManager
|
||||||
@Autowired()
|
|
||||||
private particleSpawner: particle.ParticleSpawner
|
|
||||||
|
|
||||||
protected taskId: java.util.concurrent.atomic.AtomicInteger
|
protected taskId: java.util.concurrent.atomic.AtomicInteger
|
||||||
protected cacheTasks = new Map<string, ParticleTask>()
|
protected cacheTasks = new Map<string, ParticleTask>()
|
||||||
@@ -370,10 +354,6 @@ export namespace particle {
|
|||||||
return this.taskManager
|
return this.taskManager
|
||||||
}
|
}
|
||||||
|
|
||||||
public getParticleSpawner() {
|
|
||||||
return this.particleSpawner
|
|
||||||
}
|
|
||||||
|
|
||||||
public create(particle: Particle, plugin?: plugin.Plugin) {
|
public create(particle: Particle, plugin?: plugin.Plugin) {
|
||||||
let uuid = particle.getUUID()
|
let uuid = particle.getUUID()
|
||||||
if (this.cacheTasks.has(uuid)) {
|
if (this.cacheTasks.has(uuid)) {
|
||||||
@@ -409,12 +389,14 @@ export namespace particle {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
protected create0(owner: plugin.Plugin, particle: Particle): ParticleTask {
|
protected create0(owner: plugin.Plugin, particle: Particle): ParticleTask {
|
||||||
particle.setSpawner(this.getParticleSpawner())
|
particle.setSpawner(this.getGlobalSpawner())
|
||||||
return new ParticleTask(owner, particle, this)
|
return new ParticleTask(owner, particle, this)
|
||||||
}
|
}
|
||||||
|
protected abstract getGlobalSpawner(): ParticleSpawner
|
||||||
}
|
}
|
||||||
|
|
||||||
export class ParticleTask {
|
export class ParticleTask {
|
||||||
|
|
||||||
private particle: Particle
|
private particle: Particle
|
||||||
private isAsync: boolean = false
|
private isAsync: boolean = false
|
||||||
private interval: number = 0
|
private interval: number = 0
|
||||||
@@ -504,4 +486,9 @@ export namespace particle {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export abstract class ParticleSpawner {
|
||||||
|
abstract spawnParticle(location: any, particle: any, count: number)
|
||||||
|
abstract spawn(location: any, particle: Particle)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -149,19 +149,7 @@ export namespace plugin {
|
|||||||
/**
|
/**
|
||||||
* 插件名称 不填默认为类名
|
* 插件名称 不填默认为类名
|
||||||
*/
|
*/
|
||||||
name: string
|
name?: string
|
||||||
/**
|
|
||||||
* 插件中文名称
|
|
||||||
*/
|
|
||||||
cname?: string
|
|
||||||
/**
|
|
||||||
* 付费插件ID
|
|
||||||
*/
|
|
||||||
pid?: number
|
|
||||||
/**
|
|
||||||
* 付费插件等级 付费插件自动注入
|
|
||||||
*/
|
|
||||||
level?: number
|
|
||||||
/**
|
/**
|
||||||
* 前缀
|
* 前缀
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -29,7 +29,6 @@ export namespace server {
|
|||||||
origin: any
|
origin: any
|
||||||
[key: string]: any
|
[key: string]: any
|
||||||
}
|
}
|
||||||
|
|
||||||
@injectable()
|
@injectable()
|
||||||
export abstract class NativePluginManager {
|
export abstract class NativePluginManager {
|
||||||
list(): NativePlugin[] {
|
list(): NativePlugin[] {
|
||||||
@@ -54,7 +53,6 @@ export namespace server {
|
|||||||
throw new Error("Method not implemented.")
|
throw new Error("Method not implemented.")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* MiaoScript Server
|
* MiaoScript Server
|
||||||
*/
|
*/
|
||||||
@@ -100,7 +98,6 @@ export namespace server {
|
|||||||
throw new Error("Method not implemented.")
|
throw new Error("Method not implemented.")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@injectable()
|
@injectable()
|
||||||
export class ServerChecker {
|
export class ServerChecker {
|
||||||
@Autowired(ServerType)
|
@Autowired(ServerType)
|
||||||
@@ -119,22 +116,6 @@ export namespace server {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@injectable()
|
|
||||||
export class NativePluginChecker {
|
|
||||||
@Autowired(NativePluginManager)
|
|
||||||
private nativePluginManager: NativePluginManager
|
|
||||||
|
|
||||||
check(plugins: string[]) {
|
|
||||||
// Not set plugins -> allow
|
|
||||||
if (!plugins || !plugins.length) return true
|
|
||||||
for (const plugin of plugins) {
|
|
||||||
if (!this.nativePluginManager.has(plugin)) { return false }
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@injectable()
|
@injectable()
|
||||||
export abstract class ReflectServer extends server.Server {
|
export abstract class ReflectServer extends server.Server {
|
||||||
@Autowired(ContainerInstance)
|
@Autowired(ContainerInstance)
|
||||||
@@ -191,23 +172,13 @@ export namespace server {
|
|||||||
}
|
}
|
||||||
protected reflectRootLogger(consoleServer: any) {
|
protected reflectRootLogger(consoleServer: any) {
|
||||||
try {
|
try {
|
||||||
this.rootLogger = reflect.on(consoleServer).get('LOGGER').get()
|
this.rootLogger = reflect.on(consoleServer).get('LOGGER').get().parent
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
if (global.debug) {
|
if (global.debug) {
|
||||||
console.ex(error)
|
console.ex(error)
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
this.rootLogger = reflect.on(consoleServer).get(0).get()
|
this.rootLogger = reflect.on(consoleServer).get(0).get().parent
|
||||||
} catch (error: any) {
|
|
||||||
if (global.debug) {
|
|
||||||
console.ex(error)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (this.rootLogger.class.name.indexOf('slf4j') !== -1) {
|
|
||||||
try {
|
|
||||||
let LogManager = Java.type('org.apache.logging.log4j.LogManager')
|
|
||||||
this.rootLogger = LogManager.getLogger('ROOT')
|
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
if (global.debug) {
|
if (global.debug) {
|
||||||
console.ex(error)
|
console.ex(error)
|
||||||
@@ -218,11 +189,11 @@ export namespace server {
|
|||||||
console.error('Error Logger Class: ' + this.rootLogger.class.name)
|
console.error('Error Logger Class: ' + this.rootLogger.class.name)
|
||||||
this.rootLogger = undefined
|
this.rootLogger = undefined
|
||||||
}
|
}
|
||||||
if (!this.rootLogger) { console.error("Can't found rootLogger!") }
|
|
||||||
// get root logger
|
// get root logger
|
||||||
for (let index = 0; index < 5 && this.rootLogger.parent; index++) {
|
for (let index = 0; index < 5 && this.rootLogger.parent; index++) {
|
||||||
this.rootLogger = this.rootLogger.parent
|
this.rootLogger = this.rootLogger.parent
|
||||||
}
|
}
|
||||||
|
if (!this.rootLogger) { console.error("Can't found rootLogger!") }
|
||||||
this.container.bind(constants.ServiceIdentifier.RootLogger).toConstantValue(this.rootLogger)
|
this.container.bind(constants.ServiceIdentifier.RootLogger).toConstantValue(this.rootLogger)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,5 @@
|
|||||||
import { EventEmitter } from 'events'
|
|
||||||
import { injectable } from '@ccms/container'
|
|
||||||
|
|
||||||
import { plugin } from './index'
|
import { plugin } from './index'
|
||||||
|
import { injectable } from '@ccms/container'
|
||||||
|
|
||||||
const AtomicInteger = Java.type("java.util.concurrent.atomic.AtomicInteger")
|
const AtomicInteger = Java.type("java.util.concurrent.atomic.AtomicInteger")
|
||||||
|
|
||||||
@@ -34,7 +32,9 @@ export namespace task {
|
|||||||
|
|
||||||
protected pluginDisable(plugin: plugin.Plugin) {
|
protected pluginDisable(plugin: plugin.Plugin) {
|
||||||
if (this.pluginCacheTasks.has(plugin.description.name)) {
|
if (this.pluginCacheTasks.has(plugin.description.name)) {
|
||||||
this.pluginCacheTasks.get(plugin.description.name).forEach((task) => task.cancel())
|
this.pluginCacheTasks.get(plugin.description.name).forEach((task) => {
|
||||||
|
task.cancel()
|
||||||
|
})
|
||||||
this.pluginCacheTasks.delete(plugin.description.name)
|
this.pluginCacheTasks.delete(plugin.description.name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -79,7 +79,7 @@ export namespace task {
|
|||||||
/**
|
/**
|
||||||
* 任务抽象
|
* 任务抽象
|
||||||
*/
|
*/
|
||||||
export abstract class Task extends EventEmitter implements Cancelable {
|
export abstract class Task implements Cancelable {
|
||||||
protected func: Function
|
protected func: Function
|
||||||
protected isAsync: boolean = false;
|
protected isAsync: boolean = false;
|
||||||
protected laterTime: number = 0;
|
protected laterTime: number = 0;
|
||||||
@@ -88,10 +88,7 @@ export namespace task {
|
|||||||
protected taskId: number
|
protected taskId: number
|
||||||
protected innerTask: any
|
protected innerTask: any
|
||||||
|
|
||||||
private cancelled: boolean = false
|
|
||||||
|
|
||||||
constructor(owner: plugin.Plugin, func: Function, id: number) {
|
constructor(owner: plugin.Plugin, func: Function, id: number) {
|
||||||
super()
|
|
||||||
this.owner = owner
|
this.owner = owner
|
||||||
this.func = func
|
this.func = func
|
||||||
this.taskId = id
|
this.taskId = id
|
||||||
@@ -137,36 +134,20 @@ export namespace task {
|
|||||||
*/
|
*/
|
||||||
cancel(): boolean {
|
cancel(): boolean {
|
||||||
let result = this.cancel0()
|
let result = this.cancel0()
|
||||||
this.finish()
|
process.emit('task.finish', this)
|
||||||
this.cancelled = true
|
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
protected run(...args: any[]): void {
|
protected run(...args: any[]): void {
|
||||||
try {
|
try {
|
||||||
this.emit('before', this)
|
|
||||||
if (this.cancelled) { return }
|
|
||||||
this.func(...args)
|
this.func(...args)
|
||||||
this.emit('after', this)
|
!this.interval && process.emit('task.finish', this)
|
||||||
} catch (error: any) {
|
} catch (ex: any) {
|
||||||
try {
|
console.console('§4插件执行任务时发生错误', ex)
|
||||||
this.emit('error', error)
|
console.ex(ex)
|
||||||
} catch (ignore) {
|
|
||||||
console.console('§4插件执行任务时发生错误', error)
|
|
||||||
console.ex(error)
|
|
||||||
this.cancel()
|
|
||||||
}
|
|
||||||
} finally {
|
|
||||||
this.emit('finally', this)
|
|
||||||
if (!this.interval && !this.cancelled) { this.finish() }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected finish() {
|
|
||||||
process.emit('task.finish', this)
|
|
||||||
this.emit('finish', this)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 提交任务
|
* 提交任务
|
||||||
* @param args 任务参数
|
* @param args 任务参数
|
||||||
@@ -180,7 +161,7 @@ export namespace task {
|
|||||||
* 提交任务
|
* 提交任务
|
||||||
* @param args 任务参数
|
* @param args 任务参数
|
||||||
*/
|
*/
|
||||||
protected abstract submit0(...args: any[]): Cancelable
|
protected abstract submit0(...args: any[]): any
|
||||||
/**
|
/**
|
||||||
* 取消任务
|
* 取消任务
|
||||||
*/
|
*/
|
||||||
|
|||||||
3
packages/api/src/web.ts
Normal file
3
packages/api/src/web.ts
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
export namespace web {
|
||||||
|
export const Server = Symbol('Server')
|
||||||
|
}
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@ccms/bukkit",
|
"name": "@ccms/bukkit",
|
||||||
"version": "0.28.0-beta.4",
|
"version": "0.20.0-alpha.0",
|
||||||
"description": "MiaoScript bukkit package",
|
"description": "MiaoScript bukkit package",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"miaoscript",
|
"miaoscript",
|
||||||
@@ -12,21 +12,21 @@
|
|||||||
"homepage": "https://github.com/circlecloud/ms.git",
|
"homepage": "https://github.com/circlecloud/ms.git",
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"main": "dist/index.js",
|
"main": "dist/index.js",
|
||||||
"files": [
|
|
||||||
"dist"
|
|
||||||
],
|
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"clean": "rimraf dist",
|
"clean": "rimraf dist",
|
||||||
"watch": "tsc --watch",
|
"watch": "tsc --watch",
|
||||||
"build": "pnpm clean && tsc",
|
"build": "yarn clean && tsc",
|
||||||
"test": "echo \"Error: run tests from root\" && exit 1"
|
"test": "echo \"Error: run tests from root\" && exit 1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@javatypes/spigot-api": "^0.0.3"
|
"@javatypes/spigot-api": "^0.0.3",
|
||||||
|
"reflect-metadata": "^0.1.13",
|
||||||
|
"rimraf": "^3.0.2",
|
||||||
|
"typescript": "^4.5.5"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@ccms/api": "^0.28.0-beta.4",
|
"@ccms/api": "^0.20.0-alpha.0",
|
||||||
"@ccms/common": "^0.28.0-beta.4",
|
"@ccms/common": "^0.19.0",
|
||||||
"@ccms/container": "^0.28.0-beta.4"
|
"@ccms/container": "^0.19.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ import { event, plugin } from '@ccms/api'
|
|||||||
import { inject, provideSingleton } from '@ccms/container'
|
import { inject, provideSingleton } from '@ccms/container'
|
||||||
import * as reflect from '@ccms/common/dist/reflect'
|
import * as reflect from '@ccms/common/dist/reflect'
|
||||||
|
|
||||||
const URL = Java.type('java.net.URL')
|
|
||||||
const Bukkit = Java.type("org.bukkit.Bukkit")
|
const Bukkit = Java.type("org.bukkit.Bukkit")
|
||||||
const Event = Java.type("org.bukkit.event.Event")
|
const Event = Java.type("org.bukkit.event.Event")
|
||||||
const Modifier = Java.type("java.lang.reflect.Modifier")
|
const Modifier = Java.type("java.lang.reflect.Modifier")
|
||||||
@@ -20,15 +19,7 @@ export class BukkitEvent extends event.Event {
|
|||||||
}
|
}
|
||||||
|
|
||||||
getJarFile(resource: string) {
|
getJarFile(resource: string) {
|
||||||
try {
|
return super.getJarFile('org/bukkit/Bukkit.class', Bukkit.class.classLoader)
|
||||||
return super.getJarFile('org/bukkit/Bukkit.class', Bukkit.class.classLoader)
|
|
||||||
} catch (error) {
|
|
||||||
// 兼容 LoliServer 的 Bukkit 包无法获取的问题
|
|
||||||
let ModList = Java.type('net.minecraftforge.fml.ModList').get()
|
|
||||||
let forgeFile = ModList.getModFileById("forge").getFile().getFilePath()
|
|
||||||
let jarPath = `jar:file:${forgeFile}!/org/bukkit/Bukkit.class`
|
|
||||||
return new URL(jarPath).openConnection().jarFile
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
isValidEvent(clazz: any): boolean {
|
isValidEvent(clazz: any): boolean {
|
||||||
// 继承于 org.bukkit.event.Event
|
// 继承于 org.bukkit.event.Event
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ import { server } from '@ccms/api'
|
|||||||
import { Container } from '@ccms/container'
|
import { Container } from '@ccms/container'
|
||||||
|
|
||||||
import { BukkitConsole } from './console'
|
import { BukkitConsole } from './console'
|
||||||
import './item'
|
|
||||||
import './chat'
|
import './chat'
|
||||||
import './task'
|
import './task'
|
||||||
import './event'
|
import './event'
|
||||||
|
|||||||
@@ -6,14 +6,12 @@ let bukkitChatInvoke: BukkitChatInvoke
|
|||||||
abstract class BukkitChatInvoke {
|
abstract class BukkitChatInvoke {
|
||||||
private downgrade: boolean = false
|
private downgrade: boolean = false
|
||||||
protected RemapUtils: any
|
protected RemapUtils: any
|
||||||
protected ComponentSerializer: any
|
|
||||||
|
|
||||||
protected ChatSerializer: any
|
protected ChatSerializer: any
|
||||||
protected nmsChatSerializerMethodName: string
|
protected nmsChatSerializerMethodName: string
|
||||||
protected PacketPlayOutChat: any
|
protected PacketPlayOutChat: any
|
||||||
protected chatMessageTypes: any
|
protected chatMessageTypes: any
|
||||||
protected playerConnectionFieldName: string
|
protected playerConnectionFieldName: string
|
||||||
protected playerFieldName: string
|
|
||||||
protected sendPacketMethodName: string
|
protected sendPacketMethodName: string
|
||||||
|
|
||||||
constructor(private nmsVersion) {
|
constructor(private nmsVersion) {
|
||||||
@@ -22,12 +20,12 @@ abstract class BukkitChatInvoke {
|
|||||||
init() {
|
init() {
|
||||||
try {
|
try {
|
||||||
try {
|
try {
|
||||||
this.ComponentSerializer = Java.type('net.md_5.bungee.chat.ComponentSerializer')
|
|
||||||
this.RemapUtils = Java.type('catserver.server.remapper.RemapUtils')
|
this.RemapUtils = Java.type('catserver.server.remapper.RemapUtils')
|
||||||
} catch (ex: any) {
|
} catch (ex: any) {
|
||||||
}
|
}
|
||||||
let nmsChatSerializerClass = this.getNmsChatSerializerClass()
|
let nmsChatSerializerClass = this.getNmsChatSerializerClass()
|
||||||
this.nmsChatSerializerMethodName = this.getNmsChatSerializerMethodName(nmsChatSerializerClass)
|
let nmsChatSerializerMethod = this.remapMethod(nmsChatSerializerClass, 'a', 'func_150699_a', base.getClass('java.lang.String'))
|
||||||
|
this.nmsChatSerializerMethodName = nmsChatSerializerMethod.getName()
|
||||||
this.ChatSerializer = Java.type(nmsChatSerializerClass.getName())
|
this.ChatSerializer = Java.type(nmsChatSerializerClass.getName())
|
||||||
let packetTypeClass = this.getPacketPlayOutChatClass()
|
let packetTypeClass = this.getPacketPlayOutChatClass()
|
||||||
this.PacketPlayOutChat = Java.type(packetTypeClass.getName())
|
this.PacketPlayOutChat = Java.type(packetTypeClass.getName())
|
||||||
@@ -39,14 +37,12 @@ abstract class BukkitChatInvoke {
|
|||||||
if (nmsChatMessageTypeClass.isEnum()) {
|
if (nmsChatMessageTypeClass.isEnum()) {
|
||||||
this.chatMessageTypes = nmsChatMessageTypeClass.getEnumConstants()
|
this.chatMessageTypes = nmsChatMessageTypeClass.getEnumConstants()
|
||||||
break
|
break
|
||||||
} else if (nmsChatMessageTypeClass.getName() == 'int') {
|
|
||||||
break
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let playerConnectionField = this.getPlayerConnectionField()
|
let playerConnectionField = this.getPlayerConnectionField()
|
||||||
this.playerConnectionFieldName = playerConnectionField.getName()
|
this.playerConnectionFieldName = playerConnectionField.getName()
|
||||||
this.sendPacketMethodName = this.getSendPacketMethodName(playerConnectionField.getType())
|
this.sendPacketMethodName = this.remapMethod(playerConnectionField.getType(), 'sendPacket', 'func_179290_a', this.getPacketClass()).getName()
|
||||||
} catch (ex: any) {
|
} catch (ex: any) {
|
||||||
org.bukkit.Bukkit.getConsoleSender().sendMessage(`§6[§cMS§6][§bbukkit§6][§achat§6] §cNMS Inject Error §4${ex} §cDowngrade to Command Mode...`)
|
org.bukkit.Bukkit.getConsoleSender().sendMessage(`§6[§cMS§6][§bbukkit§6][§achat§6] §cNMS Inject Error §4${ex} §cDowngrade to Command Mode...`)
|
||||||
this.downgrade = true
|
this.downgrade = true
|
||||||
@@ -54,12 +50,10 @@ abstract class BukkitChatInvoke {
|
|||||||
}
|
}
|
||||||
|
|
||||||
abstract getNmsChatSerializerClass()
|
abstract getNmsChatSerializerClass()
|
||||||
abstract getNmsChatSerializerMethodName(nmsChatSerializerClass: any)
|
|
||||||
abstract getPacketPlayOutChatClass()
|
abstract getPacketPlayOutChatClass()
|
||||||
abstract getPacketPlayOutChat(sender: any, json: any, type: number)
|
abstract getPacketPlayOutChat(sender: any, json: any, type: number)
|
||||||
abstract getPlayerConnectionField()
|
abstract getPlayerConnectionField()
|
||||||
abstract getPacketClass()
|
abstract getPacketClass()
|
||||||
abstract getSendPacketMethodName(playerConnectionClass: any)
|
|
||||||
|
|
||||||
nmsCls(name: string) {
|
nmsCls(name: string) {
|
||||||
return base.getClass(['net.minecraft.server', this.nmsVersion, name].join('.'))
|
return base.getClass(['net.minecraft.server', this.nmsVersion, name].join('.'))
|
||||||
@@ -89,9 +83,9 @@ abstract class BukkitChatInvoke {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
json(sender: any, json: string) {
|
json(sender: { name: string }, json: string) {
|
||||||
if (this.downgrade) {
|
if (this.downgrade) {
|
||||||
return sender.spigot().sendMessage(this.ComponentSerializer.parse(json))
|
return '/tellraw ' + sender.name + ' ' + json
|
||||||
} else {
|
} else {
|
||||||
this.send(sender, json, 0)
|
this.send(sender, json, 0)
|
||||||
return false
|
return false
|
||||||
@@ -106,13 +100,6 @@ abstract class BukkitChatInvoke {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class BukkitChatInvokeBase extends BukkitChatInvoke {
|
class BukkitChatInvokeBase extends BukkitChatInvoke {
|
||||||
getSendPacketMethodName(playerConnectionClass: any) {
|
|
||||||
return this.remapMethod(playerConnectionClass, 'sendPacket', 'func_179290_a', this.getPacketClass()).getName()
|
|
||||||
}
|
|
||||||
getNmsChatSerializerMethodName(nmsChatSerializerClass: any) {
|
|
||||||
let nmsChatSerializerMethod = this.remapMethod(nmsChatSerializerClass, 'a', 'func_150699_a', base.getClass('java.lang.String'))
|
|
||||||
return nmsChatSerializerMethod.getName()
|
|
||||||
}
|
|
||||||
getPacketPlayOutChat(sender: any, json: any, type: number) {
|
getPacketPlayOutChat(sender: any, json: any, type: number) {
|
||||||
return new this.PacketPlayOutChat(this.ChatSerializer[this.nmsChatSerializerMethodName](json), type)
|
return new this.PacketPlayOutChat(this.ChatSerializer[this.nmsChatSerializerMethodName](json), type)
|
||||||
}
|
}
|
||||||
@@ -161,35 +148,18 @@ class BukkitChatInvoke_1_17_1 extends BukkitChatInvoke_1_16_5 {
|
|||||||
return base.getClass('net.minecraft.network.protocol.Packet')
|
return base.getClass('net.minecraft.network.protocol.Packet')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
class BukkitChatInvoke_1_18_2 extends BukkitChatInvoke_1_17_1 {
|
|
||||||
getSendPacketMethodName(playerConnectionClass: any) {
|
|
||||||
return playerConnectionClass.getMethod('a', this.getPacketClass()).getName()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
class BukkitChatInvoke_1_19 extends BukkitChatInvoke_1_18_2 {
|
|
||||||
getPacketPlayOutChatClass() {
|
|
||||||
return base.getClass('net.minecraft.network.protocol.game.ClientboundSystemChatPacket')
|
|
||||||
}
|
|
||||||
getPacketPlayOutChat(sender: any, json: any, type: number) {
|
|
||||||
return new this.PacketPlayOutChat(this.ChatSerializer[this.nmsChatSerializerMethodName](json), type)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
let Bukkit: typeof org.bukkit.Bukkit = Java.type('org.bukkit.Bukkit')
|
let Bukkit: typeof org.bukkit.Bukkit = Java.type('org.bukkit.Bukkit')
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
let nmsVersion = Bukkit.getServer().class.name.split('.')[3]
|
let nmsVersion = Bukkit.getServer().class.name.split('.')[3]
|
||||||
let nmsSubVersion = nmsVersion.split("_")[1]
|
let nmsSubVersion = nmsVersion.split("_")[1]
|
||||||
if (nmsSubVersion >= 19) {
|
if (nmsSubVersion >= 8) {
|
||||||
bukkitChatInvoke = new BukkitChatInvoke_1_19(nmsVersion)
|
bukkitChatInvoke = new BukkitChatInvoke_1_8(nmsVersion)
|
||||||
} else if (nmsSubVersion >= 18) {
|
|
||||||
bukkitChatInvoke = new BukkitChatInvoke_1_18_2(nmsVersion)
|
|
||||||
} else if (nmsSubVersion >= 17) {
|
|
||||||
bukkitChatInvoke = new BukkitChatInvoke_1_17_1(nmsVersion)
|
|
||||||
} else if (nmsSubVersion >= 16) {
|
} else if (nmsSubVersion >= 16) {
|
||||||
bukkitChatInvoke = new BukkitChatInvoke_1_16_5(nmsVersion)
|
bukkitChatInvoke = new BukkitChatInvoke_1_16_5(nmsVersion)
|
||||||
} else if (nmsSubVersion >= 8) {
|
} else if (nmsSubVersion >= 17) {
|
||||||
bukkitChatInvoke = new BukkitChatInvoke_1_8(nmsVersion)
|
bukkitChatInvoke = new BukkitChatInvoke_1_17_1(nmsVersion)
|
||||||
} else {
|
} else {
|
||||||
bukkitChatInvoke = new BukkitChatInvoke_1_7_10(nmsVersion)
|
bukkitChatInvoke = new BukkitChatInvoke_1_7_10(nmsVersion)
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -1,128 +0,0 @@
|
|||||||
import { item } from "@ccms/api"
|
|
||||||
import { provideSingleton } from "@ccms/container"
|
|
||||||
|
|
||||||
import { itemIds } from './internal/item'
|
|
||||||
|
|
||||||
const Material: typeof org.bukkit.Material = Java.type('org.bukkit.Material')
|
|
||||||
const ItemStack: typeof org.bukkit.inventory.ItemStack = Java.type('org.bukkit.inventory.ItemStack')
|
|
||||||
|
|
||||||
@provideSingleton(item.Item)
|
|
||||||
export class BukkitItem extends item.Item {
|
|
||||||
private CraftItemStack: any
|
|
||||||
private NBTTagCompound: any
|
|
||||||
private nmsSaveNBTMethodName: any
|
|
||||||
private MojangsonParser: any
|
|
||||||
private nmsItemStack: any
|
|
||||||
private mpParseMethodName: any
|
|
||||||
private nmsVersion: any
|
|
||||||
constructor() {
|
|
||||||
super()
|
|
||||||
this.reflect()
|
|
||||||
}
|
|
||||||
builder(): item.ItemBuilder {
|
|
||||||
return new BukkitItemBuilder()
|
|
||||||
}
|
|
||||||
toJson(item: any): string {
|
|
||||||
let nbt = new this.NBTTagCompound()
|
|
||||||
return this.CraftItemStack.asNMSCopy(item)[this.nmsSaveNBTMethodName](nbt).toString()
|
|
||||||
}
|
|
||||||
fromJson(json: string) {
|
|
||||||
return this.CraftItemStack.asBukkitCopy(new this.nmsItemStack(this.MojangsonParser[this.mpParseMethodName](json)))
|
|
||||||
}
|
|
||||||
private obcCls(name: string) {
|
|
||||||
return base.getClass(['org.bukkit.craftbukkit', this.nmsVersion, name].join('.'))
|
|
||||||
}
|
|
||||||
private nmsCls(name: string) {
|
|
||||||
return base.getClass(['net.minecraft.server', this.nmsVersion, name].join('.'))
|
|
||||||
}
|
|
||||||
private reflect() {
|
|
||||||
try {
|
|
||||||
let Bukkit: typeof org.bukkit.Bukkit = Java.type('org.bukkit.Bukkit')
|
|
||||||
// @ts-ignore
|
|
||||||
this.nmsVersion = Bukkit.getServer().class.name.split('.')[3]
|
|
||||||
let CraftItemStackClass = this.obcCls('inventory.CraftItemStack')
|
|
||||||
this.CraftItemStack = Java.type(CraftItemStackClass.getName())
|
|
||||||
// @ts-ignore
|
|
||||||
let asNMSCopyMethod = CraftItemStackClass.getMethod('asNMSCopy', ItemStack.class)
|
|
||||||
let nmsItemStackClass = asNMSCopyMethod.getReturnType()
|
|
||||||
this.nmsItemStack = Java.type(nmsItemStackClass.getName())
|
|
||||||
let nmsNBTTagCompoundClass = undefined
|
|
||||||
for (let method of Java.from(nmsItemStackClass.getMethods())) {
|
|
||||||
let rt = method.getReturnType()
|
|
||||||
if (method.getParameterTypes().length == 0 && "NBTTagCompound" == rt.getSimpleName()) {
|
|
||||||
nmsNBTTagCompoundClass = rt
|
|
||||||
}
|
|
||||||
}
|
|
||||||
this.NBTTagCompound = Java.type(nmsNBTTagCompoundClass.getName())
|
|
||||||
for (let method of Java.from(nmsItemStackClass.getMethods())) {
|
|
||||||
let params = method.getParameterTypes()
|
|
||||||
let rt = method.getReturnType()
|
|
||||||
if (params.length == 1 && "NBTTagCompound" == params[0].getSimpleName() && "NBTTagCompound" == rt.getSimpleName()) {
|
|
||||||
this.nmsSaveNBTMethodName = method.getName()
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
this.MojangsonParser = this.nmsCls('MojangsonParser').static
|
|
||||||
} catch (error) {
|
|
||||||
this.MojangsonParser = Java.type('net.minecraft.nbt.MojangsonParser')
|
|
||||||
}
|
|
||||||
for (let method of Java.from(this.MojangsonParser.class.getMethods())) {
|
|
||||||
let params = method.getParameterTypes()
|
|
||||||
let rt = method.getReturnType()
|
|
||||||
if (params.length == 1 && "String" == params[0].getSimpleName() && "NBTTagCompound" == rt.getSimpleName()) {
|
|
||||||
this.mpParseMethodName = method.getName()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (error: any) {
|
|
||||||
console.log('Bukkit 物品管理器初始化失败:', error)
|
|
||||||
if (global.debug) {
|
|
||||||
console.ex(error)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export class BukkitItemBuilder implements item.ItemBuilder {
|
|
||||||
private itemStack: org.bukkit.inventory.ItemStack
|
|
||||||
private itemMeta: org.bukkit.inventory.meta.ItemMeta
|
|
||||||
|
|
||||||
from(itemStack: any): item.ItemBuilder {
|
|
||||||
this.itemStack = itemStack
|
|
||||||
this.itemMeta = this.itemStack.getItemMeta()
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
create(type: string | number): item.ItemBuilder {
|
|
||||||
let material = undefined
|
|
||||||
if (typeof type == 'number') {
|
|
||||||
type = itemIds[type]
|
|
||||||
}
|
|
||||||
material = Material[type] || Material[Material['LEGACY_PREFIX'] + type]
|
|
||||||
this.itemStack = new ItemStack(material)
|
|
||||||
this.itemMeta = this.itemStack.getItemMeta()
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
name(name: string): item.ItemBuilder {
|
|
||||||
this.itemMeta.setDisplayName(name)
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
lore(...lores: string[]): item.ItemBuilder {
|
|
||||||
this.itemMeta.setLore(lores)
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
amount(amount: number): item.ItemBuilder {
|
|
||||||
this.itemStack.setAmount(amount)
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
durability(durability: number): item.ItemBuilder {
|
|
||||||
this.itemStack.setDurability(durability)
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
clone() {
|
|
||||||
return this.build().clone()
|
|
||||||
}
|
|
||||||
build() {
|
|
||||||
this.itemStack.setItemMeta(this.itemMeta)
|
|
||||||
return this.itemStack
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -3,11 +3,20 @@ import { particle } from '@ccms/api'
|
|||||||
|
|
||||||
@provideSingleton(particle.ParticleManager)
|
@provideSingleton(particle.ParticleManager)
|
||||||
export class BukkitParticleManager extends particle.ParticleManager {
|
export class BukkitParticleManager extends particle.ParticleManager {
|
||||||
|
private globalSpawner = new BukkitParticleSpawner()
|
||||||
|
constructor() {
|
||||||
|
super()
|
||||||
|
particle.ParticleManager.globalSpawner = this.globalSpawner
|
||||||
|
}
|
||||||
|
protected getGlobalSpawner() {
|
||||||
|
return this.globalSpawner
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@provideSingleton(particle.ParticleSpawner)
|
|
||||||
export class BukkitParticleSpawner extends particle.ParticleSpawner {
|
export class BukkitParticleSpawner extends particle.ParticleSpawner {
|
||||||
spawn(location: org.bukkit.Location, particle: particle.Particle) {
|
spawnParticle(location: any, particle: any, count: number = 1) {
|
||||||
|
location.getWorld().spawnParticle(particle, location, count)
|
||||||
|
}
|
||||||
|
spawn(location: any, particle: particle.Particle) {
|
||||||
location.getWorld().spawnParticle(
|
location.getWorld().spawnParticle(
|
||||||
particle.getParticle(),
|
particle.getParticle(),
|
||||||
location,
|
location,
|
||||||
@@ -19,15 +28,4 @@ export class BukkitParticleSpawner extends particle.ParticleSpawner {
|
|||||||
particle.getData()
|
particle.getData()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
spawnToPlayer(player: org.bukkit.entity.Player, location: org.bukkit.Location, particle: particle.Particle) {
|
|
||||||
player.spawnParticle(
|
|
||||||
particle.getParticle(),
|
|
||||||
location,
|
|
||||||
particle.getCount(),
|
|
||||||
particle.getOffsetX(),
|
|
||||||
particle.getOffsetY(),
|
|
||||||
particle.getOffsetZ(),
|
|
||||||
particle.getExtra(),
|
|
||||||
particle.getData())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,6 @@
|
|||||||
"extends": "../../tsconfig.json",
|
"extends": "../../tsconfig.json",
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"baseUrl": "src",
|
"baseUrl": "src",
|
||||||
"outDir": "dist",
|
"outDir": "dist"
|
||||||
"resolveJsonModule": true
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@ccms/bungee",
|
"name": "@ccms/bungee",
|
||||||
"version": "0.28.0-beta.4",
|
"version": "0.20.0-alpha.0",
|
||||||
"description": "MiaoScript bungee package",
|
"description": "MiaoScript bungee package",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"miaoscript",
|
"miaoscript",
|
||||||
@@ -12,21 +12,21 @@
|
|||||||
"homepage": "https://github.com/circlecloud/ms.git",
|
"homepage": "https://github.com/circlecloud/ms.git",
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"main": "dist/index.js",
|
"main": "dist/index.js",
|
||||||
"files": [
|
|
||||||
"dist"
|
|
||||||
],
|
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"clean": "rimraf dist",
|
"clean": "rimraf dist",
|
||||||
"watch": "tsc --watch",
|
"watch": "tsc --watch",
|
||||||
"build": "pnpm clean && tsc",
|
"build": "yarn clean && tsc",
|
||||||
"test": "echo \"Error: run tests from root\" && exit 1"
|
"test": "echo \"Error: run tests from root\" && exit 1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@javatypes/bungee-api": "^0.0.3"
|
"@javatypes/bungee-api": "^0.0.3",
|
||||||
|
"reflect-metadata": "^0.1.13",
|
||||||
|
"rimraf": "^3.0.2",
|
||||||
|
"typescript": "^4.5.5"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@ccms/api": "^0.28.0-beta.4",
|
"@ccms/api": "^0.20.0-alpha.0",
|
||||||
"@ccms/common": "^0.28.0-beta.4",
|
"@ccms/common": "^0.19.0",
|
||||||
"@ccms/container": "^0.28.0-beta.4"
|
"@ccms/container": "^0.19.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
1
packages/client/.gitignore
vendored
Normal file
1
packages/client/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
src/emp.ts
|
||||||
1
packages/client/.npmignore
Symbolic link
1
packages/client/.npmignore
Symbolic link
@@ -0,0 +1 @@
|
|||||||
|
../../.npmignore
|
||||||
37
packages/client/package.json
Normal file
37
packages/client/package.json
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
{
|
||||||
|
"private": true,
|
||||||
|
"name": "@ccms/client",
|
||||||
|
"version": "0.19.0",
|
||||||
|
"description": "MiaoScript client package",
|
||||||
|
"keywords": [
|
||||||
|
"miaoscript",
|
||||||
|
"minecraft",
|
||||||
|
"bukkit",
|
||||||
|
"sponge"
|
||||||
|
],
|
||||||
|
"author": "MiaoWoo <admin@yumc.pw>",
|
||||||
|
"homepage": "https://github.com/circlecloud/ms.git",
|
||||||
|
"license": "ISC",
|
||||||
|
"main": "dist/index.js",
|
||||||
|
"scripts": {
|
||||||
|
"dev": "ts-node-dev --respawn --debounce=1500 src/index.ts",
|
||||||
|
"clean": "rimraf dist",
|
||||||
|
"watch": "tsc --watch",
|
||||||
|
"build": "yarn clean && tsc",
|
||||||
|
"start": "node dist/index.js",
|
||||||
|
"debug": "DEBUG=minecraft-protocol node dist/index.js",
|
||||||
|
"emp": "node dist/emp.js",
|
||||||
|
"test": "echo \"Error: run tests from root\" && exit 1"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"axios": "^0.25.0",
|
||||||
|
"minecraft-protocol": "^1.30.0",
|
||||||
|
"minecraft-protocol-forge": "^1.0.0",
|
||||||
|
"proxy-agent": "^5.0.0"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@types/node": "^17.0.17",
|
||||||
|
"rimraf": "^3.0.2",
|
||||||
|
"typescript": "^4.5.5"
|
||||||
|
}
|
||||||
|
}
|
||||||
101
packages/client/src/color.ts
Normal file
101
packages/client/src/color.ts
Normal file
@@ -0,0 +1,101 @@
|
|||||||
|
class MessagePart {
|
||||||
|
text: string
|
||||||
|
color: string
|
||||||
|
clickEvent: MessagePartEvent
|
||||||
|
hoverEvent: MessagePartEvent
|
||||||
|
translate: string
|
||||||
|
with: MessagePart[]
|
||||||
|
extra: MessagePart[]
|
||||||
|
}
|
||||||
|
|
||||||
|
class MessagePartEvent {
|
||||||
|
action: string
|
||||||
|
value: string
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
let jsonColorMap = {
|
||||||
|
"black": '0',
|
||||||
|
"dark_blue": '1',
|
||||||
|
"dark_green": '2',
|
||||||
|
"dark_aqua": '3',
|
||||||
|
"dark_red": '4',
|
||||||
|
"dark_purple": '5',
|
||||||
|
"gold": '6',
|
||||||
|
"gray": '7',
|
||||||
|
"dark_gray": '8',
|
||||||
|
"blue": '9',
|
||||||
|
"green": 'a',
|
||||||
|
"aqua": 'b',
|
||||||
|
"red": 'c',
|
||||||
|
"light_purple": 'd',
|
||||||
|
"yellow": 'e',
|
||||||
|
"white": 'f',
|
||||||
|
"obfuscated": 'k',
|
||||||
|
"bold": 'l',
|
||||||
|
"strikethrough": 'm',
|
||||||
|
"underline": 'n',
|
||||||
|
"italic": 'o',
|
||||||
|
"reset": 'r',
|
||||||
|
};
|
||||||
|
|
||||||
|
function json2text(json: MessagePart): string {
|
||||||
|
let temp = "";
|
||||||
|
if (json.color) {
|
||||||
|
temp += `§${jsonColorMap[json.color]}`
|
||||||
|
}
|
||||||
|
temp += json.text || json.translate || ''
|
||||||
|
if (json.extra) {
|
||||||
|
json.extra.forEach((ext) => {
|
||||||
|
temp += json2text(ext)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return temp += '§r'
|
||||||
|
}
|
||||||
|
|
||||||
|
function $(input: any) {
|
||||||
|
if (typeof input === "string") {
|
||||||
|
input = JSON.parse(input)
|
||||||
|
}
|
||||||
|
input = json2text(input) + '§r'
|
||||||
|
if (input.startsWith('§卐')) {
|
||||||
|
input = input.substring(2)
|
||||||
|
}
|
||||||
|
return mcColor2ANSI(input)
|
||||||
|
}
|
||||||
|
|
||||||
|
export {
|
||||||
|
json2text,
|
||||||
|
mcColor2ANSI,
|
||||||
|
$
|
||||||
|
}
|
||||||
33
packages/client/src/event.ts
Normal file
33
packages/client/src/event.ts
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
import { $ } from './color'
|
||||||
|
|
||||||
|
export function attachEvents(client) {
|
||||||
|
client.on('chat', (packet) => {
|
||||||
|
// Listen for chat messages and echo them back.
|
||||||
|
var jsonMsg = JSON.parse(packet.message)
|
||||||
|
console.log($(jsonMsg))
|
||||||
|
})
|
||||||
|
client.on('state', (newState, oldState) => {
|
||||||
|
console.log('Client Change State', oldState, 'to', newState)
|
||||||
|
let targetServer = process.argv[6]
|
||||||
|
if (newState == "play" && targetServer) {
|
||||||
|
setTimeout(() => {
|
||||||
|
client.write('chat', {
|
||||||
|
message: '/server ' + targetServer
|
||||||
|
})
|
||||||
|
}, 3000)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
client.on('update_health', (packet) => {
|
||||||
|
if (packet.health <= 0) {
|
||||||
|
console.log("Player Dead Auto Respawn...")
|
||||||
|
client.write('client_command', { payload: 0 })
|
||||||
|
} else if (packet.health > 0) {
|
||||||
|
}
|
||||||
|
})
|
||||||
|
client.on('kick_disconnect', (packet) => {
|
||||||
|
console.log($(packet.reason))
|
||||||
|
})
|
||||||
|
client.on('disconnect', (packet) => {
|
||||||
|
console.log($(packet.reason))
|
||||||
|
})
|
||||||
|
}
|
||||||
14
packages/client/src/forge.ts
Normal file
14
packages/client/src/forge.ts
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
export function attachForge(client) {
|
||||||
|
client.on('custom_payload', function(packet) {
|
||||||
|
if (packet.channel === 'FML|HS') {
|
||||||
|
client.write('custom_payload', {
|
||||||
|
channel: 'FML|HS',
|
||||||
|
data: Buffer.of(0x01, 0x02)
|
||||||
|
});
|
||||||
|
client.write('custom_payload', {
|
||||||
|
channel: 'FML|HS',
|
||||||
|
data: Buffer.of(0x02, 0x00)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
124
packages/client/src/index.ts
Normal file
124
packages/client/src/index.ts
Normal file
@@ -0,0 +1,124 @@
|
|||||||
|
import { createInterface } from 'readline'
|
||||||
|
import { Client, createClient } from 'minecraft-protocol'
|
||||||
|
|
||||||
|
import { attachForge } from './forge'
|
||||||
|
import { attachEvents } from './event'
|
||||||
|
|
||||||
|
let readUserInfo = process.argv[2] || 'Mr_jtb'
|
||||||
|
let realUserInfo = readUserInfo.split(":")
|
||||||
|
let username = realUserInfo[0]
|
||||||
|
let password = realUserInfo[1] || ''
|
||||||
|
let version = process.argv[3] || '1.12.2'
|
||||||
|
let readAddress = process.argv[4] || '192.168.2.25:25565'
|
||||||
|
let realAddress = readAddress.split(":")
|
||||||
|
let address = realAddress[0]
|
||||||
|
let port = parseInt(realAddress[1] || "25565")
|
||||||
|
let client = commandLineCreateClient()
|
||||||
|
|
||||||
|
function commandLineCreateClient() {
|
||||||
|
return createConnection(address, port, username, password)
|
||||||
|
}
|
||||||
|
|
||||||
|
function createConnection(host: string, port: number, username: string, password: string) {
|
||||||
|
let clientOptions: any = {
|
||||||
|
version,
|
||||||
|
host,
|
||||||
|
port,
|
||||||
|
username,
|
||||||
|
password,
|
||||||
|
// clientToken: 'd02c7f39-2376-45da-a5a5-50e24fa8b185',
|
||||||
|
//@ts-ignore
|
||||||
|
// authServer: 'https://skin.yumc.pw/api/yggdrasil/authserver',
|
||||||
|
// sessionServer: 'https://skin.yumc.pw/api/yggdrasil/sessionserver'
|
||||||
|
}
|
||||||
|
if (clientOptions.password) {
|
||||||
|
clientOptions.clientToken = 'd02c7f39-2376-45da-a5a5-50e24fa8b185'
|
||||||
|
clientOptions.authServer = 'https://skin.yumc.pw/api/yggdrasil/authserver'
|
||||||
|
clientOptions.sessionServer = 'https://skin.yumc.pw/api/yggdrasil/sessionserver'
|
||||||
|
}
|
||||||
|
let client = createClient(clientOptions)
|
||||||
|
|
||||||
|
attachCommon(client)
|
||||||
|
attachForge(client)
|
||||||
|
attachEvents(client)
|
||||||
|
return client
|
||||||
|
}
|
||||||
|
|
||||||
|
function attachCommon(client: Client) {
|
||||||
|
client.on('login', () => {
|
||||||
|
// client.registerChannel('updater', ['string', []])
|
||||||
|
// client.registerChannel('updater-enabled', ['string', []])
|
||||||
|
// client.registerChannel('dragoncore', ['string', []])
|
||||||
|
// client.registerChannel('dragoncore:main', ['string', []])
|
||||||
|
client.on('REGISTER', (array) => {
|
||||||
|
for (const channel of array) {
|
||||||
|
client.on('channel', console.log)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
// client.on('dragoncore:main', (data) => {
|
||||||
|
// console.log(data)
|
||||||
|
// })
|
||||||
|
})
|
||||||
|
client.on('custom_payload', (data) => {
|
||||||
|
console.log('custom_payload' + JSON.stringify(data))
|
||||||
|
})
|
||||||
|
client.on('error', (error) => {
|
||||||
|
console.log("Client Error", error)
|
||||||
|
})
|
||||||
|
client.on('end', (resone) => {
|
||||||
|
console.log("Client End Resone:", resone)
|
||||||
|
if (`${resone}` != "SocketClosed") {
|
||||||
|
setTimeout(() => {
|
||||||
|
client = commandLineCreateClient()
|
||||||
|
}, 500)
|
||||||
|
} else {
|
||||||
|
process.exit(0)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const rl = createInterface({
|
||||||
|
input: process.stdin,
|
||||||
|
output: process.stdout,
|
||||||
|
completer: (line, func) => {
|
||||||
|
let args = line.split(' ')
|
||||||
|
let comp = args[args.length - 1]
|
||||||
|
client.once('tab_complete', (msg) => {
|
||||||
|
let mcts = msg.matches.filter(s => s)
|
||||||
|
func(null, [mcts, comp])
|
||||||
|
})
|
||||||
|
client.write('tab_complete', {
|
||||||
|
text: line
|
||||||
|
})
|
||||||
|
},
|
||||||
|
terminal: true,
|
||||||
|
prompt: ''
|
||||||
|
})
|
||||||
|
|
||||||
|
rl.on('line', function (line) {
|
||||||
|
switch (line) {
|
||||||
|
case "":
|
||||||
|
break
|
||||||
|
case "eval":
|
||||||
|
break
|
||||||
|
case "write":
|
||||||
|
break
|
||||||
|
case "/respawn":
|
||||||
|
client.write('client_command', { payload: 0 })
|
||||||
|
break
|
||||||
|
case "//reco":
|
||||||
|
client.end("")
|
||||||
|
client = commandLineCreateClient()
|
||||||
|
break
|
||||||
|
case "//quit":
|
||||||
|
console.info('Disconnected')
|
||||||
|
client.end("")
|
||||||
|
break
|
||||||
|
case "//end":
|
||||||
|
console.info('Forcibly ended client')
|
||||||
|
process.exit(0)
|
||||||
|
default:
|
||||||
|
client.write('chat', { message: line })
|
||||||
|
}
|
||||||
|
rl.prompt()
|
||||||
|
})
|
||||||
5
packages/client/start.sh
Executable file
5
packages/client/start.sh
Executable file
@@ -0,0 +1,5 @@
|
|||||||
|
while :; do
|
||||||
|
yarn emp
|
||||||
|
echo 进程退出 休眠120秒!
|
||||||
|
sleep 120
|
||||||
|
done
|
||||||
7
packages/client/tsconfig.json
Normal file
7
packages/client/tsconfig.json
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"extends": "../../tsconfig.json",
|
||||||
|
"compilerOptions": {
|
||||||
|
"baseUrl": "src",
|
||||||
|
"outDir": "dist"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "@ccms/common",
|
"name": "@ccms/common",
|
||||||
"version": "0.28.0-beta.4",
|
"version": "0.19.0",
|
||||||
"description": "MiaoScript common package",
|
"description": "MiaoScript api package",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"miaoscript",
|
"miaoscript",
|
||||||
"minecraft",
|
"minecraft",
|
||||||
@@ -12,18 +12,18 @@
|
|||||||
"homepage": "https://github.com/circlecloud/ms.git",
|
"homepage": "https://github.com/circlecloud/ms.git",
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"main": "dist/index.js",
|
"main": "dist/index.js",
|
||||||
"files": [
|
|
||||||
"dist"
|
|
||||||
],
|
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"clean": "rimraf dist",
|
"clean": "rimraf dist",
|
||||||
"watch": "tsc --watch",
|
"watch": "tsc --watch",
|
||||||
"build": "pnpm clean && tsc",
|
"build": "yarn clean && tsc",
|
||||||
"test": "echo \"Error: run tests from root\" && exit 1"
|
"test": "echo \"Error: run tests from root\" && exit 1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@ccms/nashorn": "^0.28.0-beta.4",
|
"@ccms/nashorn": "^0.19.0",
|
||||||
"@javatypes/jdk": "^0.0.3"
|
"@javatypes/jdk": "^0.0.3",
|
||||||
|
"reflect-metadata": "^0.1.13",
|
||||||
|
"rimraf": "^3.0.2",
|
||||||
|
"typescript": "^4.5.5"
|
||||||
},
|
},
|
||||||
"gitHead": "562e2d00175c9d3a99c8b672aa07e6d92706a027"
|
"gitHead": "562e2d00175c9d3a99c8b672aa07e6d92706a027"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,20 +19,12 @@ interface RequestConfig {
|
|||||||
method?: Method
|
method?: Method
|
||||||
headers?: { [key: string]: string }
|
headers?: { [key: string]: string }
|
||||||
params?: { [key: string]: string }
|
params?: { [key: string]: string }
|
||||||
data?: any,
|
data?: any
|
||||||
connectTimeout?: number,
|
|
||||||
readTimeout?: number,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function request(config: RequestConfig) {
|
function request(config: RequestConfig) {
|
||||||
// @ts-ignore XMLHttpRequest class only exist nashorn polyfill
|
// @ts-ignore XMLHttpRequest class only exist nashorn polyfill
|
||||||
let xhr = new XMLHttpRequest()
|
let xhr = new XMLHttpRequest()
|
||||||
if (config.connectTimeout) {
|
|
||||||
xhr.connectTimeout = config.connectTimeout
|
|
||||||
}
|
|
||||||
if (config.readTimeout) {
|
|
||||||
xhr.readTimeout = config.readTimeout
|
|
||||||
}
|
|
||||||
xhr.open(config.method, config.url, false)
|
xhr.open(config.method, config.url, false)
|
||||||
for (const header in config.headers) {
|
for (const header in config.headers) {
|
||||||
xhr.setRequestHeader(header, config.headers[header])
|
xhr.setRequestHeader(header, config.headers[header])
|
||||||
|
|||||||
@@ -54,7 +54,6 @@ class Reflect {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!field) throw new Error(`can't reflect field ${typeof nameOrIndex == "number" ? 'index' : 'name'} ${nameOrIndex} from ${this.class.getName()}!`)
|
if (!field) throw new Error(`can't reflect field ${typeof nameOrIndex == "number" ? 'index' : 'name'} ${nameOrIndex} from ${this.class.getName()}!`)
|
||||||
fieldCache.set(key, field)
|
|
||||||
return accessible(field)
|
return accessible(field)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -130,14 +129,12 @@ function declaredField(clazz: java.lang.Class<any>, name: string | java.lang.Str
|
|||||||
let field = null
|
let field = null
|
||||||
// noinspection JSUnresolvedVariable
|
// noinspection JSUnresolvedVariable
|
||||||
while (target !== JavaObject.class) {
|
while (target !== JavaObject.class) {
|
||||||
console.debug(`reflect field ${name} from ${target.getName()}`)
|
|
||||||
try {
|
try {
|
||||||
field = target.getDeclaredField(name)
|
field = target.getDeclaredField(name)
|
||||||
if (field !== null) { break }
|
if (field !== null) { break }
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
if (target === undefined) { break }
|
if (target === undefined) { break }
|
||||||
target = target.getSuperclass()
|
target = target.getSuperclass()
|
||||||
console.debug(`switch to super class: ${target.getName()}`)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (field === null) {
|
if (field === null) {
|
||||||
@@ -149,32 +146,21 @@ function declaredField(clazz: java.lang.Class<any>, name: string | java.lang.Str
|
|||||||
function declaredMethod(clazz: java.lang.Class<any>, nameOrIndex: string | number, ...clazzs: java.lang.Class<any>[]): java.lang.reflect.Method {
|
function declaredMethod(clazz: java.lang.Class<any>, nameOrIndex: string | number, ...clazzs: java.lang.Class<any>[]): java.lang.reflect.Method {
|
||||||
let key = clazz.getName() + '.' + nameOrIndex + ':' + (clazzs || []).map(c => c.getName()).join(':')
|
let key = clazz.getName() + '.' + nameOrIndex + ':' + (clazzs || []).map(c => c.getName()).join(':')
|
||||||
if (methodCache.has(key)) { return methodCache.get(key) }
|
if (methodCache.has(key)) { return methodCache.get(key) }
|
||||||
let target = clazz
|
|
||||||
if (typeof nameOrIndex === "number") {
|
if (typeof nameOrIndex === "number") {
|
||||||
methodCache.set(key, declaredMethods(clazz)[nameOrIndex])
|
methodCache.set(key, declaredMethods(clazz)[nameOrIndex])
|
||||||
} else {
|
} else {
|
||||||
while (target !== JavaObject.class && !methodCache.has(key)) {
|
try {
|
||||||
|
methodCache.set(key, clazz.getMethod(nameOrIndex, clazzs as any))
|
||||||
|
} catch (ex: any) {
|
||||||
try {
|
try {
|
||||||
console.debug(`reflect method ${typeof nameOrIndex == "number" ? 'index' : 'name'} ${nameOrIndex} from ${target.getName()}`)
|
methodCache.set(key, clazz.getDeclaredMethod(nameOrIndex, clazzs as any))
|
||||||
try {
|
} catch (ex: any) {
|
||||||
methodCache.set(key, target.getMethod(nameOrIndex, clazzs as any))
|
for (const m of Java.from(declaredMethods(clazz))) {
|
||||||
} catch (ex: any) {
|
if (m.getName() == nameOrIndex) {
|
||||||
try {
|
methodCache.set(key, m)
|
||||||
methodCache.set(key, target.getDeclaredMethod(nameOrIndex, clazzs as any))
|
break
|
||||||
} catch (ex: any) {
|
|
||||||
for (const m of Java.from(declaredMethods(target))) {
|
|
||||||
if (m.getName() == nameOrIndex) {
|
|
||||||
methodCache.set(key, m)
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
throw new Error(`method ${typeof nameOrIndex == "number" ? 'index' : 'name'} ${nameOrIndex} not found.`)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (error) {
|
|
||||||
if (target === undefined) { break }
|
|
||||||
target = target.getSuperclass()
|
|
||||||
console.debug(`switch to super class: ${target.getName()}`)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -187,7 +173,7 @@ function declaredMethods(clazz: java.lang.Class<any>) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function mapToObject(javaObj) {
|
function mapToObject(javaObj) {
|
||||||
if (!Java.isJavaObject(javaObj)) { throw new TypeError(`argument ${javaObj} is not a java object.`) }
|
if (!Java.isJavaObject(javaObj)) { throw new TypeError(`参数 ${javaObj} 不是一个Java对象!`) }
|
||||||
let target = Proxy.newProxy(javaObj, {
|
let target = Proxy.newProxy(javaObj, {
|
||||||
apply: (target, name, args) => { return args ? javaObj[name](args) : javaObj[name]() }
|
apply: (target, name, args) => { return args ? javaObj[name](args) : javaObj[name]() }
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -17,14 +17,14 @@ class ChatMessagePart {
|
|||||||
}
|
}
|
||||||
|
|
||||||
convert() {
|
convert() {
|
||||||
return this.internal
|
return this.internal;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class Tellraw {
|
class Tellraw {
|
||||||
static duplicateChar = '§卐'
|
static duplicateChar = '§卐'
|
||||||
static create() {
|
static create() {
|
||||||
return new Tellraw().then(Tellraw.duplicateChar)
|
return new Tellraw().then(Tellraw.duplicateChar);
|
||||||
}
|
}
|
||||||
|
|
||||||
private cache: string = '';
|
private cache: string = '';
|
||||||
@@ -32,81 +32,77 @@ class Tellraw {
|
|||||||
|
|
||||||
then(part: ChatMessagePart | string) {
|
then(part: ChatMessagePart | string) {
|
||||||
if (typeof part === "string") {
|
if (typeof part === "string") {
|
||||||
var newPart = new ChatMessagePart()
|
var newPart = new ChatMessagePart();
|
||||||
newPart.text = part
|
newPart.text = part
|
||||||
this.then(newPart)
|
this.then(newPart);
|
||||||
return this
|
return this;
|
||||||
}
|
}
|
||||||
var last = this.latest()
|
var last = this.latest();
|
||||||
if (!last.text) {
|
if (!last.text) {
|
||||||
last.text = part.text
|
last.text = part.text;
|
||||||
} else {
|
} else {
|
||||||
this.parts.push(part)
|
this.parts.push(part);
|
||||||
}
|
}
|
||||||
this.cache = null
|
this.cache = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
text(text: string) {
|
text(text: string) {
|
||||||
this.latest().text = text
|
this.latest().text = text;
|
||||||
return this
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
tip(texts: string) {
|
tip(text: string) {
|
||||||
return this.hover(texts)
|
this.latest().hover("show_text", text);
|
||||||
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
hover(texts: string) {
|
item(text: string) {
|
||||||
this.latest().hover("show_text", texts)
|
this.latest().hover("show_item", text);
|
||||||
return this
|
return this;
|
||||||
}
|
|
||||||
|
|
||||||
item(item: string) {
|
|
||||||
this.latest().hover("show_item", item)
|
|
||||||
return this
|
|
||||||
}
|
}
|
||||||
|
|
||||||
command(command: string) {
|
command(command: string) {
|
||||||
this.latest().click("run_command", command)
|
this.latest().click("run_command", command);
|
||||||
return this
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
suggest(url: string) {
|
suggest(url: string) {
|
||||||
this.latest().click("suggest_command", url)
|
this.latest().click("suggest_command", url);
|
||||||
return this
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
file(path: string) {
|
file(path: string) {
|
||||||
this.latest().click("open_file", path)
|
this.latest().click("open_file", path);
|
||||||
return this
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
link(url: string) {
|
link(url: string) {
|
||||||
this.latest().click("open_url", url)
|
this.latest().click("open_url", url);
|
||||||
return this
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
latest() {
|
latest() {
|
||||||
return this.parts[this.parts.length - 1]
|
return this.parts[this.parts.length - 1];
|
||||||
}
|
}
|
||||||
|
|
||||||
json() {
|
json() {
|
||||||
if (!this.cache) {
|
if (!this.cache) {
|
||||||
var temp = []
|
var temp = [];
|
||||||
this.parts.forEach(t => {
|
this.parts.forEach(t => {
|
||||||
temp.push(t.convert())
|
temp.push(t.convert());
|
||||||
})
|
});
|
||||||
this.cache = JSON.stringify(temp)
|
this.cache = JSON.stringify(temp);
|
||||||
console.trace(this.cache)
|
console.trace(this.cache);
|
||||||
}
|
}
|
||||||
return this.cache
|
return this.cache;
|
||||||
}
|
}
|
||||||
|
|
||||||
string() {
|
string() {
|
||||||
var temp = ''
|
var temp = '';
|
||||||
this.parts.forEach(t => {
|
this.parts.forEach(t => {
|
||||||
temp += t.text
|
temp += t.text
|
||||||
})
|
});
|
||||||
return temp
|
return temp;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,35 +0,0 @@
|
|||||||
export type Version = [string, string, string]
|
|
||||||
|
|
||||||
export class VersionUtils {
|
|
||||||
static isEqual(version: string, targetVersion: string): boolean {
|
|
||||||
return version == targetVersion
|
|
||||||
}
|
|
||||||
static isGreaterOrEqual(version: string, targetVersion: string): boolean {
|
|
||||||
const v1 = parseVersion(version)
|
|
||||||
const v2 = parseVersion(targetVersion)
|
|
||||||
|
|
||||||
return (
|
|
||||||
v1[0] > v2[0] ||
|
|
||||||
(v1[0] === v2[0] && v1[1] > v2[1]) ||
|
|
||||||
(v1[0] === v2[0] && v1[1] === v2[1] && v1[2] >= v2[2])
|
|
||||||
)
|
|
||||||
}
|
|
||||||
static isGreater(version: string, targetVersion: string): boolean {
|
|
||||||
const v1 = parseVersion(version)
|
|
||||||
const v2 = parseVersion(targetVersion)
|
|
||||||
|
|
||||||
return (
|
|
||||||
v1[0] > v2[0] ||
|
|
||||||
(v1[0] === v2[0] && v1[1] > v2[1]) ||
|
|
||||||
(v1[0] === v2[0] && v1[1] === v2[1] && v1[2] > v2[2])
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function parseVersion(version: string = ""): Version {
|
|
||||||
const v: Version = ['0', '0', '0']
|
|
||||||
|
|
||||||
version.split(".").forEach((value, i) => (v[i] = value))
|
|
||||||
|
|
||||||
return v
|
|
||||||
}
|
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@ccms/compile",
|
"name": "@ccms/compile",
|
||||||
"version": "0.28.0-beta.4",
|
"version": "0.19.0",
|
||||||
"description": "MiaoScript compile package",
|
"description": "MiaoScript compile package",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"miaoscript",
|
"miaoscript",
|
||||||
@@ -12,33 +12,15 @@
|
|||||||
"homepage": "https://github.com/circlecloud/ms.git",
|
"homepage": "https://github.com/circlecloud/ms.git",
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"main": "dist/index.js",
|
"main": "dist/index.js",
|
||||||
"files": [
|
|
||||||
"dist"
|
|
||||||
],
|
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"clean": "rimraf dist",
|
"clean": "rimraf dist",
|
||||||
"watch": "tsc --watch",
|
"watch": "tsc --watch",
|
||||||
"build": "pnpm clean && tsc",
|
"build": "yarn clean && tsc",
|
||||||
"test": "echo \"Error: run tests from root\" && exit 1"
|
"test": "echo \"Error: run tests from root\" && exit 1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@ccms/api": "^0.28.0-beta.4",
|
"reflect-metadata": "^0.1.13",
|
||||||
"@ccms/bukkit": "^0.28.0-beta.4",
|
"rimraf": "^3.0.2",
|
||||||
"@ccms/bungee": "^0.28.0-beta.4",
|
"typescript": "^4.5.5"
|
||||||
"@ccms/common": "^0.28.0-beta.4",
|
|
||||||
"@ccms/container": "^0.28.0-beta.4",
|
|
||||||
"@ccms/core": "^0.28.0-beta.4",
|
|
||||||
"@ccms/database": "^0.28.0-beta.4",
|
|
||||||
"@ccms/i18n": "^0.28.0-beta.4",
|
|
||||||
"@ccms/molang": "^0.28.0-beta.4",
|
|
||||||
"@ccms/nashorn": "^0.28.0-beta.4",
|
|
||||||
"@ccms/nodejs": "^0.28.0-beta.4",
|
|
||||||
"@ccms/nukkit": "^0.28.0-beta.4",
|
|
||||||
"@ccms/plugin": "^0.28.0-beta.4",
|
|
||||||
"@ccms/polyfill": "^0.28.0-beta.4",
|
|
||||||
"@ccms/protocol": "^0.28.0-beta.4",
|
|
||||||
"@ccms/qrcode": "^0.28.0-beta.4",
|
|
||||||
"@ccms/sponge": "^0.28.0-beta.4",
|
|
||||||
"@ccms/websocket": "^0.28.0-beta.4"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@ccms/container",
|
"name": "@ccms/container",
|
||||||
"version": "0.28.0-beta.4",
|
"version": "0.19.0",
|
||||||
"description": "MiaoScript container package",
|
"description": "MiaoScript container package",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"miaoscript",
|
"miaoscript",
|
||||||
@@ -12,17 +12,17 @@
|
|||||||
"homepage": "https://github.com/circlecloud/ms.git",
|
"homepage": "https://github.com/circlecloud/ms.git",
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"main": "dist/index.js",
|
"main": "dist/index.js",
|
||||||
"files": [
|
|
||||||
"dist"
|
|
||||||
],
|
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"clean": "rimraf dist",
|
"clean": "rimraf dist",
|
||||||
"watch": "tsc --watch",
|
"watch": "tsc --watch",
|
||||||
"build": "pnpm clean && tsc",
|
"build": "yarn clean && tsc",
|
||||||
"test": "echo \"Error: run tests from root\" && exit 1"
|
"test": "echo \"Error: run tests from root\" && exit 1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@ccms/nashorn": "^0.28.0-beta.4"
|
"@ccms/nashorn": "^0.19.0",
|
||||||
|
"reflect-metadata": "^0.1.13",
|
||||||
|
"rimraf": "^3.0.2",
|
||||||
|
"typescript": "^4.5.5"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"inversify": "^6.0.1",
|
"inversify": "^6.0.1",
|
||||||
|
|||||||
@@ -1,9 +1,38 @@
|
|||||||
import { interfaces, Container } from "inversify"
|
import { interfaces, Container } from "inversify"
|
||||||
import { _proxyGetter } from "./utils"
|
|
||||||
|
|
||||||
let _container: Container
|
let _container: Container
|
||||||
|
|
||||||
const ContainerInstance = Symbol.for("@ccms/ioc:Container")
|
const ContainerInstance = Symbol.for("@ccms/ioc:Container")
|
||||||
|
const INJECTION = Symbol.for("INJECTION")
|
||||||
|
|
||||||
|
function _proxyGetter(
|
||||||
|
proto: any,
|
||||||
|
key: string,
|
||||||
|
resolve: () => any,
|
||||||
|
doCache: boolean
|
||||||
|
) {
|
||||||
|
function getter(this: object) {
|
||||||
|
if (doCache && !Reflect.hasMetadata(INJECTION, this, key)) {
|
||||||
|
Reflect.defineMetadata(INJECTION, resolve(), this, key)
|
||||||
|
}
|
||||||
|
if (Reflect.hasMetadata(INJECTION, this, key)) {
|
||||||
|
return Reflect.getMetadata(INJECTION, this, key)
|
||||||
|
} else {
|
||||||
|
return resolve()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function setter(this: object, newVal: any) {
|
||||||
|
Reflect.defineMetadata(INJECTION, newVal, this, key)
|
||||||
|
}
|
||||||
|
|
||||||
|
Object.defineProperty(proto, key, {
|
||||||
|
configurable: true,
|
||||||
|
enumerable: true,
|
||||||
|
get: getter,
|
||||||
|
set: setter
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
function initContainer(container: Container) {
|
function initContainer(container: Container) {
|
||||||
Reflect.defineMetadata(ContainerInstance, container, Reflect)
|
Reflect.defineMetadata(ContainerInstance, container, Reflect)
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ import { initContainer, getContainer } from './decorators'
|
|||||||
import { interfaces, Container, inject, named } from 'inversify'
|
import { interfaces, Container, inject, named } from 'inversify'
|
||||||
import { fluentProvide } from 'inversify-binding-decorators'
|
import { fluentProvide } from 'inversify-binding-decorators'
|
||||||
import { ioc } from "./constants"
|
import { ioc } from "./constants"
|
||||||
import { _proxyGetter } from "./utils"
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 注册一个命名对象
|
* 注册一个命名对象
|
||||||
@@ -32,37 +31,27 @@ export const provideSingletonNamed = (identifier: interfaces.ServiceIdentifier<a
|
|||||||
return fluentProvide(identifier).inSingletonScope().whenTargetNamed(name).done()
|
return fluentProvide(identifier).inSingletonScope().whenTargetNamed(name).done()
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getJavaClass(className: string) {
|
|
||||||
try { return Java.type(className).class; return } catch (error: any) { }
|
|
||||||
try { return base.getClass(className); return } catch (error: any) { }
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获得一个 java.lang.Class
|
* 获得一个 java.lang.Class
|
||||||
* @param className Java全类名
|
* @param className Java全类名
|
||||||
*/
|
*/
|
||||||
export const JavaClass = (className: string) => {
|
export const JavaClass = (className: string) => {
|
||||||
return function (target: object, propertyKey: string, index?: number) {
|
return function (target: object, propertyKey: string, index?: number) {
|
||||||
_proxyGetter(target, propertyKey, () => {
|
try { target[propertyKey] = Java.type(className).class; return } catch (error: any) { }
|
||||||
return getJavaClass(className) || console.warn('JavaClass', className, 'Inject target', target.constructor.name, 'propertyKey', propertyKey, 'failed!')
|
try { target[propertyKey] = base.getClass(className); return } catch (error: any) { }
|
||||||
}, true)
|
console.warn('JavaClass', className, 'Inject target', target.constructor.name, 'propertyKey', propertyKey, 'failed!')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getJSClass(className: string) {
|
|
||||||
try { return Java.type(className) } catch (error: any) { }
|
|
||||||
try { return base.getClass(className).static } catch (error: any) { }
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获得一个JS的Java类
|
* 获得一个JS的Java类
|
||||||
* @param className Java 全类名
|
* @param className Java 全类名
|
||||||
*/
|
*/
|
||||||
export const JSClass = (className: string) => {
|
export const JSClass = (className: string) => {
|
||||||
return function (target: object, propertyKey: string, index?: number) {
|
return function (target: object, propertyKey: string, index?: number) {
|
||||||
_proxyGetter(target, propertyKey, () => {
|
try { target[propertyKey] = Java.type(className); return } catch (error: any) { }
|
||||||
return getJSClass(className) || console.warn('JSClass', className, 'Inject target', target.constructor.name, 'propertyKey', propertyKey, 'failed!')
|
try { target[propertyKey] = base.getClass(className).static; return } catch (error: any) { }
|
||||||
}, true)
|
console.warn('JSClass', className, 'Inject target', target.constructor.name, 'propertyKey', propertyKey, 'failed!')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -99,59 +88,6 @@ export const Resource = (resourceName?: string | any) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const DocumentBuilderFactory = Java.type('javax.xml.parsers.DocumentBuilderFactory')
|
|
||||||
|
|
||||||
export const MavenDepend = (groupId: string, artifactId: string, version: string, recursion = false) => {
|
|
||||||
return function (target: any) {
|
|
||||||
loadMavenDepend(groupId, artifactId, version, recursion)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const loadedMavenDepend = new Set<string>()
|
|
||||||
|
|
||||||
export function loadMavenDepend(groupId: string, artifactId: string, version: string, recursion = false) {
|
|
||||||
const key = `${groupId}:${artifactId}:${version}`
|
|
||||||
try {
|
|
||||||
if (loadedMavenDepend.has(key)) { return }
|
|
||||||
console.info('loading maven dependency', key)
|
|
||||||
let [pom, _] = base.loadMavenDepend(groupId, artifactId, version)
|
|
||||||
loadedMavenDepend.add(key)
|
|
||||||
if (recursion) {
|
|
||||||
let doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(pom)
|
|
||||||
let dependencies = doc.getElementsByTagName("dependency")
|
|
||||||
let size = dependencies.length
|
|
||||||
if (!size) { return }
|
|
||||||
console.debug(key, 'found', size, 'dependencies loading...')
|
|
||||||
for (let i = 0; i < size; i++) {
|
|
||||||
const dependency = dependencies.item(i)
|
|
||||||
const gav = dependency.getChildNodes()
|
|
||||||
const length = gav.length
|
|
||||||
const dependencyVersion = { groupId: '', artifactId: '', version: '' }
|
|
||||||
for (let j = 0; j < length; j++) {
|
|
||||||
const prop = gav.item(j)
|
|
||||||
switch (prop.getNodeName()) {
|
|
||||||
case "groupId":
|
|
||||||
dependencyVersion.groupId = prop.getTextContent()
|
|
||||||
break
|
|
||||||
case "artifactId":
|
|
||||||
dependencyVersion.artifactId = prop.getTextContent()
|
|
||||||
break
|
|
||||||
case "version":
|
|
||||||
dependencyVersion.version = prop.getTextContent()
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
loadMavenDepend(dependencyVersion.groupId, dependencyVersion.artifactId, dependencyVersion.version, recursion)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (error: any) {
|
|
||||||
console.warn('load maven dependency', key, 'failed. Error:', error)
|
|
||||||
if (global.debug) {
|
|
||||||
console.ex(error)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export const reduceMetadata = (ctx: interfaces.Context): any => {
|
export const reduceMetadata = (ctx: interfaces.Context): any => {
|
||||||
return ctx.currentRequest.target.metadata.reduce((result, entry, index) => {
|
return ctx.currentRequest.target.metadata.reduce((result, entry, index) => {
|
||||||
result[entry.key] = entry.value
|
result[entry.key] = entry.value
|
||||||
@@ -162,10 +98,8 @@ export const reduceMetadata = (ctx: interfaces.Context): any => {
|
|||||||
function initAutowired(container: Container) {
|
function initAutowired(container: Container) {
|
||||||
container.bind(ioc.Autowired).toDynamicValue((ctx) => {
|
container.bind(ioc.Autowired).toDynamicValue((ctx) => {
|
||||||
var metadata: any = reduceMetadata(ctx)
|
var metadata: any = reduceMetadata(ctx)
|
||||||
let key = Object.prototype.toString.call(metadata.named)
|
let key = Object.toString.call(metadata.named)
|
||||||
if (key === "[object Function]" || key === "[object Symbol]") { return container.get(metadata.named) }
|
if (key === "[object Function]" || key === "[object Symbol]") { return container.get(metadata.named) }
|
||||||
console.warn('container Autowired', metadata.named, 'failed. Error: illegal serviceIdentifier type', key)
|
|
||||||
console.debug(metadata.named, 'metadata', JSON.stringify(metadata))
|
|
||||||
return undefined
|
return undefined
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,30 +0,0 @@
|
|||||||
const INJECTION = Symbol.for("INJECTION")
|
|
||||||
|
|
||||||
export function _proxyGetter(
|
|
||||||
proto: any,
|
|
||||||
key: string,
|
|
||||||
resolve: () => any,
|
|
||||||
doCache: boolean
|
|
||||||
) {
|
|
||||||
function getter(this: object) {
|
|
||||||
if (doCache && !Reflect.hasMetadata(INJECTION, this, key)) {
|
|
||||||
Reflect.defineMetadata(INJECTION, resolve(), this, key)
|
|
||||||
}
|
|
||||||
if (Reflect.hasMetadata(INJECTION, this, key)) {
|
|
||||||
return Reflect.getMetadata(INJECTION, this, key)
|
|
||||||
} else {
|
|
||||||
return resolve()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function setter(this: object, newVal: any) {
|
|
||||||
Reflect.defineMetadata(INJECTION, newVal, this, key)
|
|
||||||
}
|
|
||||||
|
|
||||||
Object.defineProperty(proto, key, {
|
|
||||||
configurable: true,
|
|
||||||
enumerable: true,
|
|
||||||
get: getter,
|
|
||||||
set: setter
|
|
||||||
})
|
|
||||||
}
|
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "@ccms/core",
|
"name": "@ccms/core",
|
||||||
"version": "0.28.0-beta.4",
|
"version": "0.20.0-alpha.0",
|
||||||
"description": "MiaoScript core package",
|
"description": "MiaoScript api package",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"miaoscript",
|
"miaoscript",
|
||||||
"minecraft",
|
"minecraft",
|
||||||
@@ -12,26 +12,20 @@
|
|||||||
"homepage": "https://github.com/circlecloud/ms.git",
|
"homepage": "https://github.com/circlecloud/ms.git",
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"main": "dist/index.js",
|
"main": "dist/index.js",
|
||||||
"files": [
|
|
||||||
"dist"
|
|
||||||
],
|
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"clean": "rimraf dist",
|
"clean": "rimraf dist",
|
||||||
"watch": "pnpm rollup -c rollup.config.js --watch",
|
"watch": "tsc --watch",
|
||||||
"build": "pnpm clean && pnpm rollup -c rollup.config.js",
|
"build": "yarn clean && tsc",
|
||||||
"test": "echo \"Error: run tests from root\" && exit 1"
|
"test": "echo \"Error: run tests from root\" && exit 1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@rollup/plugin-typescript": "^11.1.5",
|
"reflect-metadata": "^0.1.13",
|
||||||
"rollup": "^2.79.1",
|
"rimraf": "^3.0.2",
|
||||||
"rollup-obfuscator": "^3.0.2",
|
"typescript": "^4.5.5"
|
||||||
"rollup-plugin-peer-deps-external": "^2.2.4"
|
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@ccms/api": "^0.28.0-beta.4",
|
"@ccms/api": "^0.20.0-alpha.0",
|
||||||
"@ccms/common": "^0.28.0-beta.4",
|
"@ccms/container": "^0.19.0"
|
||||||
"@ccms/container": "^0.28.0-beta.4",
|
|
||||||
"js-yaml": "^4.1.0"
|
|
||||||
},
|
},
|
||||||
"gitHead": "781524f83e52cad26d7c480513e3c525df867121"
|
"gitHead": "781524f83e52cad26d7c480513e3c525df867121"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,49 +0,0 @@
|
|||||||
import typescript from '@rollup/plugin-typescript'
|
|
||||||
import peerDepsExternal from 'rollup-plugin-peer-deps-external'
|
|
||||||
import { obfuscator } from 'rollup-obfuscator'
|
|
||||||
|
|
||||||
import pkg from './package.json'
|
|
||||||
|
|
||||||
const external = ['path', 'fs', 'typescript', 'tslib']
|
|
||||||
/**
|
|
||||||
* @type {import('rollup').RollupOptions}
|
|
||||||
*/
|
|
||||||
export default {
|
|
||||||
input: 'src/index.ts',
|
|
||||||
plugins: [
|
|
||||||
peerDepsExternal(),
|
|
||||||
typescript(),
|
|
||||||
obfuscator({
|
|
||||||
compact: true,
|
|
||||||
deadCodeInjection: true,
|
|
||||||
deadCodeInjectionThreshold: 1,
|
|
||||||
identifierNamesGenerator: 'mangled-shuffled',
|
|
||||||
numbersToExpressions: true,
|
|
||||||
simplify: true,
|
|
||||||
stringArray: true,
|
|
||||||
stringArrayThreshold: 1,
|
|
||||||
stringArrayEncoding: ['rc4'],
|
|
||||||
stringArrayCallsTransform: true,
|
|
||||||
stringArrayCallsTransformThreshold: 1,
|
|
||||||
stringArrayWrappersChainedCalls: true,
|
|
||||||
stringArrayWrappersParametersMaxCount: 3,
|
|
||||||
sourceMap: true,
|
|
||||||
sourceMapSourcesMode: 'sources',
|
|
||||||
inputFileName: `${pkg.name}.ts`,
|
|
||||||
transformObjectKeys: true,
|
|
||||||
unicodeEscapeSequence: true,
|
|
||||||
target: 'browser-no-eval'
|
|
||||||
}),
|
|
||||||
],
|
|
||||||
external,
|
|
||||||
treeshake: false,
|
|
||||||
output: [
|
|
||||||
{
|
|
||||||
format: 'cjs',
|
|
||||||
interop: "auto",
|
|
||||||
exports: "named",
|
|
||||||
sourcemap: true,
|
|
||||||
file: pkg.main || `dist/${pkg.name}.js`
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
1
packages/core/src/.gitignore
vendored
1
packages/core/src/.gitignore
vendored
@@ -1 +0,0 @@
|
|||||||
script
|
|
||||||
@@ -1,15 +1,9 @@
|
|||||||
let containerStartTime = Date.now()
|
let containerStartTime = Date.now()
|
||||||
console.i18n("ms.core.ioc.initialize", { scope: global.scope })
|
console.i18n("ms.core.ioc.initialize", { scope: global.scope })
|
||||||
import { plugin, server, task, constants, console as jsconsole } from '@ccms/api'
|
import { plugin, server, task, constants } from '@ccms/api'
|
||||||
import { DefaultContainer as container, provideSingleton, ContainerInstance, buildProviderModule, Autowired } from '@ccms/container'
|
import { DefaultContainer as container, provideSingleton, ContainerInstance, buildProviderModule, Autowired } from '@ccms/container'
|
||||||
console.i18n("ms.core.ioc.completed", { scope: global.scope, time: (Date.now() - containerStartTime) / 1000 })
|
console.i18n("ms.core.ioc.completed", { scope: global.scope, time: (Date.now() - containerStartTime) / 1000 })
|
||||||
import * as yaml from 'js-yaml'
|
|
||||||
import http from '@ccms/common/dist/http'
|
import http from '@ccms/common/dist/http'
|
||||||
import * as fs from '@ccms/common/dist/fs'
|
|
||||||
import { VersionUtils } from '@ccms/common/dist/version'
|
|
||||||
|
|
||||||
const UUID = Java.type('java.util.UUID')
|
|
||||||
const MiaoScriptAPI = Java.type('pw.yumc.MiaoScript.api.MiaoScriptAPI')
|
|
||||||
|
|
||||||
@provideSingleton(MiaoScriptCore)
|
@provideSingleton(MiaoScriptCore)
|
||||||
class MiaoScriptCore {
|
class MiaoScriptCore {
|
||||||
@@ -25,17 +19,8 @@ class MiaoScriptCore {
|
|||||||
enable() {
|
enable() {
|
||||||
process.emit('core.before.enable')
|
process.emit('core.before.enable')
|
||||||
this.loadServerConsole()
|
this.loadServerConsole()
|
||||||
try {
|
|
||||||
MiaoScriptAPI.setPluginManager(this.pluginManager)
|
|
||||||
} catch (error) {
|
|
||||||
}
|
|
||||||
this.loadPlugins()
|
this.loadPlugins()
|
||||||
process.emit('core.after.enable')
|
process.emit('core.after.enable')
|
||||||
console.i18n("ms.core.engine.completed", {
|
|
||||||
loader: base.version,
|
|
||||||
version: 'v' + global.ScriptEngineVersion,
|
|
||||||
time: (Date.now() - global.ScriptEngineStartTime) / 1000
|
|
||||||
})
|
|
||||||
return () => this.disable()
|
return () => this.disable()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -110,7 +95,7 @@ function loadCoreScript(name) {
|
|||||||
try {
|
try {
|
||||||
let scriptname = name + (global.debug ? '-debug' : '')
|
let scriptname = name + (global.debug ? '-debug' : '')
|
||||||
engineLoad({
|
engineLoad({
|
||||||
script: http.get(`https://mscript.yumc.pw/api/plugin/download/name/${scriptname}`),
|
script: http.get(`https://ms.yumc.pw/api/plugin/download/name/${scriptname}`),
|
||||||
name: `core/${scriptname}.js`
|
name: `core/${scriptname}.js`
|
||||||
})
|
})
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
@@ -121,61 +106,50 @@ function loadCoreScript(name) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function loadMiaoScriptConfig() {
|
|
||||||
let configFile = fs.concat(root, 'config.yml')
|
|
||||||
if (!fs.exists(configFile)) {
|
|
||||||
global.ScriptEngineConfig = base.save(configFile, yaml.dump({
|
|
||||||
uuid: UUID.randomUUID().toString(),
|
|
||||||
slow_execute: 50
|
|
||||||
}))
|
|
||||||
} else {
|
|
||||||
global.ScriptEngineConfig = yaml.load(base.read(configFile))
|
|
||||||
}
|
|
||||||
global.ScriptSlowExecuteTime = global.ScriptEngineConfig.slow_execute || 50
|
|
||||||
}
|
|
||||||
|
|
||||||
function createCore() {
|
|
||||||
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()
|
|
||||||
|
|
||||||
process.emit('core.before.initialize.detect')
|
|
||||||
console.i18n("ms.core.initialize.detect", { scope: global.scope, type })
|
|
||||||
container.bind(server.ServerType).toConstantValue(type)
|
|
||||||
container.bind(server.ServerChecker).toSelf().inSingletonScope()
|
|
||||||
container.bind(server.NativePluginManager).toSelf().inSingletonScope()
|
|
||||||
container.bind(server.NativePluginChecker).toSelf().inSingletonScope()
|
|
||||||
process.emit('core.after.initialize.detect')
|
|
||||||
|
|
||||||
process.emit('core.before.package.initialize')
|
|
||||||
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 })
|
|
||||||
process.emit('core.after.package.initialize')
|
|
||||||
return container.get<MiaoScriptCore>(MiaoScriptCore)
|
|
||||||
}
|
|
||||||
|
|
||||||
function initialize() {
|
function initialize() {
|
||||||
process.emit('core.before.initialize')
|
process.emit('core.before.initialize')
|
||||||
loadMiaoScriptConfig()
|
global.ScriptSlowExecuteTime = 50
|
||||||
global.ScriptEngineVersion = require('../package.json').version
|
global.ScriptEngineVersion = require('../package.json').version
|
||||||
global.setGlobal('loadCoreScript', loadCoreScript)
|
global.setGlobal('loadCoreScript', loadCoreScript)
|
||||||
loadCoreScript('initialize')
|
loadCoreScript('initialize')
|
||||||
try {
|
try {
|
||||||
let core = createCore()
|
let corePackageStartTime = new Date().getTime()
|
||||||
return VersionUtils.isGreaterOrEqual(base.version, '0.22.0') ? core : core.enable()
|
container.bind(ContainerInstance).toConstantValue(container)
|
||||||
} catch (error: any) {
|
container.bind(plugin.PluginInstance).toConstantValue(base.getInstance())
|
||||||
let core = { enable: () => () => console.i18n('ms.core.engine.disable.abnormal') }
|
container.bind(plugin.PluginFolder).toConstantValue('plugins')
|
||||||
console.i18n("core.initialize.error", { error })
|
let type = detectServer()
|
||||||
jsconsole.getStackTrace(error, false).forEach(line => console.log(line))
|
|
||||||
process.emit('core.initialize.error')
|
process.emit('core.before.initialize.detect')
|
||||||
return VersionUtils.isGreaterOrEqual(base.version, '0.22.0') ? core : core.enable()
|
console.i18n("ms.core.initialize.detect", { scope: global.scope, type })
|
||||||
} finally {
|
container.bind(server.ServerType).toConstantValue(type)
|
||||||
|
container.bind(server.ServerChecker).toSelf().inSingletonScope()
|
||||||
|
container.bind(server.NativePluginManager).toSelf().inSingletonScope()
|
||||||
|
process.emit('core.after.initialize.detect')
|
||||||
|
|
||||||
|
process.emit('core.before.package.initialize')
|
||||||
|
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 })
|
||||||
|
process.emit('core.after.package.initialize')
|
||||||
|
|
||||||
|
let disable = container.get<MiaoScriptCore>(MiaoScriptCore).enable()
|
||||||
|
console.i18n("ms.core.engine.completed", {
|
||||||
|
loader: base.version,
|
||||||
|
version: 'v' + global.ScriptEngineVersion,
|
||||||
|
time: (Date.now() - global.ScriptEngineStartTime) / 1000
|
||||||
|
})
|
||||||
process.emit('core.after.initialize')
|
process.emit('core.after.initialize')
|
||||||
|
return disable
|
||||||
|
} catch (error: any) {
|
||||||
|
if (console.console) {
|
||||||
|
console.i18n("ms.core.initialize.error", { error })
|
||||||
|
console.ex(error)
|
||||||
|
} else {
|
||||||
|
error.printStackTrace()
|
||||||
|
}
|
||||||
|
return () => console.i18n('ms.core.engine.disable.abnormal')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@ccms/database",
|
"name": "@ccms/database",
|
||||||
"version": "0.28.0-beta.4",
|
"version": "0.20.0-alpha.0",
|
||||||
"description": "MiaoScript database package",
|
"description": "MiaoScript database package",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"miaoscript",
|
"miaoscript",
|
||||||
@@ -12,20 +12,20 @@
|
|||||||
"homepage": "https://github.com/circlecloud/ms.git",
|
"homepage": "https://github.com/circlecloud/ms.git",
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"main": "dist/index.js",
|
"main": "dist/index.js",
|
||||||
"files": [
|
|
||||||
"dist"
|
|
||||||
],
|
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"clean": "rimraf dist",
|
"clean": "rimraf dist",
|
||||||
"watch": "tsc --watch",
|
"watch": "tsc --watch",
|
||||||
"build": "pnpm clean && tsc",
|
"build": "yarn clean && tsc",
|
||||||
"test": "echo \"Error: run tests from root\" && exit 1"
|
"test": "echo \"Error: run tests from root\" && exit 1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@javatypes/spring-jdbc": "^0.0.3"
|
"@javatypes/spring-jdbc": "^0.0.3",
|
||||||
|
"reflect-metadata": "^0.1.13",
|
||||||
|
"rimraf": "^3.0.2",
|
||||||
|
"typescript": "^4.5.5"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@ccms/api": "^0.28.0-beta.4",
|
"@ccms/api": "^0.20.0-alpha.0",
|
||||||
"@ccms/container": "^0.28.0-beta.4"
|
"@ccms/container": "^0.19.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,109 +1,88 @@
|
|||||||
import { database } from '@ccms/api'
|
import { Model } from './model'
|
||||||
import { JSClass } from '@ccms/container'
|
|
||||||
|
|
||||||
const Thread = Java.type('java.lang.Thread')
|
const HikariDataSource = Java.type('com.zaxxer.hikari.HikariDataSource')
|
||||||
const JavaString = Java.type('java.lang.String')
|
const HikariConfig = Java.type('com.zaxxer.hikari.HikariConfig')
|
||||||
const Properties = Java.type('java.util.Properties')
|
const JdbcTemplate = Java.type('org.springframework.jdbc.core.JdbcTemplate')
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 数据库配置
|
||||||
|
*/
|
||||||
|
export interface DataBaseConfig {
|
||||||
|
/**
|
||||||
|
* 数据库连接串
|
||||||
|
*/
|
||||||
|
url: string | javax.sql.DataSource
|
||||||
|
/**
|
||||||
|
* 数据库驱动
|
||||||
|
*/
|
||||||
|
driverClassName?: string
|
||||||
|
/**
|
||||||
|
* 用户名
|
||||||
|
*/
|
||||||
|
username?: string
|
||||||
|
/**
|
||||||
|
* 密码
|
||||||
|
*/
|
||||||
|
password?: string
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 数据库封装类
|
* 数据库封装类
|
||||||
*/
|
*/
|
||||||
export class DataBase extends database.DataBase {
|
export class DataBase {
|
||||||
private dataSource: javax.sql.DataSource
|
private dataSource: javax.sql.DataSource
|
||||||
private jdbcTemplate: org.springframework.jdbc.core.JdbcTemplate
|
private jdbcTemplate: org.springframework.jdbc.core.JdbcTemplate
|
||||||
|
|
||||||
@JSClass('com.zaxxer.hikari.HikariDataSource')
|
constructor(dbConfig: DataBaseConfig) {
|
||||||
private HikariDataSource: any
|
|
||||||
@JSClass('com.zaxxer.hikari.HikariConfig')
|
|
||||||
private HikariConfig: any
|
|
||||||
@JSClass('org.springframework.jdbc.core.JdbcTemplate')
|
|
||||||
private JdbcTemplate: typeof org.springframework.jdbc.core.JdbcTemplate
|
|
||||||
|
|
||||||
constructor(dbConfig: database.DataBaseConfig) {
|
|
||||||
super()
|
|
||||||
if (!dbConfig.url) { throw new Error('DataBase url can\'t be null!') }
|
if (!dbConfig.url) { throw new Error('DataBase url can\'t be null!') }
|
||||||
this.createDataSource(dbConfig)
|
this.createDataSource(dbConfig)
|
||||||
|
this.initialize()
|
||||||
}
|
}
|
||||||
|
|
||||||
private createDataSource(dbConfig: database.DataBaseConfig) {
|
private createDataSource(dbConfig: DataBaseConfig) {
|
||||||
if (typeof dbConfig.url === "string") {
|
if (typeof dbConfig.url === "string") {
|
||||||
let originClassLoader = Thread.currentThread().getContextClassLoader()
|
if (!dbConfig.username || !dbConfig.password) {
|
||||||
Thread.currentThread().setContextClassLoader(base.getInstance().class.classLoader)
|
throw new Error('DataBase username or password can\'t be null!')
|
||||||
let config = new this.HikariConfig()
|
}
|
||||||
|
let config = new HikariConfig()
|
||||||
if (dbConfig.driverClassName) {
|
if (dbConfig.driverClassName) {
|
||||||
config.setDriverClassName(dbConfig.driverClassName)
|
config.setDriverClassName(dbConfig.driverClassName)
|
||||||
} else {
|
|
||||||
switch (dbConfig.type) {
|
|
||||||
case "h2":
|
|
||||||
config.setDriverClassName("org.h2.Driver")
|
|
||||||
break
|
|
||||||
case "sqlite":
|
|
||||||
config.setDriverClassName("org.sqlite.JDBC")
|
|
||||||
break
|
|
||||||
default:
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (dbConfig.username) {
|
|
||||||
config.setUsername(dbConfig.username)
|
|
||||||
}
|
|
||||||
if (dbConfig.password) {
|
|
||||||
config.setPassword(dbConfig.password)
|
|
||||||
}
|
}
|
||||||
|
config.setUsername(dbConfig.username)
|
||||||
|
config.setPassword(dbConfig.password)
|
||||||
config.setJdbcUrl(dbConfig.url)
|
config.setJdbcUrl(dbConfig.url)
|
||||||
if (dbConfig.properties) {
|
this.dataSource = new HikariDataSource(config)
|
||||||
let properties = new Properties()
|
|
||||||
for (const key in dbConfig.properties) {
|
|
||||||
properties.setProperty(key, dbConfig.properties[key])
|
|
||||||
}
|
|
||||||
config.setDataSourceProperties(properties)
|
|
||||||
}
|
|
||||||
console.debug('createDataSource from config ' + JSON.stringify(dbConfig))
|
|
||||||
this.dataSource = new this.HikariDataSource(config)
|
|
||||||
Thread.currentThread().setContextClassLoader(originClassLoader)
|
|
||||||
} else {
|
} else {
|
||||||
this.dataSource = dbConfig.url
|
this.dataSource = dbConfig.url
|
||||||
}
|
}
|
||||||
this.jdbcTemplate = new this.JdbcTemplate(this.dataSource)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
getDataSource() {
|
private initialize() {
|
||||||
return this.dataSource
|
this.jdbcTemplate = new JdbcTemplate(this.dataSource)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 执行SQL查询
|
* 执行SQL查询
|
||||||
* @param sql SQL语句
|
* @param sql SQL语句
|
||||||
* @param args 参数
|
|
||||||
*/
|
*/
|
||||||
query<T>(sql: string, ...args: any[]): Array<T> {
|
query<T>(sql: string, ...args: any[]): Array<T> {
|
||||||
let startTime = Date.now()
|
let startTime = Date.now()
|
||||||
let result = Java.from<any>(this.jdbcTemplate.queryForList(sql, args))
|
let result = Java.from<any>(this.jdbcTemplate.queryForList(sql, args))
|
||||||
console.debug(JavaString.format(`\n[DB] query \nSQL : ${sql.replace(/\?/ig, '%s')} \nCOST : ${Date.now() - startTime}ms`, args))
|
console.debug(java.lang.String.format(`\n[DB] query \nSQL : ${sql.replace(/\?/ig, '%s')} \nCOST : ${Date.now() - startTime}ms`, args))
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 执行SQL更新
|
* 执行SQL更新
|
||||||
* @param sql SQL语句
|
* @param sql SQL语句
|
||||||
* @param args 参数
|
|
||||||
*/
|
*/
|
||||||
update(sql: string, ...args: any[]): number {
|
update(sql: string, ...args: any[]): number {
|
||||||
let startTime = Date.now()
|
let startTime = Date.now()
|
||||||
let result = this.jdbcTemplate.update(sql, args)
|
let result = this.jdbcTemplate.update(sql, args)
|
||||||
console.debug(JavaString.format(`\n[DB] update \nSQL : ${sql.replace(/\?/ig, '%s')} \nCOST : ${Date.now() - startTime}ms`, args))
|
console.debug(java.lang.String.format(`\n[DB] update \nSQL : ${sql.replace(/\?/ig, '%s')} \nCOST : ${Date.now() - startTime}ms`, args))
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 执行SQL语句
|
|
||||||
* @param sql SQL语句
|
|
||||||
*/
|
|
||||||
execute(sql: string): void {
|
|
||||||
let startTime = Date.now()
|
|
||||||
this.jdbcTemplate.execute(sql)
|
|
||||||
console.debug(`\n[DB] execute \nSQL : ${sql} \nCOST : ${Date.now() - startTime}ms`)
|
|
||||||
}
|
|
||||||
|
|
||||||
close() {
|
close() {
|
||||||
//@ts-ignore
|
//@ts-ignore
|
||||||
this.dataSource.close()
|
this.dataSource.close()
|
||||||
|
|||||||
7
packages/database/src/decorators.ts
Normal file
7
packages/database/src/decorators.ts
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
import 'reflect-metadata'
|
||||||
|
|
||||||
|
export function id() {
|
||||||
|
return (target: Object, propertyKey: string | symbol) => void {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,11 +2,5 @@
|
|||||||
/// <reference types="@javatypes/jdk" />
|
/// <reference types="@javatypes/jdk" />
|
||||||
/// <reference types="@javatypes/spring-jdbc" />
|
/// <reference types="@javatypes/spring-jdbc" />
|
||||||
|
|
||||||
import { loadMavenDepend } from '@ccms/container'
|
|
||||||
|
|
||||||
loadMavenDepend('com.h2database', 'h2', '2.1.212')
|
|
||||||
loadMavenDepend("com.zaxxer", "HikariCP", "4.0.3")
|
|
||||||
loadMavenDepend("org.springframework", "spring-jdbc", "5.3.19", true)
|
|
||||||
|
|
||||||
export * from './database'
|
export * from './database'
|
||||||
export * from './manager'
|
export * from './manager'
|
||||||
@@ -1,46 +1,27 @@
|
|||||||
import { database } from '@ccms/api'
|
import { plugin, database } from '@ccms/api'
|
||||||
import { JSClass, provideSingleton } from '@ccms/container'
|
import { provideSingleton, inject, postConstruct } from '@ccms/container'
|
||||||
import { DataBase } from './database'
|
import { DataBase, DataBaseConfig } from './database'
|
||||||
|
|
||||||
@provideSingleton(database.DataBaseManager)
|
@provideSingleton(database.DataBaseManager)
|
||||||
export class DataBaseManager extends database.DataBaseManager {
|
export class DataBaseManager {
|
||||||
|
@inject(plugin.PluginInstance)
|
||||||
|
private instance: any
|
||||||
|
|
||||||
|
private beanFactory: any
|
||||||
private mainDatabase: DataBase
|
private mainDatabase: DataBase
|
||||||
private databases = new Map<string, DataBase>()
|
private databases: { [key: string]: DataBase } = {}
|
||||||
|
|
||||||
@JSClass('org.h2.tools.Server')
|
@postConstruct()
|
||||||
private Server: any
|
initialize() {
|
||||||
|
try {
|
||||||
private webManager: any
|
this.beanFactory = this.instance.getAutowireCapableBeanFactory()
|
||||||
|
let mainDatasource = this.beanFactory.getBean(Packages.javax.sql.DataSource.class)
|
||||||
constructor() {
|
this.mainDatabase = new DataBase({ url: mainDatasource })
|
||||||
super()
|
} catch (error: any) {
|
||||||
process.on('exit', () => this.shutdown())
|
console.ex(error)
|
||||||
}
|
|
||||||
|
|
||||||
startWebManager(...args: string[]) {
|
|
||||||
this.webManager = this.Server.createWebServer(args)
|
|
||||||
this.webManager.start()
|
|
||||||
}
|
|
||||||
|
|
||||||
stopWebManager() {
|
|
||||||
if (this.webManager) {
|
|
||||||
this.webManager.stop()
|
|
||||||
this.webManager.shutdown()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
shutdown() {
|
|
||||||
this.stopWebManager()
|
|
||||||
this.disable()
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* 设置主数据库
|
|
||||||
* @param mainDatabase 主数据库
|
|
||||||
*/
|
|
||||||
setMainDatabase(mainDatabase: DataBase) {
|
|
||||||
this.mainDatabase = mainDatabase
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获得主数据库
|
* 获得主数据库
|
||||||
* Get MainDatabase
|
* Get MainDatabase
|
||||||
@@ -55,28 +36,18 @@ export class DataBaseManager extends database.DataBaseManager {
|
|||||||
* @param name 数据库名称 用于代码 database Name use at code
|
* @param name 数据库名称 用于代码 database Name use at code
|
||||||
* @param config 数据库配置
|
* @param config 数据库配置
|
||||||
*/
|
*/
|
||||||
createDatabase(name: string, config: database.DataBaseConfig) {
|
createDatabase(name: string, config: DataBaseConfig) {
|
||||||
return Java.synchronized(() => {
|
Java.synchronized(() => {
|
||||||
if (!this.databases.has(name)) {
|
if (this.databases[name]) return this.databases[name]
|
||||||
this.databases.set(name, new DataBase(config))
|
return this.databases[name] = new DataBase(config)
|
||||||
}
|
|
||||||
return this.databases.get(name)
|
|
||||||
}, this.databases)()
|
}, this.databases)()
|
||||||
}
|
}
|
||||||
|
|
||||||
removeDatabase(name: string) {
|
|
||||||
if (this.databases.has(name)) {
|
|
||||||
this.databases.get(name).close()
|
|
||||||
}
|
|
||||||
return this.databases.delete(name)
|
|
||||||
}
|
|
||||||
|
|
||||||
getDatabase(name: string) {
|
getDatabase(name: string) {
|
||||||
return this.databases.get(name)
|
return this.databases[name]
|
||||||
}
|
}
|
||||||
|
|
||||||
disable() {
|
disable() {
|
||||||
this.databases.forEach((db) => db.close())
|
Object.values(this.databases).forEach((ds) => ds?.close())
|
||||||
this.databases.clear()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
11
packages/database/src/model.ts
Normal file
11
packages/database/src/model.ts
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
import { DataBase } from "./database"
|
||||||
|
|
||||||
|
export class Model<T> {
|
||||||
|
constructor(private database: DataBase) {
|
||||||
|
|
||||||
|
}
|
||||||
|
queryForList(): Array<T> {
|
||||||
|
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -34,10 +34,10 @@ ms.api.command.tab.completer.slow: "§c注意! §6玩家 §a{player} §6执行
|
|||||||
ms.api.command.tab.completer.error: "§6玩家 §a{player} §6执行 §b{plugin} §6插件 §d{command} {args} §6补全时发生异常 §4{ex}"
|
ms.api.command.tab.completer.error: "§6玩家 §a{player} §6执行 §b{plugin} §6插件 §d{command} {args} §6补全时发生异常 §4{ex}"
|
||||||
|
|
||||||
ms.plugin.initialize: "初始化 MiaoScript 插件系统: 实例: {plugin} 加载器: {loader}..."
|
ms.plugin.initialize: "初始化 MiaoScript 插件系统: 实例: {plugin} 加载器: {loader}..."
|
||||||
ms.plugin.event.map: "映射 {type} 事件 成功 总计 {count} 个 {type} 事件..."
|
ms.plugin.event.map: "总计 {count} 个 {type} 事件 映射完成..."
|
||||||
ms.plugin.event.map.error: "映射 {type} 事件 异常 将无法使用事件简称. Error: {error}"
|
ms.plugin.event.map.error: "映射 {type} 事件 异常 将无法使用事件简称. Error: {error}"
|
||||||
ms.plugin.manager.scan: "扫描器 {scanner} 扫描 {folder} 中的插件..."
|
ms.plugin.manager.scan: "扫描器 {scanner} 扫描 {folder} 中的插件..."
|
||||||
ms.plugin.manager.scan.finish: "扫描器 {scanner} 在 {folder} 中 发现 {size} 个插件 开始编译..."
|
ms.plugin.manager.scan.finish: "扫描器 {scanner} 在 {folder} 中 发现 {size} 个插件 开始构建..."
|
||||||
ms.plugin.manager.initialize.error: "§6插件 §b{name} §6初始化错误 §4{ex}"
|
ms.plugin.manager.initialize.error: "§6插件 §b{name} §6初始化错误 §4{ex}"
|
||||||
ms.plugin.manager.stage: "{stage} {plugin} 版本 {version} 作者 {author}"
|
ms.plugin.manager.stage: "{stage} {plugin} 版本 {version} 作者 {author}"
|
||||||
ms.plugin.manager.stage.exec: "[{plugin}] 执行 {stage} 阶段函数 {name} 匹配类型 {servers}..."
|
ms.plugin.manager.stage.exec: "[{plugin}] 执行 {stage} 阶段函数 {name} 匹配类型 {servers}..."
|
||||||
@@ -45,7 +45,7 @@ ms.plugin.manager.stage.exec.error: "§6插件 §b{plugin} §6执行 §d{executo
|
|||||||
ms.plugin.manager.stage.load: "加载"
|
ms.plugin.manager.stage.load: "加载"
|
||||||
ms.plugin.manager.stage.enable: "启用"
|
ms.plugin.manager.stage.enable: "启用"
|
||||||
ms.plugin.manager.stage.disable: "关闭"
|
ms.plugin.manager.stage.disable: "关闭"
|
||||||
ms.plugin.manager.build: "插件 {name}({version}) 编译完成 来源: {file}({scanner}) 引导: {loader} 编译耗时: {cost}s."
|
ms.plugin.manager.build: "插件 {name}({version}) 构建完成 来源: {file}({scanner}) 引导: {loader} 构建耗时: {cost}s."
|
||||||
ms.plugin.manager.build.error: "§6从文件 §b{file} §6加载插件失败 §4错误: §c{error}"
|
ms.plugin.manager.build.error: "§6从文件 §b{file} §6加载插件失败 §4错误: §c{error}"
|
||||||
ms.plugin.manager.build.update: "自动更新插件 {name} ..."
|
ms.plugin.manager.build.update: "自动更新插件 {name} ..."
|
||||||
ms.plugin.manager.build.not.extends: "§4发现错误的插件 §b{source} §4未继承接口 interfaces.Plugin, 将不会被载入到服务器!"
|
ms.plugin.manager.build.not.extends: "§4发现错误的插件 §b{source} §4未继承接口 interfaces.Plugin, 将不会被载入到服务器!"
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@ccms/i18n",
|
"name": "@ccms/i18n",
|
||||||
"version": "0.28.0-beta.4",
|
"version": "0.20.0-alpha.0",
|
||||||
"description": "MiaoScript i18n package",
|
"description": "MiaoScript i18n package",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"miaoscript",
|
"miaoscript",
|
||||||
@@ -12,19 +12,18 @@
|
|||||||
"homepage": "https://github.com/circlecloud/ms.git",
|
"homepage": "https://github.com/circlecloud/ms.git",
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"main": "dist/index.js",
|
"main": "dist/index.js",
|
||||||
"files": [
|
|
||||||
"dist",
|
|
||||||
"languages"
|
|
||||||
],
|
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"clean": "rimraf dist",
|
"clean": "rimraf dist",
|
||||||
"watch": "tsc --watch",
|
"watch": "tsc --watch",
|
||||||
"build": "pnpm clean && tsc",
|
"build": "yarn clean && tsc",
|
||||||
"test": "echo \"Error: run tests from root\" && exit 1"
|
"test": "echo \"Error: run tests from root\" && exit 1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@ccms/nashorn": "^0.28.0-beta.4",
|
"@ccms/nashorn": "^0.19.0",
|
||||||
"@types/js-yaml": "^4.0.5"
|
"@types/js-yaml": "^4.0.5",
|
||||||
|
"reflect-metadata": "^0.1.13",
|
||||||
|
"rimraf": "^3.0.2",
|
||||||
|
"typescript": "^4.5.5"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"js-yaml": "^4.1.0"
|
"js-yaml": "^4.1.0"
|
||||||
|
|||||||
1
packages/keyvalue/.npmignore
Symbolic link
1
packages/keyvalue/.npmignore
Symbolic link
@@ -0,0 +1 @@
|
|||||||
|
../../.npmignore
|
||||||
36
packages/keyvalue/package.json
Normal file
36
packages/keyvalue/package.json
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
{
|
||||||
|
"name": "@ccms/keyvalue",
|
||||||
|
"version": "0.20.0-alpha.0",
|
||||||
|
"description": "MiaoScript keyvalue package",
|
||||||
|
"keywords": [
|
||||||
|
"miaoscript",
|
||||||
|
"minecraft",
|
||||||
|
"bukkit",
|
||||||
|
"sponge"
|
||||||
|
],
|
||||||
|
"author": "MiaoWoo <admin@yumc.pw>",
|
||||||
|
"homepage": "https://github.com/circlecloud/ms.git",
|
||||||
|
"license": "ISC",
|
||||||
|
"main": "dist/index.js",
|
||||||
|
"scripts": {
|
||||||
|
"clean": "rimraf dist",
|
||||||
|
"watch": "tsc --watch",
|
||||||
|
"build": "yarn clean && tsc",
|
||||||
|
"test": "echo \"Error: run tests from root\" && exit 1"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@ccms/api": "^0.20.0-alpha.0",
|
||||||
|
"@ccms/common": "^0.19.0",
|
||||||
|
"@ccms/container": "^0.19.0"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@ccms/nashorn": "^0.19.0",
|
||||||
|
"@javatypes/amqp-client": "^0.0.3",
|
||||||
|
"@javatypes/spring-amqp": "^0.0.3",
|
||||||
|
"@javatypes/spring-rabbit": "^0.0.3",
|
||||||
|
"reflect-metadata": "^0.1.13",
|
||||||
|
"rimraf": "^3.0.2",
|
||||||
|
"typescript": "^4.5.5"
|
||||||
|
},
|
||||||
|
"gitHead": "2589633069d24f646ac09261b1b2304c21d4ea75"
|
||||||
|
}
|
||||||
3
packages/keyvalue/src/index.ts
Normal file
3
packages/keyvalue/src/index.ts
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
/// <reference types="@ccms/nashorn" />
|
||||||
|
/// <reference types="@javatypes/jdk" />
|
||||||
|
export { }
|
||||||
7
packages/keyvalue/tsconfig.json
Normal file
7
packages/keyvalue/tsconfig.json
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"extends": "../../tsconfig.json",
|
||||||
|
"compilerOptions": {
|
||||||
|
"baseUrl": "src",
|
||||||
|
"outDir": "dist"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,16 +1,13 @@
|
|||||||
{
|
{
|
||||||
"name": "@ccms/molang",
|
"name": "@ccms/molang",
|
||||||
"version": "0.28.0-beta.4",
|
"version": "0.19.0",
|
||||||
"description": "A fast parser for Minecraft's MoLang",
|
"description": "A fast parser for Minecraft's MoLang",
|
||||||
"main": "dist/index.js",
|
"main": "dist/index.js",
|
||||||
"types": "dist/index.d.ts",
|
"types": "dist/index.d.ts",
|
||||||
"files": [
|
|
||||||
"dist"
|
|
||||||
],
|
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"clean": "rimraf dist",
|
"clean": "rimraf dist",
|
||||||
"watch": "tsc --watch",
|
"watch": "tsc --watch",
|
||||||
"build": "pnpm clean && tsc",
|
"build": "yarn clean && tsc",
|
||||||
"test": "echo \"Error: run tests from root\" && exit 1"
|
"test": "echo \"Error: run tests from root\" && exit 1"
|
||||||
},
|
},
|
||||||
"repository": {
|
"repository": {
|
||||||
@@ -24,6 +21,9 @@
|
|||||||
},
|
},
|
||||||
"homepage": "https://github.com/solvedDev/MoLang#readme",
|
"homepage": "https://github.com/solvedDev/MoLang#readme",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/node": "^18.17.15"
|
"@types/node": "^17.0.17",
|
||||||
|
"rimraf": "^3.0.2",
|
||||||
|
"tslib": "^2.3.1",
|
||||||
|
"typescript": "^4.5.5"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "@ccms/nashorn",
|
"name": "@ccms/nashorn",
|
||||||
"version": "0.28.0-beta.4",
|
"version": "0.19.0",
|
||||||
"description": "MiaoScript nashorn package",
|
"description": "MiaoScript api package",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"miaoscript",
|
"miaoscript",
|
||||||
"minecraft",
|
"minecraft",
|
||||||
@@ -13,13 +13,15 @@
|
|||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"main": "dist/index.js",
|
"main": "dist/index.js",
|
||||||
"types": "dist/index.d.ts",
|
"types": "dist/index.d.ts",
|
||||||
"files": [
|
|
||||||
"dist"
|
|
||||||
],
|
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"clean": "rimraf dist",
|
"clean": "rimraf dist",
|
||||||
"watch": "tsc --watch",
|
"watch": "tsc --watch",
|
||||||
"build": "pnpm clean && tsc",
|
"build": "yarn clean && tsc",
|
||||||
"test": "echo \"Error: run tests from root\" && exit 1"
|
"test": "echo \"Error: run tests from root\" && exit 1"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"reflect-metadata": "^0.1.13",
|
||||||
|
"rimraf": "^3.0.2",
|
||||||
|
"typescript": "^4.5.5"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -48,34 +48,10 @@ declare global {
|
|||||||
scope: string
|
scope: string
|
||||||
logger: any
|
logger: any
|
||||||
debug: boolean
|
debug: boolean
|
||||||
/**
|
level: string
|
||||||
* 引擎日志等级
|
|
||||||
*/
|
|
||||||
ScriptEngineLoggerLevel: string
|
|
||||||
/**
|
|
||||||
* 引擎配置
|
|
||||||
*/
|
|
||||||
ScriptEngineConfig: any
|
|
||||||
/**
|
|
||||||
* 引擎版本
|
|
||||||
*/
|
|
||||||
ScriptEngineVersion: string
|
ScriptEngineVersion: string
|
||||||
/**
|
|
||||||
* 引擎渠道
|
|
||||||
*/
|
|
||||||
ScriptEngineChannel: string
|
|
||||||
/**
|
|
||||||
* 慢执行检测时间
|
|
||||||
*/
|
|
||||||
ScriptSlowExecuteTime: number
|
ScriptSlowExecuteTime: number
|
||||||
ScriptEngineStartTime: number
|
ScriptEngineStartTime: number
|
||||||
/**
|
|
||||||
* 设置全局对象
|
|
||||||
* @param key 对象名称
|
|
||||||
* @param value 对象值
|
|
||||||
* @param config 对象属性
|
|
||||||
* @returns
|
|
||||||
*/
|
|
||||||
setGlobal: (key: string, value: any, config?: PropertyDescriptor & ThisType<any>) => void
|
setGlobal: (key: string, value: any, config?: PropertyDescriptor & ThisType<any>) => void
|
||||||
noop: () => void
|
noop: () => void
|
||||||
console: Console
|
console: Console
|
||||||
@@ -95,7 +71,6 @@ declare global {
|
|||||||
getProxyClass(): any
|
getProxyClass(): any
|
||||||
getJavaScriptTaskClass(): any
|
getJavaScriptTaskClass(): any
|
||||||
getInstance(): any
|
getInstance(): any
|
||||||
loadMavenDepend(groupId: string, artifactId: string, version: string): [any, any]
|
|
||||||
read(path: string): string
|
read(path: string): string
|
||||||
save(path: string, content: string): void
|
save(path: string, content: string): void
|
||||||
delete(path: string): void
|
delete(path: string): void
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@ccms/nodejs",
|
"name": "@ccms/nodejs",
|
||||||
"version": "0.28.0-beta.4",
|
"version": "0.19.0",
|
||||||
"description": "MiaoScript nodejs package",
|
"description": "MiaoScript nodejs package",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"miaoscript",
|
"miaoscript",
|
||||||
@@ -12,17 +12,18 @@
|
|||||||
"homepage": "https://github.com/circlecloud/ms.git",
|
"homepage": "https://github.com/circlecloud/ms.git",
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"main": "dist/index.js",
|
"main": "dist/index.js",
|
||||||
"files": [
|
|
||||||
"dist"
|
|
||||||
],
|
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"clean": "rimraf dist",
|
"clean": "rimraf dist",
|
||||||
"watch": "tsc --watch",
|
"watch": "tsc --watch",
|
||||||
"build": "pnpm clean && tsc",
|
"build": "yarn clean && tsc",
|
||||||
"test": "echo \"Error: run tests from root\" && exit 1"
|
"test": "echo \"Error: run tests from root\" && exit 1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@ccms/nashorn": "^0.28.0-beta.4"
|
"@ccms/nashorn": "^0.19.0",
|
||||||
|
"reflect-metadata": "^0.1.13",
|
||||||
|
"rimraf": "^3.0.2",
|
||||||
|
"tslib": "^2.3.1",
|
||||||
|
"typescript": "^4.5.5"
|
||||||
},
|
},
|
||||||
"gitHead": "781524f83e52cad26d7c480513e3c525df867121"
|
"gitHead": "781524f83e52cad26d7c480513e3c525df867121"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,7 +20,6 @@
|
|||||||
// USE OR OTHER DEALINGS IN THE SOFTWARE.
|
// USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
var Throwable = Java.type('java.lang.Throwable')
|
|
||||||
var R = typeof Reflect === 'object' ? Reflect : null
|
var R = typeof Reflect === 'object' ? Reflect : null
|
||||||
var ReflectApply = R && typeof R.apply === 'function'
|
var ReflectApply = R && typeof R.apply === 'function'
|
||||||
? R.apply
|
? R.apply
|
||||||
@@ -137,19 +136,13 @@ EventEmitter.prototype.emit = function emit(type) {
|
|||||||
var er;
|
var er;
|
||||||
if (args.length > 0)
|
if (args.length > 0)
|
||||||
er = args[0];
|
er = args[0];
|
||||||
if (er instanceof Error || er instanceof Throwable) {
|
if (er instanceof Error) {
|
||||||
// Note: The comments on the `throw` lines are intentional, they show
|
// Note: The comments on the `throw` lines are intentional, they show
|
||||||
// up in Node's output if this results in an unhandled exception.
|
// up in Node's output if this results in an unhandled exception.
|
||||||
throw er; // Unhandled 'error' event
|
throw er; // Unhandled 'error' event
|
||||||
}
|
}
|
||||||
if (er.error instanceof Error || er.error instanceof Throwable) {
|
|
||||||
throw er.error; // Unhandled 'error' event
|
|
||||||
}
|
|
||||||
if (er.cause instanceof Error || er.cause instanceof Throwable) {
|
|
||||||
throw er.cause; // Unhandled 'error' event
|
|
||||||
}
|
|
||||||
// At least give some kind of context to the user
|
// At least give some kind of context to the user
|
||||||
var err = new Error('Unhandled error.' + (er ? ' (' + (er.message || er.error || er.cause || er) + ')' : ''));
|
var err = new Error('Unhandled error.' + (er ? ' (' + er.message + ')' : ''));
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
err.context = er;
|
err.context = er;
|
||||||
throw err; // Unhandled 'error' event
|
throw err; // Unhandled 'error' event
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ const Path = Java.type("java.nio.file.Path");
|
|||||||
const JavaString = Java.type("java.lang.String");
|
const JavaString = Java.type("java.lang.String");
|
||||||
const File = Java.type("java.io.File");
|
const File = Java.type("java.io.File");
|
||||||
const Files = Java.type("java.nio.file.Files");
|
const Files = Java.type("java.nio.file.Files");
|
||||||
const Paths = Java.type("java.nio.file.Paths");
|
|
||||||
const Collector = Java.type("java.util.stream.Collector")
|
const Collector = Java.type("java.util.stream.Collector")
|
||||||
const separatorChar = File.separatorChar;
|
const separatorChar = File.separatorChar;
|
||||||
const StandardCopyOption = Java.type("java.nio.file.StandardCopyOption");
|
const StandardCopyOption = Java.type("java.nio.file.StandardCopyOption");
|
||||||
@@ -38,7 +37,7 @@ function javaFile(...opts: any[]) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function renameSync(oldPath: PathLike, newPath: PathLike): void {
|
export function renameSync(oldPath: PathLike, newPath: PathLike): void {
|
||||||
Files.move(Paths.get(oldPath), Paths.get(oldPath), StandardCopyOption['ATOMIC_MOVE'])
|
|
||||||
}
|
}
|
||||||
export function truncateSync() {
|
export function truncateSync() {
|
||||||
|
|
||||||
|
|||||||
@@ -715,7 +715,6 @@ function callbackify(original) {
|
|||||||
// implications (stack, `uncaughtException`, `async_hooks`)
|
// implications (stack, `uncaughtException`, `async_hooks`)
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
original.apply(this, args)
|
original.apply(this, args)
|
||||||
// @ts-ignore
|
|
||||||
.then(function (ret) { process.nextTick(cb.bind(null, null, ret)) },
|
.then(function (ret) { process.nextTick(cb.bind(null, null, ret)) },
|
||||||
function (rej) { process.nextTick(callbackifyOnRejected.bind(null, rej, cb)) });
|
function (rej) { process.nextTick(callbackifyOnRejected.bind(null, rej, cb)) });
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@ccms/nukkit",
|
"name": "@ccms/nukkit",
|
||||||
"version": "0.28.0-beta.4",
|
"version": "0.20.0-alpha.0",
|
||||||
"description": "MiaoScript nukkit package",
|
"description": "MiaoScript nukkit package",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"miaoscript",
|
"miaoscript",
|
||||||
@@ -12,21 +12,21 @@
|
|||||||
"homepage": "https://github.com/circlecloud/ms.git",
|
"homepage": "https://github.com/circlecloud/ms.git",
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"main": "dist/index.js",
|
"main": "dist/index.js",
|
||||||
"files": [
|
|
||||||
"dist"
|
|
||||||
],
|
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"clean": "rimraf dist",
|
"clean": "rimraf dist",
|
||||||
"watch": "tsc --watch",
|
"watch": "tsc --watch",
|
||||||
"build": "pnpm clean && tsc",
|
"build": "yarn clean && tsc",
|
||||||
"test": "echo \"Error: run tests from root\" && exit 1"
|
"test": "echo \"Error: run tests from root\" && exit 1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@javatypes/nukkit-api": "^0.0.3"
|
"@javatypes/nukkit-api": "^0.0.3",
|
||||||
|
"reflect-metadata": "^0.1.13",
|
||||||
|
"rimraf": "^3.0.2",
|
||||||
|
"typescript": "^4.5.5"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@ccms/api": "^0.28.0-beta.4",
|
"@ccms/api": "^0.20.0-alpha.0",
|
||||||
"@ccms/common": "^0.28.0-beta.4",
|
"@ccms/common": "^0.19.0",
|
||||||
"@ccms/container": "^0.28.0-beta.4"
|
"@ccms/container": "^0.19.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "@ccms/plugin",
|
"name": "@ccms/plugin",
|
||||||
"version": "0.28.0-beta.4",
|
"version": "0.20.0-alpha.0",
|
||||||
"description": "MiaoScript plugin package",
|
"description": "MiaoScript api package",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"miaoscript",
|
"miaoscript",
|
||||||
"minecraft",
|
"minecraft",
|
||||||
@@ -12,25 +12,24 @@
|
|||||||
"homepage": "https://github.com/circlecloud/ms.git",
|
"homepage": "https://github.com/circlecloud/ms.git",
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"main": "dist/index.js",
|
"main": "dist/index.js",
|
||||||
"files": [
|
|
||||||
"dist"
|
|
||||||
],
|
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"clean": "rimraf dist",
|
"clean": "rimraf dist",
|
||||||
"watch": "tsc --watch",
|
"watch": "tsc --watch",
|
||||||
"build": "pnpm clean && tsc",
|
"build": "yarn clean && tsc",
|
||||||
"test": "echo \"Error: run tests from root\" && exit 1"
|
"test": "echo \"Error: run tests from root\" && exit 1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/crypto-js": "^4.1.2",
|
"@types/crypto-js": "^4.1.1",
|
||||||
"@types/js-yaml": "^4.0.5"
|
"@types/js-yaml": "^4.0.5",
|
||||||
|
"reflect-metadata": "^0.1.13",
|
||||||
|
"rimraf": "^3.0.2",
|
||||||
|
"typescript": "^4.5.5"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@ccms/api": "^0.28.0-beta.4",
|
"@ccms/api": "^0.20.0-alpha.0",
|
||||||
"@ccms/common": "^0.28.0-beta.4",
|
"@ccms/common": "^0.19.0",
|
||||||
"@ccms/container": "^0.28.0-beta.4",
|
"@ccms/container": "^0.19.0",
|
||||||
"@ccms/i18n": "^0.28.0-beta.4",
|
"@ccms/i18n": "^0.20.0-alpha.0",
|
||||||
"@ccms/verify": "^0.26.1",
|
|
||||||
"crypto-js": "^4.1.1",
|
"crypto-js": "^4.1.1",
|
||||||
"js-yaml": "^4.1.0"
|
"js-yaml": "^4.1.0"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,51 +15,51 @@ export class PluginCommandManager {
|
|||||||
process.on('plugin.after.disable', this.unregistryCommand.bind(this))
|
process.on('plugin.after.disable', this.unregistryCommand.bind(this))
|
||||||
}
|
}
|
||||||
|
|
||||||
public registryCommand(pluginInstance: plugin.Plugin, executor: any = pluginInstance) {
|
private registryCommand(pluginInstance: plugin.Plugin) {
|
||||||
let cmds = getPluginCommandMetadata(executor)
|
let cmds = getPluginCommandMetadata(pluginInstance)
|
||||||
let tabs = getPluginTabCompleterMetadata(executor)
|
let tabs = getPluginTabCompleterMetadata(pluginInstance)
|
||||||
for (const cmd of cmds) {
|
for (const cmd of cmds) {
|
||||||
if (!this.ServerChecker.check(cmd.servers)) {
|
if (!this.ServerChecker.check(cmd.servers)) {
|
||||||
console.debug(`[${pluginInstance.description.name}] ${cmd.target.constructor.name} incompatible command ${cmd.name} server(${cmd.servers}) ignore.`)
|
console.debug(`[${pluginInstance.description.name}] ${cmd.target.constructor.name} incompatible command ${cmd.name} server(${cmd.servers}) ignore.`)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
for (let command of [cmd.name, ...cmd.alias]) {
|
for (let command of [cmd.name, ...cmd.alias]) {
|
||||||
let [cmdExecutor, cmdCompleter] = this.generateAutoMainCommand(pluginInstance, executor, cmd, tabs.get(command))
|
let [cmdExecutor, cmdCompleter] = this.generateAutoMainCommand(pluginInstance, cmd, tabs.get(command))
|
||||||
this.CommandManager.on(pluginInstance, command, {
|
this.CommandManager.on(pluginInstance, command, {
|
||||||
cmd: cmdExecutor.bind(executor),
|
cmd: cmdExecutor.bind(pluginInstance),
|
||||||
tab: cmdCompleter?.bind(executor)
|
tab: cmdCompleter?.bind(pluginInstance)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public unregistryCommand(pluginInstance: plugin.Plugin, executor: any = pluginInstance) {
|
private unregistryCommand(pluginInstance: plugin.Plugin) {
|
||||||
let cmds = getPluginCommandMetadata(executor)
|
let cmds = getPluginCommandMetadata(pluginInstance)
|
||||||
for (const cmd of cmds) {
|
for (const cmd of cmds) {
|
||||||
if (!this.ServerChecker.check(cmd.servers)) {
|
if (!this.ServerChecker.check(cmd.servers)) {
|
||||||
console.debug(`[${pluginInstance.description.name}] ${cmd.target.constructor.name} incompatible command ${cmd.name} server(${cmd.servers}) ignore.`)
|
console.debug(`[${pluginInstance.description.name}] ${cmd.target.constructor.name} incompatible command ${cmd.name} server(${cmd.servers}) ignore.`)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
for (let command of [cmd.name, ...cmd.alias]) {
|
for (let command of [cmd.name, ...cmd.alias]) {
|
||||||
this.CommandManager.off(executor, command)
|
this.CommandManager.off(pluginInstance, command)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private generateAutoMainCommand(pluginInstance: plugin.Plugin, executor: any, cmd: interfaces.CommandMetadata, tab: interfaces.CommandMetadata) {
|
private generateAutoMainCommand(pluginInstance: plugin.Plugin, cmd: interfaces.CommandMetadata, tab: interfaces.CommandMetadata) {
|
||||||
let cmdExecutor = executor[cmd.executor]
|
let cmdExecutor = pluginInstance[cmd.executor]
|
||||||
let cmdCompleter = tab ? executor[tab.executor] : undefined
|
let cmdCompleter = tab ? pluginInstance[tab.executor] : undefined
|
||||||
let cmdSubCache = Object.keys(executor.constructor.prototype).filter(s => s.startsWith('cmd')).map(s => s.substring(3))
|
let cmdSubCache = Object.keys(pluginInstance.constructor.prototype).filter(s => s.startsWith('cmd')).map(s => s.substring(3))
|
||||||
if (cmd.autoMain) {
|
if (cmd.autoMain) {
|
||||||
cmdExecutor = (sender: any, command: string, args: string[]) => {
|
cmdExecutor = (sender: any, command: string, args: string[]) => {
|
||||||
let subcommand = args[0]
|
let subcommand = args[0]
|
||||||
let cmdKey = 'cmd' + subcommand
|
let cmdKey = 'cmd' + subcommand
|
||||||
if (!cmdSubCache.includes(subcommand)) {
|
if (!cmdSubCache.includes(subcommand)) {
|
||||||
if (!executor[cmd.executor].apply(executor, [sender, command, args])) {
|
if (!pluginInstance[cmd.executor].apply(pluginInstance, [sender, command, args])) {
|
||||||
subcommand && pluginInstance.logger.sender(sender, `§4未知的命令: §b/${command} §c${subcommand}`)
|
subcommand && pluginInstance.logger.sender(sender, '§4未知的子命令: §c' + subcommand)
|
||||||
pluginInstance.logger.sender(
|
pluginInstance.logger.sender(
|
||||||
sender,
|
sender,
|
||||||
executor['cmdhelp'] ?
|
pluginInstance['cmdhelp'] ?
|
||||||
`§6请执行 §b/${command} §ahelp §6查看帮助!` :
|
`§6请执行 §b/${command} §ahelp §6查看帮助!` :
|
||||||
[
|
[
|
||||||
`§6插件: §b${pluginInstance.description.name}`,
|
`§6插件: §b${pluginInstance.description.name}`,
|
||||||
@@ -69,7 +69,7 @@ export class PluginCommandManager {
|
|||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
let subcommandexec = executor[cmdKey]
|
let subcommandexec = pluginInstance[cmdKey]
|
||||||
let permission: string
|
let permission: string
|
||||||
if (cmd.permission && sender.hasPermission) {
|
if (cmd.permission && sender.hasPermission) {
|
||||||
if (typeof cmd.permission == "string") {
|
if (typeof cmd.permission == "string") {
|
||||||
@@ -78,11 +78,11 @@ export class PluginCommandManager {
|
|||||||
permission = `${pluginInstance.description.name.toLocaleLowerCase()}.${command}.${subcommand || 'main'}`
|
permission = `${pluginInstance.description.name.toLocaleLowerCase()}.${command}.${subcommand || 'main'}`
|
||||||
}
|
}
|
||||||
if (!sender.hasPermission(permission)) {
|
if (!sender.hasPermission(permission)) {
|
||||||
return pluginInstance.logger.sender(sender, `§c你需要 §4${permission} §c权限 才可执行此命令.`)
|
return pluginInstance.logger.sender(sender, `§c你需要 ${permission} 权限 才可执行此命令.`)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
args.shift()
|
args.shift()
|
||||||
return subcommandexec.apply(executor, [sender, ...args])
|
return subcommandexec.apply(pluginInstance, [sender, ...args])
|
||||||
}
|
}
|
||||||
let originCompleter = cmdCompleter
|
let originCompleter = cmdCompleter
|
||||||
cmdCompleter = (sender: any, command: string, args: string[]) => {
|
cmdCompleter = (sender: any, command: string, args: string[]) => {
|
||||||
@@ -95,10 +95,10 @@ export class PluginCommandManager {
|
|||||||
}
|
}
|
||||||
if (!sender.hasPermission(permission)) { return [] }
|
if (!sender.hasPermission(permission)) { return [] }
|
||||||
}
|
}
|
||||||
return (args.length == 1 ? cmdSubCache : []).concat(originCompleter?.apply(executor, [sender, command, args]) || [])
|
return (args.length == 1 ? cmdSubCache : []).concat(originCompleter?.apply(pluginInstance, [sender, command, args]) || [])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!cmdCompleter) { console.debug(`[${pluginInstance.description.name}] command ${cmd.name} is not registry tabCompleter`) }
|
if (!cmdCompleter) { console.warn(`[${pluginInstance.description.name}] command ${cmd.name} is not registry tabCompleter`) }
|
||||||
return [cmdExecutor, cmdCompleter]
|
return [cmdExecutor, cmdCompleter]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,7 +7,8 @@ import { interfaces } from './interfaces'
|
|||||||
import { getPluginConfigMetadata } from './utils'
|
import { getPluginConfigMetadata } from './utils'
|
||||||
|
|
||||||
import { PluginConfigLoader } from './config/interfaces'
|
import { PluginConfigLoader } from './config/interfaces'
|
||||||
import './config/loader'
|
import './config/loader/json-loader'
|
||||||
|
import './config/loader/yaml-loader'
|
||||||
|
|
||||||
@provideSingleton(PluginConfigManager)
|
@provideSingleton(PluginConfigManager)
|
||||||
export class PluginConfigManager {
|
export class PluginConfigManager {
|
||||||
@@ -67,25 +68,30 @@ export class PluginConfigManager {
|
|||||||
private loadConfig0(plugin: plugin.Plugin, metadata: interfaces.ConfigMetadata) {
|
private loadConfig0(plugin: plugin.Plugin, metadata: interfaces.ConfigMetadata) {
|
||||||
try {
|
try {
|
||||||
let defaultValue = metadata.default ?? plugin[metadata.variable]
|
let defaultValue = metadata.default ?? plugin[metadata.variable]
|
||||||
metadata.file = fs.concat(
|
let configValue = defaultValue || {}
|
||||||
fs.file(plugin.description.loadMetadata.file).parent,
|
if (defaultValue) {
|
||||||
plugin.description.name,
|
metadata.file = fs.concat(
|
||||||
metadata.filename
|
fs.file(plugin.description.loadMetadata.file).parent,
|
||||||
)
|
plugin.description.name,
|
||||||
let configLoader = this.getConfigLoader(metadata.format)
|
metadata.filename
|
||||||
if (!fs.exists(metadata.file) && defaultValue) {
|
)
|
||||||
base.save(metadata.file, configLoader.dump(defaultValue))
|
let configLoader = this.getConfigLoader(metadata.format)
|
||||||
console.i18n("ms.plugin.manager.config.save.default", {
|
if (!fs.exists(metadata.file)) {
|
||||||
plugin: plugin.description.name,
|
base.save(metadata.file, configLoader.dump(defaultValue))
|
||||||
name: metadata.name,
|
console.i18n("ms.plugin.manager.config.save.default", {
|
||||||
format: metadata.format
|
plugin: plugin.description.name,
|
||||||
})
|
name: metadata.name,
|
||||||
|
format: metadata.format
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
configValue = configLoader.load(base.read(metadata.file)) || {}
|
||||||
|
if (defaultValue && this.setDefaultValue(configValue, defaultValue, !!metadata.default)) {
|
||||||
|
base.save(metadata.file, configLoader.dump(configValue))
|
||||||
|
}
|
||||||
|
console.debug(`[${plugin.description.name}] Load Config ${metadata.variable} from file ${metadata.file} =>
|
||||||
|
${JSON.stringify(configValue, undefined, 4).substring(0, 500)}`)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
let configValue = configLoader.load(base.read(metadata.file)) || {}
|
|
||||||
if (metadata.migrate && defaultValue && this.setDefaultValue(configValue, defaultValue, !!metadata.default)) {
|
|
||||||
base.save(metadata.file, configLoader.dump(configValue))
|
|
||||||
}
|
|
||||||
console.debug(`[${plugin.description.name}] Load Config ${metadata.variable} from file ${metadata.file}`)
|
|
||||||
this.defienConfigProp(plugin, metadata, configValue)
|
this.defienConfigProp(plugin, metadata, configValue)
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
console.i18n("ms.plugin.manager.config.load.error", {
|
console.i18n("ms.plugin.manager.config.load.error", {
|
||||||
|
|||||||
@@ -1,3 +0,0 @@
|
|||||||
export * from "./loader"
|
|
||||||
export * from "./interfaces"
|
|
||||||
export * from "./file-config"
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
export * from './json-loader'
|
|
||||||
export * from './yaml-loader'
|
|
||||||
@@ -76,7 +76,6 @@ export function config(metadata: interfaces.ConfigMetadata = {}) {
|
|||||||
metadata.variable = key
|
metadata.variable = key
|
||||||
metadata.version = metadata.version ?? 1
|
metadata.version = metadata.version ?? 1
|
||||||
metadata.format = metadata.format ?? 'yml'
|
metadata.format = metadata.format ?? 'yml'
|
||||||
metadata.migrate = metadata.migrate ?? true
|
|
||||||
metadata.autosave = metadata.autosave ?? false
|
metadata.autosave = metadata.autosave ?? false
|
||||||
metadata.filename = metadata.filename ?? metadata.name + '.' + metadata.format
|
metadata.filename = metadata.filename ?? metadata.name + '.' + metadata.format
|
||||||
let previousMetadata = getPluginConfigMetadata(target)
|
let previousMetadata = getPluginConfigMetadata(target)
|
||||||
|
|||||||
@@ -5,13 +5,9 @@ import { getPluginListenerMetadata } from './utils'
|
|||||||
@provideSingleton(PluginEventManager)
|
@provideSingleton(PluginEventManager)
|
||||||
export class PluginEventManager {
|
export class PluginEventManager {
|
||||||
@Autowired()
|
@Autowired()
|
||||||
private eventManager: event.Event
|
private EventManager: event.Event
|
||||||
@Autowired()
|
@Autowired()
|
||||||
private serverChecker: server.ServerChecker
|
private ServerChecker: server.ServerChecker
|
||||||
@Autowired()
|
|
||||||
private nativePluginChecker: server.NativePluginChecker
|
|
||||||
|
|
||||||
private listenerMap = [];
|
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
process.on('plugin.before.enable', this.registryListener.bind(this))
|
process.on('plugin.before.enable', this.registryListener.bind(this))
|
||||||
@@ -19,44 +15,26 @@ export class PluginEventManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
mapEventName() {
|
mapEventName() {
|
||||||
return this.eventManager.mapEventName().toFixed(0)
|
return this.EventManager.mapEventName().toFixed(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
public registryListener(pluginInstance: plugin.Plugin, listener: any = pluginInstance) {
|
private registryListener(pluginInstance: plugin.Plugin) {
|
||||||
let events = getPluginListenerMetadata(listener)
|
let events = getPluginListenerMetadata(pluginInstance)
|
||||||
let execes = []
|
|
||||||
for (const event of events) {
|
for (const event of events) {
|
||||||
// ignore space listener
|
// ignore space listener
|
||||||
if (!this.serverChecker.check(event.servers)) {
|
if (!this.ServerChecker.check(event.servers)) {
|
||||||
console.debug(`[${pluginInstance.description.name}] ${event.target.constructor.name} incompatible server(${event.servers}) ignore event ${event.name}.`)
|
console.debug(`[${pluginInstance.description.name}] ${event.target.constructor.name} incompatible event ${event.name} server(${event.servers}) ignore.`)
|
||||||
continue
|
|
||||||
}
|
|
||||||
// ignore space listener
|
|
||||||
if (!this.nativePluginChecker.check(event.plugins)) {
|
|
||||||
console.debug(`[${pluginInstance.description.name}] ${event.target.constructor.name} require native plugins(${event.plugins}) ignore event ${event.name}.`)
|
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
// here must bind this to pluginInstance
|
// here must bind this to pluginInstance
|
||||||
let exec = event.target[event.executor]
|
let exec = event.target[event.executor]
|
||||||
let execBinded = exec.bind(listener)
|
let execBinded = exec.bind(pluginInstance)
|
||||||
execBinded.executor = event.executor
|
execBinded.executor = event.executor
|
||||||
exec.off = this.eventManager.listen(pluginInstance, event.name, execBinded, event.priority, event.ignoreCancel)
|
exec.off = this.EventManager.listen(pluginInstance, event.name, execBinded, event.priority, event.ignoreCancel)
|
||||||
execes.push(exec)
|
|
||||||
}
|
}
|
||||||
let off = () => {
|
|
||||||
if (off['offed']) return
|
|
||||||
off['offed'] = true
|
|
||||||
execes.forEach((exec: { off: () => void }) => exec.off())
|
|
||||||
}
|
|
||||||
listener.off = off
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public unregistryListener(pluginInstance: plugin.Plugin, listener: any = pluginInstance) {
|
private unregistryListener(pluginInstance: plugin.Plugin) {
|
||||||
if (listener && listener.off) {
|
this.EventManager.disable(pluginInstance)
|
||||||
listener.off()
|
|
||||||
}
|
|
||||||
if (pluginInstance) {
|
|
||||||
this.eventManager.disable(pluginInstance)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,18 +1,14 @@
|
|||||||
import '@ccms/verify'
|
import './scanner/ms-scanner'
|
||||||
import './scanner/js-scanner'
|
import './scanner/js-scanner'
|
||||||
|
|
||||||
import './loader/ioc-loader'
|
import './loader/ioc-loader'
|
||||||
import './loader/basic-loader'
|
import './loader/basic-loader'
|
||||||
|
|
||||||
export * from './config'
|
export * from './config'
|
||||||
export * from './config/config'
|
|
||||||
export * from './manager'
|
export * from './manager'
|
||||||
export * from './decorators'
|
export * from './decorators'
|
||||||
export * from './interfaces'
|
export * from './interfaces'
|
||||||
|
|
||||||
export * from './event'
|
|
||||||
export * from './command'
|
|
||||||
|
|
||||||
export {
|
export {
|
||||||
plugin as JSPlugin,
|
plugin as JSPlugin,
|
||||||
cmd as Cmd,
|
cmd as Cmd,
|
||||||
@@ -21,5 +17,3 @@ export {
|
|||||||
config as Config,
|
config as Config,
|
||||||
playerdata as PlayerData
|
playerdata as PlayerData
|
||||||
} from './decorators'
|
} from './decorators'
|
||||||
|
|
||||||
import '@ccms/database'
|
|
||||||
|
|||||||
@@ -1,8 +1,6 @@
|
|||||||
import { server, MiaoScriptConsole, event, plugin, task, command } from "@ccms/api"
|
import { server, MiaoScriptConsole, event, plugin } from "@ccms/api"
|
||||||
import { injectable, inject, postConstruct, Autowired } from "@ccms/container"
|
import { injectable, inject, postConstruct } from "@ccms/container"
|
||||||
import { getPluginMetadata } from "./utils"
|
import { getPluginMetadata } from "./utils"
|
||||||
import { PluginEventManager } from "./event"
|
|
||||||
import { PluginCommandManager } from "./command"
|
|
||||||
|
|
||||||
const File = Java.type('java.io.File')
|
const File = Java.type('java.io.File')
|
||||||
|
|
||||||
@@ -10,15 +8,9 @@ export namespace interfaces {
|
|||||||
@injectable()
|
@injectable()
|
||||||
export abstract class Plugin implements plugin.Plugin {
|
export abstract class Plugin implements plugin.Plugin {
|
||||||
public description: plugin.PluginMetadata
|
public description: plugin.PluginMetadata
|
||||||
public logger: MiaoScriptConsole
|
public logger: Console
|
||||||
@inject(server.Console)
|
@inject(server.Console)
|
||||||
private Console: MiaoScriptConsole
|
private Console: MiaoScriptConsole
|
||||||
@Autowired()
|
|
||||||
private taskManager: task.TaskManager
|
|
||||||
@Autowired()
|
|
||||||
private eventManager: PluginEventManager
|
|
||||||
@Autowired()
|
|
||||||
private commandManager: PluginCommandManager
|
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
this.description = getPluginMetadata(this)
|
this.description = getPluginMetadata(this)
|
||||||
@@ -36,43 +28,6 @@ export namespace interfaces {
|
|||||||
return dataFolder.getAbsolutePath()
|
return dataFolder.getAbsolutePath()
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 注册命令
|
|
||||||
* @param executor 命令执行器
|
|
||||||
*/
|
|
||||||
public registryCommand(executor: any) {
|
|
||||||
this.commandManager.registryCommand(this, executor)
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* 注销命令
|
|
||||||
* @param executor 命令执行器
|
|
||||||
*/
|
|
||||||
public unregistryCommand(executor: any) {
|
|
||||||
this.commandManager.unregistryCommand(this, executor)
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* 注册事件
|
|
||||||
* @param listener 事件监听器
|
|
||||||
*/
|
|
||||||
public registryListener(listener: any) {
|
|
||||||
this.eventManager.registryListener(this, listener)
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* 注销事件
|
|
||||||
* @param listener 事件监听器
|
|
||||||
*/
|
|
||||||
public unregistryListener(listener: any) {
|
|
||||||
this.eventManager.unregistryListener(this, listener)
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* 创建任务
|
|
||||||
* @param func 任务内容
|
|
||||||
* @returns 任务
|
|
||||||
*/
|
|
||||||
public createTask(func: Function) {
|
|
||||||
return this.taskManager.create(func, this)
|
|
||||||
}
|
|
||||||
|
|
||||||
public load() { }
|
public load() { }
|
||||||
public enable() { }
|
public enable() { }
|
||||||
public disable() { }
|
public disable() { }
|
||||||
@@ -118,10 +73,6 @@ export namespace interfaces {
|
|||||||
* 是否忽略已取消的事件
|
* 是否忽略已取消的事件
|
||||||
*/
|
*/
|
||||||
ignoreCancel?: boolean
|
ignoreCancel?: boolean
|
||||||
/**
|
|
||||||
* 依赖插件 没有就不加载
|
|
||||||
*/
|
|
||||||
plugins?: string[]
|
|
||||||
}
|
}
|
||||||
export interface ConfigMetadata extends plugin.BaseMetadata {
|
export interface ConfigMetadata extends plugin.BaseMetadata {
|
||||||
/**
|
/**
|
||||||
@@ -140,10 +91,6 @@ export namespace interfaces {
|
|||||||
* 配置文件格式 默认 yml
|
* 配置文件格式 默认 yml
|
||||||
*/
|
*/
|
||||||
format?: string
|
format?: string
|
||||||
/**
|
|
||||||
* 是否合并默认配置
|
|
||||||
*/
|
|
||||||
migrate?: boolean
|
|
||||||
/**
|
/**
|
||||||
* 自动保存 默认为 false
|
* 自动保存 默认为 false
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -63,13 +63,13 @@ export class IocLoader implements plugin.PluginLoader {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private bindPlugin(metadata: plugin.PluginMetadata) {
|
private bindPlugin(metadata: plugin.PluginMetadata) {
|
||||||
if (this.container.isBoundNamed(plugin.Plugin, metadata.name)) {
|
try {
|
||||||
let pluginInstance = this.container.getNamed<plugin.Plugin>(plugin.Plugin, metadata.name)
|
let pluginInstance = this.container.getNamed<plugin.Plugin>(plugin.Plugin, metadata.name)
|
||||||
if (pluginInstance.description.source + '' !== metadata.source + '') {
|
if (pluginInstance.description.source + '' !== metadata.source + '') {
|
||||||
console.i18n('ms.plugin.manager.build.duplicate', { exists: pluginInstance.description.source, source: metadata.source })
|
console.i18n('ms.plugin.manager.build.duplicate', { exists: pluginInstance.description.source, source: metadata.source })
|
||||||
}
|
}
|
||||||
this.container.rebind(plugin.Plugin).to(metadata.target).inSingletonScope().whenTargetNamed(metadata.name)
|
this.container.rebind(plugin.Plugin).to(metadata.target).inSingletonScope().whenTargetNamed(metadata.name)
|
||||||
} else {
|
} catch {
|
||||||
this.container.bind(plugin.Plugin).to(metadata.target).inSingletonScope().whenTargetNamed(metadata.name)
|
this.container.bind(plugin.Plugin).to(metadata.target).inSingletonScope().whenTargetNamed(metadata.name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,11 +2,12 @@ import i18n from '@ccms/i18n'
|
|||||||
import { plugin, server } from '@ccms/api'
|
import { plugin, server } from '@ccms/api'
|
||||||
import { provideSingleton, Container, ContainerInstance, Autowired } from '@ccms/container'
|
import { provideSingleton, Container, ContainerInstance, Autowired } from '@ccms/container'
|
||||||
|
|
||||||
|
import './config'
|
||||||
import { interfaces } from './interfaces'
|
import { interfaces } from './interfaces'
|
||||||
import { PluginTaskManager } from './task'
|
import { PluginTaskManager } from './task'
|
||||||
import { PluginEventManager } from './event'
|
import { PluginEventManager } from './event'
|
||||||
import { PluginConfigManager } from './config'
|
|
||||||
import { PluginCommandManager } from './command'
|
import { PluginCommandManager } from './command'
|
||||||
|
import { PluginConfigManager } from './config'
|
||||||
|
|
||||||
const Thread = Java.type('java.lang.Thread')
|
const Thread = Java.type('java.lang.Thread')
|
||||||
|
|
||||||
@@ -68,7 +69,7 @@ export class PluginManagerImpl implements plugin.PluginManager {
|
|||||||
try {
|
try {
|
||||||
console.i18n('ms.plugin.event.map', { count: this.eventManager.mapEventName(), type: this.serverType })
|
console.i18n('ms.plugin.event.map', { count: this.eventManager.mapEventName(), type: this.serverType })
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.i18n('ms.plugin.event.map.error', { type: this.serverType, error })
|
console.i18n('ms.plugin.event.map.error', { error })
|
||||||
}
|
}
|
||||||
let pluginScanner = this.container.getAll<plugin.PluginScanner>(plugin.PluginScanner)
|
let pluginScanner = this.container.getAll<plugin.PluginScanner>(plugin.PluginScanner)
|
||||||
pluginScanner.forEach((scanner) => {
|
pluginScanner.forEach((scanner) => {
|
||||||
@@ -92,17 +93,18 @@ export class PluginManagerImpl implements plugin.PluginManager {
|
|||||||
for (const [, scanner] of this.sacnnerMap) {
|
for (const [, scanner] of this.sacnnerMap) {
|
||||||
try {
|
try {
|
||||||
console.i18n('ms.plugin.manager.scan', { scanner: scanner.type, folder })
|
console.i18n('ms.plugin.manager.scan', { scanner: scanner.type, folder })
|
||||||
let loadMetadatas = scanner.scan(folder)
|
let plugins = scanner.scan(folder)
|
||||||
console.i18n('ms.plugin.manager.scan.finish', { scanner: scanner.type, folder, size: loadMetadatas.length })
|
console.i18n('ms.plugin.manager.scan.finish', { scanner: scanner.type, folder, size: plugins.length })
|
||||||
for (const loadMetadata of loadMetadatas) {
|
plugins.forEach(loadMetadata => {
|
||||||
try {
|
try {
|
||||||
this.loadAndRequirePlugin(loadMetadata)
|
this.loadAndRequirePlugin(loadMetadata)
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
console.console(`§c扫描器 §4${scanner.type} §c文件 §4${loadMetadata.file.toString().replace(root, '')} §c编译失败 请提供下列错误给开发者`)
|
console.error(`plugin scanner ${scanner.type} load ${loadMetadata.file} occurred error ${error}`)
|
||||||
console.ex(error)
|
console.ex(error)
|
||||||
}
|
}
|
||||||
}
|
})
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
|
console.error(`plugin scanner ${scanner.type} occurred error ${error}`)
|
||||||
console.ex(error)
|
console.ex(error)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -227,16 +229,8 @@ export class PluginManagerImpl implements plugin.PluginManager {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
has(name: string) {
|
|
||||||
return this.instanceMap.has(name)
|
|
||||||
}
|
|
||||||
|
|
||||||
get(name: string) {
|
|
||||||
return this.instanceMap.get(name) || null
|
|
||||||
}
|
|
||||||
|
|
||||||
getPlugin(name: string) {
|
getPlugin(name: string) {
|
||||||
return this.instanceMap.get(name) || null
|
return this.instanceMap.get(name)
|
||||||
}
|
}
|
||||||
|
|
||||||
getPlugins() {
|
getPlugins() {
|
||||||
@@ -289,6 +283,7 @@ export class PluginManagerImpl implements plugin.PluginManager {
|
|||||||
try {
|
try {
|
||||||
return this.buildPlugin(metadata)
|
return this.buildPlugin(metadata)
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
|
console.console(`§4无法加载插件 §b${metadata.name} §4构建插件失败!`)
|
||||||
console.ex(error)
|
console.ex(error)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
132
packages/plugin/src/scanner/ms-scanner.ts
Normal file
132
packages/plugin/src/scanner/ms-scanner.ts
Normal file
@@ -0,0 +1,132 @@
|
|||||||
|
import { plugin } from "@ccms/api"
|
||||||
|
import http from '@ccms/common/dist/http'
|
||||||
|
import { provideSingletonNamed } from "@ccms/container"
|
||||||
|
|
||||||
|
import * as fs from '@ccms/common/dist/fs'
|
||||||
|
|
||||||
|
import * as Utf8 from "crypto-js/enc-utf8"
|
||||||
|
import * as AES from "crypto-js/aes"
|
||||||
|
|
||||||
|
const SCANNER_TYPE_NAME = 'ms'
|
||||||
|
|
||||||
|
@provideSingletonNamed(plugin.PluginScanner, SCANNER_TYPE_NAME)
|
||||||
|
export class SecretJSFileScanner implements plugin.PluginScanner {
|
||||||
|
type: string = SCANNER_TYPE_NAME
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
global.setGlobal('MiaoScriptPackageCenterQQCache', {})
|
||||||
|
global.setGlobal('MiaoScriptPackageCenterInfoCache', {})
|
||||||
|
global.setGlobal('MiaoScriptPackageCenterTokenCache', {})
|
||||||
|
global.setGlobal('MiaoScriptPackageCenterResultCache', {})
|
||||||
|
}
|
||||||
|
|
||||||
|
scan(target: any): plugin.PluginLoadMetadata[] {
|
||||||
|
return this.scanFolder(fs.concat(root, target)).map((file) => this.read(file))
|
||||||
|
}
|
||||||
|
|
||||||
|
read(file: any): plugin.PluginLoadMetadata {
|
||||||
|
return { file, type: this.type, scanner: this, loaded: false }
|
||||||
|
}
|
||||||
|
|
||||||
|
load(metadata: plugin.PluginLoadMetadata): plugin.PluginLoadMetadata {
|
||||||
|
if (metadata.type !== this.type) { return }
|
||||||
|
this.updatePlugin(metadata.file)
|
||||||
|
let encryptPlugin: any
|
||||||
|
// @ts-ignore load plugin not use cache
|
||||||
|
metadata.instance = require(metadata.file.toString(), {
|
||||||
|
cache: false,
|
||||||
|
beforeCompile: (source: string) => {
|
||||||
|
try {
|
||||||
|
encryptPlugin = JSON.parse(source)
|
||||||
|
} catch (error) {
|
||||||
|
encryptPlugin = require(metadata.file.toString())
|
||||||
|
}
|
||||||
|
if (!encryptPlugin || !encryptPlugin.encrypt) {
|
||||||
|
let filename = metadata.file.toString()
|
||||||
|
filename = filename.startsWith(root) ? filename.split(root)[1] : filename
|
||||||
|
throw new Error(`无效的加密插件: ${filename}.`)
|
||||||
|
}
|
||||||
|
let qq = encryptPlugin.qq
|
||||||
|
let token = this.decrypt(encryptPlugin.token, qq, encryptPlugin.timestamp)
|
||||||
|
global.MiaoScriptPackageCenterQQCache[encryptPlugin.name] = qq
|
||||||
|
global.MiaoScriptPackageCenterInfoCache[encryptPlugin.name] = encryptPlugin
|
||||||
|
global.MiaoScriptPackageCenterTokenCache[encryptPlugin.name] = token
|
||||||
|
let encrypt = encryptPlugin.encrypt
|
||||||
|
try {
|
||||||
|
let needUpdate = Date.now() / 1000 - encryptPlugin.timestamp > 3 * 24 * 60 * 60
|
||||||
|
console.console(`§6[§b圈云授权系统§6] §6加密插件: §b${encryptPlugin.name} §e授权效验中...`)
|
||||||
|
let result = http.post('https://ms.yumc.pw/api/plugin/check', {
|
||||||
|
"pid": encryptPlugin.pid,
|
||||||
|
"qq": qq,
|
||||||
|
"token": token,
|
||||||
|
"source": needUpdate
|
||||||
|
})
|
||||||
|
if (!result) { throw new Error(`授权服务器请求失败.`) }
|
||||||
|
global.MiaoScriptPackageCenterResultCache[encryptPlugin.name] = result
|
||||||
|
if (result.code != 200) {
|
||||||
|
throw new Error(`授权效验失败: ${result.msg}.`)
|
||||||
|
}
|
||||||
|
console.console(`§6[§b圈云授权系统§6] §6加密插件: §b${encryptPlugin.name} §a授权效验通过 正在构建插件...`)
|
||||||
|
if (needUpdate) {
|
||||||
|
if (!result.data) {
|
||||||
|
throw new Error(`授权效验失败: 服务器返回异常数据.`)
|
||||||
|
}
|
||||||
|
base.save(metadata.file, result.data.encrypt)
|
||||||
|
return result.data.source
|
||||||
|
}
|
||||||
|
return this.decrypt(encrypt, qq, token)
|
||||||
|
} catch (error) {
|
||||||
|
console.console(`§6[§b圈云授权系统§6] §6加密插件: §b${encryptPlugin.name} §c授权效验失败: §4${error}.`)
|
||||||
|
}
|
||||||
|
if (Date.now() / 1000 - encryptPlugin.timestamp > 7 * 24 * 60 * 60) {
|
||||||
|
throw new Error(`授权效验失败: 离线授权已过期.`)
|
||||||
|
}
|
||||||
|
console.console(`§6[§b圈云授权系统§6] §6加密插件: §b${encryptPlugin.name} §e离线授权效验通过 正在解密插件...`)
|
||||||
|
let decrypt = this.decrypt(encrypt, qq, token)
|
||||||
|
console.console(`§6[§b圈云授权系统§6] §6加密插件: §b${encryptPlugin.name} §a离线解密成功 正在构建插件...`)
|
||||||
|
return decrypt
|
||||||
|
},
|
||||||
|
afterCompile: () => {
|
||||||
|
delete global.MiaoScriptPackageCenterResultCache[encryptPlugin.name].data
|
||||||
|
global.MiaoScriptPackageCenterResultCache[encryptPlugin.name].timestamp = Date.now()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return metadata
|
||||||
|
}
|
||||||
|
|
||||||
|
private decrypt(encrypt: string, key: string, iv: string) {
|
||||||
|
return AES.decrypt(encrypt,
|
||||||
|
Utf8.parse(`${key}`.padEnd(16, "\0").substring(0, 16)), {
|
||||||
|
iv: Utf8.parse(`${iv}`.padEnd(16, "\0").substring(0, 16))
|
||||||
|
}).toString(Utf8)
|
||||||
|
}
|
||||||
|
|
||||||
|
private scanFolder(folder: any): string[] {
|
||||||
|
var files = []
|
||||||
|
this.checkUpdateFolder(folder)
|
||||||
|
// must check file is exist maybe is a illegal symbolic link file
|
||||||
|
fs.list(folder).forEach((path: any) => {
|
||||||
|
let file = path.toFile()
|
||||||
|
if (file.exists() && file.getName().endsWith(".ms")) {
|
||||||
|
files.push(file)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return files
|
||||||
|
}
|
||||||
|
|
||||||
|
private checkUpdateFolder(path: any) {
|
||||||
|
var update = fs.file(path, "update")
|
||||||
|
if (!update.exists()) {
|
||||||
|
update.mkdirs()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private updatePlugin(file: any) {
|
||||||
|
var update = fs.file(fs.file(fs.file(file).parentFile, 'update'), file.name)
|
||||||
|
if (update.exists()) {
|
||||||
|
console.i18n("ms.plugin.manager.build.update", { name: file.name })
|
||||||
|
fs.move(update, file, true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,27 +1,27 @@
|
|||||||
{
|
{
|
||||||
"name": "@ccms/polyfill",
|
"name": "@ccms/polyfill",
|
||||||
"version": "0.28.0-beta.4",
|
"version": "0.20.0-alpha.0",
|
||||||
"description": "MiaoScript polyfill package",
|
"description": "MiaoScript polyfill package",
|
||||||
"author": "MiaoWoo <admin@yumc.pw>",
|
"author": "MiaoWoo <admin@yumc.pw>",
|
||||||
"homepage": "https://github.com/circlecloud/ms.git",
|
"homepage": "https://github.com/circlecloud/ms.git",
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"main": "dist/index.js",
|
"main": "dist/index.js",
|
||||||
"types": "dist/index.d.ts",
|
"types": "dist/index.d.ts",
|
||||||
"files": [
|
|
||||||
"dist"
|
|
||||||
],
|
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"clean": "rimraf dist",
|
"clean": "rimraf dist",
|
||||||
"watch": "tsc --watch",
|
"watch": "tsc --watch",
|
||||||
"build": "pnpm clean && tsc",
|
"build": "yarn clean && tsc",
|
||||||
"test": "echo \"Error: run tests from root\" && exit 1"
|
"test": "echo \"Error: run tests from root\" && exit 1"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@ccms/i18n": "^0.28.0-beta.4",
|
"@ccms/i18n": "^0.20.0-alpha.0",
|
||||||
"@ccms/nodejs": "^0.28.0-beta.4",
|
"@ccms/nodejs": "^0.19.0",
|
||||||
"core-js": "^3.32.2"
|
"core-js": "^3.21.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@ccms/nashorn": "^0.28.0-beta.4"
|
"@ccms/nashorn": "^0.19.0",
|
||||||
|
"reflect-metadata": "^0.1.13",
|
||||||
|
"rimraf": "^3.0.2",
|
||||||
|
"typescript": "^4.5.5"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user