melo-example-robot 1.7.6

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.
@@ -0,0 +1,911 @@
1
+
2
+ import * as egret from './ByteArray';
3
+ import * as WebSocket from 'ws';
4
+
5
+ /**
6
+ * Created by govo on 15/8/14.
7
+ *
8
+ * Melo Client for Egret, with protobuf support, with js ws client version 0.0.5
9
+ * Github: https://github.com/govo/MeloForEgret.git
10
+ *
11
+ * Thanks to:
12
+ * D-Deo @ https://github.com/D-Deo/melo-flash-tcp.git
13
+ * and yicaoyimu @ http://bbs.egret.com/forum.php?mod=viewthread&tid=2538&highlight=melo
14
+ */
15
+
16
+
17
+
18
+
19
+ export class WSClient {
20
+
21
+ static DEBUG: boolean = false;
22
+ static EVENT_IO_ERROR: string = 'io-error';
23
+ static EVENT_CLOSE: string = 'close';
24
+ static EVENT_KICK: string = 'onKick';
25
+ static EVENT_HEART_BEAT_TIMEOUT: string = 'heartbeat timeout';
26
+
27
+ private JS_WS_CLIENT_TYPE: string = 'js-websocket';
28
+ private JS_WS_CLIENT_VERSION: string = '0.0.5';
29
+
30
+ private RES_OK: number = 200;
31
+ private RES_FAIL: number = 500;
32
+ private RES_OLD_CLIENT: number = 501;
33
+
34
+
35
+ private socket: WebSocket = null;
36
+ private callbacks: any = {};
37
+ private handlers: any = {};
38
+ // Map from request id to route
39
+ private routeMap = {};
40
+
41
+ private heartbeatInterval: number = 0;
42
+ private heartbeatTimeout: number = 0;
43
+ private nextHeartbeatTimeout: number = 0;
44
+ private gapThreshold: number = 100;
45
+ private heartbeatId: any = null;
46
+ private heartbeatTimeoutId: any = null;
47
+
48
+ private handshakeCallback: any = null;
49
+ private handshakeBuffer: any;
50
+ private initCallback: Function = null;
51
+
52
+ private _callbacks: any = {};
53
+
54
+ private reqId: number = 0;
55
+
56
+
57
+ private _package: IPackage;
58
+ private _message: IMessage;
59
+
60
+ constructor() {
61
+
62
+ this.socket = null;
63
+ this.callbacks = {};
64
+ this.handlers = {};
65
+ // Map from request id to route
66
+ this.routeMap = {};
67
+ this._message = new Message(this.routeMap);
68
+ this._package = new Package();
69
+
70
+
71
+ this.heartbeatInterval = 0;
72
+ this.heartbeatTimeout = 0;
73
+ this.nextHeartbeatTimeout = 0;
74
+ this.gapThreshold = 100;
75
+ this.heartbeatId = null;
76
+ this.heartbeatTimeoutId = null;
77
+
78
+ this.handshakeCallback = null;
79
+
80
+ this.handshakeBuffer = {
81
+ 'sys': {
82
+ type: this.JS_WS_CLIENT_TYPE,
83
+ version: this.JS_WS_CLIENT_VERSION
84
+ },
85
+ 'user': {
86
+ }
87
+ };
88
+
89
+ this.initCallback = null;
90
+
91
+ this.reqId = 0;
92
+
93
+ this.handlers[Package.TYPE_HANDSHAKE] = this.handshake;
94
+ this.handlers[Package.TYPE_HEARTBEAT] = this.heartbeat;
95
+ this.handlers[Package.TYPE_DATA] = this.onData;
96
+ this.handlers[Package.TYPE_KICK] = this.onKick;
97
+ }
98
+
99
+
100
+ public init(params, cb: Function): void {
101
+ console.log('init', params);
102
+ this.initCallback = cb;
103
+ let host = params.host;
104
+ let port = params.port;
105
+ //
106
+ // var url = 'ws://' + host;
107
+ // if(port) {
108
+ // url += ':' + port;
109
+ // }
110
+
111
+ this.handshakeBuffer.user = params.user;
112
+ this.handshakeCallback = params.handshakeCallback;
113
+ this.initWebSocket(host, port, cb);
114
+ }
115
+ private initWebSocket(host, port, cb: Function): void {
116
+ console.log('[Melo] connect to:', host, port);
117
+
118
+ let onopen = (event) => {
119
+ this.onConnect();
120
+ };
121
+ let onmessage = (event) => {
122
+ this.onMessage(event);
123
+ };
124
+ let onerror = (event) => {
125
+ this.onIOError(event);
126
+ };
127
+ let onclose = (event) => {
128
+ this.onClose(event);
129
+ };
130
+ let url = 'ws://' + host;
131
+ if (port) {
132
+ url += ':' + port;
133
+ }
134
+ let socket = new WebSocket(url);
135
+ socket.binaryType = 'arraybuffer';
136
+ socket.onopen = onopen;
137
+ socket.onmessage = onmessage;
138
+ socket.onerror = onerror;
139
+ socket.onclose = onclose;
140
+ this.socket = socket;
141
+ }
142
+
143
+
144
+ public on(event, fn) {
145
+ (this._callbacks[event] = this._callbacks[event] || []).push(fn);
146
+ }
147
+ public request(route, msg, cb) {
148
+ if (arguments.length === 2 && typeof msg === 'function') {
149
+ cb = msg;
150
+ msg = {};
151
+ } else {
152
+ msg = msg || {};
153
+ }
154
+ route = route || msg.route;
155
+ if (!route) {
156
+ return;
157
+ }
158
+
159
+ this.reqId++;
160
+ if (this.reqId > 127) {
161
+ this.reqId = 1;
162
+ }
163
+ let reqId = this.reqId;
164
+
165
+
166
+ if (WSClient.DEBUG) {
167
+ console.log(`REQUEST:route:${route} , reqId:${reqId}, msg:${msg}`);
168
+ }
169
+
170
+ this.sendMessage(reqId, route, msg);
171
+
172
+ this.callbacks[reqId] = cb;
173
+ this.routeMap[reqId] = route;
174
+ }
175
+
176
+ public notify(route: string, msg: any): void {
177
+ this.sendMessage(0, route, msg);
178
+ }
179
+
180
+ private onMessage(event: { data: string | Buffer | ArrayBuffer | Buffer[]; type: string; target: WebSocket }): void {
181
+ this.processPackage(this._package.decode(new egret.ByteArray(<ArrayBuffer>event.data)));
182
+
183
+ }
184
+ private sendMessage(reqId, route, msg) {
185
+ let byte: egret.ByteArray;
186
+
187
+ byte = this._message.encode(reqId, route, msg);
188
+ byte = this._package.encode(Package.TYPE_DATA, byte);
189
+
190
+ this.send(byte);
191
+
192
+ }
193
+
194
+ private onConnect(): void {
195
+ console.log('[Melo] connect success');
196
+ this.send(this._package.encode(Package.TYPE_HANDSHAKE, Protocol.strencode(JSON.stringify(this.handshakeBuffer))));
197
+ }
198
+
199
+ private onClose(e: any): void {
200
+ console.error('[Melo] connect close:', e);
201
+ // this.emit(Melo.EVENT_CLOSE,e);
202
+ }
203
+
204
+ private onIOError(e: any): void {
205
+ // this.emit(Melo.EVENT_IO_ERROR, e);
206
+ console.error('socket error: ', e);
207
+ }
208
+
209
+ private onKick(event) {
210
+ event = JSON.parse(Protocol.strdecode(event));
211
+ this.emit(WSClient.EVENT_KICK, event);
212
+ }
213
+ private onData(data) {
214
+ // probuff decode
215
+ let msg = this._message.decode(data);
216
+
217
+ if (msg.id > 0) {
218
+ msg.route = this.routeMap[msg.id];
219
+ delete this.routeMap[msg.id];
220
+ if (!msg.route) {
221
+ return;
222
+ }
223
+ }
224
+
225
+ // msg.body = this.deCompose(msg);
226
+
227
+ this.processMessage(msg);
228
+
229
+ }
230
+
231
+ private processMessage(msg) {
232
+ if (!msg.id) {
233
+ // server push message
234
+
235
+ if (WSClient.DEBUG) {
236
+ console.log(`EVENT: Route:${msg.route} Msg:${msg.body}`);
237
+ }
238
+
239
+ this.emit(msg.route, msg.body);
240
+ return;
241
+ }
242
+ if (WSClient.DEBUG) {
243
+ console.log(`RESPONSE: Id:${msg.id} Msg:${msg.body}`);
244
+ }
245
+
246
+ // if have a id then find the callback function with the request
247
+ let cb = this.callbacks[msg.id];
248
+
249
+ delete this.callbacks[msg.id];
250
+ if (typeof cb !== 'function') {
251
+ return;
252
+ }
253
+ if (msg.body && msg.body.code === 500) {
254
+ let obj: any = { 'code': 500, 'desc': '服务器内部错误', 'key': 'INTERNAL_ERROR' };
255
+ msg.body.error = obj;
256
+ }
257
+ cb(msg.body);
258
+ return;
259
+ }
260
+
261
+ private heartbeat(data) {
262
+
263
+ if (!this.heartbeatInterval) {
264
+ // no heartbeat
265
+ return;
266
+ }
267
+
268
+ let obj = this._package.encode(Package.TYPE_HEARTBEAT);
269
+ if (this.heartbeatTimeoutId) {
270
+ clearTimeout(this.heartbeatTimeoutId);
271
+ this.heartbeatTimeoutId = null;
272
+ }
273
+
274
+ if (this.heartbeatId) {
275
+ // already in a heartbeat interval
276
+ return;
277
+ }
278
+
279
+ let self = this;
280
+ self.heartbeatId = setTimeout(function () {
281
+ self.heartbeatId = null;
282
+ self.send(obj);
283
+
284
+ self.nextHeartbeatTimeout = Date.now() + self.heartbeatTimeout;
285
+ self.heartbeatTimeoutId = setTimeout(self.heartbeatTimeoutCb.bind(self, data), self.heartbeatTimeout);
286
+ }, self.heartbeatInterval);
287
+ }
288
+ private heartbeatTimeoutCb(data) {
289
+ let gap = this.nextHeartbeatTimeout - Date.now();
290
+ if (gap > this.gapThreshold) {
291
+ this.heartbeatTimeoutId = setTimeout(this.heartbeatTimeoutCb.bind(this, data), gap);
292
+ } else {
293
+ console.error('server heartbeat timeout', data);
294
+ // this.emit(WSClient.EVENT_HEART_BEAT_TIMEOUT,data);
295
+ this._disconnect();
296
+ }
297
+ }
298
+ public off(event?, fn?) {
299
+ this.removeAllListeners(event, fn);
300
+ }
301
+ public removeAllListeners(event?, fn?) {
302
+ // all
303
+ if (0 === arguments.length) {
304
+ this._callbacks = {};
305
+ return;
306
+ }
307
+
308
+ // specific event
309
+ let callbacks = this._callbacks[event];
310
+ if (!callbacks) {
311
+ return;
312
+ }
313
+
314
+ // remove all handlers
315
+ if (event && !fn) {
316
+ delete this._callbacks[event];
317
+ return;
318
+ }
319
+
320
+ // remove specific handler
321
+ let i = this.index(callbacks, fn._off || fn);
322
+ if (~i) {
323
+ callbacks.splice(i, 1);
324
+ }
325
+ return;
326
+ }
327
+ private index(arr, obj) {
328
+ if ([].indexOf) {
329
+ return arr.indexOf(obj);
330
+ }
331
+
332
+ for (let i = 0; i < arr.length; ++i) {
333
+ if (arr[i] === obj)
334
+ return i;
335
+ }
336
+ return -1;
337
+ }
338
+ public disconnect(): void {
339
+ this._disconnect();
340
+ }
341
+ private _disconnect(): void {
342
+ console.warn('[Melo] client disconnect ...');
343
+
344
+ if (this.socket) this.socket.close();
345
+ this.socket = null;
346
+ if (this.heartbeatId) {
347
+ clearTimeout(this.heartbeatId);
348
+ this.heartbeatId = null;
349
+ }
350
+
351
+ if (this.heartbeatTimeoutId) {
352
+ clearTimeout(this.heartbeatTimeoutId);
353
+ this.heartbeatTimeoutId = null;
354
+ }
355
+
356
+ }
357
+ private processPackage(msg): void {
358
+ this.handlers[msg.type].apply(this, [msg.body]);
359
+ }
360
+ private handshake(resData) {
361
+
362
+ let data = JSON.parse(Protocol.strdecode(resData));
363
+ if (data.code === this.RES_OLD_CLIENT) {
364
+ // this.emit(WSClient.EVENT_IO_ERROR, 'client version not fullfill');
365
+ return;
366
+ }
367
+
368
+ if (data.code !== this.RES_OK) {
369
+ // this.emit(WSClient.EVENT_IO_ERROR, 'handshake fail');
370
+ return;
371
+ }
372
+
373
+ this.handshakeInit(data);
374
+
375
+ let obj = this._package.encode(Package.TYPE_HANDSHAKE_ACK);
376
+ this.send(obj);
377
+ if (this.initCallback) {
378
+ this.initCallback(data);
379
+ this.initCallback = null;
380
+ }
381
+ }
382
+ private handshakeInit(data): void {
383
+
384
+ if (data.sys) {
385
+ Routedic.init(data.sys.dict);
386
+ Protobuf.init(data.sys.protos);
387
+ }
388
+ if (data.sys && data.sys.heartbeat) {
389
+ this.heartbeatInterval = data.sys.heartbeat * 1000; // heartbeat interval
390
+ this.heartbeatTimeout = this.heartbeatInterval * 2; // max heartbeat timeout
391
+ } else {
392
+ this.heartbeatInterval = 0;
393
+ this.heartbeatTimeout = 0;
394
+ }
395
+
396
+ if (typeof this.handshakeCallback === 'function') {
397
+ this.handshakeCallback(data.user);
398
+ }
399
+ }
400
+ private send(byte: egret.ByteArray): void {
401
+ if (this.socket) {
402
+ this.socket.send(byte.buffer);
403
+ }
404
+ }
405
+ // private deCompose(msg){
406
+ // return JSON.parse(Protocol.strdecode(msg.body));
407
+ // }
408
+ private emit(event, ...args: any[]) {
409
+ let params = [].slice.call(arguments, 1);
410
+ let callbacks = this._callbacks[event];
411
+
412
+ if (callbacks) {
413
+ callbacks = callbacks.slice(0);
414
+ for (let i = 0, len = callbacks.length; i < len; ++i) {
415
+ callbacks[i].apply(this, params);
416
+ }
417
+ }
418
+
419
+ return this;
420
+ }
421
+
422
+
423
+ }
424
+
425
+ class Package implements IPackage {
426
+ static TYPE_HANDSHAKE: number = 1;
427
+ static TYPE_HANDSHAKE_ACK: number = 2;
428
+ static TYPE_HEARTBEAT: number = 3;
429
+ static TYPE_DATA: number = 4;
430
+ static TYPE_KICK: number = 5;
431
+
432
+ public encode(type: number, body?: egret.ByteArray) {
433
+ let length: number = body ? body.length : 0;
434
+
435
+ let buffer: egret.ByteArray = new egret.ByteArray();
436
+ buffer.writeByte(type & 0xff);
437
+ buffer.writeByte((length >> 16) & 0xff);
438
+ buffer.writeByte((length >> 8) & 0xff);
439
+ buffer.writeByte(length & 0xff);
440
+
441
+ if (body) buffer.writeBytes(body, 0, body.length);
442
+
443
+ return buffer;
444
+ }
445
+ public decode(buffer: egret.ByteArray) {
446
+
447
+ let type: number = buffer.readUnsignedByte();
448
+ let len: number = (buffer.readUnsignedByte() << 16 | buffer.readUnsignedByte() << 8 | buffer.readUnsignedByte()) >>> 0;
449
+
450
+ let body: egret.ByteArray;
451
+
452
+ if (buffer.bytesAvailable >= len) {
453
+ body = new egret.ByteArray();
454
+ if (len) buffer.readBytes(body, 0, len);
455
+ }
456
+ else {
457
+ console.log('[Package] no enough length for current type:', type);
458
+ }
459
+
460
+ return { type: type, body: body, length: len };
461
+ }
462
+ }
463
+
464
+ class Message implements IMessage {
465
+
466
+ public static MSG_FLAG_BYTES: number = 1;
467
+ public static MSG_ROUTE_CODE_BYTES: number = 2;
468
+ public static MSG_ID_MAX_BYTES: number = 5;
469
+ public static MSG_ROUTE_LEN_BYTES: number = 1;
470
+
471
+ public static MSG_ROUTE_CODE_MAX: number = 0xffff;
472
+
473
+ public static MSG_COMPRESS_ROUTE_MASK: number = 0x1;
474
+ public static MSG_TYPE_MASK: number = 0x7;
475
+
476
+ static TYPE_REQUEST: number = 0;
477
+ static TYPE_NOTIFY: number = 1;
478
+ static TYPE_RESPONSE: number = 2;
479
+ static TYPE_PUSH: number = 3;
480
+
481
+ constructor(private routeMap: {}) {
482
+
483
+ }
484
+
485
+ public encode(id: number, route: string, msg: any) {
486
+ let buffer: egret.ByteArray = new egret.ByteArray();
487
+
488
+ let type: number = id ? Message.TYPE_REQUEST : Message.TYPE_NOTIFY;
489
+
490
+ let byte: egret.ByteArray = Protobuf.encode(route, msg) || Protocol.strencode(JSON.stringify(msg));
491
+
492
+ let rot: any = Routedic.getID(route) || route;
493
+
494
+ buffer.writeByte((type << 1) | ((typeof (rot) === 'string') ? 0 : 1));
495
+
496
+ if (id) {
497
+ // 7.x
498
+ do {
499
+ let tmp: number = id % 128;
500
+ let next: number = Math.floor(id / 128);
501
+
502
+ if (next !== 0) {
503
+ tmp = tmp + 128;
504
+ }
505
+
506
+ buffer.writeByte(tmp);
507
+
508
+ id = next;
509
+ } while (id !== 0);
510
+
511
+ // 5.x
512
+ // var len:Array = [];
513
+ // len.push(id & 0x7f);
514
+ // id >>= 7;
515
+ // while(id > 0)
516
+ // {
517
+ // len.push(id & 0x7f | 0x80);
518
+ // id >>= 7;
519
+ // }
520
+ //
521
+ // for (var i:int = len.length - 1; i >= 0; i--)
522
+ // {
523
+ // buffer.writeByte(len[i]);
524
+ // }
525
+ }
526
+
527
+ if (rot) {
528
+ if (typeof rot === 'string') {
529
+ buffer.writeByte(rot.length & 0xff);
530
+ buffer.writeUTFBytes(rot);
531
+ }
532
+ else {
533
+ buffer.writeByte((rot >> 8) & 0xff);
534
+ buffer.writeByte(rot & 0xff);
535
+ }
536
+ }
537
+
538
+ if (byte) {
539
+ buffer.writeBytes(byte);
540
+ }
541
+
542
+ return buffer;
543
+ }
544
+
545
+ public decode(buffer: egret.ByteArray): any {
546
+ // parse flag
547
+ let flag: number = buffer.readUnsignedByte();
548
+ let compressRoute: number = flag & Message.MSG_COMPRESS_ROUTE_MASK;
549
+ let type: number = (flag >> 1) & Message.MSG_TYPE_MASK;
550
+ let route: any;
551
+
552
+ // parse id
553
+ let id: number = 0;
554
+ if (type === Message.TYPE_REQUEST || type === Message.TYPE_RESPONSE) {
555
+ // 7.x
556
+ let i: number = 0;
557
+ let m: number;
558
+ do {
559
+ m = buffer.readUnsignedByte();
560
+ id = id + ((m & 0x7f) * Math.pow(2, (7 * i)));
561
+ i++;
562
+ } while (m >= 128);
563
+
564
+ // 5.x
565
+ // var byte:int = buffer.readUnsignedByte();
566
+ // id = byte & 0x7f;
567
+ // while(byte & 0x80)
568
+ // {
569
+ // id <<= 7;
570
+ // byte = buffer.readUnsignedByte();
571
+ // id |= byte & 0x7f;
572
+ // }
573
+ }
574
+
575
+ // parse route
576
+ if (type === Message.TYPE_REQUEST || type === Message.TYPE_NOTIFY || type === Message.TYPE_PUSH) {
577
+
578
+ if (compressRoute) {
579
+ route = buffer.readUnsignedShort();
580
+ }
581
+ else {
582
+ let routeLen: number = buffer.readUnsignedByte();
583
+ route = routeLen ? buffer.readUTFBytes(routeLen) : '';
584
+ }
585
+ }
586
+ else if (type === Message.TYPE_RESPONSE) {
587
+ route = this.routeMap[id];
588
+ }
589
+
590
+ if (!id && !(typeof (route) === 'string')) {
591
+ route = Routedic.getName(route);
592
+ }
593
+
594
+ let body: any = Protobuf.decode(route, buffer) || JSON.parse(Protocol.strdecode(buffer));
595
+
596
+ return { id: id, type: type, route: route, body: body };
597
+ }
598
+
599
+ }
600
+ class Protocol {
601
+
602
+ public static strencode(str: string): egret.ByteArray {
603
+ let buffer: egret.ByteArray = new egret.ByteArray();
604
+ buffer.length = str.length;
605
+ buffer.writeUTFBytes(str);
606
+ return buffer;
607
+ }
608
+
609
+ public static strdecode(byte: egret.ByteArray): string {
610
+ return byte.readUTFBytes(byte.bytesAvailable);
611
+ }
612
+ }
613
+ class Protobuf {
614
+ static TYPES: any = {
615
+ uInt32: 0,
616
+ sInt32: 0,
617
+ int32: 0,
618
+ double: 1,
619
+ string: 2,
620
+ message: 2,
621
+ float: 5
622
+ };
623
+ private static _clients: any = {};
624
+ private static _servers: any = {};
625
+
626
+ static init(protos: any): void {
627
+ this._clients = protos && protos.client || {};
628
+ this._servers = protos && protos.server || {};
629
+ }
630
+
631
+ static encode(route: string, msg: any): egret.ByteArray {
632
+
633
+ let protos: any = this._clients[route];
634
+
635
+ if (!protos) return null;
636
+
637
+ return this.encodeProtos(protos, msg);
638
+ }
639
+
640
+ static decode(route: string, buffer: egret.ByteArray): any {
641
+
642
+ let protos: any = this._servers[route];
643
+
644
+ if (!protos) return null;
645
+
646
+ return this.decodeProtos(protos, buffer);
647
+ }
648
+ private static encodeProtos(protos: any, msg: any): egret.ByteArray {
649
+ let buffer: egret.ByteArray = new egret.ByteArray();
650
+
651
+ for (let name in msg) {
652
+ if (protos[name]) {
653
+ let proto: any = protos[name];
654
+
655
+ switch (proto.option) {
656
+ case 'optional':
657
+ case 'required':
658
+ buffer.writeBytes(this.encodeTag(proto.type, proto.tag));
659
+ this.encodeProp(msg[name], proto.type, protos, buffer);
660
+ break;
661
+ case 'repeated':
662
+ if (!!msg[name] && msg[name].length > 0) {
663
+ this.encodeArray(msg[name], proto, protos, buffer);
664
+ }
665
+ break;
666
+ }
667
+ }
668
+ }
669
+
670
+ return buffer;
671
+ }
672
+ static decodeProtos(protos: any, buffer: egret.ByteArray): any {
673
+ let msg: any = {};
674
+
675
+ while (buffer.bytesAvailable) {
676
+ let head: any = this.getHead(buffer);
677
+ let name: string = protos.__tags[head.tag];
678
+
679
+ switch (protos[name].option) {
680
+ case 'optional':
681
+ case 'required':
682
+ msg[name] = this.decodeProp(protos[name].type, protos, buffer);
683
+ break;
684
+ case 'repeated':
685
+ if (!msg[name]) {
686
+ msg[name] = [];
687
+ }
688
+ this.decodeArray(msg[name], protos[name].type, protos, buffer);
689
+ break;
690
+ }
691
+ }
692
+
693
+ return msg;
694
+ }
695
+
696
+ static encodeTag(type: number, tag: number): egret.ByteArray {
697
+ let value: number = this.TYPES[type] !== undefined ? this.TYPES[type] : 2;
698
+
699
+ return this.encodeUInt32((tag << 3) | value);
700
+ }
701
+ static getHead(buffer: egret.ByteArray): any {
702
+ let tag: number = this.decodeUInt32(buffer);
703
+
704
+ return { type: tag & 0x7, tag: tag >> 3 };
705
+ }
706
+ static encodeProp(value: any, type: string, protos: any, buffer: egret.ByteArray): void {
707
+ switch (type) {
708
+ case 'uInt32':
709
+ buffer.writeBytes(this.encodeUInt32(value));
710
+ break;
711
+ case 'int32':
712
+ case 'sInt32':
713
+ buffer.writeBytes(this.encodeSInt32(value));
714
+ break;
715
+ case 'float':
716
+ // Float32Array
717
+ let floats: egret.ByteArray = new egret.ByteArray();
718
+ floats.endian = egret.Endian.LITTLE_ENDIAN;
719
+ floats.writeFloat(value);
720
+ buffer.writeBytes(floats);
721
+ break;
722
+ case 'double':
723
+ let doubles: egret.ByteArray = new egret.ByteArray();
724
+ doubles.endian = egret.Endian.LITTLE_ENDIAN;
725
+ doubles.writeDouble(value);
726
+ buffer.writeBytes(doubles);
727
+ break;
728
+ case 'string':
729
+ buffer.writeBytes(this.encodeUInt32(value.length));
730
+ buffer.writeUTFBytes(value);
731
+ break;
732
+ default:
733
+ let proto: any = protos.__messages[type] || this._clients['message ' + type];
734
+ if (!!proto) {
735
+ let buf: egret.ByteArray = this.encodeProtos(proto, value);
736
+ buffer.writeBytes(this.encodeUInt32(buf.length));
737
+ buffer.writeBytes(buf);
738
+ }
739
+ break;
740
+ }
741
+ }
742
+
743
+ static decodeProp(type: string, protos: any, buffer: egret.ByteArray): any {
744
+ switch (type) {
745
+ case 'uInt32':
746
+ return this.decodeUInt32(buffer);
747
+ case 'int32':
748
+ case 'sInt32':
749
+ return this.decodeSInt32(buffer);
750
+ case 'float':
751
+ let floats: egret.ByteArray = new egret.ByteArray();
752
+ buffer.readBytes(floats, 0, 4);
753
+ floats.endian = egret.Endian.LITTLE_ENDIAN;
754
+ let float: number = buffer.readFloat();
755
+ return floats.readFloat();
756
+ case 'double':
757
+ let doubles: egret.ByteArray = new egret.ByteArray();
758
+ buffer.readBytes(doubles, 0, 8);
759
+ doubles.endian = egret.Endian.LITTLE_ENDIAN;
760
+ return doubles.readDouble();
761
+ case 'string':
762
+ let length: number = this.decodeUInt32(buffer);
763
+ return buffer.readUTFBytes(length);
764
+ default:
765
+ let proto: any = protos && (protos.__messages[type] || this._servers['message ' + type]);
766
+ if (proto) {
767
+ let len: number = this.decodeUInt32(buffer);
768
+ let buf: egret.ByteArray;
769
+ if (len) {
770
+ buf = new egret.ByteArray();
771
+ buffer.readBytes(buf, 0, len);
772
+ }
773
+
774
+ return len ? Protobuf.decodeProtos(proto, buf) : false;
775
+ }
776
+ break;
777
+ }
778
+ }
779
+
780
+ static isSimpleType(type: string): boolean {
781
+ return (
782
+ type === 'uInt32' ||
783
+ type === 'sInt32' ||
784
+ type === 'int32' ||
785
+ type === 'uInt64' ||
786
+ type === 'sInt64' ||
787
+ type === 'float' ||
788
+ type === 'double'
789
+ );
790
+ }
791
+ static encodeArray(array: Array<any>, proto: any, protos: any, buffer: egret.ByteArray): void {
792
+ let isSimpleType = this.isSimpleType;
793
+ if (isSimpleType(proto.type)) {
794
+ buffer.writeBytes(this.encodeTag(proto.type, proto.tag));
795
+ buffer.writeBytes(this.encodeUInt32(array.length));
796
+ let encodeProp = this.encodeProp;
797
+ for (let i: number = 0; i < array.length; i++) {
798
+ encodeProp(array[i], proto.type, protos, buffer);
799
+ }
800
+ } else {
801
+ let encodeTag = this.encodeTag;
802
+ for (let j: number = 0; j < array.length; j++) {
803
+ buffer.writeBytes(encodeTag(proto.type, proto.tag));
804
+ this.encodeProp(array[j], proto.type, protos, buffer);
805
+ }
806
+ }
807
+ }
808
+ static decodeArray(array: Array<any>, type: string, protos: any, buffer: egret.ByteArray): void {
809
+ let isSimpleType = this.isSimpleType;
810
+
811
+ if (isSimpleType(type)) {
812
+ let length: number = this.decodeUInt32(buffer);
813
+ for (let i: number = 0; i < length; i++) {
814
+ array.push(this.decodeProp(type, protos, buffer));
815
+ }
816
+ } else {
817
+ array.push(this.decodeProp(type, protos, buffer));
818
+ }
819
+ }
820
+
821
+ static encodeUInt32(n: number): egret.ByteArray {
822
+ let result: egret.ByteArray = new egret.ByteArray();
823
+
824
+ do {
825
+ let tmp: number = n % 128;
826
+ let next: number = Math.floor(n / 128);
827
+
828
+ if (next !== 0) {
829
+ tmp = tmp + 128;
830
+ }
831
+
832
+ result.writeByte(tmp);
833
+ n = next;
834
+ }
835
+ while (n !== 0);
836
+
837
+ return result;
838
+ }
839
+ static decodeUInt32(buffer: egret.ByteArray): number {
840
+ let n: number = 0;
841
+
842
+ for (let i: number = 0; i < buffer.length; i++) {
843
+ let m: number = buffer.readUnsignedByte();
844
+ n = n + ((m & 0x7f) * Math.pow(2, (7 * i)));
845
+ if (m < 128) {
846
+ return n;
847
+ }
848
+ }
849
+ return n;
850
+ }
851
+ static encodeSInt32(n: number): egret.ByteArray {
852
+ n = n < 0 ? (Math.abs(n) * 2 - 1) : n * 2;
853
+
854
+ return this.encodeUInt32(n);
855
+ }
856
+ static decodeSInt32(buffer: egret.ByteArray): number {
857
+ let n: number = this.decodeUInt32(buffer);
858
+
859
+ let flag: number = ((n % 2) === 1) ? -1 : 1;
860
+
861
+ n = ((n % 2 + n) / 2) * flag;
862
+
863
+ return n;
864
+ }
865
+
866
+ }
867
+ class Routedic {
868
+ private static _ids: Object = {};
869
+ private static _names: Object = {};
870
+
871
+ static init(dict: any): void {
872
+ this._names = dict || {};
873
+ let _names = this._names;
874
+ let _ids = this._ids;
875
+ for (let name in _names) {
876
+ _ids[_names[name]] = name;
877
+ }
878
+ }
879
+
880
+ static getID(name: string) {
881
+ return this._names[name];
882
+ }
883
+ static getName(id: number) {
884
+ return this._ids[id];
885
+ }
886
+ }
887
+
888
+ interface IMessage {
889
+ /**
890
+ * encode
891
+ * @param id
892
+ * @param route
893
+ * @param msg
894
+ * @return ByteArray
895
+ */
896
+ encode(id: number, route: string, msg: any): egret.ByteArray;
897
+
898
+ /**
899
+ * decode
900
+ * @param buffer
901
+ * @return Object
902
+ */
903
+ decode(buffer: egret.ByteArray): any;
904
+ }
905
+ interface IPackage {
906
+
907
+ encode(type: number, body?: egret.ByteArray): egret.ByteArray;
908
+
909
+ decode(buffer: egret.ByteArray): any;
910
+ }
911
+