@cc-component/cc-core 1.4.2 → 1.4.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/assets/core/config/CommonEnum.ts +0 -1
- package/assets/core/lib/net/net/HttpManager.ts +6 -10
- package/assets/core/lib/net/net/HttpManager.ts.meta +1 -1
- package/assets/core/lib/net/net/NetInterface.ts +7 -0
- package/assets/core/lib/net/net/NetInterface.ts.meta +1 -1
- package/assets/core/lib/net/net/NetManager.ts.meta +1 -1
- package/assets/core/lib/net/net/NetNode.ts +102 -4
- package/assets/core/lib/net/net/NetNode.ts.meta +1 -1
- package/assets/core/lib/net/net/WebSock.ts.meta +1 -1
- package/assets/core/lib/net/net/protocol/Builder.ts +176 -0
- package/assets/core/lib/net/net/{custom/NetChannelManager.ts.meta → protocol/Builder.ts.meta} +1 -1
- package/assets/core/lib/net/net/protocol/MessageWrapper.ts +84 -0
- package/assets/core/lib/net/{libs/proto/output/protobuf_custom.d.ts.meta → net/protocol/MessageWrapper.ts.meta} +1 -1
- package/assets/core/lib/net/net/protocol/NetProtocolJson.ts.meta +1 -1
- package/assets/core/lib/net/net/protocol/NetProtocolProtobuf.ts +124 -12
- package/assets/core/lib/net/net/protocol/NetProtocolProtobuf.ts.meta +1 -1
- package/assets/core/lib/net/net/protocol.meta +1 -1
- package/index.ts +18 -0
- package/package.json +1 -1
- package/assets/core/lib/net/libs/proto/output/protobuf.d.ts +0 -2729
- package/assets/core/lib/net/libs/proto/output/protobuf.d.ts.meta +0 -9
- package/assets/core/lib/net/libs/proto/output/protobuf.min.js +0 -8
- package/assets/core/lib/net/libs/proto/output/protobuf.min.js.meta +0 -9
- package/assets/core/lib/net/libs/proto/output/protobuf_custom.d.ts +0 -102
- package/assets/core/lib/net/libs/proto/output/protobuf_custom.js +0 -222
- package/assets/core/lib/net/libs/proto/output/protobuf_custom.js.meta +0 -9
- package/assets/core/lib/net/libs/proto/output.meta +0 -9
- package/assets/core/lib/net/libs/proto/source/Cmd.proto +0 -6
- package/assets/core/lib/net/libs/proto/source/Cmd.proto.meta +0 -11
- package/assets/core/lib/net/libs/proto/source/UserLogin.proto +0 -12
- package/assets/core/lib/net/libs/proto/source/UserLogin.proto.meta +0 -11
- package/assets/core/lib/net/libs/proto/source/base.proto +0 -24
- package/assets/core/lib/net/libs/proto/source/base.proto.meta +0 -11
- package/assets/core/lib/net/libs/proto/source/command.proto +0 -31
- package/assets/core/lib/net/libs/proto/source/command.proto.meta +0 -11
- package/assets/core/lib/net/libs/proto/source/domain/boos_battle_info.proto +0 -13
- package/assets/core/lib/net/libs/proto/source/domain/boos_battle_info.proto.meta +0 -11
- package/assets/core/lib/net/libs/proto/source/domain/player_auth.proto +0 -26
- package/assets/core/lib/net/libs/proto/source/domain/player_auth.proto.meta +0 -11
- package/assets/core/lib/net/libs/proto/source/domain.meta +0 -9
- package/assets/core/lib/net/libs/proto/source/message/game_push.proto +0 -23
- package/assets/core/lib/net/libs/proto/source/message/game_push.proto.meta +0 -11
- package/assets/core/lib/net/libs/proto/source/message/game_request.proto +0 -24
- package/assets/core/lib/net/libs/proto/source/message/game_request.proto.meta +0 -11
- package/assets/core/lib/net/libs/proto/source/message/game_response.proto +0 -24
- package/assets/core/lib/net/libs/proto/source/message/game_response.proto.meta +0 -11
- package/assets/core/lib/net/libs/proto/source/message.meta +0 -9
- package/assets/core/lib/net/libs/proto/source/push/boss_battle_events.proto +0 -43
- package/assets/core/lib/net/libs/proto/source/push/boss_battle_events.proto.meta +0 -11
- package/assets/core/lib/net/libs/proto/source/push.meta +0 -9
- package/assets/core/lib/net/libs/proto/source.meta +0 -12
- package/assets/core/lib/net/libs/proto.meta +0 -9
- package/assets/core/lib/net/libs.meta +0 -9
- package/assets/core/lib/net/net/custom/NetChannelManager.ts +0 -41
- package/assets/core/lib/net/net/custom/NetConfig.ts +0 -11
- package/assets/core/lib/net/net/custom/NetConfig.ts.meta +0 -9
- package/assets/core/lib/net/net/custom/NetErrorCode.ts +0 -4
- package/assets/core/lib/net/net/custom/NetErrorCode.ts.meta +0 -9
- package/assets/core/lib/net/net/custom/NetGameTips.ts +0 -52
- package/assets/core/lib/net/net/custom/NetGameTips.ts.meta +0 -9
- package/assets/core/lib/net/net/custom/NetNodeGame.ts +0 -105
- package/assets/core/lib/net/net/custom/NetNodeGame.ts.meta +0 -9
- package/assets/core/lib/net/net/custom.meta +0 -9
|
@@ -5,8 +5,7 @@
|
|
|
5
5
|
* @LastEditTime: 2022-09-09 18:10:50
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
-
import { IExtData } from "
|
|
9
|
-
|
|
8
|
+
import { IExtData } from "db://assets/start/Interface/base/BaseCommon";
|
|
10
9
|
|
|
11
10
|
/** HTTP请求返回值 */
|
|
12
11
|
export class HttpReturn<T> {
|
|
@@ -64,8 +63,7 @@ export class HttpManager {
|
|
|
64
63
|
server: string = "http://127.0.0.1/";
|
|
65
64
|
/** 请求超时(毫秒) */
|
|
66
65
|
timeout: number = 10000;
|
|
67
|
-
|
|
68
|
-
open: (finish: (isOk: boolean) => void) => void
|
|
66
|
+
|
|
69
67
|
/**
|
|
70
68
|
* GET请求获取文本格式数据
|
|
71
69
|
* @param name 协议名
|
|
@@ -163,12 +161,10 @@ export class HttpManager {
|
|
|
163
161
|
let url: string = r[0];
|
|
164
162
|
let key: string = r[1];
|
|
165
163
|
let pss: string = r[2];
|
|
166
|
-
|
|
167
|
-
pss = JSON.stringify(params);
|
|
168
|
-
}
|
|
164
|
+
|
|
169
165
|
let hrd = urls.get(key);
|
|
170
166
|
if (hrd && hrd.pss == pss) {
|
|
171
|
-
|
|
167
|
+
console.warn(`地址【${key}】已正在请求中,不能重复请求`);
|
|
172
168
|
return;
|
|
173
169
|
}
|
|
174
170
|
|
|
@@ -176,7 +172,7 @@ export class HttpManager {
|
|
|
176
172
|
|
|
177
173
|
// 防重复请求功能
|
|
178
174
|
urls.set(key, { xhr, pss });
|
|
179
|
-
//
|
|
175
|
+
//console.warn(ext && ext.query ? key : url)
|
|
180
176
|
if (method == HttpMethod.POST)
|
|
181
177
|
xhr.open(HttpMethod.POST, ext && ext.query ? key : url);
|
|
182
178
|
else
|
|
@@ -198,7 +194,7 @@ export class HttpManager {
|
|
|
198
194
|
resolve(ret);
|
|
199
195
|
}
|
|
200
196
|
xhr.onloadend = (ev: ProgressEvent) => {
|
|
201
|
-
if (xhr.status == 500
|
|
197
|
+
if (xhr.status == 500) {
|
|
202
198
|
urls.delete(key);
|
|
203
199
|
|
|
204
200
|
ret.isSucc = false;
|
|
@@ -27,6 +27,8 @@ export interface IRequestProtocol {
|
|
|
27
27
|
buffer?: NetData,
|
|
28
28
|
/** 等待响应的回调对象 */
|
|
29
29
|
callback: CallbackObject,
|
|
30
|
+
/**包名 */
|
|
31
|
+
packageObj?: any
|
|
30
32
|
}
|
|
31
33
|
|
|
32
34
|
/** 响应协议 */
|
|
@@ -67,6 +69,11 @@ export class IProtocolHelper {
|
|
|
67
69
|
decodeCommon(msg: NetData): IResponseProtocol { return null! };
|
|
68
70
|
/** 解析自定义响应数据 */
|
|
69
71
|
decodeCustom(ireqp: IRequestProtocol, iresp: IResponseProtocol): void { };
|
|
72
|
+
|
|
73
|
+
encodeCustomPackage(packageObj: any, ireqp: IRequestProtocol): void { };
|
|
74
|
+
decodeCustomPackage(packageObj: any, ireqp: IRequestProtocol, iresp: IResponseProtocol): void { };
|
|
75
|
+
|
|
76
|
+
|
|
70
77
|
/** 返回一个心跳包 */
|
|
71
78
|
onHearbeat(): void { };
|
|
72
79
|
}
|
|
@@ -71,7 +71,7 @@ export class NetNode {
|
|
|
71
71
|
protected _keepAliveTimer: any = null; // 心跳定时器
|
|
72
72
|
protected _receiveMsgTimer: any = null; // 接收数据定时器
|
|
73
73
|
protected _reconnectTimer: any = null; // 重连定时器
|
|
74
|
-
protected _heartTime: number =
|
|
74
|
+
protected _heartTime: number = 20000; // 心跳间隔
|
|
75
75
|
protected _receiveTime: number = 30000; // 多久没收到数据断开
|
|
76
76
|
protected _reconnetTimeOut: number = 5000; // 重连间隔
|
|
77
77
|
protected _requests: IRequestProtocol[] = Array<IRequestProtocol>(); // 请求列表
|
|
@@ -184,7 +184,7 @@ export class NetNode {
|
|
|
184
184
|
protected initSocket() {
|
|
185
185
|
if (this._socket) {
|
|
186
186
|
this._socket.onConnected = (event) => { this.onConnected(event) };
|
|
187
|
-
this._socket.onMessage = (msg) => { this.
|
|
187
|
+
this._socket.onMessage = (msg) => { this.onMessageCust(msg) };
|
|
188
188
|
this._socket.onError = (event) => { this.onError(event) };
|
|
189
189
|
this._socket.onClosed = (event) => { this.onClosed(event) };
|
|
190
190
|
this._isSocketInit = true;
|
|
@@ -327,6 +327,11 @@ export class NetNode {
|
|
|
327
327
|
|
|
328
328
|
this.base_request(reqProtocol, showTips, force);
|
|
329
329
|
}
|
|
330
|
+
requestCust(packageoObj: any, reqProtocol: IRequestProtocol, showTips: boolean = true, force: boolean = false) {
|
|
331
|
+
this._protocolHelper.encodeCustomPackage(packageoObj, reqProtocol);
|
|
332
|
+
|
|
333
|
+
this.base_request(reqProtocol, showTips, force);
|
|
334
|
+
}
|
|
330
335
|
|
|
331
336
|
/**
|
|
332
337
|
* 唯一request,确保没有同一响应的请求(避免一个请求重复发送,netTips界面的屏蔽也是一个好的方法)
|
|
@@ -355,7 +360,7 @@ export class NetNode {
|
|
|
355
360
|
this._socket.send(reqProtocol.buffer!);
|
|
356
361
|
}
|
|
357
362
|
|
|
358
|
-
Logger.debug(`队列命令为【${reqProtocol.cmd}】的请求,等待请求数据的回调`);
|
|
363
|
+
// Logger.debug(`队列命令为【${reqProtocol.cmd}】的请求,等待请求数据的回调`);
|
|
359
364
|
|
|
360
365
|
// 进入发送缓存列表
|
|
361
366
|
this._requests.push(reqProtocol);
|
|
@@ -447,7 +452,7 @@ export class NetNode {
|
|
|
447
452
|
}
|
|
448
453
|
|
|
449
454
|
this._keepAliveTimer = setTimeout(() => {
|
|
450
|
-
Logger.
|
|
455
|
+
// Logger.logModel("网络节点发送心跳信息");
|
|
451
456
|
if (this._state == NetNodeState.Working) {
|
|
452
457
|
this._protocolHelper.onHearbeat();
|
|
453
458
|
}
|
|
@@ -467,4 +472,97 @@ export class NetNode {
|
|
|
467
472
|
}
|
|
468
473
|
}
|
|
469
474
|
//#endregion
|
|
475
|
+
|
|
476
|
+
|
|
477
|
+
/** 接收到一个完整的消息包 */
|
|
478
|
+
protected onMessageCust(msg: NetData): void {
|
|
479
|
+
// Logger.debug(`接受消息状态为【${NetNodeStateStrs[this._state]}】`);
|
|
480
|
+
|
|
481
|
+
var iresp: IResponseProtocol = this._protocolHelper.decodeCommon(msg);
|
|
482
|
+
const game_resp = message.GameResponse.decode(iresp.data);
|
|
483
|
+
iresp.data = game_resp
|
|
484
|
+
|
|
485
|
+
// 接受到数据,重新定时收数据计时器
|
|
486
|
+
this.resetReceiveMsgTimer();
|
|
487
|
+
// 重置心跳包发送器
|
|
488
|
+
this.resetHearbeatTimer();
|
|
489
|
+
// 触发消息执行
|
|
490
|
+
var id = iresp.id = game_resp.id;
|
|
491
|
+
var cmd = iresp.cmd = game_resp.cmd;
|
|
492
|
+
|
|
493
|
+
if (cmd === command.CommandType.CMD_HEARTBEAT) {
|
|
494
|
+
|
|
495
|
+
} else {
|
|
496
|
+
Logger.debug(`接受到命令【${cmd}】的消息`);
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
// 触发请求队列中的回调函数
|
|
500
|
+
if (this._requests.length > 0) {
|
|
501
|
+
for (let reqIdx in this._requests) {
|
|
502
|
+
let ireqp = this._requests[reqIdx];
|
|
503
|
+
const idd = ireqp.params.id;
|
|
504
|
+
if (idd == id) {
|
|
505
|
+
//Logger.debug(`触发请求命令【${cmd}】的回调`);
|
|
506
|
+
// this._protocolHelper.decodeCustomPackage(ireqp.packageObj, ireqp, iresp);
|
|
507
|
+
this._callbackExecuter(ireqp.callback, iresp);
|
|
508
|
+
this._requests.splice(parseInt(reqIdx), 1);
|
|
509
|
+
break;
|
|
510
|
+
}
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
// 触发请求结束
|
|
514
|
+
if (this._requests.length == 0) {
|
|
515
|
+
this.updateNetTips(NetTipsType.Requesting, false);
|
|
516
|
+
}
|
|
517
|
+
else {
|
|
518
|
+
Logger.debug(`请求队列中还有【${this._requests.length}】个请求在等待`);
|
|
519
|
+
}
|
|
520
|
+
}
|
|
521
|
+
|
|
522
|
+
// 服务器推送回调触发
|
|
523
|
+
let listeners = this._listener[cmd];
|
|
524
|
+
if (null != listeners) {
|
|
525
|
+
for (const ireqp of listeners) {
|
|
526
|
+
//Logger.debug(`触发监听命令【${cmd}】的回调`);
|
|
527
|
+
// this._protocolHelper.decodeCustomPackage(ireqp.packageObj, ireqp, iresp);
|
|
528
|
+
this._callbackExecuter(ireqp.callback, iresp.data);
|
|
529
|
+
}
|
|
530
|
+
}
|
|
531
|
+
}
|
|
532
|
+
|
|
533
|
+
|
|
534
|
+
/**
|
|
535
|
+
* 监听服务器推送
|
|
536
|
+
* @param cmd 协议命令号
|
|
537
|
+
* @param respName Protobuf返回协议名
|
|
538
|
+
* @param callback 回调方法
|
|
539
|
+
* @param target 目标对象
|
|
540
|
+
*/
|
|
541
|
+
addResponeHandlerCust(reqProtocol: IRequestProtocol): void {
|
|
542
|
+
var cmd = reqProtocol.cmd;
|
|
543
|
+
if (null == this._listener[cmd]) {
|
|
544
|
+
this._listener[cmd] = [reqProtocol];
|
|
545
|
+
}
|
|
546
|
+
else {
|
|
547
|
+
let index = this.getNetListenersIndex(cmd, reqProtocol.callback);
|
|
548
|
+
if (-1 == index) {
|
|
549
|
+
this._listener[cmd]!.push(reqProtocol);
|
|
550
|
+
}
|
|
551
|
+
}
|
|
552
|
+
}
|
|
553
|
+
|
|
554
|
+
/**
|
|
555
|
+
* 删除一个监听中指定子回调
|
|
556
|
+
* @param cmd 命令字串
|
|
557
|
+
* @param callback 回调方法
|
|
558
|
+
* @param target 目标对象
|
|
559
|
+
*/
|
|
560
|
+
removeResponeHandlerCust(cmd: number, callback: NetCallFunc, target?: any) {
|
|
561
|
+
if (null != this._listener[cmd] && callback != null) {
|
|
562
|
+
let index = this.getNetListenersIndex(cmd, { target, callback });
|
|
563
|
+
if (-1 != index) {
|
|
564
|
+
this._listener[cmd]!.splice(index, 1);
|
|
565
|
+
}
|
|
566
|
+
}
|
|
567
|
+
}
|
|
470
568
|
}
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @Builder 装饰器 - 自动为类添加Builder模式支持
|
|
3
|
+
* @param {Object} options - 配置选项
|
|
4
|
+
* @param {string} options.prefix - 方法前缀,默认'set'
|
|
5
|
+
* @param {string} options.suffix - 方法后缀,默认''
|
|
6
|
+
* @param {Object} options.customMethods - 自定义方法
|
|
7
|
+
* @param {Array} options.exclude - 排除的属性名
|
|
8
|
+
* @param {Array} options.include - 包含的属性名(手动指定,优先级高于自动收集)
|
|
9
|
+
* @param {boolean} options.immutable - 是否不可变,返回新实例
|
|
10
|
+
* @param {boolean} options.usePropertyNames - 是否使用属性名作为方法名(如 .name() 而不是 .setName())
|
|
11
|
+
*/
|
|
12
|
+
export function Builder(options = {}) {
|
|
13
|
+
return function (target) {
|
|
14
|
+
const {
|
|
15
|
+
prefix = 'set',
|
|
16
|
+
suffix = '',
|
|
17
|
+
customMethods = {},
|
|
18
|
+
exclude = [],
|
|
19
|
+
include = null,
|
|
20
|
+
immutable = false,
|
|
21
|
+
usePropertyNames = false
|
|
22
|
+
} = options;
|
|
23
|
+
|
|
24
|
+
// 收集类的属性
|
|
25
|
+
const collectProperties = (cls) => {
|
|
26
|
+
// 如果手动指定了 include,直接使用
|
|
27
|
+
if (include && include.length > 0) {
|
|
28
|
+
return include;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const props = new Set();
|
|
32
|
+
let current = cls;
|
|
33
|
+
|
|
34
|
+
// 遍历原型链
|
|
35
|
+
while (current && current !== Function.prototype) {
|
|
36
|
+
// 方法1: 获取实例自身的属性(已赋值的)
|
|
37
|
+
try {
|
|
38
|
+
const instance = new cls();
|
|
39
|
+
Object.getOwnPropertyNames(instance).forEach(prop => {
|
|
40
|
+
if (prop !== 'constructor' && !exclude.includes(prop)) {
|
|
41
|
+
props.add(prop);
|
|
42
|
+
}
|
|
43
|
+
});
|
|
44
|
+
} catch (e) {
|
|
45
|
+
// 如果构造函数需要参数,忽略错误
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// 方法2: 获取原型上的属性描述符
|
|
49
|
+
const descriptors = Object.getOwnPropertyDescriptors(current.prototype || {});
|
|
50
|
+
Object.entries(descriptors).forEach(([prop, desc]) => {
|
|
51
|
+
// 收集所有非方法属性(包括 getter 和普通属性)
|
|
52
|
+
if (prop !== 'constructor' && !exclude.includes(prop)) {
|
|
53
|
+
// 排除函数类型的方法
|
|
54
|
+
if (typeof desc.value !== 'function' || desc.get) {
|
|
55
|
+
props.add(prop);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
current = Object.getPrototypeOf(current);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
return Array.from(props);
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
const properties = collectProperties(target);
|
|
67
|
+
|
|
68
|
+
// 创建Builder类
|
|
69
|
+
class DynamicBuilder {
|
|
70
|
+
constructor() {
|
|
71
|
+
this._data = {};
|
|
72
|
+
this._targetClass = target;
|
|
73
|
+
this._isImmutable = immutable;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
build() {
|
|
77
|
+
const instance = new this._targetClass();
|
|
78
|
+
|
|
79
|
+
// 将 _data 中的属性赋值到实例上
|
|
80
|
+
Object.assign(instance, this._data);
|
|
81
|
+
|
|
82
|
+
// 如果是不可变模式,冻结对象
|
|
83
|
+
if (this._isImmutable) {
|
|
84
|
+
Object.freeze(instance);
|
|
85
|
+
if (instance.battleInfoList) {
|
|
86
|
+
Object.freeze(instance.battleInfoList);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
return instance;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// 重置数据
|
|
94
|
+
reset() {
|
|
95
|
+
this._data = {};
|
|
96
|
+
return this;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// 批量设置
|
|
100
|
+
setAll(data) {
|
|
101
|
+
this._data = {...this._data, ...data};
|
|
102
|
+
return this;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// 为所有属性创建setter方法
|
|
107
|
+
properties.forEach(prop => {
|
|
108
|
+
// 根据 usePropertyNames 决定使用属性名还是带前缀的方法名
|
|
109
|
+
const methodName = usePropertyNames ? prop : `${prefix}${prop.charAt(0).toUpperCase() + prop.slice(1)}${suffix}`;
|
|
110
|
+
|
|
111
|
+
DynamicBuilder.prototype[methodName] = function (value) {
|
|
112
|
+
this._data[prop] = value;
|
|
113
|
+
return this;
|
|
114
|
+
};
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
// 添加特殊方法
|
|
118
|
+
DynamicBuilder.prototype.addAllBattleInfoList = function (list) {
|
|
119
|
+
this._data.battleInfoList = Array.isArray(list) ? [...list] : list;
|
|
120
|
+
return this;
|
|
121
|
+
};
|
|
122
|
+
|
|
123
|
+
DynamicBuilder.prototype.addBattleInfo = function (item) {
|
|
124
|
+
if (!this._data.battleInfoList) {
|
|
125
|
+
this._data.battleInfoList = [];
|
|
126
|
+
}
|
|
127
|
+
this._data.battleInfoList.push(item);
|
|
128
|
+
return this;
|
|
129
|
+
};
|
|
130
|
+
|
|
131
|
+
// 添加自定义方法
|
|
132
|
+
Object.keys(customMethods).forEach(methodName => {
|
|
133
|
+
DynamicBuilder.prototype[methodName] = customMethods[methodName];
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
// 为原始类添加builder方法
|
|
137
|
+
target.builder = function () {
|
|
138
|
+
return new DynamicBuilder();
|
|
139
|
+
};
|
|
140
|
+
|
|
141
|
+
// 添加快速创建方法
|
|
142
|
+
target.create = function (data) {
|
|
143
|
+
return target.builder().setAll(data).build();
|
|
144
|
+
};
|
|
145
|
+
|
|
146
|
+
return target;
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* @Buildable 装饰器 - 简化版Builder(默认使用 set 前缀)
|
|
152
|
+
*/
|
|
153
|
+
export function Buildable(target) {
|
|
154
|
+
return Builder()(target);
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
/**
|
|
158
|
+
* @ToBuilder 装饰器 - 流式API版Builder(使用属性名,不带 set 前缀)
|
|
159
|
+
*/
|
|
160
|
+
export function ToBuilder(target) {
|
|
161
|
+
return Builder({...{}, usePropertyNames: true})(target);
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* @FluentBuilder 装饰器 - 流式API版Builder(使用属性名,不带 set 前缀)
|
|
166
|
+
*/
|
|
167
|
+
export function FluentBuilder(options = {}) {
|
|
168
|
+
return Builder({...options, usePropertyNames: true});
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
/**
|
|
172
|
+
* @ImmutableBuilder 装饰器 - 创建不可变对象
|
|
173
|
+
*/
|
|
174
|
+
export function ImmutableBuilder(target) {
|
|
175
|
+
return Builder({immutable: true})(target);
|
|
176
|
+
}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Protobuf Message 包装器
|
|
3
|
+
*
|
|
4
|
+
* 为 message.GameRequest 等提供类似 Builder 的链式调用
|
|
5
|
+
* 完全不修改 protobuf 生成的代码
|
|
6
|
+
*
|
|
7
|
+
* 使用示例:
|
|
8
|
+
* // 在 NetProtocolProtobuf.ts 中使用
|
|
9
|
+
* data(cmd: number, subCmd: number) {
|
|
10
|
+
* return GameRequestWrapper.builder()
|
|
11
|
+
* .cmd(cmd)
|
|
12
|
+
* .subCmd(subCmd)
|
|
13
|
+
* .id(this.getRequestId())
|
|
14
|
+
* .timestamp(Date.now())
|
|
15
|
+
* .build();
|
|
16
|
+
* }
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* 通用 Builder 类 - 使用 Proxy 自动处理所有字段
|
|
21
|
+
* 协议字段改动时无需手动更新
|
|
22
|
+
*/
|
|
23
|
+
class AutoBuilder<T extends object> {
|
|
24
|
+
private message: T;
|
|
25
|
+
|
|
26
|
+
constructor(message: T) {
|
|
27
|
+
this.message = message;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* 使用 Proxy 拦截所有属性访问,自动生成对应的 setter 方法
|
|
32
|
+
* 例如: builder.cmd(100) -> 实际调用 builder.set('cmd', 100)
|
|
33
|
+
*/
|
|
34
|
+
static create<T extends object>(message: T): any {
|
|
35
|
+
const builder = new AutoBuilder(message);
|
|
36
|
+
|
|
37
|
+
const proxyObj = new Proxy(builder, {
|
|
38
|
+
get(_target, prop) {
|
|
39
|
+
// 如果是 build 方法,直接返回原始 message 对象
|
|
40
|
+
if (prop === 'build') {
|
|
41
|
+
return () => builder.message;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// 如果是 set 方法,允许手动设置
|
|
45
|
+
if (prop === 'set') {
|
|
46
|
+
return <K extends keyof T>(key: K, value: T[K]) => {
|
|
47
|
+
builder.message[key] = value;
|
|
48
|
+
return proxyObj;
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// 其他所有属性都作为 setter 方法处理
|
|
53
|
+
return (value: any) => {
|
|
54
|
+
// @ts-ignore - 动态设置属性
|
|
55
|
+
builder.message[prop] = value;
|
|
56
|
+
return proxyObj;
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
return proxyObj;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* 通用的 Message 包装器工厂
|
|
67
|
+
* 适用于任何 Protobuf Message 类型
|
|
68
|
+
*/
|
|
69
|
+
export function createMessageWrapper<T extends object>(
|
|
70
|
+
messageConstructor: new (...args: any[]) => T
|
|
71
|
+
) {
|
|
72
|
+
return {
|
|
73
|
+
/**
|
|
74
|
+
* 创建 Builder
|
|
75
|
+
* 支持链式调用,协议字段改动时无需更新
|
|
76
|
+
*/
|
|
77
|
+
builder: () => AutoBuilder.create(new messageConstructor()),
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* 快速创建(带初始值)
|
|
81
|
+
*/
|
|
82
|
+
create: (data?: Partial<T>) => new messageConstructor(data)
|
|
83
|
+
};
|
|
84
|
+
}
|