teeworlds 2.4.1 → 2.4.2
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/index.js +7 -2
- package/lib/client.js +6 -4
- package/lib/client.ts +1 -1
- package/lib/snapshot.js +31 -16
- package/lib/snapshot.ts +34 -18
- package/package.json +1 -1
- package/test.js +32 -0
package/index.js
CHANGED
|
@@ -1,15 +1,20 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
3
|
if (k2 === undefined) k2 = k;
|
|
4
|
-
Object.
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
5
9
|
}) : (function(o, m, k, k2) {
|
|
6
10
|
if (k2 === undefined) k2 = k;
|
|
7
11
|
o[k2] = m[k];
|
|
8
12
|
}));
|
|
9
13
|
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
10
|
-
for (var p in m) if (p !== "default" && !
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
11
15
|
};
|
|
12
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
exports.Client = void 0;
|
|
13
18
|
var client_1 = require("./lib/client");
|
|
14
19
|
Object.defineProperty(exports, "Client", { enumerable: true, get: function () { return client_1.Client; } });
|
|
15
20
|
__exportStar(require("./lib/MsgPacker"), exports);
|
package/lib/client.js
CHANGED
|
@@ -3,10 +3,12 @@ var __extends = (this && this.__extends) || (function () {
|
|
|
3
3
|
var extendStatics = function (d, b) {
|
|
4
4
|
extendStatics = Object.setPrototypeOf ||
|
|
5
5
|
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
|
|
6
|
-
function (d, b) { for (var p in b) if (
|
|
6
|
+
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
|
|
7
7
|
return extendStatics(d, b);
|
|
8
8
|
};
|
|
9
9
|
return function (d, b) {
|
|
10
|
+
if (typeof b !== "function" && b !== null)
|
|
11
|
+
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
|
|
10
12
|
extendStatics(d, b);
|
|
11
13
|
function __() { this.constructor = d; }
|
|
12
14
|
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
|
|
@@ -411,7 +413,7 @@ var Client = /** @class */ (function (_super) {
|
|
|
411
413
|
var client_version = new MsgPacker_1.MsgPacker(0, true, 1);
|
|
412
414
|
client_version.AddBuffer(Buffer.from("8c00130484613e478787f672b3835bd4", 'hex'));
|
|
413
415
|
var randomUuid = Buffer.alloc(16);
|
|
414
|
-
crypto_1.randomBytes(16).copy(randomUuid);
|
|
416
|
+
(0, crypto_1.randomBytes)(16).copy(randomUuid);
|
|
415
417
|
client_version.AddBuffer(randomUuid);
|
|
416
418
|
if (((_d = _this.options) === null || _d === void 0 ? void 0 : _d.ddnet_version) !== undefined) {
|
|
417
419
|
client_version.AddInt((_e = _this.options) === null || _e === void 0 ? void 0 : _e.ddnet_version.version);
|
|
@@ -426,7 +428,7 @@ var Client = /** @class */ (function (_super) {
|
|
|
426
428
|
else if (packet.toJSON().data[3] == 0x4) {
|
|
427
429
|
// disconnected
|
|
428
430
|
_this.State = States.STATE_OFFLINE;
|
|
429
|
-
var reason = (MsgUnpacker_1.unpackString(packet.toJSON().data.slice(4)).result);
|
|
431
|
+
var reason = ((0, MsgUnpacker_1.unpackString)(packet.toJSON().data.slice(4)).result);
|
|
430
432
|
_this.emit("disconnect", reason);
|
|
431
433
|
}
|
|
432
434
|
if (packet.toJSON().data[3] !== 0x0) { // keepalive
|
|
@@ -547,7 +549,7 @@ var Client = /** @class */ (function (_super) {
|
|
|
547
549
|
if (_this.SnapshotParts == ((1 << NumParts) - 1)) {
|
|
548
550
|
var mergedSnaps = Buffer.concat(_this.snaps);
|
|
549
551
|
_this.SnapshotParts = 0;
|
|
550
|
-
var snapUnpacked = _this.SnapUnpacker.unpackSnapshot(mergedSnaps.toJSON().data, DeltaTick, GameTick);
|
|
552
|
+
var snapUnpacked = _this.SnapUnpacker.unpackSnapshot(mergedSnaps.toJSON().data, DeltaTick, GameTick, Crc);
|
|
551
553
|
_this.emit("snapshot");
|
|
552
554
|
_this.AckGameTick = snapUnpacked.recvTick;
|
|
553
555
|
if (Math.abs(_this.PredGameTick - _this.AckGameTick) > 10)
|
package/lib/client.ts
CHANGED
|
@@ -711,7 +711,7 @@ export class Client extends EventEmitter {
|
|
|
711
711
|
let mergedSnaps = Buffer.concat(this.snaps);
|
|
712
712
|
this.SnapshotParts = 0;
|
|
713
713
|
|
|
714
|
-
let snapUnpacked = this.SnapUnpacker.unpackSnapshot(mergedSnaps.toJSON().data, DeltaTick, GameTick);
|
|
714
|
+
let snapUnpacked = this.SnapUnpacker.unpackSnapshot(mergedSnaps.toJSON().data, DeltaTick, GameTick, Crc);
|
|
715
715
|
|
|
716
716
|
this.emit("snapshot");
|
|
717
717
|
this.AckGameTick = snapUnpacked.recvTick;
|
package/lib/snapshot.js
CHANGED
|
@@ -54,6 +54,7 @@ var Snapshot = /** @class */ (function () {
|
|
|
54
54
|
function Snapshot() {
|
|
55
55
|
this.deltas = [];
|
|
56
56
|
this.eSnapHolder = [];
|
|
57
|
+
this.crc_errors = 0;
|
|
57
58
|
}
|
|
58
59
|
Snapshot.prototype.IntsToStr = function (pInts) {
|
|
59
60
|
var pIntz = [];
|
|
@@ -291,7 +292,15 @@ var Snapshot = /** @class */ (function () {
|
|
|
291
292
|
}
|
|
292
293
|
return _item;
|
|
293
294
|
};
|
|
294
|
-
Snapshot.prototype.
|
|
295
|
+
Snapshot.prototype.crc = function (tick) {
|
|
296
|
+
var checksum = 0;
|
|
297
|
+
this.eSnapHolder.forEach(function (snap) {
|
|
298
|
+
if (snap.ack == tick)
|
|
299
|
+
snap.Snapshot.Data.forEach(function (el) { return checksum += el; });
|
|
300
|
+
});
|
|
301
|
+
return checksum & 0xffffffff;
|
|
302
|
+
};
|
|
303
|
+
Snapshot.prototype.unpackSnapshot = function (snap, deltatick, recvTick, WantedCrc) {
|
|
295
304
|
var _this = this;
|
|
296
305
|
var unpacker = new MsgUnpacker_1.MsgUnpacker(snap);
|
|
297
306
|
if (deltatick == -1) {
|
|
@@ -330,7 +339,6 @@ var Snapshot = /** @class */ (function () {
|
|
|
330
339
|
var deleted_key = unpacker.unpackInt(); // removed_item_keys
|
|
331
340
|
// let index = this.deltas.map(delta => delta.key).indexOf(deleted_key);
|
|
332
341
|
var index = this_1.deltas.findIndex(function (delta) { return delta.key === deleted_key; });
|
|
333
|
-
// console.log("deleting ", deleted_key, index)
|
|
334
342
|
if (index > -1)
|
|
335
343
|
this_1.deltas.splice(index, 1);
|
|
336
344
|
deleted.push(deleted_key);
|
|
@@ -349,13 +357,8 @@ var Snapshot = /** @class */ (function () {
|
|
|
349
357
|
var items = { items: [], /* client_infos: client_infos, player_infos: player_infos,*/ lost: 0 };
|
|
350
358
|
var deltaSnaps = this.eSnapHolder.filter(function (a) { return a.ack === deltatick; });
|
|
351
359
|
if (deltaSnaps.length == 0 && deltatick >= 0) {
|
|
352
|
-
// console.log("RESET recvtick")
|
|
353
360
|
return { items: [], recvTick: -1 };
|
|
354
361
|
}
|
|
355
|
-
var newSnaps = [];
|
|
356
|
-
deltaSnaps.forEach(function (a) {
|
|
357
|
-
newSnaps.push({ Snapshot: a.Snapshot, ack: recvTick });
|
|
358
|
-
});
|
|
359
362
|
var _loop_2 = function (i) {
|
|
360
363
|
var type_id = unpacker.unpackInt();
|
|
361
364
|
var id = unpacker.unpackInt();
|
|
@@ -370,10 +373,7 @@ var Snapshot = /** @class */ (function () {
|
|
|
370
373
|
for (var j = 0; j < _size; j++) {
|
|
371
374
|
if (unpacker.remaining.length > 0)
|
|
372
375
|
data.push(unpacker.unpackInt());
|
|
373
|
-
// else
|
|
374
|
-
// console.log("wrong size")
|
|
375
376
|
}
|
|
376
|
-
// console.log(index, deltatick)
|
|
377
377
|
if (deltatick >= 0) {
|
|
378
378
|
// let index = deltaSnaps.map(delta => delta.Snapshot.Key).indexOf(key)
|
|
379
379
|
var index = deltaSnaps.findIndex(function (delta) { return delta.Snapshot.Key === key; });
|
|
@@ -391,7 +391,7 @@ var Snapshot = /** @class */ (function () {
|
|
|
391
391
|
_loop_2(i);
|
|
392
392
|
}
|
|
393
393
|
var _loop_3 = function (newSnap) {
|
|
394
|
-
if (this_3.eSnapHolder.findIndex(function (a) { return a.ack ==
|
|
394
|
+
if (this_3.eSnapHolder.findIndex(function (a) { return a.ack == recvTick && a.Snapshot.Key == newSnap.Snapshot.Key; }) === -1) { // ugly copy new snap to eSnapHolder (if it isnt pushed already)
|
|
395
395
|
this_3.eSnapHolder.push({ Snapshot: { Data: newSnap.Snapshot.Data, Key: newSnap.Snapshot.Key }, ack: recvTick });
|
|
396
396
|
}
|
|
397
397
|
if (deltatick > -1) {
|
|
@@ -404,10 +404,24 @@ var Snapshot = /** @class */ (function () {
|
|
|
404
404
|
this_3.deltas.push({ data: newSnap.Snapshot.Data, key: newSnap.Snapshot.Key, id: newSnap.Snapshot.Key & 0xffff, type_id: ((newSnap.Snapshot.Key >> 16) & 0xffff), parsed: this_3.parseItem(newSnap.Snapshot.Data, ((newSnap.Snapshot.Key >> 16) & 0xffff), ((newSnap.Snapshot.Key) & 0xffff)) });
|
|
405
405
|
};
|
|
406
406
|
var this_3 = this;
|
|
407
|
-
for (var _i = 0,
|
|
408
|
-
var newSnap =
|
|
407
|
+
for (var _i = 0, deltaSnaps_1 = deltaSnaps; _i < deltaSnaps_1.length; _i++) {
|
|
408
|
+
var newSnap = deltaSnaps_1[_i];
|
|
409
409
|
_loop_3(newSnap);
|
|
410
410
|
}
|
|
411
|
+
if (this.crc(recvTick) !== WantedCrc) {
|
|
412
|
+
this.crc_errors++;
|
|
413
|
+
if (this.crc_errors > 5) {
|
|
414
|
+
recvTick = -1;
|
|
415
|
+
this.crc_errors = 0;
|
|
416
|
+
this.eSnapHolder = [];
|
|
417
|
+
this.deltas = [];
|
|
418
|
+
}
|
|
419
|
+
else {
|
|
420
|
+
recvTick = deltatick;
|
|
421
|
+
}
|
|
422
|
+
}
|
|
423
|
+
else if (this.crc_errors > 0)
|
|
424
|
+
this.crc_errors--;
|
|
411
425
|
return { items: items, recvTick: recvTick };
|
|
412
426
|
};
|
|
413
427
|
return Snapshot;
|
|
@@ -415,14 +429,15 @@ var Snapshot = /** @class */ (function () {
|
|
|
415
429
|
exports.Snapshot = Snapshot;
|
|
416
430
|
function UndiffItem(oldItem, newItem) {
|
|
417
431
|
var out = newItem;
|
|
418
|
-
if (JSON.stringify(newItem) === JSON.stringify(oldItem))
|
|
419
|
-
|
|
432
|
+
// if (JSON.stringify(newItem) === JSON.stringify(oldItem))
|
|
433
|
+
// return newItem;
|
|
420
434
|
oldItem.forEach(function (a, i) {
|
|
421
435
|
if (a !== undefined && out[i] !== undefined) {
|
|
422
436
|
out[i] += a;
|
|
423
437
|
}
|
|
424
|
-
else
|
|
438
|
+
else {
|
|
425
439
|
out[i] = 0;
|
|
440
|
+
}
|
|
426
441
|
});
|
|
427
442
|
return out;
|
|
428
443
|
}
|
package/lib/snapshot.ts
CHANGED
|
@@ -57,6 +57,7 @@ interface eSnap {
|
|
|
57
57
|
export class Snapshot {
|
|
58
58
|
deltas: {'data': number[], 'parsed': Item, 'type_id': number, 'id': number, 'key': number}[] = [];
|
|
59
59
|
eSnapHolder: eSnap[] = [];
|
|
60
|
+
crc_errors: number = 0;
|
|
60
61
|
|
|
61
62
|
private IntsToStr(pInts: number[]): string {
|
|
62
63
|
var pIntz: number[] = [];
|
|
@@ -297,7 +298,18 @@ export class Snapshot {
|
|
|
297
298
|
|
|
298
299
|
return _item;
|
|
299
300
|
}
|
|
300
|
-
|
|
301
|
+
|
|
302
|
+
crc(tick: number) {
|
|
303
|
+
var checksum = 0;
|
|
304
|
+
this.eSnapHolder.forEach(snap => {
|
|
305
|
+
if (snap.ack == tick)
|
|
306
|
+
snap.Snapshot.Data.forEach(el => checksum += el);
|
|
307
|
+
})
|
|
308
|
+
|
|
309
|
+
return checksum & 0xffffffff;
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
unpackSnapshot(snap: number[], deltatick: number, recvTick: number, WantedCrc: number) {
|
|
301
313
|
let unpacker = new MsgUnpacker(snap);
|
|
302
314
|
if (deltatick == -1) {
|
|
303
315
|
this.eSnapHolder = [];
|
|
@@ -309,7 +321,7 @@ export class Snapshot {
|
|
|
309
321
|
// empty snap, copy old one into new ack
|
|
310
322
|
this.eSnapHolder.forEach(snap => {
|
|
311
323
|
if (snap.ack == deltatick)
|
|
312
|
-
|
|
324
|
+
this.eSnapHolder.push({Snapshot: snap.Snapshot, ack: recvTick});
|
|
313
325
|
|
|
314
326
|
})
|
|
315
327
|
return {items: [], recvTick: recvTick};
|
|
@@ -337,12 +349,11 @@ export class Snapshot {
|
|
|
337
349
|
let deleted_key = unpacker.unpackInt(); // removed_item_keys
|
|
338
350
|
// let index = this.deltas.map(delta => delta.key).indexOf(deleted_key);
|
|
339
351
|
let index = this.deltas.findIndex(delta => delta.key === deleted_key);
|
|
340
|
-
// console.log("deleting ", deleted_key, index)
|
|
341
352
|
if (index > -1)
|
|
342
353
|
this.deltas.splice(index, 1);
|
|
343
354
|
deleted.push(deleted_key)
|
|
344
355
|
}
|
|
345
|
-
if (deleted.length)
|
|
356
|
+
if (deleted.length)
|
|
346
357
|
this.eSnapHolder = this.eSnapHolder.filter(a => !deleted.includes(a.Snapshot.Key));
|
|
347
358
|
|
|
348
359
|
/*item_delta:
|
|
@@ -355,14 +366,8 @@ export class Snapshot {
|
|
|
355
366
|
let deltaSnaps = this.eSnapHolder.filter(a => a.ack === deltatick);
|
|
356
367
|
|
|
357
368
|
if (deltaSnaps.length == 0 && deltatick >= 0) {
|
|
358
|
-
// console.log("RESET recvtick")
|
|
359
369
|
return {items: [], recvTick: -1};
|
|
360
370
|
}
|
|
361
|
-
let newSnaps: eSnap[] = [];
|
|
362
|
-
deltaSnaps.forEach((a) => {
|
|
363
|
-
|
|
364
|
-
newSnaps.push({Snapshot: a.Snapshot, ack: recvTick});
|
|
365
|
-
})
|
|
366
371
|
|
|
367
372
|
|
|
368
373
|
for (let i = 0; i < num_item_deltas; i++) {
|
|
@@ -380,10 +385,7 @@ export class Snapshot {
|
|
|
380
385
|
for (let j = 0; j < _size; j++) {
|
|
381
386
|
if (unpacker.remaining.length > 0)
|
|
382
387
|
data.push(unpacker.unpackInt());
|
|
383
|
-
// else
|
|
384
|
-
// console.log("wrong size")
|
|
385
388
|
}
|
|
386
|
-
// console.log(index, deltatick)
|
|
387
389
|
if (deltatick >= 0) {
|
|
388
390
|
// let index = deltaSnaps.map(delta => delta.Snapshot.Key).indexOf(key)
|
|
389
391
|
let index = deltaSnaps.findIndex(delta => delta.Snapshot.Key === key);
|
|
@@ -402,8 +404,8 @@ export class Snapshot {
|
|
|
402
404
|
|
|
403
405
|
|
|
404
406
|
}
|
|
405
|
-
for (let newSnap of
|
|
406
|
-
if (this.eSnapHolder.findIndex(a => a.ack ==
|
|
407
|
+
for (let newSnap of deltaSnaps) {
|
|
408
|
+
if (this.eSnapHolder.findIndex(a => a.ack == recvTick && a.Snapshot.Key == newSnap.Snapshot.Key) === -1) { // ugly copy new snap to eSnapHolder (if it isnt pushed already)
|
|
407
409
|
this.eSnapHolder.push({Snapshot: {Data: newSnap.Snapshot.Data, Key: newSnap.Snapshot.Key}, ack: recvTick});
|
|
408
410
|
}
|
|
409
411
|
if (deltatick > -1) {
|
|
@@ -417,6 +419,19 @@ export class Snapshot {
|
|
|
417
419
|
this.deltas.push({data: newSnap.Snapshot.Data, key: newSnap.Snapshot.Key, id: newSnap.Snapshot.Key & 0xffff, type_id: ((newSnap.Snapshot.Key >> 16) & 0xffff), parsed: this.parseItem(newSnap.Snapshot.Data, ((newSnap.Snapshot.Key >> 16) & 0xffff), ((newSnap.Snapshot.Key) & 0xffff))});
|
|
418
420
|
}
|
|
419
421
|
|
|
422
|
+
if (this.crc(recvTick) !== WantedCrc) {
|
|
423
|
+
this.crc_errors++;
|
|
424
|
+
if (this.crc_errors > 5) {
|
|
425
|
+
recvTick = -1;
|
|
426
|
+
this.crc_errors = 0;
|
|
427
|
+
this.eSnapHolder = [];
|
|
428
|
+
this.deltas = [];
|
|
429
|
+
} else {
|
|
430
|
+
recvTick = deltatick;
|
|
431
|
+
|
|
432
|
+
}
|
|
433
|
+
} else if (this.crc_errors > 0)
|
|
434
|
+
this.crc_errors--;
|
|
420
435
|
|
|
421
436
|
return {items, recvTick};
|
|
422
437
|
}
|
|
@@ -424,13 +439,14 @@ export class Snapshot {
|
|
|
424
439
|
|
|
425
440
|
function UndiffItem(oldItem: number[], newItem: number[]): number[] {
|
|
426
441
|
let out: number[] = newItem;
|
|
427
|
-
if (JSON.stringify(newItem) === JSON.stringify(oldItem))
|
|
428
|
-
return newItem;
|
|
442
|
+
// if (JSON.stringify(newItem) === JSON.stringify(oldItem))
|
|
443
|
+
// return newItem;
|
|
429
444
|
oldItem.forEach((a, i) => {
|
|
430
445
|
if (a !== undefined && out[i] !== undefined) {
|
|
431
446
|
out[i] += a;
|
|
432
|
-
} else
|
|
447
|
+
} else {
|
|
433
448
|
out[i] = 0;
|
|
449
|
+
}
|
|
434
450
|
})
|
|
435
451
|
return out;
|
|
436
452
|
}
|
package/package.json
CHANGED
package/test.js
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
const { Snapshot } = require("./lib/snapshot")
|
|
2
|
+
|
|
3
|
+
let test_snap1 = [0,18,0,4,18,1744,1072,2,3,4,17,1840,912,1,0,4,16,880,880,0,0,4,15,1840,848,1,0,4,14,912,848,0,0,4,13,880,848,1,0,4,12,848,848,0,0,4,11,880,816,0,0,4,9,1264,656,0,0,4,8,1104,656,0,0,4,7,912,656,0,0,4,6,1712,624,2,2,4,5,1840,432,1,0,4,3,1840,336,1,0,9,0,292,1584,305,0,128,0,0,0,-1,0,0,1584,304,0,0,0,10,0,10,1,0,0,6,0,0,0,0,0,20,0,0,1,11,0,-287183387,-320474125,-1594563099,-2139062272,-2139062144,-2139062144,-2139062272,-1,-454695199,-169020288,-2139062144,-2139062144,-2139062144,-2139062272,0,65408,65408,10,0,1,0,0,0,0]
|
|
4
|
+
let first_crc = 0x5b96263a;
|
|
5
|
+
let test_snap2 = [0,1,0,9,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,];
|
|
6
|
+
let second_crc = 0x5b96263b;
|
|
7
|
+
let snapunpacker = new Snapshot();
|
|
8
|
+
|
|
9
|
+
let sum = (nums) => {
|
|
10
|
+
var sum = 0;
|
|
11
|
+
nums.forEach(a => {
|
|
12
|
+
// if (a < 0)
|
|
13
|
+
sum += a
|
|
14
|
+
})
|
|
15
|
+
console.log(sum, master_sum)
|
|
16
|
+
return sum;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
let master_sum = 0;
|
|
20
|
+
|
|
21
|
+
// test_snap.forEach(a => master_sum += sum(...a));
|
|
22
|
+
// master_sum = sum(...test_snap)
|
|
23
|
+
// test_snap.forEach(a => {master_sum += a; console.log(master_sum)})
|
|
24
|
+
// console.log(snapunpacker.unpackSnapshot(test_snap).items.items);
|
|
25
|
+
|
|
26
|
+
snapunpacker = new Snapshot();
|
|
27
|
+
console.log(snapunpacker.unpackSnapshot(test_snap1, -1, 1, first_crc));
|
|
28
|
+
console.log(snapunpacker.unpackSnapshot(test_snap2, 1, 2, second_crc));
|
|
29
|
+
// console.log(snapunpacker.eSnapHolder)
|
|
30
|
+
// snapunpacker.eSnapHolder.forEach(a => console.log(a.Snapshot.Data))
|
|
31
|
+
snapunpacker.eSnapHolder.forEach(a => master_sum += sum(a.Snapshot.Data))
|
|
32
|
+
console.log(master_sum & 0xffffffff, 0x5b96263a)
|