Remove baseClient and simplify packet client selection

Deleted baseClient.ts and moved its logic into nativeClient.ts, making NativePacketClient a standalone class. Refactored PacketClientContext to always use NativePacketClient, removing support for multiple packet backends and related selection logic. Updated binary for napi2native.win32.x64.node.
This commit is contained in:
手瓜一十雪 2025-10-29 21:24:28 +08:00
parent 0c88319248
commit 55ef040852
4 changed files with 69 additions and 126 deletions

View File

@ -1,75 +0,0 @@
import { OidbPacket, PacketHexStr } from '@/core/packet/transformer/base';
import { LogStack } from '@/core/packet/context/clientContext';
import { NapCoreContext } from '@/core/packet/context/napCoreContext';
import { PacketLogger } from '@/core/packet/context/loggerContext';
import { CancelableTask } from '@/common/cancel-task';
export interface RecvPacket {
type: string, // 仅recv
data: RecvPacketData
}
export interface RecvPacketData {
seq: number
cmd: string
data: Buffer
}
export abstract class IPacketClient {
protected readonly napcore: NapCoreContext;
protected readonly logger: PacketLogger;
protected readonly cb = new Map<string, (json: RecvPacketData) => Promise<any> | any>(); // hash-type callback
logStack: LogStack;
available: boolean = false;
protected constructor(napCore: NapCoreContext, logger: PacketLogger, logStack: LogStack) {
this.napcore = napCore;
this.logger = logger;
this.logStack = logStack;
}
abstract check(): boolean;
abstract init(pid: number, recv: string, send: string): Promise<void>;
async sendPacket(cmd: string, data: PacketHexStr, rsp = false, timeout = 5000): Promise<RecvPacketData> {
if (!rsp) {
this.napcore.sendSsoCmdReqByContend(cmd, Buffer.from(data, 'hex')).catch(err => {
this.logger.error(`[PacketClient] sendPacket 无响应命令发送失败 cmd=${cmd} err=${err}`);
});
return { seq: 0, cmd: cmd, data: Buffer.alloc(0) };
}
const task = new CancelableTask<RecvPacketData>((resolve, reject, onCancel) => {
const timeoutId = setTimeout(() => {
reject(new Error(`[PacketClient] sendPacket 超时 cmd=${cmd} timeout=${timeout}ms`));
}, timeout);
onCancel(() => {
clearTimeout(timeoutId);
});
this.napcore.sendSsoCmdReqByContend(cmd, Buffer.from(data, 'hex'))
.then(ret => {
clearTimeout(timeoutId);
const result = ret as { rspbuffer: Buffer };
resolve({
seq: 0,
cmd: cmd,
data: result.rspbuffer
});
})
.catch(err => {
clearTimeout(timeoutId);
reject(err);
});
});
return await task;
}
async sendOidbPacket(pkt: OidbPacket, rsp = false, timeout = 5000): Promise<RecvPacketData> {
return await this.sendPacket(pkt.cmd, pkt.data, rsp, timeout);
}
}

View File

@ -1,22 +1,42 @@
import path, { dirname } from 'path';
import { fileURLToPath } from 'url';
import fs from 'fs';
import { IPacketClient } from '@/core/packet/client/baseClient';
import { constants } from 'node:os';
import { LogStack } from '@/core/packet/context/clientContext';
import { NapCoreContext } from '@/core/packet/context/napCoreContext';
import { PacketLogger } from '@/core/packet/context/loggerContext';
import { OidbPacket, PacketHexStr } from '@/core/packet/transformer/base';
import { CancelableTask } from '@/common/cancel-task';
export interface RecvPacket {
type: string, // 仅recv
data: RecvPacketData
}
export interface RecvPacketData {
seq: number
cmd: string
data: Buffer
}
// 0 send 1 recv
export interface NativePacketExportType {
initHook?: (send: string, recv: string) => boolean;
}
export class NativePacketClient extends IPacketClient {
export class NativePacketClient {
protected readonly napcore: NapCoreContext;
protected readonly logger: PacketLogger;
protected readonly cb = new Map<string, (json: RecvPacketData) => Promise<any> | any>(); // hash-type callback
logStack: LogStack;
available: boolean = false;
private readonly supportedPlatforms = ['win32.x64', 'linux.x64', 'linux.arm64', 'darwin.x64', 'darwin.arm64'];
private readonly MoeHooExport: { exports: NativePacketExportType } = { exports: {} };
constructor(napCore: NapCoreContext, logger: PacketLogger, logStack: LogStack) {
super(napCore, logger, logStack);
this.napcore = napCore;
this.logger = logger;
this.logStack = logStack;
}
check(): boolean {
@ -43,4 +63,44 @@ export class NativePacketClient extends IPacketClient {
this.available = true;
}
}
async sendPacket(cmd: string, data: PacketHexStr, rsp = false, timeout = 5000): Promise<RecvPacketData> {
if (!rsp) {
this.napcore.sendSsoCmdReqByContend(cmd, Buffer.from(data, 'hex')).catch(err => {
this.logger.error(`[PacketClient] sendPacket 无响应命令发送失败 cmd=${cmd} err=${err}`);
});
return { seq: 0, cmd: cmd, data: Buffer.alloc(0) };
}
const task = new CancelableTask<RecvPacketData>((resolve, reject, onCancel) => {
const timeoutId = setTimeout(() => {
reject(new Error(`[PacketClient] sendPacket 超时 cmd=${cmd} timeout=${timeout}ms`));
}, timeout);
onCancel(() => {
clearTimeout(timeoutId);
});
this.napcore.sendSsoCmdReqByContend(cmd, Buffer.from(data, 'hex'))
.then(ret => {
clearTimeout(timeoutId);
const result = ret as { rspbuffer: Buffer };
resolve({
seq: 0,
cmd: cmd,
data: result.rspbuffer
});
})
.catch(err => {
clearTimeout(timeoutId);
reject(err);
});
});
return await task;
}
async sendOidbPacket(pkt: OidbPacket, rsp = false, timeout = 5000): Promise<RecvPacketData> {
return await this.sendPacket(pkt.cmd, pkt.data, rsp, timeout);
}
}

View File

@ -1,17 +1,8 @@
import { IPacketClient } from '@/core/packet/client/baseClient';
import { NativePacketClient } from '@/core/packet/client/nativeClient';
import { OidbPacket } from '@/core/packet/transformer/base';
import { PacketLogger } from '@/core/packet/context/loggerContext';
import { NapCoreContext } from '@/core/packet/context/napCoreContext';
type clientPriorityType = {
[key: number]: (napCore: NapCoreContext, logger: PacketLogger, logStack: LogStack) => IPacketClient;
}
const clientPriority: clientPriorityType = {
10: (napCore: NapCoreContext, logger: PacketLogger, logStack: LogStack) => new NativePacketClient(napCore, logger, logStack)
};
export class LogStack {
private stack: string[] = [];
private readonly logger: PacketLogger;
@ -52,7 +43,7 @@ export class PacketClientContext {
private readonly napCore: NapCoreContext;
private readonly logger: PacketLogger;
private readonly logStack: LogStack;
private readonly _client: IPacketClient;
private readonly _client: NativePacketClient;
constructor(napCore: NapCoreContext, logger: PacketLogger) {
this.napCore = napCore;
@ -78,45 +69,12 @@ export class PacketClientContext {
return raw.data as T extends true ? Buffer : void;
}
private newClient(): IPacketClient {
const prefer = this.napCore.config.packetBackend;
let client: IPacketClient | null;
switch (prefer) {
case 'native':
this.logger.info('使用指定的 NativePacketClient 作为后端');
client = new NativePacketClient(this.napCore, this.logger, this.logStack);
break;
case 'auto':
case undefined:
client = this.judgeClient();
break;
default:
this.logger.error(`未知的PacketBackend ${prefer},请检查配置文件!`);
client = null;
}
if (!client?.check()) {
throw new Error('[Core] [Packet] 无可用的后端NapCat.Packet将不会加载');
}
if (!client) {
throw new Error('[Core] [Packet] 后端异常NapCat.Packet将不会加载');
private newClient(): NativePacketClient {
this.logger.info('使用 NativePacketClient 作为后端');
const client = new NativePacketClient(this.napCore, this.logger, this.logStack);
if (!client.check()) {
throw new Error('[Core] [Packet] NativePacketClient 不可用NapCat.Packet将不会加载');
}
return client;
}
private judgeClient(): IPacketClient {
const sortedClients = Object.entries(clientPriority)
.map(([priority, clientFactory]) => {
const client = clientFactory(this.napCore, this.logger, this.logStack);
const score = +priority * +client.check();
return { client, score };
})
.filter(({ score }) => score > 0)
.sort((a, b) => b.score - a.score);
const selectedClient = sortedClients[0]?.client;
if (!selectedClient) {
throw new Error('[Core] [Packet] 无可用的后端NapCat.Packet将不会加载');
}
this.logger.info(`自动选择 ${selectedClient.constructor.name} 作为后端`);
return selectedClient;
}
}