Big News: Socket raises $60M Series C at a $1B valuation to secure software supply chains for AI-driven development.Announcement
Sign In

zero-remote

Package Overview
Dependencies
Maintainers
1
Versions
22
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

zero-remote - npm Package Compare versions

Comparing version
1.1.3
to
1.2.0
+33
dist/IZeroRomeote.js
"use strict";
/**
* 数据序列化标准
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.ReportCode = exports.jsonPack = void 0;
/**
* Json序列化方案
*/
exports.jsonPack = {
parse: (value) => {
try {
return JSON.parse(value);
}
catch (error) {
return null;
}
},
stringify: (value) => {
try {
return JSON.stringify(value);
}
catch (error) {
return null;
}
}
};
var ReportCode;
(function (ReportCode) {
ReportCode[ReportCode["CALLBACK"] = 50] = "CALLBACK";
ReportCode[ReportCode["KICK"] = 10] = "KICK";
ReportCode[ReportCode["ERROR"] = 5] = "ERROR";
})(ReportCode = exports.ReportCode || (exports.ReportCode = {}));
/**
* 数据序列化标准
*/
export interface IPack {
stringify(value: any): any | null;
parse(value: any): any | null;
}
/**
* 数据通信标准
*/
export interface IChannel<T> {
close(): void;
send(body: T): void;
}
/**
* Json序列化方案
*/
export let jsonPack: IPack = {
parse: (value) => {
try {
return JSON.parse(value)
} catch (error) {
return null
}
},
stringify: (value) => {
try {
return JSON.stringify(value)
} catch (error) {
return null
}
}
}
export enum ReportCode {
CALLBACK = 50,
KICK = 10,//踢人
ERROR = 5,//踢人
}
export interface ISCMessage {
code?: ReportCode,//空为常规,成功
route?: string,//路由号
key?: string, //二级路由
data?: any//数据
error?: string//错误消息
ci?: number
args?: any[]//回调参数
}
export interface ICSMessage {
route: string,//路由号
key: string, //二级路由
data: any//数据
cbs?: { [key: string]: number }//回调 只支持发送有回调
index?: number//标准回调
}
type Parameters<T> = T extends (...args: infer P) => any ? P : never;
type ReturnType<T> = T extends (...args: any) => infer R ? R : any;
export type Sender<T> = { [K in keyof T]: T[K] }
export type PromiseSender<T> = { [K in keyof T]: (...value: Parameters<T[K]>) => Promise<ReturnType<T[K]>> }
export type Receiver<T> = { [K in keyof T]: (callback: (...value: Parameters<T[K]>) => void) => void }
export type ReturnReceiver<T> = { [K in keyof T]: (callback: (...value: Parameters<T[K]>) => Promise<ReturnType<T[K]>>) => void }
+20
-336
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.ZeroRemoteClient = exports.GameVisitor = exports.LiteStack = exports.ReportCode = exports.jsonPack = exports.Visitor = void 0;
const ws_1 = __importDefault(require("ws"));
exports.GameVisitor = exports.Visitor = void 0;
const zero_mvc_1 = require("zero-mvc");
const IZeroRomeote_1 = require("./IZeroRomeote");
/**

@@ -35,77 +32,6 @@ * Ginger用户基础

/**
* Json序列化方案
*/
exports.jsonPack = {
parse: (value) => {
try {
return JSON.parse(value);
}
catch (error) {
return null;
}
},
stringify: (value) => {
try {
return JSON.stringify(value);
}
catch (error) {
return null;
}
}
};
var ReportCode;
(function (ReportCode) {
ReportCode[ReportCode["CALLBACK"] = 50] = "CALLBACK";
ReportCode[ReportCode["KICK"] = 10] = "KICK";
ReportCode[ReportCode["ERROR"] = 5] = "ERROR";
})(ReportCode = exports.ReportCode || (exports.ReportCode = {}));
/**
* 清洁型堆栈
*/
class LiteStack {
constructor() {
this.pool = {};
this.index = 0;
this.size = 0;
this.maxCount = 100;
}
push(item) {
this.index++;
this.size++;
this.pool[this.index] = item;
return this.index;
}
pull(index) {
let item = this.pool[index];
if (item != null) {
delete this.pool[index];
this.size--;
}
return item;
}
clear(keepLength) {
if (this.size > keepLength) {
let delLen = this.size - keepLength;
for (const key in this.pool) {
if (delLen > 0) {
delete this.pool[key];
}
else {
break;
}
delLen--;
}
}
this.size = keepLength;
}
gc() {
this.clear(this.maxCount);
}
}
exports.LiteStack = LiteStack;
/**
* 通信基础
*/
class ZeroRemote extends zero_mvc_1.ZeroDispatcher {
constructor(ws, callback, pack = exports.jsonPack) {
constructor(ws, callback, pack = IZeroRomeote_1.jsonPack) {
super();

@@ -125,4 +51,4 @@ this.ws = ws;

if (err) {
console.warn(err);
console.log(value);
// console.warn(err)
// console.log(value)
}

@@ -169,5 +95,9 @@ });

this.routerPool = {};
this.pingTime = 0;
}
receive(body) {
if (body.route == null) {
if (body.data) {
this.pingTime = body.data;
}
this.channel.send({}); //空对象当ping

@@ -183,3 +113,3 @@ }

this.channel.send({
code: ReportCode.CALLBACK,
code: IZeroRomeote_1.ReportCode.CALLBACK,
ci: element,

@@ -198,3 +128,3 @@ args: cbArgs

this.channel.send({
code: ReportCode.CALLBACK,
code: IZeroRomeote_1.ReportCode.CALLBACK,
ci: body.index,

@@ -222,3 +152,8 @@ args: [isError, data]

}).catch((error) => {
back(false, error);
if (error instanceof Error) {
back(false, error.message);
}
else {
back(false, error);
}
});

@@ -245,3 +180,3 @@ }

if (back != null) {
back(false, "这个路由没有实现");
back(false, route + " 这个路由没有实现");
}

@@ -279,260 +214,9 @@ }

kick() {
this.channel.send({ code: ReportCode.KICK });
this.channel.send({ code: IZeroRomeote_1.ReportCode.KICK });
super.kick();
}
error(message) {
this.channel.send({ code: ReportCode.ERROR, error: message });
this.channel.send({ code: IZeroRomeote_1.ReportCode.ERROR, error: message });
}
}
exports.GameVisitor = GameVisitor;
/**
* 错误错误会弹窗
* 重连多次后会弹窗
*/
/**
* 与后端协议
* 所有数据以IMessage接收和发送
* 只支持一级属性是个回调函数
*/
class ZeroRemoteClient extends zero_mvc_1.ZeroDispatcher {
constructor(url) {
super();
this.url = url;
this.relinkMaxCount = 3;
this.relinkTime = 2000;
/**
* 回调函数缓存个数
*/
this.callBackMaxIndex = 1000;
this.outTime = 1; //整秒
this.heartbeatTime = 5; //整秒=5
this.pack = exports.jsonPack;
this.isOpen = false;
this.isBusy = false;
this.isRelink = true;
this.relinkCount = 0;
this.router = new zero_mvc_1.ZeroDispatcher();
this.callbackPool = {};
this.ci = 0;
this.pingIndex = 0;
this._mask = false;
setInterval(() => {
if (this.isOpen) {
if (this.pingIndex == this.heartbeatTime + this.outTime) {
this.mask = true;
}
else if (this.pingIndex == this.heartbeatTime) {
this.ws.send(this.pack.stringify({}));
}
this.pingIndex++;
}
}, 1000);
}
get mask() {
return this._mask;
}
set mask(value) {
if (this._mask != value) {
this._mask = value;
if (this._mask) {
// this.showMask()
this.emit("showMask");
}
else {
// this.hideMask()
this.emit("hideMask");
}
}
}
/**
* 本条结构协议
* @param route 要发送的路由名
* @returns
*/
getSender(route) {
return new Proxy({}, {
get: (target, p, receiver) => {
return (data) => {
return new Promise((resolve, reject) => {
this.send(route, p, data, (isError, value) => {
if (isError) {
resolve(value);
}
else {
reject(value);
this.emit("error", value);
}
});
});
};
}
});
}
getReceiver(r) {
return new Proxy({}, {
get: (target, p, receiver) => {
return (data) => {
this.receive(r, p, data);
};
}
});
}
send(route, key, data, callback) {
if (this.isOpen) {
if (!this.mask) {
let cbs = undefined;
for (const key in data) {
if (data.hasOwnProperty(key)) {
const element = data[key];
if (typeof element == "function") {
this.ci++;
delete this.callbackPool[this.ci - this.callBackMaxIndex];
this.callbackPool[this.ci] = element;
if (cbs == null) {
cbs = {};
}
cbs[key] = this.ci;
}
}
}
let index = undefined;
if (callback != null) {
this.ci++;
delete this.callbackPool[this.ci - this.callBackMaxIndex];
index = this.ci;
this.callbackPool[this.ci] = callback;
}
this.ws.send(this.pack.stringify({ route: route, key: key, data: data, cbs: cbs, index: index }));
}
else {
// console.log("弱网环境,send信息被忽略" + route)
callback(false, "弱网环境,send信息被忽略");
}
}
else {
// console.log("游戏服务器未连接,send信息被忽略" + route)
callback(false, "服务器未连接,send信息被忽略");
}
}
receive(route, key, callback) {
this.router.on(route + "." + key, callback);
}
reLink() {
if (this.relinkCount < this.relinkMaxCount) {
this.relinkTimeOut = setTimeout(() => {
this.relinkTimeOut == null;
this.relinkCount++;
this.link();
}, this.relinkTime);
}
else {
this.relinkCount = 0;
this.emit("popup");
}
}
message(value) {
let obj;
try {
obj = this.pack.parse(value);
}
catch (_a) {
throw new Error("服务器数据无法序列化");
}
this.pong();
if (obj.code == null) {
if (obj.route != null) {
if (obj.key == null) {
throw new Error("服务器数据出错");
}
else {
this.router.emit(obj.route + "." + obj.key, obj.data);
}
}
}
else if (obj.code == ReportCode.CALLBACK) {
if (obj.ci != null) {
let method = this.callbackPool[obj.ci];
if (method) {
method.apply(this, obj.args);
delete this.callbackPool[obj.ci];
}
}
}
else if (obj.code == ReportCode.KICK) {
this.close();
}
else {
this.emit("error", obj.error);
}
}
pong() {
this.emit("heartbeat");
this.pingIndex = 0;
this.mask = false;
}
/**
* 这个callback 在重连里不会触发
* 如需要触发 请使用 on("linked")
* @param callback
*/
link(callback) {
this.isRelink = true;
if (this.url == "" || this.url == null) {
throw new Error("服务器地址为空");
}
else {
if (this.isBusy) {
throw new Error("重复连接服务");
}
else {
this.ws = new ws_1.default(this.url);
this.isBusy = true;
this.emit("linking");
this.ws.onerror = () => {
this.emit("error", "网络出错");
};
this.ws.onopen = () => {
this.mask = false;
this.relinkCount = 0;
this.isOpen = true;
this.emit("linked");
if (callback) {
callback();
}
};
this.ws.onclose = () => {
this.mask = true;
this.isOpen = false;
this.isBusy = false;
this.emit("suspend");
for (const key in this.callbackPool) {
if (Object.prototype.hasOwnProperty.call(this.callbackPool, key)) {
const element = this.callbackPool[key];
element(false, "网络断开");
delete this.callbackPool[key];
}
}
if (this.isRelink) {
this.reLink();
}
else {
this.emit("stop");
}
};
this.ws.onmessage = (evt) => {
this.message(evt.data.toString());
};
}
}
}
close() {
if (this.relinkTimeOut) {
clearTimeout(this.relinkTimeOut);
this.relinkTimeOut == null;
}
this.isRelink = false;
this.isOpen = false;
this.ws.close();
}
}
exports.ZeroRemoteClient = ZeroRemoteClient;
+13
-400

@@ -1,12 +0,5 @@

import WebSocket from "ws"
import { ZeroDispatcher } from "zero-mvc";
import { IChannel, ICSMessage, IPack, ISCMessage, jsonPack, ReportCode, ReturnReceiver, Sender } from "./IZeroRomeote";
/**
* 数据通信标准
*/
export interface IChannel<T> {
close(): void;
send(body: T): void;
}

@@ -39,98 +32,2 @@ /**

/**
* 数据序列化标准
*/
export interface IPack {
stringify(value: any): any | null;
parse(value: any): any | null;
}
/**
* Json序列化方案
*/
export let jsonPack: IPack = {
parse: (value) => {
try {
return JSON.parse(value)
} catch (error) {
return null
}
},
stringify: (value) => {
try {
return JSON.stringify(value)
} catch (error) {
return null
}
}
}
export enum ReportCode {
CALLBACK = 50,
KICK = 10,//踢人
ERROR = 5,//踢人
}
export interface ISCMessage {
code?: ReportCode,//空为常规,成功
route?: string,//路由号
key?: string, //二级路由
data?: any//数据
error?: string//错误消息
ci?: number
args?: any[]//回调参数
}
export interface ICSMessage {
route: string,//路由号
key: string, //二级路由
data: any//数据
cbs?: { [key: string]: number }//回调 只支持发送有回调
index?: number//标准回调
}
/**
* 清洁型堆栈
*/
export class LiteStack<T> {
private pool: { [key: number]: T; } = {};
private index: number = 0;
public size: number = 0;
public maxCount: number = 100
push(item: T): number {
this.index++;
this.size++;
this.pool[this.index] = item;
return this.index;
}
pull(index: number): T | null {
let item = this.pool[index];
if (item != null) {
delete this.pool[index];
this.size--;
}
return item;
}
clear(keepLength: number) {
if (this.size > keepLength) {
let delLen = this.size - keepLength;
for (const key in this.pool) {
if (delLen > 0) {
delete this.pool[key];
} else {
break;
}
delLen--;
}
}
this.size = keepLength;
}
gc() {
this.clear(this.maxCount)
}
}
/**
* 通信基础

@@ -153,4 +50,4 @@ */

if (err) {
console.warn(err)
console.log(value)
// console.warn(err)
// console.log(value)
}

@@ -194,5 +91,9 @@ })

protected routerPool: { [key: string]: { [key: string]: Function } } = {}
pingTime: number = 0;
receive(body: ICSMessage): void {
if (body.route == null) {
if (body.data) {
this.pingTime = body.data
}
this.channel.send({})//空对象当ping

@@ -244,3 +145,7 @@ } else {

}).catch((error) => {
back!(false, error)
if (error instanceof Error) {
back!(false, error.message)
} else {
back!(false, error)
}
})

@@ -263,3 +168,3 @@ } else {

if (back != null) {
back(false, "这个路由没有实现")
back(false, route + " 这个路由没有实现")
}

@@ -304,293 +209,1 @@ }

}
type Parameters<T> = T extends (...args: infer P) => any ? P : never;
type ReturnType<T> = T extends (...args: any) => infer R ? R : any;
export type Sender<T> = { [K in keyof T]: T[K] }
export type PromiseSender<T> = { [K in keyof T]: (...value: Parameters<T[K]>) => Promise<ReturnType<T[K]>> }
export type Receiver<T> = { [K in keyof T]: (callback: (...value: Parameters<T[K]>) => void) => void }
export type ReturnReceiver<T> = { [K in keyof T]: (callback: (...value: Parameters<T[K]>) => Promise<ReturnType<T[K]>>) => void }
/**
* 错误错误会弹窗
* 重连多次后会弹窗
*/
/**
* 与后端协议
* 所有数据以IMessage接收和发送
* 只支持一级属性是个回调函数
*/
export class ZeroRemoteClient extends ZeroDispatcher<{
/**
* 消息阻塞
*/
showMask: []
/**
* 阻塞后收到消息
*/
hideMask: []
/**
* 主动错误
* 用于debug
*/
error: [string?]
/**
* 重连提示
*/
popup: []
/**
* 心跳
*/
heartbeat: []
/**
* 开始连接
*/
linking: []
/**
* 连接完成
*/
linked: []
/**
* 连接中断
*/
suspend: []
/**
* 连接结束
*/
stop: []
}> {
relinkMaxCount: number = 3
relinkTime: number = 2000
/**
* 回调函数缓存个数
*/
callBackMaxIndex: number = 1000
outTime: number = 1;//整秒
heartbeatTime: number = 5;//整秒=5
public pack: IPack = jsonPack
isOpen = false
isBusy = false
private isRelink: boolean = true
private relinkCount: number = 0
protected ws!: WebSocket;
protected router: ZeroDispatcher<any> = new ZeroDispatcher();
protected callbackPool: { [key: number]: Function } = {}
private ci: number = 0
private pingIndex: number = 0
private _mask: boolean = false
relinkTimeOut?: NodeJS.Timeout;
public get mask(): boolean {
return this._mask
}
public set mask(value: boolean) {
if (this._mask != value) {
this._mask = value
if (this._mask) {
// this.showMask()
this.emit("showMask")
} else {
// this.hideMask()
this.emit("hideMask")
}
}
}
constructor(public url: string) {
super()
setInterval(() => {
if (this.isOpen) {
if (this.pingIndex == this.heartbeatTime + this.outTime) {
this.mask = true
} else if (this.pingIndex == this.heartbeatTime) {
this.ws.send(this.pack.stringify({}))
}
this.pingIndex++
}
}, 1000)
}
/**
* 本条结构协议
* @param route 要发送的路由名
* @returns
*/
getSender<T>(route: string): PromiseSender<T> {
return new Proxy<PromiseSender<T>>({} as any, {
get: (target: any, p: string, receiver: any) => {
return (data: any) => {
return new Promise((resolve: (value: any) => void, reject: (reason?: any) => void) => {
this.send(route, p, data, (isError: boolean, value: any) => {
if (isError) {
resolve(value)
} else {
reject(value)
this.emit("error", value)
}
})
})
}
}
})
}
getReceiver<T>(r: string): Receiver<T> {
return new Proxy<Receiver<T>>({} as any, {
get: (target: any, p: string, receiver: any) => {
return (data: any) => {
this.receive(r, p, data)
}
}
})
}
send(route: string, key: string, data: any, callback: (isOK: boolean, value: any) => void) {
if (this.isOpen) {
if (!this.mask) {
let cbs: { [key: string]: number } | undefined = undefined
for (const key in data) {
if (data.hasOwnProperty(key)) {
const element = data[key];
if (typeof element == "function") {
this.ci++
delete this.callbackPool[this.ci - this.callBackMaxIndex]
this.callbackPool[this.ci] = element
if (cbs == null) {
cbs = {}
}
cbs[key] = this.ci
}
}
}
let index: number | undefined = undefined
if (callback != null) {
this.ci++
delete this.callbackPool[this.ci - this.callBackMaxIndex]
index = this.ci
this.callbackPool[this.ci] = callback
}
this.ws.send(this.pack.stringify(
{ route: route, key: key, data: data, cbs: cbs, index: index }
))
} else {
// console.log("弱网环境,send信息被忽略" + route)
callback(false, "弱网环境,send信息被忽略")
}
} else {
// console.log("游戏服务器未连接,send信息被忽略" + route)
callback(false, "服务器未连接,send信息被忽略")
}
}
receive(route: string, key: string, callback: (value: any) => void) {
this.router.on(route + "." + key, callback)
}
protected reLink() {
if (this.relinkCount < this.relinkMaxCount) {
this.relinkTimeOut = setTimeout(() => {
this.relinkTimeOut == null
this.relinkCount++
this.link()
}, this.relinkTime)
} else {
this.relinkCount = 0
this.emit("popup")
}
}
message(value: string) {
let obj: ISCMessage
try {
obj = this.pack.parse(value)
} catch {
throw new Error("服务器数据无法序列化")
}
this.pong()
if (obj.code == null) {
if (obj.route != null) {
if (obj.key == null) {
throw new Error("服务器数据出错")
} else {
this.router.emit(obj.route + "." + obj.key, obj.data)
}
}
} else if (obj.code == ReportCode.CALLBACK) {
if (obj.ci != null) {
let method = this.callbackPool[obj.ci]
if (method) {
method.apply(this, obj.args);
delete this.callbackPool[obj.ci]
}
}
} else if (obj.code == ReportCode.KICK) {
this.close()
} else {
this.emit("error", obj.error)
}
}
protected pong() {
this.emit("heartbeat")
this.pingIndex = 0
this.mask = false
}
/**
* 这个callback 在重连里不会触发
* 如需要触发 请使用 on("linked")
* @param callback
*/
link(callback?: () => void) {
this.isRelink = true
if (this.url == "" || this.url == null) {
throw new Error("服务器地址为空")
} else {
if (this.isBusy) {
throw new Error("重复连接服务")
} else {
this.ws = new WebSocket(this.url)
this.isBusy = true
this.emit("linking")
this.ws.onerror = () => {
this.emit("error", "网络出错")
}
this.ws.onopen = () => {
this.mask = false
this.relinkCount = 0
this.isOpen = true
this.emit("linked")
if (callback) {
callback()
}
}
this.ws.onclose = () => {
this.mask = true
this.isOpen = false
this.isBusy = false
this.emit("suspend")
for (const key in this.callbackPool) {
if (Object.prototype.hasOwnProperty.call(this.callbackPool, key)) {
const element = this.callbackPool[key];
element(false, "网络断开")
delete this.callbackPool[key]
}
}
if (this.isRelink) {
this.reLink()
} else {
this.emit("stop")
}
}
this.ws.onmessage = (evt) => {
this.message(evt.data.toString())
};
}
}
}
close() {
if (this.relinkTimeOut) {
clearTimeout(this.relinkTimeOut)
this.relinkTimeOut == null
}
this.isRelink = false
this.isOpen = false
this.ws.close()
}
}
{
"name": "zero-remote",
"version": "1.1.3",
"version": "1.2.0",
"description": "常连接网络",
"main": "dist/index.js",
"scripts": {
"demo1": "ts-node-dev demo1.ts",
"demo2": "ts-node-dev demo2.ts"
},
"scripts": {},
"keywords": [

@@ -17,9 +14,6 @@ "网络",

"ws": "^7.4.2",
"zero-mvc": "^1.0.0"
"zero-dispatcher": "^1.2.0"
},
"devDependencies": {
"@types/ws": "^7.4.0",
"@types/node": "^14.14.16",
"ts-node-dev": "^1.1.6",
"typescript": "^4.1.5"
"@types/ws": "^7.4.0"
},

@@ -26,0 +20,0 @@ "author": "蓝面包wc24@qq.com",

{
"version": "0.2.0",
"configurations": [
{
"type": "pwa-node",
"request": "launch",
"name": "服务",
"runtimeExecutable": "yarn",
"args": [
"demo1",
]
},
{
"type": "pwa-node",
"request": "launch",
"name": "客户",
"runtimeExecutable": "yarn",
"args": [
"demo2",
]
},
]
}
// import ws from "ws";
// import { address as getLocalIp } from "ip"
// import ZeroRemote, { GameVisitor, IChannel, ICSMessage, ISCMessage, ReturnReceiver, ZeroRemoteClient } from "zero-remote";
// type CMType = new (...ary: any[]) => ZeroServerNode
// type MType = new (...ary: any[]) => ZeroServerNode
// export let routeMap: WeakMap<CMType, string> = new WeakMap()
// export let balancePool: { [key: string]: (player: any, totle: number) => number } = {}
// /**
// * 装饰器
// * @param key
// * @returns
// */
// export function route(key: string) {
// return (type: CMType) => {
// routeMap.set(type, key)
// }
// }
// /**
// * 装饰器 用去落点均衡
// * @param callback
// * @returns
// */
// export function balance<T extends UserInfo>(callback: (player: T, totle: number) => number) {
// return (type: MType) => {
// let route = getRoute(type)
// if (route) {
// balancePool[route] = callback
// }
// }
// }
// /**
// * 获取装饰器路由名
// * @param connectorType
// * @returns
// */
// export function getRoute(connectorType: new (...args: any[]) => any): string {
// let route = routeMap.get(connectorType)
// if (route) {
// return route
// } else {
// throw new Error("这个类没有@route")
// }
// }
// /**
// * server类型
// */
// enum ServerType {
// MODULE,
// CONNECT,
// SPECIAL,
// }
// interface IZeroServerCS {
// init: (value: { url: string, name: string, models: string[], type: ServerType, pid: number }) => void
// getPid: () => number
// addLine: (sid: number) => void
// removeLine: (sid: number) => void
// }
// interface IZeroServerInfo {
// url: string,
// models: string[],
// type: ServerType,
// sid: number
// }
// interface IZeroServerSC {
// clustered: (value: number) => void
// add: (value: IZeroServerInfo) => void
// remove: (value: number) => void
// }
// type ModuleType = new (...arg: any[]) => Module & { route: string }
// /**
// * server基类
// */
// export class ZeroServer extends ZeroRemoteClient {
// serverType: ServerType = ServerType.MODULE
// url: string;
// static mainUrl: string
// static modelPool: { [key: string]: Module } = {}
// models: any = []
// clusterSender = this.getSender<IZeroServerCS>("")
// clusterReceiver = this.getReceiver<IZeroServerSC>("")
// static pid: number
// serverPool: { [key: string]: IZeroServerInfo } = {}
// name: string
// serverId!: number;
// isClustered: boolean = false
// constructor(public port: number) {
// super()
// this.name = this.constructor.name
// if (ZeroServer.mainUrl == null) {
// throw "请配置主服务器地址ZeroServer.mainUrl=\"XXX\""
// }
// this.url = ZeroServer.mainUrl
// /**
// * 保存所有服务节点以方便扩展
// */
// this.clusterReceiver.add((info) => {
// this.serverPool[info.sid] = info
// })
// this.clusterReceiver.clustered((sid: number) => {
// this.isClustered = true
// this.serverId = sid
// this.clustered()
// })
// this.link()
// }
// clustered(): void {
// }
// showMask(): void {
// }
// hideMask(): void {
// }
// stringify(value: ISCMessage | ICSMessage): string {
// return JSON.stringify(value)
// }
// error(error: any): void {
// }
// linked(): void {
// if (ZeroServer.pid == null) {
// this.clusterSender.getPid().then((pid) => {
// if (ZeroServer.pid == null) {
// ZeroServer.pid = pid
// }
// this.sendInit()
// })
// } else {
// this.sendInit()
// }
// }
// private sendInit() {
// this.clusterSender.init({ url: getLocalIp() + ":" + this.port, name: this.name, type: this.serverType, models: this.models, pid: ZeroServer.pid })
// }
// /**
// * 生命不息 重连不止
// */
// popup(): void {
// console.log("集群失败")
// }
// linking(): void {
// }
// addModule(modelType: ModuleType) {
// let route = getRoute(modelType)
// if (route) {
// let model = new modelType(route)
// model.server = this
// model.start()
// ZeroServer.modelPool[route] = model
// this.models.push(route)
// }
// }
// }
// /**
// * 放在Connector服务上
// * 用来连接Module的线路
// */
// class ClientFotModule extends ZeroRemoteClient {
// relinkMaxCount = 100
// popupReLinkTime: number = 1000
// popupReLinkTimeIndex!: NodeJS.Timeout;
// constructor(public url: string) {
// super()
// }
// showMask(): void {
// // throw new Error("Method not implemented.");
// }
// hideMask(): void {
// // throw new Error("Method not implemented.");
// }
// stringify(value: ICSMessage | ISCMessage): string {
// return JSON.stringify(value)
// }
// error(error: any): void {
// // throw new Error("Method not implemented.");
// }
// linked(): void {
// this.popupReLinkTime = 1000
// }
// popup(): void {
// console.log("pppppp")
// for (const key in this.callbackPool) {
// const element = this.callbackPool[key];
// console.log(element)
// element(false, "服务器被断开")
// }
// this.popupReLinkTimeIndex = setTimeout(() => {
// this.link()
// this.popupReLinkTime += 1000
// }, this.popupReLinkTime)
// // throw new Error("Method not implemented.");
// }
// linking(): void {
// // throw new Error("Method not implemented.");
// }
// }
// /**
// * 用户
// */
// export class ZeroServerUser<T extends UserInfo = UserInfo> extends GameVisitor {
// static pool: { [key: string]: ZeroServerUser } = {}
// static index: number = 0
// static getAtuoId() {
// return this.index++
// }
// clear(): void {
// }
// constructor(channel: IChannel<ISCMessage>, server: ZeroRemote, public info: T) {
// super(channel, server)
// ZeroServerUser.pool[info.userId] = this
// }
// }
// /**
// * 连接服务器 用于连接用户
// */
// export class ConnectorServer<T extends UserInfo> extends ZeroServer {
// connectorTypePool: { [key: string]: new (...args: any[]) => Connector } = {};
// serverType = ServerType.CONNECT
// modelsChannels: { [key: string]: ClientFotModule[] } = {};
// constructor(port: number, private playerInfoType: new (sid: number, uid: number) => T) {
// super(port)
// }
// clustered() {
// console.log("创建连接服务:", this.serverId)
// new ZeroRemote(new ws.Server({ port: this.port }), (channel, server) => {
// let user = new ZeroServerUser(channel, server, new this.playerInfoType(this.serverId, ZeroServerUser.getAtuoId()))
// for (const key in this.connectorTypePool) {
// if (Object.prototype.hasOwnProperty.call(this.connectorTypePool, key)) {
// const element = this.connectorTypePool[key];
// let connector = new element(this, user, key);
// connector.start()
// }
// }
// return user
// })
// this.clusterReceiver.add((info) => {
// if (info.type == ServerType.MODULE) {
// let clientFotModule = new ClientFotModule("ws://" + info.url)
// clientFotModule.link(() => {
// this.clusterSender.addLine(info.sid)
// })
// clientFotModule.receive("", "", this.partMessage.bind(this))
// info.models.forEach((modelsName: string) => {
// let clinets = this.modelsChannels[modelsName]
// if (clinets == null) {
// clinets = []
// this.modelsChannels[modelsName] = clinets
// }
// clinets.push(clientFotModule)
// })
// }
// })
// this.clusterReceiver.remove((info) => {
// })
// }
// /**
// * 转发到前端
// * @param data
// */
// private partMessage(data: { key: string, data: any, userId: number, route: string }) {
// let user = ZeroServerUser.pool[data.userId]
// user.channel.send({
// route: data.route,
// key: data.key,
// data: data.data
// })
// }
// addConnector(connectorType: (new (...args: any[]) => Connector)) {
// let route = getRoute(connectorType)
// if (route) {
// this.connectorTypePool[route] = connectorType
// }
// }
// }
// /**
// * 有个CONNECT服务器做为客户端连了上来
// * 添加 ping
// * 添加 callback
// * 添加 kick
// */
// export class ConnectorVisitor extends GameVisitor {
// clear(): void {
// console.log("clear")
// }
// constructor(channel: IChannel<ISCMessage>, public moduleServer: ModuleServer) {
// super(channel, moduleServer.connectorServer)
// }
// handle(route: string, key: string, data: any, back: (Function | undefined)) {
// let model: any = ZeroServer.modelPool[route]
// let method: Function = model[key]
// if (method) {
// model.playerInfo = data.p
// model.isRemote = true
// let visitor = this.moduleServer.connectorVisitorPool[model.playerInfo.serverId]
// if (visitor == null) {
// this.moduleServer.connectorVisitorPool[model.playerInfo.serverId] = this
// } else {
// // console.log("这里应该为true", visitor == this)
// }
// let p = method.apply(model, data.a)
// if (back != null) {
// if (p instanceof Promise) {
// p.then((valueThen) => {
// back!(true, valueThen)
// }).catch((error) => {
// back!(false, error)
// })
// } else {
// back(true, p)
// }
// }
// }
// }
// }
// export class ModuleServer extends ZeroServer {
// serverType = ServerType.MODULE
// connectorVisitorPool: { [key: string]: ConnectorVisitor } = {}
// connectorServer: ZeroRemote
// constructor(port: number) {
// super(port)
// this.connectorServer = new ZeroRemote(new ws.Server({ port: this.port }), (channel, server) => {
// return new ConnectorVisitor(channel, this)
// })
// }
// clustered() {
// console.log("创建功能服务:", this.serverId)
// }
// }
// /**
// * 被序列化的传递的用户信息
// */
// export class UserInfo {
// name: string
// /**
// *
// * @param serverId
// * @param userId 用于路由到用户不发给前端
// */
// constructor(public serverId: number, public userId: number) {
// this.name = "S" + serverId + "U" + userId
// }
// }
// /**
// * 一个服务节点
// */
// export class ZeroServerNode {
// constructor(public route: string) {
// }
// start() {
// }
// }
// type Parameters<T> = T extends (...args: infer P) => any ? P : never;
// type ReturnType<T> = T extends (...args: any) => infer R ? R : any;
// export type ModuleSender<T> = { [K in keyof T]: ((value: Parameters<T[K]>[0], playerInfo?: UserInfo) => Promise<ReturnType<T[K]>>) }
// /**
// *
// */
// export class Module<SC = any> extends ZeroServerNode {
// sender: ModuleSender<SC>
// public playerInfo!: UserInfo
// public isRemote: boolean = false
// public server!: ZeroServer
// constructor(route: string) {
// super(route)
// this.sender = new Proxy<ModuleSender<SC>>({} as any, {
// get: (target: any, p: string, receiver: any) => {
// return (data: any, playerInfo: UserInfo | null = null) => {
// // let playerInfo
// if (playerInfo == null) {
// playerInfo = this.playerInfo
// }
// if (playerInfo) {
// if (this.isRemote) {
// let sendInfo = {
// route: "",
// key: "",
// data: {
// route: this.route,
// key: p,
// data: data,
// userId: playerInfo.userId
// }
// }
// let visitor = (this.server as ModuleServer).connectorVisitorPool[this.playerInfo.serverId]
// visitor.channel.send(sendInfo)
// } else {
// let sendInfo = {
// route: route,
// key: p,
// data: data
// }
// let user = ZeroServerUser.pool[playerInfo.userId]
// if (user != null) {
// user.channel.send(sendInfo)
// } else {
// console.warn("no User")
// }
// }
// }
// }
// }
// })
// }
// }
// export class Connector<CS = any> extends ZeroServerNode {
// player!: ZeroServerUser<any>
// receiver: ReturnReceiver<CS>;
// private isFree: Boolean = true
// private lastCallback: (() => Promise<void>)[] = []
// constructor(public server: ConnectorServer<any>, player: ZeroServerUser<any>, route: string) {
// super(route)
// this.player = player;
// this.route = route;
// /**
// * 接收来自己玩家的请求所有做了队例处理 防攻击
// */
// this.receiver = new Proxy<ReturnReceiver<CS>>({} as any, {
// get: (target: any, p: string, receiver: any) => {
// return (callback: (value: any) => Promise<void>) => {
// let router = (this.player as any).routerPool[route]
// if (router == null) {
// router = {};
// (this.player as any).routerPool[route] = router
// }
// router[p] = (...args: any) => {
// if (this.lastCallback.length >= 100) {
// this.player.kick()
// } else {
// this.lastCallback.push(() => {
// return callback.apply(null, args)
// })
// }
// if (this.isFree) {
// this.isFree = false
// this.nextReceiver()
// }
// }
// }
// }
// })
// }
// private nextReceiver() {
// if (this.lastCallback.length > 0) {
// let callback = this.lastCallback.shift()
// if (callback) {
// callback().then(() => {
// this.nextReceiver()
// }).catch((err: Error | string) => {
// if (typeof err == "string") {
// this.player.error(err)
// } else {
// this.player.error(err.message)
// }
// this.nextReceiver()
// })
// }
// } else {
// this.isFree = true
// }
// }
// protected getModule<T extends Module>(modelType: new (...args: any[]) => T): T {
// let routeKey = getRoute(modelType)
// let model = ZeroServer.modelPool[routeKey]
// if (model == null) {
// let remoteModule = this.getRemoteModule(routeKey)
// return new Proxy<T>({} as any, {
// get: (target: any, p: string, receiver: any) => {
// if (typeof modelType.prototype[p] == "function") {
// return (...args: any[]) => {
// console.log("__1__")
// return new Promise((resolve: (value: any) => void, reject: (reason?: any) => void) => {
// console.log("__2__")
// if (remoteModule == null) {
// remoteModule = this.getRemoteModule(routeKey)
// }
// if (remoteModule != null) {
// console.log("___3_")
// if (remoteModule.isOpen) {
// console.log("send")
// remoteModule.send(routeKey, p, {
// p: this.player.info,
// a: args
// }, (isError: boolean, value: any) => {
// if (isError) {
// resolve(value)
// } else {
// reject(value)
// }
// })
// }
// } else {
// reject("没有这个服务")
// }
// })
// }
// } else {
// //TODO
// }
// },
// set: (target: T, p: string, value: any, receiver: any) => {
// console.log(p)
// return true
// }
// })
// } else {
// return new Proxy<T>({} as any, {
// get: (target: any, p: string, receiver: any) => {
// if (typeof modelType.prototype[p] == "function") {
// return (...args: any[]) => {
// model.playerInfo = this.player.info
// let _model: any = model
// return _model[p].apply(model, args)
// }
// } else {
// }
// },
// set: (target: T, p: string, value: any, receiver: any) => {
// console.log(p)
// return true
// }
// })
// }
// }
// getRemoteModule(routeKey: string): ClientFotModule | null {
// let remoteModules = this.server.modelsChannels[routeKey]
// if (remoteModules) {
// let pick = balancePool[routeKey](this.player, remoteModules.length)
// return remoteModules[pick]
// } else {
// return null
// }
// }
// }
// export default class ZeroCluster extends ZeroRemote<{ change: [] }> {
// constructor(port: number) {
// super(new ws.Server({ port: port }), (channel, server) => {
// return new ClusterVisitor(channel, server)
// })
// }
// }
// export class ClusterVisitor extends GameVisitor {
// static serverIndex: number = 0
// static serverPid: number = 0
// static pool: { [url: string]: ClusterVisitor } = {}
// receiver = this.getReceiver<IZeroServerCS>("")
// sender = this.getSender<IZeroServerSC>("")
// url!: string
// name!: string
// models!: string[]
// sid!: number//在同一个server有相同的sid
// pid!: number//在同一内存中有相同的pid
// type!: ServerType;
// lines: Set<number> = new Set()
// clusterServer!: ZeroCluster
// start() {
// this.clusterServer = this.server
// this.receiver.init(async (info) => {
// //TODO 这里要加密
// let server = ClusterVisitor.pool[info.url]
// if (server == null) {
// this.sid = ClusterVisitor.serverIndex
// this.url = info.url
// this.models = info.models
// this.type = info.type
// this.pid = info.pid
// this.name = info.name
// ClusterVisitor.serverIndex++
// /**
// * 给自己发一个完成的信息
// */
// this.sender.clustered(this.sid)
// for (const key in ClusterVisitor.pool) {
// if (Object.prototype.hasOwnProperty.call(ClusterVisitor.pool, key)) {
// const element = ClusterVisitor.pool[key];
// /**
// * 向新入加者发送已加入者信息
// */
// this.sender.add({
// url: element.url,
// models: element.models,
// type: element.type,
// sid: element.sid,
// })
// /**
// * 向所有已加入者发送新入加者信息
// */
// element.sender.add({
// url: info.url,
// models: info.models,
// type: info.type,
// sid: this.sid,
// })
// }
// }
// ClusterVisitor.pool[info.url] = this
// } else {
// console.log("出现URL重复")
// this.kick()
// }
// this.clusterServer.emit("change")
// })
// this.receiver.getPid(async () => {
// return ClusterVisitor.serverPid++
// })
// this.receiver.addLine(async (sid) => {
// this.lines.add(sid)
// this.clusterServer.emit("change")
// })
// this.receiver.removeLine(async (sid) => {
// this.lines.delete(sid)
// this.clusterServer.emit("change")
// })
// }
// clear(): void {
// delete ClusterVisitor.pool[this.url]
// for (const key in ClusterVisitor.pool) {
// if (Object.prototype.hasOwnProperty.call(ClusterVisitor.pool, key)) {
// const element = ClusterVisitor.pool[key];
// element.sender.remove(this.sid)
// }
// }
// }
// }
import ZeroRemote, { GameVisitor, ICSMessage, ISCMessage, ZeroRemoteClient } from "./index"
import ws from "ws"
import { T2 } from "./T2"
class User extends GameVisitor {
clear(): void {
}
a = 0
start() {
this.getReceiver<T2>("fuck").getPid(async () => {
throw "fuck"
this.a++
return this.a
})
// this.getReceiver<T1>("fuck").on("fuck", (data) => {
// setTimeout(() => {
// data.b()
// }, 2000);
// })
// this.getReceiver<T1>("fuck").fuck((data) => {
// console.log("___________")
// setTimeout(() => {
// data.b()
// }, 2000);
// return 5
// })
// this.getSender<T1>("tt").fuck({
// a: 1, b: () => {
// console.log("____nonono")
// }
// })
}
}
let zn = new ZeroRemote(new ws.Server({ port: 8888 }), (carer, server) => {
return new User(carer, server)
})
//-------------------------------------------------
// interface A {
// init(a: string, b: number): number
// init2(): void
// }
// interface B {
// a(): void
// }
// /**
// * 新建服务
// */
// new ZeroRemote(new ws.Server({ port: 2000 }), (carer) => {
// return new RPCVisitor(carer)
// })
// RPCVisitor.addRemote<A>(async (visitor) => {
// let a = await visitor.rs.init("a", 4)
// console.log("打印远程回调结果")
// console.log(a)
// }, "tt")
// RPCVisitor.addRemote<B>(async (visitor) => {
// let xx = async () => {
// await visitor.rs.a()
// xx()
// }
// xx()
// })
// class CS extends RPCClient implements A {
// constructor() {
// super("ws:127.0.0.1:2000", "tt")
// }
// init(a: string, b: number): number {
// console.log(a)
// return 5 + b
// }
// init2(): void {
// console.log("_init2____")
// }
// }
// class CS2 extends RPCClient implements B {
// constructor() {
// super("ws:127.0.0.1:2000")
// }
// a(): void {
// console.log("aaa")
// }
// }
// let client = new CS()
// let client2 = new CS2()
// client.link()
// client.on("open", () => {
// console.log("rpc linked")
// })
// client2.link()
import { ICSMessage, ISCMessage, ZeroRemoteClient } from "."
import { T2 } from "./T2"
setTimeout(() => {
let cc = new ZeroRemoteClient("ws://192.168.16.195:8888")
cc.link(() => {
console.log("linkEd")
})
cc.on("linked", () => {
console.log("linked")
})
let sender = cc.getSender<T2>("fuck")
cc.on("showMask",()=>{
console.log("showMask")
})
setInterval(() => {
sender.getPid().then((a) => {
console.log(a)
}).catch((e) => {
console.log("___", e)
})
// sender.tt("sss").then((a)=>{
// console.log(a)
// }).catch((b)=>{
// console.log(b)
// })
}, 500)
}, 2000)
"use strict";
// import ws from "ws";
// import { address as getLocalIp } from "ip"
// import ZeroRemote, { GameVisitor, IChannel, ICSMessage, ISCMessage, ReturnReceiver, ZeroRemoteClient } from "zero-remote";
// type CMType = new (...ary: any[]) => ZeroServerNode
// type MType = new (...ary: any[]) => ZeroServerNode
// export let routeMap: WeakMap<CMType, string> = new WeakMap()
// export let balancePool: { [key: string]: (player: any, totle: number) => number } = {}
// /**
// * 装饰器
// * @param key
// * @returns
// */
// export function route(key: string) {
// return (type: CMType) => {
// routeMap.set(type, key)
// }
// }
// /**
// * 装饰器 用去落点均衡
// * @param callback
// * @returns
// */
// export function balance<T extends UserInfo>(callback: (player: T, totle: number) => number) {
// return (type: MType) => {
// let route = getRoute(type)
// if (route) {
// balancePool[route] = callback
// }
// }
// }
// /**
// * 获取装饰器路由名
// * @param connectorType
// * @returns
// */
// export function getRoute(connectorType: new (...args: any[]) => any): string {
// let route = routeMap.get(connectorType)
// if (route) {
// return route
// } else {
// throw new Error("这个类没有@route")
// }
// }
// /**
// * server类型
// */
// enum ServerType {
// MODULE,
// CONNECT,
// SPECIAL,
// }
// interface IZeroServerCS {
// init: (value: { url: string, name: string, models: string[], type: ServerType, pid: number }) => void
// getPid: () => number
// addLine: (sid: number) => void
// removeLine: (sid: number) => void
// }
// interface IZeroServerInfo {
// url: string,
// models: string[],
// type: ServerType,
// sid: number
// }
// interface IZeroServerSC {
// clustered: (value: number) => void
// add: (value: IZeroServerInfo) => void
// remove: (value: number) => void
// }
// type ModuleType = new (...arg: any[]) => Module & { route: string }
// /**
// * server基类
// */
// export class ZeroServer extends ZeroRemoteClient {
// serverType: ServerType = ServerType.MODULE
// url: string;
// static mainUrl: string
// static modelPool: { [key: string]: Module } = {}
// models: any = []
// clusterSender = this.getSender<IZeroServerCS>("")
// clusterReceiver = this.getReceiver<IZeroServerSC>("")
// static pid: number
// serverPool: { [key: string]: IZeroServerInfo } = {}
// name: string
// serverId!: number;
// isClustered: boolean = false
// constructor(public port: number) {
// super()
// this.name = this.constructor.name
// if (ZeroServer.mainUrl == null) {
// throw "请配置主服务器地址ZeroServer.mainUrl=\"XXX\""
// }
// this.url = ZeroServer.mainUrl
// /**
// * 保存所有服务节点以方便扩展
// */
// this.clusterReceiver.add((info) => {
// this.serverPool[info.sid] = info
// })
// this.clusterReceiver.clustered((sid: number) => {
// this.isClustered = true
// this.serverId = sid
// this.clustered()
// })
// this.link()
// }
// clustered(): void {
// }
// showMask(): void {
// }
// hideMask(): void {
// }
// stringify(value: ISCMessage | ICSMessage): string {
// return JSON.stringify(value)
// }
// error(error: any): void {
// }
// linked(): void {
// if (ZeroServer.pid == null) {
// this.clusterSender.getPid().then((pid) => {
// if (ZeroServer.pid == null) {
// ZeroServer.pid = pid
// }
// this.sendInit()
// })
// } else {
// this.sendInit()
// }
// }
// private sendInit() {
// this.clusterSender.init({ url: getLocalIp() + ":" + this.port, name: this.name, type: this.serverType, models: this.models, pid: ZeroServer.pid })
// }
// /**
// * 生命不息 重连不止
// */
// popup(): void {
// console.log("集群失败")
// }
// linking(): void {
// }
// addModule(modelType: ModuleType) {
// let route = getRoute(modelType)
// if (route) {
// let model = new modelType(route)
// model.server = this
// model.start()
// ZeroServer.modelPool[route] = model
// this.models.push(route)
// }
// }
// }
// /**
// * 放在Connector服务上
// * 用来连接Module的线路
// */
// class ClientFotModule extends ZeroRemoteClient {
// relinkMaxCount = 100
// popupReLinkTime: number = 1000
// popupReLinkTimeIndex!: NodeJS.Timeout;
// constructor(public url: string) {
// super()
// }
// showMask(): void {
// // throw new Error("Method not implemented.");
// }
// hideMask(): void {
// // throw new Error("Method not implemented.");
// }
// stringify(value: ICSMessage | ISCMessage): string {
// return JSON.stringify(value)
// }
// error(error: any): void {
// // throw new Error("Method not implemented.");
// }
// linked(): void {
// this.popupReLinkTime = 1000
// }
// popup(): void {
// console.log("pppppp")
// for (const key in this.callbackPool) {
// const element = this.callbackPool[key];
// console.log(element)
// element(false, "服务器被断开")
// }
// this.popupReLinkTimeIndex = setTimeout(() => {
// this.link()
// this.popupReLinkTime += 1000
// }, this.popupReLinkTime)
// // throw new Error("Method not implemented.");
// }
// linking(): void {
// // throw new Error("Method not implemented.");
// }
// }
// /**
// * 用户
// */
// export class ZeroServerUser<T extends UserInfo = UserInfo> extends GameVisitor {
// static pool: { [key: string]: ZeroServerUser } = {}
// static index: number = 0
// static getAtuoId() {
// return this.index++
// }
// clear(): void {
// }
// constructor(channel: IChannel<ISCMessage>, server: ZeroRemote, public info: T) {
// super(channel, server)
// ZeroServerUser.pool[info.userId] = this
// }
// }
// /**
// * 连接服务器 用于连接用户
// */
// export class ConnectorServer<T extends UserInfo> extends ZeroServer {
// connectorTypePool: { [key: string]: new (...args: any[]) => Connector } = {};
// serverType = ServerType.CONNECT
// modelsChannels: { [key: string]: ClientFotModule[] } = {};
// constructor(port: number, private playerInfoType: new (sid: number, uid: number) => T) {
// super(port)
// }
// clustered() {
// console.log("创建连接服务:", this.serverId)
// new ZeroRemote(new ws.Server({ port: this.port }), (channel, server) => {
// let user = new ZeroServerUser(channel, server, new this.playerInfoType(this.serverId, ZeroServerUser.getAtuoId()))
// for (const key in this.connectorTypePool) {
// if (Object.prototype.hasOwnProperty.call(this.connectorTypePool, key)) {
// const element = this.connectorTypePool[key];
// let connector = new element(this, user, key);
// connector.start()
// }
// }
// return user
// })
// this.clusterReceiver.add((info) => {
// if (info.type == ServerType.MODULE) {
// let clientFotModule = new ClientFotModule("ws://" + info.url)
// clientFotModule.link(() => {
// this.clusterSender.addLine(info.sid)
// })
// clientFotModule.receive("", "", this.partMessage.bind(this))
// info.models.forEach((modelsName: string) => {
// let clinets = this.modelsChannels[modelsName]
// if (clinets == null) {
// clinets = []
// this.modelsChannels[modelsName] = clinets
// }
// clinets.push(clientFotModule)
// })
// }
// })
// this.clusterReceiver.remove((info) => {
// })
// }
// /**
// * 转发到前端
// * @param data
// */
// private partMessage(data: { key: string, data: any, userId: number, route: string }) {
// let user = ZeroServerUser.pool[data.userId]
// user.channel.send({
// route: data.route,
// key: data.key,
// data: data.data
// })
// }
// addConnector(connectorType: (new (...args: any[]) => Connector)) {
// let route = getRoute(connectorType)
// if (route) {
// this.connectorTypePool[route] = connectorType
// }
// }
// }
// /**
// * 有个CONNECT服务器做为客户端连了上来
// * 添加 ping
// * 添加 callback
// * 添加 kick
// */
// export class ConnectorVisitor extends GameVisitor {
// clear(): void {
// console.log("clear")
// }
// constructor(channel: IChannel<ISCMessage>, public moduleServer: ModuleServer) {
// super(channel, moduleServer.connectorServer)
// }
// handle(route: string, key: string, data: any, back: (Function | undefined)) {
// let model: any = ZeroServer.modelPool[route]
// let method: Function = model[key]
// if (method) {
// model.playerInfo = data.p
// model.isRemote = true
// let visitor = this.moduleServer.connectorVisitorPool[model.playerInfo.serverId]
// if (visitor == null) {
// this.moduleServer.connectorVisitorPool[model.playerInfo.serverId] = this
// } else {
// // console.log("这里应该为true", visitor == this)
// }
// let p = method.apply(model, data.a)
// if (back != null) {
// if (p instanceof Promise) {
// p.then((valueThen) => {
// back!(true, valueThen)
// }).catch((error) => {
// back!(false, error)
// })
// } else {
// back(true, p)
// }
// }
// }
// }
// }
// export class ModuleServer extends ZeroServer {
// serverType = ServerType.MODULE
// connectorVisitorPool: { [key: string]: ConnectorVisitor } = {}
// connectorServer: ZeroRemote
// constructor(port: number) {
// super(port)
// this.connectorServer = new ZeroRemote(new ws.Server({ port: this.port }), (channel, server) => {
// return new ConnectorVisitor(channel, this)
// })
// }
// clustered() {
// console.log("创建功能服务:", this.serverId)
// }
// }
// /**
// * 被序列化的传递的用户信息
// */
// export class UserInfo {
// name: string
// /**
// *
// * @param serverId
// * @param userId 用于路由到用户不发给前端
// */
// constructor(public serverId: number, public userId: number) {
// this.name = "S" + serverId + "U" + userId
// }
// }
// /**
// * 一个服务节点
// */
// export class ZeroServerNode {
// constructor(public route: string) {
// }
// start() {
// }
// }
// type Parameters<T> = T extends (...args: infer P) => any ? P : never;
// type ReturnType<T> = T extends (...args: any) => infer R ? R : any;
// export type ModuleSender<T> = { [K in keyof T]: ((value: Parameters<T[K]>[0], playerInfo?: UserInfo) => Promise<ReturnType<T[K]>>) }
// /**
// *
// */
// export class Module<SC = any> extends ZeroServerNode {
// sender: ModuleSender<SC>
// public playerInfo!: UserInfo
// public isRemote: boolean = false
// public server!: ZeroServer
// constructor(route: string) {
// super(route)
// this.sender = new Proxy<ModuleSender<SC>>({} as any, {
// get: (target: any, p: string, receiver: any) => {
// return (data: any, playerInfo: UserInfo | null = null) => {
// // let playerInfo
// if (playerInfo == null) {
// playerInfo = this.playerInfo
// }
// if (playerInfo) {
// if (this.isRemote) {
// let sendInfo = {
// route: "",
// key: "",
// data: {
// route: this.route,
// key: p,
// data: data,
// userId: playerInfo.userId
// }
// }
// let visitor = (this.server as ModuleServer).connectorVisitorPool[this.playerInfo.serverId]
// visitor.channel.send(sendInfo)
// } else {
// let sendInfo = {
// route: route,
// key: p,
// data: data
// }
// let user = ZeroServerUser.pool[playerInfo.userId]
// if (user != null) {
// user.channel.send(sendInfo)
// } else {
// console.warn("no User")
// }
// }
// }
// }
// }
// })
// }
// }
// export class Connector<CS = any> extends ZeroServerNode {
// player!: ZeroServerUser<any>
// receiver: ReturnReceiver<CS>;
// private isFree: Boolean = true
// private lastCallback: (() => Promise<void>)[] = []
// constructor(public server: ConnectorServer<any>, player: ZeroServerUser<any>, route: string) {
// super(route)
// this.player = player;
// this.route = route;
// /**
// * 接收来自己玩家的请求所有做了队例处理 防攻击
// */
// this.receiver = new Proxy<ReturnReceiver<CS>>({} as any, {
// get: (target: any, p: string, receiver: any) => {
// return (callback: (value: any) => Promise<void>) => {
// let router = (this.player as any).routerPool[route]
// if (router == null) {
// router = {};
// (this.player as any).routerPool[route] = router
// }
// router[p] = (...args: any) => {
// if (this.lastCallback.length >= 100) {
// this.player.kick()
// } else {
// this.lastCallback.push(() => {
// return callback.apply(null, args)
// })
// }
// if (this.isFree) {
// this.isFree = false
// this.nextReceiver()
// }
// }
// }
// }
// })
// }
// private nextReceiver() {
// if (this.lastCallback.length > 0) {
// let callback = this.lastCallback.shift()
// if (callback) {
// callback().then(() => {
// this.nextReceiver()
// }).catch((err: Error | string) => {
// if (typeof err == "string") {
// this.player.error(err)
// } else {
// this.player.error(err.message)
// }
// this.nextReceiver()
// })
// }
// } else {
// this.isFree = true
// }
// }
// protected getModule<T extends Module>(modelType: new (...args: any[]) => T): T {
// let routeKey = getRoute(modelType)
// let model = ZeroServer.modelPool[routeKey]
// if (model == null) {
// let remoteModule = this.getRemoteModule(routeKey)
// return new Proxy<T>({} as any, {
// get: (target: any, p: string, receiver: any) => {
// if (typeof modelType.prototype[p] == "function") {
// return (...args: any[]) => {
// console.log("__1__")
// return new Promise((resolve: (value: any) => void, reject: (reason?: any) => void) => {
// console.log("__2__")
// if (remoteModule == null) {
// remoteModule = this.getRemoteModule(routeKey)
// }
// if (remoteModule != null) {
// console.log("___3_")
// if (remoteModule.isOpen) {
// console.log("send")
// remoteModule.send(routeKey, p, {
// p: this.player.info,
// a: args
// }, (isError: boolean, value: any) => {
// if (isError) {
// resolve(value)
// } else {
// reject(value)
// }
// })
// }
// } else {
// reject("没有这个服务")
// }
// })
// }
// } else {
// //TODO
// }
// },
// set: (target: T, p: string, value: any, receiver: any) => {
// console.log(p)
// return true
// }
// })
// } else {
// return new Proxy<T>({} as any, {
// get: (target: any, p: string, receiver: any) => {
// if (typeof modelType.prototype[p] == "function") {
// return (...args: any[]) => {
// model.playerInfo = this.player.info
// let _model: any = model
// return _model[p].apply(model, args)
// }
// } else {
// }
// },
// set: (target: T, p: string, value: any, receiver: any) => {
// console.log(p)
// return true
// }
// })
// }
// }
// getRemoteModule(routeKey: string): ClientFotModule | null {
// let remoteModules = this.server.modelsChannels[routeKey]
// if (remoteModules) {
// let pick = balancePool[routeKey](this.player, remoteModules.length)
// return remoteModules[pick]
// } else {
// return null
// }
// }
// }
// export default class ZeroCluster extends ZeroRemote<{ change: [] }> {
// constructor(port: number) {
// super(new ws.Server({ port: port }), (channel, server) => {
// return new ClusterVisitor(channel, server)
// })
// }
// }
// export class ClusterVisitor extends GameVisitor {
// static serverIndex: number = 0
// static serverPid: number = 0
// static pool: { [url: string]: ClusterVisitor } = {}
// receiver = this.getReceiver<IZeroServerCS>("")
// sender = this.getSender<IZeroServerSC>("")
// url!: string
// name!: string
// models!: string[]
// sid!: number//在同一个server有相同的sid
// pid!: number//在同一内存中有相同的pid
// type!: ServerType;
// lines: Set<number> = new Set()
// clusterServer!: ZeroCluster
// start() {
// this.clusterServer = this.server
// this.receiver.init(async (info) => {
// //TODO 这里要加密
// let server = ClusterVisitor.pool[info.url]
// if (server == null) {
// this.sid = ClusterVisitor.serverIndex
// this.url = info.url
// this.models = info.models
// this.type = info.type
// this.pid = info.pid
// this.name = info.name
// ClusterVisitor.serverIndex++
// /**
// * 给自己发一个完成的信息
// */
// this.sender.clustered(this.sid)
// for (const key in ClusterVisitor.pool) {
// if (Object.prototype.hasOwnProperty.call(ClusterVisitor.pool, key)) {
// const element = ClusterVisitor.pool[key];
// /**
// * 向新入加者发送已加入者信息
// */
// this.sender.add({
// url: element.url,
// models: element.models,
// type: element.type,
// sid: element.sid,
// })
// /**
// * 向所有已加入者发送新入加者信息
// */
// element.sender.add({
// url: info.url,
// models: info.models,
// type: info.type,
// sid: this.sid,
// })
// }
// }
// ClusterVisitor.pool[info.url] = this
// } else {
// console.log("出现URL重复")
// this.kick()
// }
// this.clusterServer.emit("change")
// })
// this.receiver.getPid(async () => {
// return ClusterVisitor.serverPid++
// })
// this.receiver.addLine(async (sid) => {
// this.lines.add(sid)
// this.clusterServer.emit("change")
// })
// this.receiver.removeLine(async (sid) => {
// this.lines.delete(sid)
// this.clusterServer.emit("change")
// })
// }
// clear(): void {
// delete ClusterVisitor.pool[this.url]
// for (const key in ClusterVisitor.pool) {
// if (Object.prototype.hasOwnProperty.call(ClusterVisitor.pool, key)) {
// const element = ClusterVisitor.pool[key];
// element.sender.remove(this.sid)
// }
// }
// }
// }
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const index_1 = __importStar(require("./index"));
const ws_1 = __importDefault(require("ws"));
class User extends index_1.GameVisitor {
constructor() {
super(...arguments);
this.a = 0;
}
clear() {
}
start() {
this.getReceiver("fuck").getPid(() => __awaiter(this, void 0, void 0, function* () {
throw "fuck";
this.a++;
return this.a;
}));
// this.getReceiver<T1>("fuck").on("fuck", (data) => {
// setTimeout(() => {
// data.b()
// }, 2000);
// })
// this.getReceiver<T1>("fuck").fuck((data) => {
// console.log("___________")
// setTimeout(() => {
// data.b()
// }, 2000);
// return 5
// })
// this.getSender<T1>("tt").fuck({
// a: 1, b: () => {
// console.log("____nonono")
// }
// })
}
}
let zn = new index_1.default(new ws_1.default.Server({ port: 8888 }), (carer, server) => {
return new User(carer, server);
});
//-------------------------------------------------
// interface A {
// init(a: string, b: number): number
// init2(): void
// }
// interface B {
// a(): void
// }
// /**
// * 新建服务
// */
// new ZeroRemote(new ws.Server({ port: 2000 }), (carer) => {
// return new RPCVisitor(carer)
// })
// RPCVisitor.addRemote<A>(async (visitor) => {
// let a = await visitor.rs.init("a", 4)
// console.log("打印远程回调结果")
// console.log(a)
// }, "tt")
// RPCVisitor.addRemote<B>(async (visitor) => {
// let xx = async () => {
// await visitor.rs.a()
// xx()
// }
// xx()
// })
// class CS extends RPCClient implements A {
// constructor() {
// super("ws:127.0.0.1:2000", "tt")
// }
// init(a: string, b: number): number {
// console.log(a)
// return 5 + b
// }
// init2(): void {
// console.log("_init2____")
// }
// }
// class CS2 extends RPCClient implements B {
// constructor() {
// super("ws:127.0.0.1:2000")
// }
// a(): void {
// console.log("aaa")
// }
// }
// let client = new CS()
// let client2 = new CS2()
// client.link()
// client.on("open", () => {
// console.log("rpc linked")
// })
// client2.link()
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const _1 = require(".");
setTimeout(() => {
let cc = new _1.ZeroRemoteClient("ws://192.168.16.195:8888");
cc.link(() => {
console.log("linkEd");
});
cc.on("linked", () => {
console.log("linked");
});
let sender = cc.getSender("fuck");
cc.on("showMask", () => {
console.log("showMask");
});
setInterval(() => {
sender.getPid().then((a) => {
console.log(a);
}).catch((e) => {
console.log("___", e);
});
// sender.tt("sss").then((a)=>{
// console.log(a)
// }).catch((b)=>{
// console.log(b)
// })
}, 500);
}, 2000);
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.RPCClient = exports.RPCVisitor = exports.RPCCode = void 0;
const zero_mvc_1 = require("zero-mvc");
const _1 = require(".");
const ws_1 = __importDefault(require("ws"));
var RPCCode;
(function (RPCCode) {
RPCCode[RPCCode["INITIATIVE"] = 0] = "INITIATIVE";
RPCCode[RPCCode["FAIL"] = 1] = "FAIL";
RPCCode[RPCCode["CALLBACK"] = 50] = "CALLBACK";
RPCCode[RPCCode["SUCCESS"] = 200] = "SUCCESS";
RPCCode[RPCCode["KICK"] = 30] = "KICK";
})(RPCCode = exports.RPCCode || (exports.RPCCode = {}));
class RPCHandle {
constructor(carer, owner) {
this.carer = carer;
this.owner = owner;
this.target = null;
this.callbackStack = new _1.LiteStack();
let k;
let f = (...args) => {
return new Promise((resolve, reject) => {
let cbs = {};
args.forEach((arg, index) => {
if (typeof arg == "function") {
cbs[index] = this.callbackStack.push({ resolve: arg });
}
});
this.carer.send({
code: RPCCode.INITIATIVE,
key: k,
args: args,
cbs: cbs,
index: this.callbackStack.push({ resolve: resolve, reject: reject }),
});
if (this.callbackStack.size > RPCHandle.callbackMaxStack) {
this.callbackStack.clear(RPCHandle.callbackMaxStack / 2);
}
});
};
this.rs = new Proxy({}, {
get: (target, p, receiver) => {
k = p;
return f;
}
});
}
receive(body) {
if (body.code == RPCCode.INITIATIVE || body.code == RPCCode.SUCCESS) {
let target;
if (this.target && this.target[body.key] != null) {
target = this.target;
}
else if (this.owner[body.key] == null) {
target = this.target;
}
else {
target = this.owner;
}
if (target == null) {
this.reject(body.index, "no remote traget " + body.key);
}
else {
let method = target[body.key];
if (method) {
if (body.cbs) {
for (const key in body.cbs) {
if (body.cbs.hasOwnProperty(key)) {
const element = body.cbs[key];
body.args[key] = (...CbArgs) => {
this.carer.send({
code: RPCCode.CALLBACK,
key: element,
args: CbArgs
});
};
}
}
}
Promise.resolve(method.apply(target, body.args || [])).then((value) => {
this.carer.send({
code: RPCCode.CALLBACK,
key: body.index,
args: [value]
});
}).catch(err => {
console.log(err);
});
}
else {
this.reject(body.index, "no remote method " + body.key);
}
}
}
else if (body.code == RPCCode.CALLBACK) {
let method = this.callbackStack.pull(body.key);
if (method) {
method.resolve.apply(null, body.args);
}
else {
this.error();
}
body.args;
}
else if (body.code == RPCCode.FAIL) {
if (body.key != null) {
let method = this.callbackStack.pull(body.key);
if (method && method.reject) {
method.reject(body.error);
}
}
}
}
error(value) {
this.carer.send({
code: RPCCode.FAIL,
error: value,
});
}
reject(key, value) {
this.carer.send({
code: RPCCode.FAIL,
key: key,
error: value,
});
}
}
RPCHandle.callbackMaxStack = 20;
/**
* RPC模式下的用户
* 回调函数在第没有被调用的情况下会被回收
*/
class RPCVisitor extends _1.Visitor {
constructor(carer, server) {
super(carer, server);
this.key = null;
this.handle = new RPCHandle(carer, this);
this.handle.rs.getKey().then((key) => {
this.key = key;
let callback = RPCVisitor.remotePool[key];
if (callback) {
callback(this).catch((err) => {
console.warn(err);
});
}
else {
console.log("主没上没有命名为\"" + key + "\"的的RPC服务");
}
}).catch((err) => {
console.log(err, "rpc error");
});
}
set owner(value) {
this.handle.target = value;
}
/**
* RemoteServer
* 远程服务
*/
get rs() {
return this.handle.rs;
}
static addRemote(callback, key = "") {
RPCVisitor.remotePool[key] = callback;
}
ping() {
return true;
}
error(value) {
this.handle.error(value);
}
receive(body) {
this.handle.receive(body);
}
clear() {
}
}
exports.RPCVisitor = RPCVisitor;
RPCVisitor.remotePool = {};
/**
* RPC模式 客户端
* 支持 双向 添加回调函数
* 支持返回值
* 支持智能提示
* 支持一对多
*/
class RPCClient extends zero_mvc_1.ZeroDispatcher {
constructor(address, key = "", pack = _1.jsonPack) {
super();
this.address = address;
this.key = key;
this.pack = pack;
this.isClose = false;
this.maxRelinkCount = 20;
this.isLinking = false;
this.linkOutTime = 200;
this.relinkCount = 0;
this.handle = new RPCHandle({
close: () => {
this.clear();
this.isLinking = false;
},
send: (body) => {
this.send(body);
}
}, this);
}
set owner(value) {
this.handle.target = value;
}
getKey() {
return this.key;
}
ping() {
return __awaiter(this, void 0, void 0, function* () {
return yield this.rs.ping();
});
}
link() {
if (!this.isLinking) {
this.isLinking = true;
console.log("正在连接" + this.address);
this.ws = new ws_1.default(this.address, { handshakeTimeout: 2000 });
this.ws.addEventListener("message", (evt) => {
let obj;
try {
obj = this.pack.parse(evt.data);
}
catch (_a) {
console.warn("RPCClient: can't parse for data");
}
this.receive(obj);
});
this.ws.addEventListener("close", () => {
this.reset();
});
this.ws.addEventListener("error", (event) => {
console.warn(event);
this.reset();
});
this.ws.addEventListener("open", () => {
this.emit("open");
this.relinkCount = 0;
this.linkOutTime = 200;
});
}
}
reset() {
this.emit("reset");
this.clear();
this.isLinking = false;
if (this.maxRelinkCount > this.relinkCount && !this.isClose) {
this.linkOutTime *= 1.5;
this.relinkCount++;
setTimeout(() => {
this.link();
this.emit("relink");
}, this.linkOutTime);
}
else {
this.emit("stop");
}
}
clear() {
if (this.ws) {
this.ws.removeAllListeners("message");
this.ws.removeAllListeners("close");
this.ws.removeAllListeners("error");
this.ws.removeAllListeners("open");
}
}
close() {
if (this.ws) {
this.isClose = true;
this.ws.close();
}
else {
console.log("RPCClient: no ws");
}
}
send(body) {
if (this.ws) {
let value = null;
try {
value = this.pack.stringify(body);
}
catch (e) {
console.warn("RPCClient: can't stringify " + e);
}
if (value != null) {
this.ws.send(value);
}
else {
console.log("RPCClient: can't send null");
}
}
else {
console.warn("RPCClient: no ws");
}
}
get rs() {
return this.handle.rs;
}
receive(body) {
this.handle.receive(body);
}
error(value) {
this.handle.error(value);
}
}
exports.RPCClient = RPCClient;
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
-337
import { ZeroDispatcher } from "zero-mvc"
import ZeroRemote, { IChannel, IPack, jsonPack, LiteStack, Visitor } from "."
import WebSocket from "ws"
export enum RPCCode {
INITIATIVE = 0,
FAIL = 1,
CALLBACK = 50,
SUCCESS = 200,
KICK = 30,
}
interface IChannelVO {
code: RPCCode.INITIATIVE | RPCCode.SUCCESS
key: string,
args: any[]
cbs: { [key: number]: number }
index: number
}
interface IChannelCbVO {
code: RPCCode.CALLBACK
key: number,
args: any[]
}
interface IChannelErrVO {
code: RPCCode.FAIL
key?: number,
error?: number | string
}
interface IChannelKickVO {
code: RPCCode.KICK
}
export type IRPCProto = IChannelErrVO | IChannelCbVO | IChannelVO | IChannelKickVO
export type IRSC<T> = { [P in keyof T]: (...args: any) => any }
export type IRSP<T> = { [P in keyof T]: IRS<T[P]> }
export type IRS<T extends IRSC<T>> = { [P in keyof T]: (...args: Parameters<T[P]>) => Promise<ReturnType<T[P]>> }
class RPCHandle<T = any> {
static callbackMaxStack = 20
rs: T
public target: object | null = null
private callbackStack = new LiteStack<{ resolve: Function, reject?: Function }>()
constructor(public carer: IChannel<IRPCProto>, public owner: object) {
let k: string
let f = (...args: T[]) => {
return new Promise((resolve: (value: any) => void, reject: () => void) => {
let cbs: { [key: number]: number } = {}
args.forEach((arg, index) => {
if (typeof arg == "function") {
cbs[index] = this.callbackStack.push({ resolve: arg })
}
})
this.carer.send({
code: RPCCode.INITIATIVE,
key: k,
args: args,
cbs: cbs,
index: this.callbackStack.push({ resolve: resolve, reject: reject }),
})
if (this.callbackStack.size > RPCHandle.callbackMaxStack) {
this.callbackStack.clear(RPCHandle.callbackMaxStack / 2)
}
})
}
this.rs = new Proxy({} as any, {
get: (target: any, p: string, receiver: any) => {
k = p
return f
}
})
}
receive(body: IRPCProto): void {
if (body.code == RPCCode.INITIATIVE || body.code == RPCCode.SUCCESS) {
let target
if (this.target && (this.target as any)[body.key] != null) {
target = this.target
} else if ((this.owner as any)[body.key] == null) {
target = this.target
} else {
target = this.owner
}
if (target == null) {
this.reject(body.index, "no remote traget " + body.key)
} else {
let method = ((target as any)[body.key] as Function)
if (method) {
if (body.cbs) {
for (const key in body.cbs) {
if (body.cbs.hasOwnProperty(key)) {
const element = body.cbs[key];
body.args[key] = (...CbArgs: any[]) => {
this.carer.send({
code: RPCCode.CALLBACK,
key: element,
args: CbArgs
})
}
}
}
}
Promise.resolve(method.apply(target, body.args || [])).then((value) => {
this.carer.send({
code: RPCCode.CALLBACK,
key: body.index,
args: [value]
})
}).catch(err => {
console.log(err);
})
} else {
this.reject(body.index, "no remote method " + body.key)
}
}
} else if (body.code == RPCCode.CALLBACK) {
let method = this.callbackStack.pull(body.key)
if (method) {
method.resolve.apply(null, body.args);
} else {
this.error()
}
body.args
} else if (body.code == RPCCode.FAIL) {
if (body.key != null) {
let method = this.callbackStack.pull(body.key)
if (method && method.reject) {
method.reject(body.error);
}
}
}
}
error(value?: number | string) {
this.carer.send({
code: RPCCode.FAIL,
error: value,
})
}
reject(key: number, value?: string) {
this.carer.send({
code: RPCCode.FAIL,
key: key,
error: value,
})
}
}
/**
* RPC模式下的用户
* 回调函数在第没有被调用的情况下会被回收
*/
export class RPCVisitor<T extends IRSC<T> = any> extends Visitor<IRPCProto, IRPCProto> {
handle!: RPCHandle
key: string | null = null
static remotePool: { [key: string]: (rs: RPCVisitor) => Promise<void> } = {};
set owner(value: any) {
this.handle.target = value
}
constructor(carer: IChannel<IRPCProto>, server: ZeroRemote) {
super(carer, server);
this.handle = new RPCHandle(carer, this)
this.handle.rs.getKey().then((key: string) => {
this.key = key
let callback = RPCVisitor.remotePool[key]
if (callback) {
callback(this).catch((err: any) => {
console.warn(err)
})
} else {
console.log("主没上没有命名为\"" + key + "\"的的RPC服务")
}
}).catch((err: any) => {
console.log(err, "rpc error")
})
}
/**
* RemoteServer
* 远程服务
*/
get rs(): IRS<T> {
return this.handle.rs
}
static addRemote<T extends IRSC<T> = any>(callback: (rs: RPCVisitor<T>) => Promise<void>, key: string = "") {
RPCVisitor.remotePool[key] = callback
}
ping(): boolean {
return true
}
error(value?: number | string) {
this.handle.error(value)
}
receive(body: IRPCProto): void {
this.handle.receive(body)
}
clear() {
}
}
/**
* RPC模式 客户端
* 支持 双向 添加回调函数
* 支持返回值
* 支持智能提示
* 支持一对多
*/
export class RPCClient<T extends IRSC<T> = any> extends ZeroDispatcher<{
stop: []
open: []
relink: []
reset: []
}> {
public ws!: WebSocket
private isClose = false
public maxRelinkCount = 20
private isLinking = false
private handle: RPCHandle<IRS<T>>
private linkOutTime: number = 200
private relinkCount = 0
set owner(value: any) {
this.handle.target = value
}
constructor(private address: string, public key: string = "", public pack: IPack = jsonPack) {
super()
this.handle = new RPCHandle({
close: () => {
this.clear()
this.isLinking = false
},
send: (body) => {
this.send(body)
}
}, this)
}
getKey() {
return this.key
}
async ping(): Promise<boolean> {
return await (this.rs as any).ping()
}
link(): void {
if (!this.isLinking) {
this.isLinking = true
console.log("正在连接" + this.address)
this.ws = new WebSocket(this.address, { handshakeTimeout: 2000 })
this.ws.addEventListener("message", (evt: { data: any }) => {
let obj: any;
try {
obj = this.pack.parse(evt.data);
}
catch {
console.warn("RPCClient: can't parse for data");
}
this.receive(obj);
});
this.ws.addEventListener("close", () => {
this.reset()
});
this.ws.addEventListener("error", (event) => {
console.warn(event)
this.reset()
});
this.ws.addEventListener("open", () => {
this.emit("open")
this.relinkCount = 0
this.linkOutTime = 200
});
}
}
reset() {
this.emit("reset")
this.clear()
this.isLinking = false
if (this.maxRelinkCount > this.relinkCount && !this.isClose) {
this.linkOutTime *= 1.5
this.relinkCount++
setTimeout(() => {
this.link()
this.emit("relink")
}, this.linkOutTime);
} else {
this.emit("stop")
}
}
clear() {
if (this.ws) {
this.ws.removeAllListeners("message");
this.ws.removeAllListeners("close");
this.ws.removeAllListeners("error");
this.ws.removeAllListeners("open");
}
}
close() {
if (this.ws) {
this.isClose = true
this.ws.close();
} else {
console.log("RPCClient: no ws");
}
}
send(body: IRPCProto) {
if (this.ws) {
let value: any = null;
try {
value = this.pack.stringify(body)
} catch (e) {
console.warn("RPCClient: can't stringify " + e)
}
if (value != null) {
this.ws.send(value);
}
else {
console.log("RPCClient: can't send null")
}
} else {
console.warn("RPCClient: no ws")
}
}
get rs() {
return this.handle.rs
}
receive(body: IRPCProto): void {
this.handle.receive(body)
}
error(value?: number | string) {
this.handle.error(value)
}
}
// interface T1 {
// fuck: (value: { a: number, b: Function }) => number
// }
export interface T2 {
getPid: () => number;
tt: (message: string) => void;
}