127 lines
4.3 KiB
TypeScript
127 lines
4.3 KiB
TypeScript
import { IncomingMessage } from "http";
|
|
import { WebSocket } from "ws";
|
|
import { CoroutineV2 } from "../../../../CatanEngine/CoroutineV2/CoroutineV2";
|
|
import { Action } from "../../../../CatanEngine/CSharp/System/Action";
|
|
import { Encoding } from "../../../../CatanEngine/CSharp/System/Text/Encoding";
|
|
import { ClientData } from "../../../../shared/protocols/define/interface";
|
|
import { INetRequest } from "./Core/INetRequest";
|
|
import { INetResponse } from "./Core/INetResponse";
|
|
|
|
let id = 1;
|
|
|
|
export class NetConnector {
|
|
readonly OnDataReceived: Action<INetResponse<any>> = new Action<INetResponse<any>>();
|
|
readonly OnDisconnected: Action<void> = new Action<void>();
|
|
readonly OnLoadUIMask: Action<boolean> = new Action<boolean>();
|
|
public static readonly clients = new Map<WebSocket, ClientData>();
|
|
|
|
public static OnWebSocketConnection(socket: WebSocket, request: IncomingMessage) {
|
|
const ip = request.socket.remoteAddress.replace("::ffff:", "") || 'Unknown IP';
|
|
console.log(`Client connected from IP: ${ip}`);
|
|
|
|
NetConnector.clients.set(socket, { socket, id: id, name: "", money: 0 });
|
|
id++;
|
|
|
|
socket.on('message', (message: Buffer) => NetConnector.OnWebSocketMessage(socket, message));
|
|
|
|
socket.on('close', NetConnector.OnWebSocketClose);
|
|
}
|
|
|
|
public static async OnWebSocketMessage(socket: WebSocket, message: Buffer) {
|
|
// 将 Buffer 转换为 ArrayBuffer
|
|
const buffer = message.buffer.slice(message.byteOffset, message.byteOffset + message.byteLength);
|
|
let startIndex = 0, byteLength = buffer.byteLength;
|
|
while (startIndex + 4 < byteLength) {
|
|
const view: DataView = new DataView(buffer, 0, 3);
|
|
const strlen: number = view.getUint16(0, true) + (view.getUint8(2) << 16);
|
|
const decoder: TextDecoder = new TextDecoder("utf-8");
|
|
const str: string = decoder.decode(new Uint8Array(buffer, startIndex + 4, strlen));
|
|
startIndex += strlen + 4;
|
|
|
|
// try {
|
|
let json = JSON.parse(str);
|
|
let method = <string>json[0];
|
|
let data = json[1];
|
|
|
|
let req = <INetRequest<any>>{
|
|
Method: method,
|
|
Data: data,
|
|
};
|
|
|
|
if (data) {
|
|
console.log(`[RPC] 收到client呼叫: ${req.Method}(${JSON.stringify(req.Data)})`);
|
|
} else {
|
|
console.log(`[RPC] 收到client呼叫: ${req.Method}()`);
|
|
}
|
|
|
|
// 动态导入处理函数
|
|
try {
|
|
// 动态导入文件
|
|
const module = await import(`../../../../api/${req.Method.replace(".", "/")}`);
|
|
|
|
// 调用导入模块中的处理函数
|
|
if (module.default) {
|
|
let AsyncFunction: () => IterableIterator<any> = function* (): IterableIterator<any> {
|
|
const clientData: ClientData = NetConnector.clients.get(socket);
|
|
const response: INetResponse<any> = yield* module.default(clientData, req);
|
|
if (response) {
|
|
NetConnector.Send(socket, response);
|
|
}
|
|
};
|
|
CoroutineV2.Single(AsyncFunction()).Start();
|
|
} else {
|
|
throw new Error(`Module for ${req.Method} does not export a default function.`);
|
|
}
|
|
} catch (error) {
|
|
console.error(`Error handling request ${req.Method}: ${error.message}`);
|
|
const response: INetResponse<any> = {
|
|
Status: -1,
|
|
Method: req.Method,
|
|
Data: null,
|
|
IsValid: false
|
|
};
|
|
NetConnector.Send(socket, response);
|
|
}
|
|
}
|
|
}
|
|
|
|
public static OnWebSocketClose() {
|
|
console.log('Client disconnected');
|
|
}
|
|
|
|
private static Send(socket: WebSocket, resp: INetResponse<any>) {
|
|
let json: any = [resp.Method, [resp.Status]];
|
|
//@ts-ignore
|
|
if (resp.Data != null && resp.Data != undefined && resp.Data != NaN) {
|
|
json[1].push(resp.Data);
|
|
}
|
|
|
|
//@ts-ignore
|
|
if (resp.Data != null && resp.Data != undefined && resp.Data != NaN) {
|
|
console.log(`[RPC] 回傳client呼叫:(${resp.Status}): ${resp.Method}(${JSON.stringify(resp.Data)})`);
|
|
} else {
|
|
console.log(`[RPC] 回傳client呼叫:(${resp.Status}): ${resp.Method}()`);
|
|
}
|
|
|
|
let str = JSON.stringify(json);
|
|
if (str.length > 65535) {
|
|
throw new Error("要傳的資料太大囉");
|
|
}
|
|
|
|
let strary = Encoding.UTF8.GetBytes(str);
|
|
let buffer = new Uint8Array(4 + strary.byteLength);
|
|
let u16ary = new Uint16Array(buffer.buffer, 0, 3);
|
|
u16ary[0] = strary.byteLength;
|
|
buffer[3] = 0x01;
|
|
buffer.set(strary, 4);
|
|
|
|
socket.send(buffer);
|
|
}
|
|
}
|
|
|
|
const ErrorResponse: INetResponse<any> = {
|
|
Status: -1,
|
|
Method: "",
|
|
Data: {},
|
|
IsValid: false
|
|
}; |