quake2ts 0.0.78 → 0.0.79
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/package.json +1 -1
- package/packages/client/dist/browser/index.global.js +1 -1
- package/packages/client/dist/browser/index.global.js.map +1 -1
- package/packages/client/dist/cjs/index.cjs +856 -1
- package/packages/client/dist/cjs/index.cjs.map +1 -1
- package/packages/client/dist/esm/index.js +856 -1
- package/packages/client/dist/esm/index.js.map +1 -1
- package/packages/client/dist/tsconfig.tsbuildinfo +1 -1
- package/packages/client/dist/types/index.d.ts +2 -1
- package/packages/client/dist/types/index.d.ts.map +1 -1
- package/packages/engine/dist/browser/index.global.js +14 -14
- package/packages/engine/dist/browser/index.global.js.map +1 -1
- package/packages/engine/dist/cjs/index.cjs +875 -0
- package/packages/engine/dist/cjs/index.cjs.map +1 -1
- package/packages/engine/dist/esm/index.js +871 -0
- package/packages/engine/dist/esm/index.js.map +1 -1
- package/packages/engine/dist/tsconfig.tsbuildinfo +1 -1
- package/packages/engine/dist/types/demo/demoReader.d.ts +27 -0
- package/packages/engine/dist/types/demo/demoReader.d.ts.map +1 -0
- package/packages/engine/dist/types/demo/index.d.ts +4 -0
- package/packages/engine/dist/types/demo/index.d.ts.map +1 -0
- package/packages/engine/dist/types/demo/playback.d.ts +3 -4
- package/packages/engine/dist/types/demo/playback.d.ts.map +1 -1
- package/packages/engine/dist/types/index.d.ts +1 -0
- package/packages/engine/dist/types/index.d.ts.map +1 -1
- package/packages/game/dist/tsconfig.tsbuildinfo +1 -1
|
@@ -43,6 +43,8 @@ __export(index_exports, {
|
|
|
43
43
|
ConfigStringRegistry: () => ConfigStringRegistry,
|
|
44
44
|
Cvar: () => Cvar,
|
|
45
45
|
CvarRegistry: () => CvarRegistry,
|
|
46
|
+
DemoPlaybackController: () => DemoPlaybackController,
|
|
47
|
+
DemoReader: () => DemoReader,
|
|
46
48
|
EngineHost: () => EngineHost,
|
|
47
49
|
EngineRuntime: () => EngineRuntime,
|
|
48
50
|
FixedTimestepLoop: () => FixedTimestepLoop,
|
|
@@ -64,6 +66,7 @@ __export(index_exports, {
|
|
|
64
66
|
Md3Pipeline: () => Md3Pipeline,
|
|
65
67
|
Md3SurfaceMesh: () => Md3SurfaceMesh,
|
|
66
68
|
MusicSystem: () => MusicSystem,
|
|
69
|
+
NetworkMessageParser: () => NetworkMessageParser,
|
|
67
70
|
PARTICLE_FRAGMENT_SHADER: () => PARTICLE_FRAGMENT_SHADER,
|
|
68
71
|
PARTICLE_VERTEX_SHADER: () => PARTICLE_VERTEX_SHADER,
|
|
69
72
|
PakArchive: () => PakArchive,
|
|
@@ -74,6 +77,7 @@ __export(index_exports, {
|
|
|
74
77
|
PakValidator: () => PakValidator,
|
|
75
78
|
ParticleRenderer: () => ParticleRenderer,
|
|
76
79
|
ParticleSystem: () => ParticleSystem,
|
|
80
|
+
PlaybackState: () => PlaybackState,
|
|
77
81
|
RERELEASE_KNOWN_PAKS: () => RERELEASE_KNOWN_PAKS,
|
|
78
82
|
SKYBOX_FRAGMENT_SHADER: () => SKYBOX_FRAGMENT_SHADER,
|
|
79
83
|
SKYBOX_VERTEX_SHADER: () => SKYBOX_VERTEX_SHADER,
|
|
@@ -463,6 +467,193 @@ function configStringSize(index) {
|
|
|
463
467
|
return CS_MAX_STRING_LENGTH;
|
|
464
468
|
}
|
|
465
469
|
var WATERJUMP_CLEAR = 8 | 16 | 32 | 1024;
|
|
470
|
+
var ServerCommand = /* @__PURE__ */ ((ServerCommand2) => {
|
|
471
|
+
ServerCommand2[ServerCommand2["bad"] = 0] = "bad";
|
|
472
|
+
ServerCommand2[ServerCommand2["muzzleflash"] = 1] = "muzzleflash";
|
|
473
|
+
ServerCommand2[ServerCommand2["muzzleflash2"] = 2] = "muzzleflash2";
|
|
474
|
+
ServerCommand2[ServerCommand2["temp_entity"] = 3] = "temp_entity";
|
|
475
|
+
ServerCommand2[ServerCommand2["layout"] = 4] = "layout";
|
|
476
|
+
ServerCommand2[ServerCommand2["inventory"] = 5] = "inventory";
|
|
477
|
+
ServerCommand2[ServerCommand2["nop"] = 6] = "nop";
|
|
478
|
+
ServerCommand2[ServerCommand2["disconnect"] = 7] = "disconnect";
|
|
479
|
+
ServerCommand2[ServerCommand2["reconnect"] = 8] = "reconnect";
|
|
480
|
+
ServerCommand2[ServerCommand2["sound"] = 9] = "sound";
|
|
481
|
+
ServerCommand2[ServerCommand2["print"] = 10] = "print";
|
|
482
|
+
ServerCommand2[ServerCommand2["stufftext"] = 11] = "stufftext";
|
|
483
|
+
ServerCommand2[ServerCommand2["serverdata"] = 12] = "serverdata";
|
|
484
|
+
ServerCommand2[ServerCommand2["configstring"] = 13] = "configstring";
|
|
485
|
+
ServerCommand2[ServerCommand2["spawnbaseline"] = 14] = "spawnbaseline";
|
|
486
|
+
ServerCommand2[ServerCommand2["centerprint"] = 15] = "centerprint";
|
|
487
|
+
ServerCommand2[ServerCommand2["download"] = 16] = "download";
|
|
488
|
+
ServerCommand2[ServerCommand2["playerinfo"] = 17] = "playerinfo";
|
|
489
|
+
ServerCommand2[ServerCommand2["packetentities"] = 18] = "packetentities";
|
|
490
|
+
ServerCommand2[ServerCommand2["deltapacketentities"] = 19] = "deltapacketentities";
|
|
491
|
+
ServerCommand2[ServerCommand2["frame"] = 20] = "frame";
|
|
492
|
+
return ServerCommand2;
|
|
493
|
+
})(ServerCommand || {});
|
|
494
|
+
var TempEntity = /* @__PURE__ */ ((TempEntity2) => {
|
|
495
|
+
TempEntity2[TempEntity2["GUNSHOT"] = 0] = "GUNSHOT";
|
|
496
|
+
TempEntity2[TempEntity2["BLOOD"] = 1] = "BLOOD";
|
|
497
|
+
TempEntity2[TempEntity2["BLASTER"] = 2] = "BLASTER";
|
|
498
|
+
TempEntity2[TempEntity2["RAILTRAIL"] = 3] = "RAILTRAIL";
|
|
499
|
+
TempEntity2[TempEntity2["SHOTGUN"] = 4] = "SHOTGUN";
|
|
500
|
+
TempEntity2[TempEntity2["EXPLOSION1"] = 5] = "EXPLOSION1";
|
|
501
|
+
TempEntity2[TempEntity2["EXPLOSION2"] = 6] = "EXPLOSION2";
|
|
502
|
+
TempEntity2[TempEntity2["ROCKET_EXPLOSION"] = 7] = "ROCKET_EXPLOSION";
|
|
503
|
+
TempEntity2[TempEntity2["GRENADE_EXPLOSION"] = 8] = "GRENADE_EXPLOSION";
|
|
504
|
+
TempEntity2[TempEntity2["SPARKS"] = 9] = "SPARKS";
|
|
505
|
+
TempEntity2[TempEntity2["SPLASH"] = 10] = "SPLASH";
|
|
506
|
+
TempEntity2[TempEntity2["BUBBLETRAIL"] = 11] = "BUBBLETRAIL";
|
|
507
|
+
TempEntity2[TempEntity2["SCREEN_SPARKS"] = 12] = "SCREEN_SPARKS";
|
|
508
|
+
TempEntity2[TempEntity2["SHIELD_SPARKS"] = 13] = "SHIELD_SPARKS";
|
|
509
|
+
TempEntity2[TempEntity2["BULLET_SPARKS"] = 14] = "BULLET_SPARKS";
|
|
510
|
+
TempEntity2[TempEntity2["LASER_SPARKS"] = 15] = "LASER_SPARKS";
|
|
511
|
+
TempEntity2[TempEntity2["PARASITE_ATTACK"] = 16] = "PARASITE_ATTACK";
|
|
512
|
+
TempEntity2[TempEntity2["ROCKET_EXPLOSION_WATER"] = 17] = "ROCKET_EXPLOSION_WATER";
|
|
513
|
+
TempEntity2[TempEntity2["GRENADE_EXPLOSION_WATER"] = 18] = "GRENADE_EXPLOSION_WATER";
|
|
514
|
+
TempEntity2[TempEntity2["MEDIC_CABLE_ATTACK"] = 19] = "MEDIC_CABLE_ATTACK";
|
|
515
|
+
TempEntity2[TempEntity2["BFG_EXPLOSION"] = 20] = "BFG_EXPLOSION";
|
|
516
|
+
TempEntity2[TempEntity2["BFG_BIGEXPLOSION"] = 21] = "BFG_BIGEXPLOSION";
|
|
517
|
+
TempEntity2[TempEntity2["BOSSTPORT"] = 22] = "BOSSTPORT";
|
|
518
|
+
TempEntity2[TempEntity2["BFG_LASER"] = 23] = "BFG_LASER";
|
|
519
|
+
TempEntity2[TempEntity2["GRAPPLE_CABLE"] = 24] = "GRAPPLE_CABLE";
|
|
520
|
+
TempEntity2[TempEntity2["WELDING_SPARKS"] = 25] = "WELDING_SPARKS";
|
|
521
|
+
TempEntity2[TempEntity2["GREENBLOOD"] = 26] = "GREENBLOOD";
|
|
522
|
+
TempEntity2[TempEntity2["BLUEHYPERBLASTER"] = 27] = "BLUEHYPERBLASTER";
|
|
523
|
+
TempEntity2[TempEntity2["PLASMA_EXPLOSION"] = 28] = "PLASMA_EXPLOSION";
|
|
524
|
+
TempEntity2[TempEntity2["TUNNEL_SPARKS"] = 29] = "TUNNEL_SPARKS";
|
|
525
|
+
TempEntity2[TempEntity2["BLASTER2"] = 30] = "BLASTER2";
|
|
526
|
+
TempEntity2[TempEntity2["RAILTRAIL2"] = 31] = "RAILTRAIL2";
|
|
527
|
+
TempEntity2[TempEntity2["FLAME"] = 32] = "FLAME";
|
|
528
|
+
TempEntity2[TempEntity2["LIGHTNING"] = 33] = "LIGHTNING";
|
|
529
|
+
TempEntity2[TempEntity2["DEBUGTRAIL"] = 34] = "DEBUGTRAIL";
|
|
530
|
+
TempEntity2[TempEntity2["PLAIN_EXPLOSION"] = 35] = "PLAIN_EXPLOSION";
|
|
531
|
+
TempEntity2[TempEntity2["FLASHLIGHT"] = 36] = "FLASHLIGHT";
|
|
532
|
+
TempEntity2[TempEntity2["FORCEWALL"] = 37] = "FORCEWALL";
|
|
533
|
+
TempEntity2[TempEntity2["HEATBEAM"] = 38] = "HEATBEAM";
|
|
534
|
+
TempEntity2[TempEntity2["MONSTER_HEATBEAM"] = 39] = "MONSTER_HEATBEAM";
|
|
535
|
+
TempEntity2[TempEntity2["STEAM"] = 40] = "STEAM";
|
|
536
|
+
TempEntity2[TempEntity2["BUBBLETRAIL2"] = 41] = "BUBBLETRAIL2";
|
|
537
|
+
TempEntity2[TempEntity2["MOREBLOOD"] = 42] = "MOREBLOOD";
|
|
538
|
+
TempEntity2[TempEntity2["HEATBEAM_SPARKS"] = 43] = "HEATBEAM_SPARKS";
|
|
539
|
+
TempEntity2[TempEntity2["HEATBEAM_STEAM"] = 44] = "HEATBEAM_STEAM";
|
|
540
|
+
TempEntity2[TempEntity2["CHAINFIST_SMOKE"] = 45] = "CHAINFIST_SMOKE";
|
|
541
|
+
TempEntity2[TempEntity2["ELECTRIC_SPARKS"] = 46] = "ELECTRIC_SPARKS";
|
|
542
|
+
TempEntity2[TempEntity2["TRACKER_EXPLOSION"] = 47] = "TRACKER_EXPLOSION";
|
|
543
|
+
TempEntity2[TempEntity2["TELEPORT_EFFECT"] = 48] = "TELEPORT_EFFECT";
|
|
544
|
+
TempEntity2[TempEntity2["DBALL_GOAL"] = 49] = "DBALL_GOAL";
|
|
545
|
+
TempEntity2[TempEntity2["WIDOWBEAMOUT"] = 50] = "WIDOWBEAMOUT";
|
|
546
|
+
TempEntity2[TempEntity2["NUKEBLAST"] = 51] = "NUKEBLAST";
|
|
547
|
+
TempEntity2[TempEntity2["WIDOWSPLASH"] = 52] = "WIDOWSPLASH";
|
|
548
|
+
TempEntity2[TempEntity2["EXPLOSION1_BIG"] = 53] = "EXPLOSION1_BIG";
|
|
549
|
+
TempEntity2[TempEntity2["EXPLOSION1_NP"] = 54] = "EXPLOSION1_NP";
|
|
550
|
+
TempEntity2[TempEntity2["FLECHETTE"] = 55] = "FLECHETTE";
|
|
551
|
+
return TempEntity2;
|
|
552
|
+
})(TempEntity || {});
|
|
553
|
+
var BinaryStream = class {
|
|
554
|
+
constructor(buffer) {
|
|
555
|
+
if (buffer instanceof Uint8Array) {
|
|
556
|
+
this.view = new DataView(buffer.buffer, buffer.byteOffset, buffer.byteLength);
|
|
557
|
+
} else {
|
|
558
|
+
this.view = new DataView(buffer);
|
|
559
|
+
}
|
|
560
|
+
this.offset = 0;
|
|
561
|
+
this.length = this.view.byteLength;
|
|
562
|
+
}
|
|
563
|
+
getPosition() {
|
|
564
|
+
return this.offset;
|
|
565
|
+
}
|
|
566
|
+
seek(position) {
|
|
567
|
+
if (position < 0 || position > this.length) {
|
|
568
|
+
throw new Error(`Seek out of bounds: ${position} (length: ${this.length})`);
|
|
569
|
+
}
|
|
570
|
+
this.offset = position;
|
|
571
|
+
}
|
|
572
|
+
hasMore() {
|
|
573
|
+
return this.offset < this.length;
|
|
574
|
+
}
|
|
575
|
+
readChar() {
|
|
576
|
+
const value = this.view.getInt8(this.offset);
|
|
577
|
+
this.offset += 1;
|
|
578
|
+
return value;
|
|
579
|
+
}
|
|
580
|
+
readByte() {
|
|
581
|
+
const value = this.view.getUint8(this.offset);
|
|
582
|
+
this.offset += 1;
|
|
583
|
+
return value;
|
|
584
|
+
}
|
|
585
|
+
readShort() {
|
|
586
|
+
const value = this.view.getInt16(this.offset, true);
|
|
587
|
+
this.offset += 2;
|
|
588
|
+
return value;
|
|
589
|
+
}
|
|
590
|
+
readLong() {
|
|
591
|
+
const value = this.view.getInt32(this.offset, true);
|
|
592
|
+
this.offset += 4;
|
|
593
|
+
return value;
|
|
594
|
+
}
|
|
595
|
+
readFloat() {
|
|
596
|
+
const value = this.view.getFloat32(this.offset, true);
|
|
597
|
+
this.offset += 4;
|
|
598
|
+
return value;
|
|
599
|
+
}
|
|
600
|
+
readString() {
|
|
601
|
+
let str = "";
|
|
602
|
+
while (this.offset < this.length) {
|
|
603
|
+
const charCode = this.readChar();
|
|
604
|
+
if (charCode === -1 || charCode === 0) {
|
|
605
|
+
break;
|
|
606
|
+
}
|
|
607
|
+
str += String.fromCharCode(charCode);
|
|
608
|
+
}
|
|
609
|
+
return str;
|
|
610
|
+
}
|
|
611
|
+
readStringLine() {
|
|
612
|
+
let str = "";
|
|
613
|
+
while (this.offset < this.length) {
|
|
614
|
+
const charCode = this.readChar();
|
|
615
|
+
if (charCode === -1 || charCode === 0 || charCode === 10) {
|
|
616
|
+
break;
|
|
617
|
+
}
|
|
618
|
+
str += String.fromCharCode(charCode);
|
|
619
|
+
}
|
|
620
|
+
return str;
|
|
621
|
+
}
|
|
622
|
+
readCoord() {
|
|
623
|
+
return this.readShort() * (1 / 8);
|
|
624
|
+
}
|
|
625
|
+
readAngle() {
|
|
626
|
+
return this.readChar() * (360 / 256);
|
|
627
|
+
}
|
|
628
|
+
readAngle16() {
|
|
629
|
+
return this.readShort() * 360 / 65536;
|
|
630
|
+
}
|
|
631
|
+
readData(length) {
|
|
632
|
+
if (this.offset + length > this.length) {
|
|
633
|
+
throw new Error(`Read out of bounds: ${this.offset + length} (length: ${this.length})`);
|
|
634
|
+
}
|
|
635
|
+
const data = new Uint8Array(this.view.buffer, this.view.byteOffset + this.offset, length);
|
|
636
|
+
this.offset += length;
|
|
637
|
+
return new Uint8Array(data);
|
|
638
|
+
}
|
|
639
|
+
readPos(out) {
|
|
640
|
+
out.x = this.readCoord();
|
|
641
|
+
out.y = this.readCoord();
|
|
642
|
+
out.z = this.readCoord();
|
|
643
|
+
}
|
|
644
|
+
readDir(out) {
|
|
645
|
+
const b = this.readByte();
|
|
646
|
+
if (b >= 162) {
|
|
647
|
+
out.x = 0;
|
|
648
|
+
out.y = 0;
|
|
649
|
+
out.z = 0;
|
|
650
|
+
return;
|
|
651
|
+
}
|
|
652
|
+
out.x = 0;
|
|
653
|
+
out.y = 0;
|
|
654
|
+
out.z = 0;
|
|
655
|
+
}
|
|
656
|
+
};
|
|
466
657
|
|
|
467
658
|
// src/configstrings.ts
|
|
468
659
|
function assertWithinBounds(index) {
|
|
@@ -5608,6 +5799,686 @@ function spawnTrail(context) {
|
|
|
5608
5799
|
}
|
|
5609
5800
|
}
|
|
5610
5801
|
|
|
5802
|
+
// src/demo/demoReader.ts
|
|
5803
|
+
var DemoReader = class {
|
|
5804
|
+
constructor(buffer) {
|
|
5805
|
+
this.buffer = buffer;
|
|
5806
|
+
this.view = new DataView(buffer);
|
|
5807
|
+
this.offset = 0;
|
|
5808
|
+
}
|
|
5809
|
+
/**
|
|
5810
|
+
* Checks if there are more blocks to read.
|
|
5811
|
+
*/
|
|
5812
|
+
hasMore() {
|
|
5813
|
+
return this.offset < this.buffer.byteLength;
|
|
5814
|
+
}
|
|
5815
|
+
/**
|
|
5816
|
+
* Reads the next message block from the demo file.
|
|
5817
|
+
* Format is [Length (4 bytes)] + [Message Block (Length bytes)].
|
|
5818
|
+
* Returns null if end of file or incomplete block.
|
|
5819
|
+
*/
|
|
5820
|
+
readNextBlock() {
|
|
5821
|
+
if (this.offset + 4 > this.buffer.byteLength) {
|
|
5822
|
+
return null;
|
|
5823
|
+
}
|
|
5824
|
+
const length = this.view.getInt32(this.offset, true);
|
|
5825
|
+
this.offset += 4;
|
|
5826
|
+
if (length < 0 || length > 262144) {
|
|
5827
|
+
console.warn(`DemoReader: Invalid block length ${length} at offset ${this.offset - 4}`);
|
|
5828
|
+
return null;
|
|
5829
|
+
}
|
|
5830
|
+
if (this.offset + length > this.buffer.byteLength) {
|
|
5831
|
+
console.warn(`DemoReader: Incomplete block. Expected ${length} bytes, but only ${this.buffer.byteLength - this.offset} remain.`);
|
|
5832
|
+
return null;
|
|
5833
|
+
}
|
|
5834
|
+
const blockData = this.buffer.slice(this.offset, this.offset + length);
|
|
5835
|
+
this.offset += length;
|
|
5836
|
+
return {
|
|
5837
|
+
length,
|
|
5838
|
+
data: new BinaryStream(blockData)
|
|
5839
|
+
};
|
|
5840
|
+
}
|
|
5841
|
+
/**
|
|
5842
|
+
* Resets the reader to the beginning.
|
|
5843
|
+
*/
|
|
5844
|
+
reset() {
|
|
5845
|
+
this.offset = 0;
|
|
5846
|
+
}
|
|
5847
|
+
getOffset() {
|
|
5848
|
+
return this.offset;
|
|
5849
|
+
}
|
|
5850
|
+
};
|
|
5851
|
+
|
|
5852
|
+
// src/demo/parser.ts
|
|
5853
|
+
var U_ORIGIN1 = 1 << 0;
|
|
5854
|
+
var U_ORIGIN2 = 1 << 1;
|
|
5855
|
+
var U_ANGLE2 = 1 << 2;
|
|
5856
|
+
var U_ANGLE3 = 1 << 3;
|
|
5857
|
+
var U_FRAME8 = 1 << 4;
|
|
5858
|
+
var U_EVENT = 1 << 5;
|
|
5859
|
+
var U_REMOVE = 1 << 6;
|
|
5860
|
+
var U_MOREBITS1 = 1 << 7;
|
|
5861
|
+
var U_NUMBER16 = 1 << 8;
|
|
5862
|
+
var U_ORIGIN3 = 1 << 9;
|
|
5863
|
+
var U_ANGLE1 = 1 << 10;
|
|
5864
|
+
var U_MODEL = 1 << 11;
|
|
5865
|
+
var U_RENDERFX8 = 1 << 12;
|
|
5866
|
+
var U_EFFECTS8 = 1 << 14;
|
|
5867
|
+
var U_MOREBITS2 = 1 << 15;
|
|
5868
|
+
var U_SKIN8 = 1 << 16;
|
|
5869
|
+
var U_FRAME16 = 1 << 17;
|
|
5870
|
+
var U_RENDERFX16 = 1 << 18;
|
|
5871
|
+
var U_EFFECTS16 = 1 << 19;
|
|
5872
|
+
var U_MODEL2 = 1 << 20;
|
|
5873
|
+
var U_MODEL3 = 1 << 21;
|
|
5874
|
+
var U_MODEL4 = 1 << 22;
|
|
5875
|
+
var U_MOREBITS3 = 1 << 23;
|
|
5876
|
+
var U_OLDORIGIN = 1 << 24;
|
|
5877
|
+
var U_SKIN16 = 1 << 25;
|
|
5878
|
+
var U_SOUND = 1 << 26;
|
|
5879
|
+
var U_SOLID = 1 << 27;
|
|
5880
|
+
var createEmptyEntityState = () => ({
|
|
5881
|
+
number: 0,
|
|
5882
|
+
modelindex: 0,
|
|
5883
|
+
modelindex2: 0,
|
|
5884
|
+
modelindex3: 0,
|
|
5885
|
+
modelindex4: 0,
|
|
5886
|
+
frame: 0,
|
|
5887
|
+
skinnum: 0,
|
|
5888
|
+
effects: 0,
|
|
5889
|
+
renderfx: 0,
|
|
5890
|
+
origin: { x: 0, y: 0, z: 0 },
|
|
5891
|
+
old_origin: { x: 0, y: 0, z: 0 },
|
|
5892
|
+
angles: { x: 0, y: 0, z: 0 },
|
|
5893
|
+
sound: 0,
|
|
5894
|
+
event: 0,
|
|
5895
|
+
solid: 0
|
|
5896
|
+
});
|
|
5897
|
+
var NetworkMessageParser = class {
|
|
5898
|
+
constructor(stream) {
|
|
5899
|
+
this.stream = stream;
|
|
5900
|
+
}
|
|
5901
|
+
parseMessage() {
|
|
5902
|
+
while (this.stream.hasMore()) {
|
|
5903
|
+
const cmd = this.stream.readByte();
|
|
5904
|
+
if (cmd === -1) {
|
|
5905
|
+
break;
|
|
5906
|
+
}
|
|
5907
|
+
switch (cmd) {
|
|
5908
|
+
case ServerCommand.nop:
|
|
5909
|
+
break;
|
|
5910
|
+
case ServerCommand.disconnect:
|
|
5911
|
+
console.log("Server disconnected");
|
|
5912
|
+
break;
|
|
5913
|
+
case ServerCommand.reconnect:
|
|
5914
|
+
console.log("Server reconnect");
|
|
5915
|
+
break;
|
|
5916
|
+
case ServerCommand.print:
|
|
5917
|
+
const printId = this.stream.readByte();
|
|
5918
|
+
const printMsg = this.stream.readString();
|
|
5919
|
+
console.log(`[Server Print ${printId}]: ${printMsg}`);
|
|
5920
|
+
break;
|
|
5921
|
+
case ServerCommand.serverdata:
|
|
5922
|
+
this.parseServerData();
|
|
5923
|
+
break;
|
|
5924
|
+
case ServerCommand.configstring:
|
|
5925
|
+
this.parseConfigString();
|
|
5926
|
+
break;
|
|
5927
|
+
case ServerCommand.spawnbaseline:
|
|
5928
|
+
this.parseSpawnBaseline();
|
|
5929
|
+
break;
|
|
5930
|
+
case ServerCommand.centerprint:
|
|
5931
|
+
const centerMsg = this.stream.readString();
|
|
5932
|
+
console.log(`[Center Print]: ${centerMsg}`);
|
|
5933
|
+
break;
|
|
5934
|
+
case ServerCommand.download:
|
|
5935
|
+
this.parseDownload();
|
|
5936
|
+
break;
|
|
5937
|
+
case ServerCommand.frame:
|
|
5938
|
+
this.parseFrame();
|
|
5939
|
+
break;
|
|
5940
|
+
case ServerCommand.packetentities:
|
|
5941
|
+
this.parsePacketEntities(false);
|
|
5942
|
+
break;
|
|
5943
|
+
case ServerCommand.deltapacketentities:
|
|
5944
|
+
this.parsePacketEntities(true);
|
|
5945
|
+
break;
|
|
5946
|
+
case ServerCommand.stufftext:
|
|
5947
|
+
const text = this.stream.readString();
|
|
5948
|
+
console.log(`[StuffText]: ${text}`);
|
|
5949
|
+
break;
|
|
5950
|
+
case ServerCommand.layout:
|
|
5951
|
+
const layout = this.stream.readString();
|
|
5952
|
+
break;
|
|
5953
|
+
case ServerCommand.inventory:
|
|
5954
|
+
this.parseInventory();
|
|
5955
|
+
break;
|
|
5956
|
+
case ServerCommand.sound:
|
|
5957
|
+
this.parseSound();
|
|
5958
|
+
break;
|
|
5959
|
+
case ServerCommand.muzzleflash:
|
|
5960
|
+
this.parseMuzzleFlash();
|
|
5961
|
+
break;
|
|
5962
|
+
case ServerCommand.muzzleflash2:
|
|
5963
|
+
this.parseMuzzleFlash2();
|
|
5964
|
+
break;
|
|
5965
|
+
case ServerCommand.temp_entity:
|
|
5966
|
+
this.parseTempEntity();
|
|
5967
|
+
break;
|
|
5968
|
+
default:
|
|
5969
|
+
console.warn(`Unknown server command: ${cmd}`);
|
|
5970
|
+
return;
|
|
5971
|
+
}
|
|
5972
|
+
}
|
|
5973
|
+
}
|
|
5974
|
+
parseServerData() {
|
|
5975
|
+
const protocol = this.stream.readLong();
|
|
5976
|
+
const serverCount = this.stream.readLong();
|
|
5977
|
+
const attractLoop = this.stream.readByte();
|
|
5978
|
+
const gameDir = this.stream.readString();
|
|
5979
|
+
const playerNum = this.stream.readShort();
|
|
5980
|
+
const levelName = this.stream.readString();
|
|
5981
|
+
console.log(`Server Data: Protocol ${protocol}, Level ${levelName}, GameDir ${gameDir}`);
|
|
5982
|
+
}
|
|
5983
|
+
parseConfigString() {
|
|
5984
|
+
const index = this.stream.readShort();
|
|
5985
|
+
const str = this.stream.readString();
|
|
5986
|
+
}
|
|
5987
|
+
parseDownload() {
|
|
5988
|
+
const size = this.stream.readShort();
|
|
5989
|
+
const percent = this.stream.readByte();
|
|
5990
|
+
if (size > 0) {
|
|
5991
|
+
this.stream.readData(size);
|
|
5992
|
+
}
|
|
5993
|
+
}
|
|
5994
|
+
parseInventory() {
|
|
5995
|
+
const MAX_ITEMS2 = 256;
|
|
5996
|
+
for (let i = 0; i < MAX_ITEMS2; i++) {
|
|
5997
|
+
this.stream.readShort();
|
|
5998
|
+
}
|
|
5999
|
+
}
|
|
6000
|
+
parseSound() {
|
|
6001
|
+
const flags = this.stream.readByte();
|
|
6002
|
+
const soundNum = this.stream.readByte();
|
|
6003
|
+
if (flags & 1) {
|
|
6004
|
+
this.stream.readByte();
|
|
6005
|
+
}
|
|
6006
|
+
if (flags & 2) {
|
|
6007
|
+
this.stream.readByte();
|
|
6008
|
+
}
|
|
6009
|
+
if (flags & 16) {
|
|
6010
|
+
this.stream.readByte();
|
|
6011
|
+
}
|
|
6012
|
+
if (flags & 8) {
|
|
6013
|
+
this.stream.readShort();
|
|
6014
|
+
}
|
|
6015
|
+
if (flags & 4) {
|
|
6016
|
+
const pos = { x: 0, y: 0, z: 0 };
|
|
6017
|
+
this.stream.readPos(pos);
|
|
6018
|
+
}
|
|
6019
|
+
}
|
|
6020
|
+
parseMuzzleFlash() {
|
|
6021
|
+
const ent = this.stream.readShort();
|
|
6022
|
+
const weapon = this.stream.readByte();
|
|
6023
|
+
}
|
|
6024
|
+
parseMuzzleFlash2() {
|
|
6025
|
+
const ent = this.stream.readShort();
|
|
6026
|
+
const weapon = this.stream.readByte();
|
|
6027
|
+
}
|
|
6028
|
+
parseTempEntity() {
|
|
6029
|
+
const type = this.stream.readByte();
|
|
6030
|
+
const pos = { x: 0, y: 0, z: 0 };
|
|
6031
|
+
const pos2 = { x: 0, y: 0, z: 0 };
|
|
6032
|
+
const dir = { x: 0, y: 0, z: 0 };
|
|
6033
|
+
switch (type) {
|
|
6034
|
+
case TempEntity.BLOOD:
|
|
6035
|
+
this.stream.readPos(pos);
|
|
6036
|
+
this.stream.readDir(dir);
|
|
6037
|
+
break;
|
|
6038
|
+
case TempEntity.GUNSHOT:
|
|
6039
|
+
case TempEntity.SPARKS:
|
|
6040
|
+
case TempEntity.BULLET_SPARKS:
|
|
6041
|
+
this.stream.readPos(pos);
|
|
6042
|
+
this.stream.readDir(dir);
|
|
6043
|
+
break;
|
|
6044
|
+
case TempEntity.SCREEN_SPARKS:
|
|
6045
|
+
case TempEntity.SHIELD_SPARKS:
|
|
6046
|
+
this.stream.readPos(pos);
|
|
6047
|
+
this.stream.readDir(dir);
|
|
6048
|
+
break;
|
|
6049
|
+
case TempEntity.SHOTGUN:
|
|
6050
|
+
this.stream.readPos(pos);
|
|
6051
|
+
this.stream.readDir(dir);
|
|
6052
|
+
break;
|
|
6053
|
+
case TempEntity.SPLASH:
|
|
6054
|
+
this.stream.readByte();
|
|
6055
|
+
this.stream.readPos(pos);
|
|
6056
|
+
this.stream.readDir(dir);
|
|
6057
|
+
this.stream.readByte();
|
|
6058
|
+
break;
|
|
6059
|
+
case TempEntity.LASER_SPARKS:
|
|
6060
|
+
this.stream.readByte();
|
|
6061
|
+
this.stream.readPos(pos);
|
|
6062
|
+
this.stream.readDir(dir);
|
|
6063
|
+
this.stream.readByte();
|
|
6064
|
+
break;
|
|
6065
|
+
case TempEntity.BLUEHYPERBLASTER:
|
|
6066
|
+
this.stream.readPos(pos);
|
|
6067
|
+
this.stream.readPos(dir);
|
|
6068
|
+
break;
|
|
6069
|
+
case TempEntity.BLASTER:
|
|
6070
|
+
this.stream.readPos(pos);
|
|
6071
|
+
this.stream.readDir(dir);
|
|
6072
|
+
break;
|
|
6073
|
+
case TempEntity.RAILTRAIL:
|
|
6074
|
+
this.stream.readPos(pos);
|
|
6075
|
+
this.stream.readPos(pos2);
|
|
6076
|
+
break;
|
|
6077
|
+
case TempEntity.EXPLOSION2:
|
|
6078
|
+
case TempEntity.GRENADE_EXPLOSION:
|
|
6079
|
+
case TempEntity.GRENADE_EXPLOSION_WATER:
|
|
6080
|
+
this.stream.readPos(pos);
|
|
6081
|
+
break;
|
|
6082
|
+
case TempEntity.PLASMA_EXPLOSION:
|
|
6083
|
+
this.stream.readPos(pos);
|
|
6084
|
+
break;
|
|
6085
|
+
case TempEntity.EXPLOSION1:
|
|
6086
|
+
case TempEntity.EXPLOSION1_BIG:
|
|
6087
|
+
case TempEntity.ROCKET_EXPLOSION:
|
|
6088
|
+
case TempEntity.ROCKET_EXPLOSION_WATER:
|
|
6089
|
+
case TempEntity.EXPLOSION1_NP:
|
|
6090
|
+
this.stream.readPos(pos);
|
|
6091
|
+
break;
|
|
6092
|
+
case TempEntity.BFG_EXPLOSION:
|
|
6093
|
+
this.stream.readPos(pos);
|
|
6094
|
+
break;
|
|
6095
|
+
case TempEntity.BFG_BIGEXPLOSION:
|
|
6096
|
+
this.stream.readPos(pos);
|
|
6097
|
+
break;
|
|
6098
|
+
case TempEntity.BFG_LASER:
|
|
6099
|
+
this.stream.readPos(pos);
|
|
6100
|
+
this.stream.readPos(pos2);
|
|
6101
|
+
break;
|
|
6102
|
+
case TempEntity.BUBBLETRAIL:
|
|
6103
|
+
this.stream.readPos(pos);
|
|
6104
|
+
this.stream.readPos(pos2);
|
|
6105
|
+
break;
|
|
6106
|
+
case TempEntity.PARASITE_ATTACK:
|
|
6107
|
+
case TempEntity.MEDIC_CABLE_ATTACK:
|
|
6108
|
+
this.stream.readShort();
|
|
6109
|
+
this.stream.readPos(pos);
|
|
6110
|
+
this.stream.readPos(pos2);
|
|
6111
|
+
break;
|
|
6112
|
+
case TempEntity.BOSSTPORT:
|
|
6113
|
+
this.stream.readPos(pos);
|
|
6114
|
+
break;
|
|
6115
|
+
case TempEntity.GRAPPLE_CABLE:
|
|
6116
|
+
this.stream.readShort();
|
|
6117
|
+
this.stream.readPos(pos);
|
|
6118
|
+
this.stream.readPos(pos2);
|
|
6119
|
+
this.stream.readPos(dir);
|
|
6120
|
+
break;
|
|
6121
|
+
case TempEntity.WELDING_SPARKS:
|
|
6122
|
+
this.stream.readByte();
|
|
6123
|
+
this.stream.readPos(pos);
|
|
6124
|
+
this.stream.readDir(dir);
|
|
6125
|
+
this.stream.readByte();
|
|
6126
|
+
break;
|
|
6127
|
+
case TempEntity.GREENBLOOD:
|
|
6128
|
+
this.stream.readPos(pos);
|
|
6129
|
+
this.stream.readDir(dir);
|
|
6130
|
+
break;
|
|
6131
|
+
case TempEntity.TUNNEL_SPARKS:
|
|
6132
|
+
this.stream.readByte();
|
|
6133
|
+
this.stream.readPos(pos);
|
|
6134
|
+
this.stream.readDir(dir);
|
|
6135
|
+
this.stream.readByte();
|
|
6136
|
+
break;
|
|
6137
|
+
case TempEntity.BLASTER2:
|
|
6138
|
+
case TempEntity.FLECHETTE:
|
|
6139
|
+
this.stream.readPos(pos);
|
|
6140
|
+
this.stream.readDir(dir);
|
|
6141
|
+
break;
|
|
6142
|
+
case TempEntity.LIGHTNING:
|
|
6143
|
+
this.stream.readShort();
|
|
6144
|
+
this.stream.readShort();
|
|
6145
|
+
this.stream.readPos(pos);
|
|
6146
|
+
this.stream.readPos(pos2);
|
|
6147
|
+
break;
|
|
6148
|
+
case TempEntity.DEBUGTRAIL:
|
|
6149
|
+
this.stream.readPos(pos);
|
|
6150
|
+
this.stream.readPos(pos2);
|
|
6151
|
+
break;
|
|
6152
|
+
case TempEntity.PLAIN_EXPLOSION:
|
|
6153
|
+
this.stream.readPos(pos);
|
|
6154
|
+
break;
|
|
6155
|
+
case TempEntity.FLASHLIGHT:
|
|
6156
|
+
this.stream.readPos(pos);
|
|
6157
|
+
this.stream.readShort();
|
|
6158
|
+
break;
|
|
6159
|
+
case TempEntity.FORCEWALL:
|
|
6160
|
+
this.stream.readPos(pos);
|
|
6161
|
+
this.stream.readPos(pos2);
|
|
6162
|
+
this.stream.readByte();
|
|
6163
|
+
break;
|
|
6164
|
+
case TempEntity.HEATBEAM:
|
|
6165
|
+
this.stream.readShort();
|
|
6166
|
+
this.stream.readPos(pos);
|
|
6167
|
+
this.stream.readPos(pos2);
|
|
6168
|
+
this.stream.readPos(dir);
|
|
6169
|
+
break;
|
|
6170
|
+
case TempEntity.MONSTER_HEATBEAM:
|
|
6171
|
+
this.stream.readShort();
|
|
6172
|
+
this.stream.readPos(pos);
|
|
6173
|
+
this.stream.readPos(pos2);
|
|
6174
|
+
this.stream.readPos(dir);
|
|
6175
|
+
break;
|
|
6176
|
+
case TempEntity.HEATBEAM_SPARKS:
|
|
6177
|
+
this.stream.readPos(pos);
|
|
6178
|
+
this.stream.readDir(dir);
|
|
6179
|
+
break;
|
|
6180
|
+
case TempEntity.HEATBEAM_STEAM:
|
|
6181
|
+
this.stream.readPos(pos);
|
|
6182
|
+
this.stream.readDir(dir);
|
|
6183
|
+
break;
|
|
6184
|
+
case TempEntity.STEAM:
|
|
6185
|
+
const steamId = this.stream.readShort();
|
|
6186
|
+
if (steamId !== -1) {
|
|
6187
|
+
this.stream.readByte();
|
|
6188
|
+
this.stream.readPos(pos);
|
|
6189
|
+
this.stream.readDir(dir);
|
|
6190
|
+
this.stream.readByte();
|
|
6191
|
+
this.stream.readShort();
|
|
6192
|
+
this.stream.readLong();
|
|
6193
|
+
} else {
|
|
6194
|
+
this.stream.readByte();
|
|
6195
|
+
this.stream.readPos(pos);
|
|
6196
|
+
this.stream.readDir(dir);
|
|
6197
|
+
this.stream.readByte();
|
|
6198
|
+
this.stream.readShort();
|
|
6199
|
+
}
|
|
6200
|
+
break;
|
|
6201
|
+
case TempEntity.BUBBLETRAIL2:
|
|
6202
|
+
this.stream.readPos(pos);
|
|
6203
|
+
this.stream.readPos(pos2);
|
|
6204
|
+
break;
|
|
6205
|
+
case TempEntity.MOREBLOOD:
|
|
6206
|
+
this.stream.readPos(pos);
|
|
6207
|
+
this.stream.readDir(dir);
|
|
6208
|
+
break;
|
|
6209
|
+
case TempEntity.CHAINFIST_SMOKE:
|
|
6210
|
+
this.stream.readPos(pos);
|
|
6211
|
+
break;
|
|
6212
|
+
case TempEntity.ELECTRIC_SPARKS:
|
|
6213
|
+
this.stream.readPos(pos);
|
|
6214
|
+
this.stream.readDir(dir);
|
|
6215
|
+
break;
|
|
6216
|
+
case TempEntity.TRACKER_EXPLOSION:
|
|
6217
|
+
this.stream.readPos(pos);
|
|
6218
|
+
break;
|
|
6219
|
+
case TempEntity.TELEPORT_EFFECT:
|
|
6220
|
+
case TempEntity.DBALL_GOAL:
|
|
6221
|
+
this.stream.readPos(pos);
|
|
6222
|
+
break;
|
|
6223
|
+
case TempEntity.WIDOWBEAMOUT:
|
|
6224
|
+
const wbId = this.stream.readShort();
|
|
6225
|
+
this.stream.readPos(pos);
|
|
6226
|
+
break;
|
|
6227
|
+
case TempEntity.NUKEBLAST:
|
|
6228
|
+
this.stream.readPos(pos);
|
|
6229
|
+
break;
|
|
6230
|
+
case TempEntity.WIDOWSPLASH:
|
|
6231
|
+
this.stream.readPos(pos);
|
|
6232
|
+
break;
|
|
6233
|
+
default:
|
|
6234
|
+
console.warn(`CL_ParseTEnt: bad type ${type}`);
|
|
6235
|
+
break;
|
|
6236
|
+
}
|
|
6237
|
+
}
|
|
6238
|
+
parseSpawnBaseline() {
|
|
6239
|
+
const bits = this.parseEntityBits();
|
|
6240
|
+
this.parseDelta(createEmptyEntityState(), createEmptyEntityState(), bits.number, bits.bits);
|
|
6241
|
+
}
|
|
6242
|
+
parseFrame() {
|
|
6243
|
+
const serverFrame = this.stream.readLong();
|
|
6244
|
+
const deltaFrame = this.stream.readLong();
|
|
6245
|
+
const surpressCount = this.stream.readByte();
|
|
6246
|
+
const areaBytes = this.stream.readByte();
|
|
6247
|
+
this.stream.readData(areaBytes);
|
|
6248
|
+
const piCmd = this.stream.readByte();
|
|
6249
|
+
if (piCmd !== ServerCommand.playerinfo) {
|
|
6250
|
+
throw new Error(`Expected svc_playerinfo after svc_frame, got ${piCmd}`);
|
|
6251
|
+
}
|
|
6252
|
+
this.parsePlayerState();
|
|
6253
|
+
const peCmd = this.stream.readByte();
|
|
6254
|
+
if (peCmd !== ServerCommand.packetentities && peCmd !== ServerCommand.deltapacketentities) {
|
|
6255
|
+
throw new Error(`Expected svc_packetentities after svc_playerinfo, got ${peCmd}`);
|
|
6256
|
+
}
|
|
6257
|
+
this.parsePacketEntities(peCmd === ServerCommand.deltapacketentities);
|
|
6258
|
+
}
|
|
6259
|
+
parsePlayerState() {
|
|
6260
|
+
const flags = this.stream.readShort();
|
|
6261
|
+
if (flags & 1) this.stream.readByte();
|
|
6262
|
+
if (flags & 2) {
|
|
6263
|
+
this.stream.readShort();
|
|
6264
|
+
this.stream.readShort();
|
|
6265
|
+
this.stream.readShort();
|
|
6266
|
+
}
|
|
6267
|
+
if (flags & 4) {
|
|
6268
|
+
this.stream.readShort();
|
|
6269
|
+
this.stream.readShort();
|
|
6270
|
+
this.stream.readShort();
|
|
6271
|
+
}
|
|
6272
|
+
if (flags & 8) this.stream.readByte();
|
|
6273
|
+
if (flags & 16) this.stream.readByte();
|
|
6274
|
+
if (flags & 32) this.stream.readShort();
|
|
6275
|
+
if (flags & 64) {
|
|
6276
|
+
this.stream.readShort();
|
|
6277
|
+
this.stream.readShort();
|
|
6278
|
+
this.stream.readShort();
|
|
6279
|
+
}
|
|
6280
|
+
if (flags & 128) {
|
|
6281
|
+
this.stream.readChar();
|
|
6282
|
+
this.stream.readChar();
|
|
6283
|
+
this.stream.readChar();
|
|
6284
|
+
}
|
|
6285
|
+
if (flags & 256) {
|
|
6286
|
+
this.stream.readAngle16();
|
|
6287
|
+
this.stream.readAngle16();
|
|
6288
|
+
this.stream.readAngle16();
|
|
6289
|
+
}
|
|
6290
|
+
if (flags & 512) {
|
|
6291
|
+
this.stream.readChar();
|
|
6292
|
+
this.stream.readChar();
|
|
6293
|
+
this.stream.readChar();
|
|
6294
|
+
}
|
|
6295
|
+
if (flags & 4096) this.stream.readByte();
|
|
6296
|
+
if (flags & 8192) {
|
|
6297
|
+
this.stream.readByte();
|
|
6298
|
+
this.stream.readChar();
|
|
6299
|
+
this.stream.readChar();
|
|
6300
|
+
this.stream.readChar();
|
|
6301
|
+
this.stream.readChar();
|
|
6302
|
+
this.stream.readChar();
|
|
6303
|
+
this.stream.readChar();
|
|
6304
|
+
}
|
|
6305
|
+
if (flags & 1024) {
|
|
6306
|
+
this.stream.readByte();
|
|
6307
|
+
this.stream.readByte();
|
|
6308
|
+
this.stream.readByte();
|
|
6309
|
+
this.stream.readByte();
|
|
6310
|
+
}
|
|
6311
|
+
if (flags & 2048) this.stream.readByte();
|
|
6312
|
+
if (flags & 16384) this.stream.readByte();
|
|
6313
|
+
const statbits = this.stream.readLong();
|
|
6314
|
+
for (let i = 0; i < 32; i++) {
|
|
6315
|
+
if (statbits & 1 << i) {
|
|
6316
|
+
this.stream.readShort();
|
|
6317
|
+
}
|
|
6318
|
+
}
|
|
6319
|
+
}
|
|
6320
|
+
parsePacketEntities(delta) {
|
|
6321
|
+
while (true) {
|
|
6322
|
+
const bits = this.parseEntityBits();
|
|
6323
|
+
if (bits.number === 0) {
|
|
6324
|
+
break;
|
|
6325
|
+
}
|
|
6326
|
+
this.parseDelta(createEmptyEntityState(), createEmptyEntityState(), bits.number, bits.bits);
|
|
6327
|
+
}
|
|
6328
|
+
}
|
|
6329
|
+
parseEntityBits() {
|
|
6330
|
+
let total = this.stream.readByte();
|
|
6331
|
+
if (total & U_MOREBITS1) {
|
|
6332
|
+
total |= this.stream.readByte() << 8;
|
|
6333
|
+
}
|
|
6334
|
+
if (total & U_MOREBITS2) {
|
|
6335
|
+
total |= this.stream.readByte() << 16;
|
|
6336
|
+
}
|
|
6337
|
+
if (total & U_MOREBITS3) {
|
|
6338
|
+
total |= this.stream.readByte() << 24;
|
|
6339
|
+
}
|
|
6340
|
+
let number;
|
|
6341
|
+
if (total & U_NUMBER16) {
|
|
6342
|
+
number = this.stream.readShort();
|
|
6343
|
+
} else {
|
|
6344
|
+
number = this.stream.readByte();
|
|
6345
|
+
}
|
|
6346
|
+
return { number, bits: total };
|
|
6347
|
+
}
|
|
6348
|
+
parseDelta(from, to, number, bits) {
|
|
6349
|
+
to.number = from.number;
|
|
6350
|
+
to.modelindex = from.modelindex;
|
|
6351
|
+
to.modelindex2 = from.modelindex2;
|
|
6352
|
+
to.modelindex3 = from.modelindex3;
|
|
6353
|
+
to.modelindex4 = from.modelindex4;
|
|
6354
|
+
to.frame = from.frame;
|
|
6355
|
+
to.skinnum = from.skinnum;
|
|
6356
|
+
to.effects = from.effects;
|
|
6357
|
+
to.renderfx = from.renderfx;
|
|
6358
|
+
to.origin.x = from.origin.x;
|
|
6359
|
+
to.origin.y = from.origin.y;
|
|
6360
|
+
to.origin.z = from.origin.z;
|
|
6361
|
+
to.old_origin.x = from.origin.x;
|
|
6362
|
+
to.old_origin.y = from.origin.y;
|
|
6363
|
+
to.old_origin.z = from.origin.z;
|
|
6364
|
+
to.angles.x = from.angles.x;
|
|
6365
|
+
to.angles.y = from.angles.y;
|
|
6366
|
+
to.angles.z = from.angles.z;
|
|
6367
|
+
to.sound = from.sound;
|
|
6368
|
+
to.event = from.event;
|
|
6369
|
+
to.solid = from.solid;
|
|
6370
|
+
to.number = number;
|
|
6371
|
+
if (bits & U_MODEL) to.modelindex = this.stream.readByte();
|
|
6372
|
+
if (bits & U_MODEL2) to.modelindex2 = this.stream.readByte();
|
|
6373
|
+
if (bits & U_MODEL3) to.modelindex3 = this.stream.readByte();
|
|
6374
|
+
if (bits & U_MODEL4) to.modelindex4 = this.stream.readByte();
|
|
6375
|
+
if (bits & U_FRAME8) to.frame = this.stream.readByte();
|
|
6376
|
+
if (bits & U_FRAME16) to.frame = this.stream.readShort();
|
|
6377
|
+
if (bits & U_SKIN8 && bits & U_SKIN16) {
|
|
6378
|
+
to.skinnum = this.stream.readLong();
|
|
6379
|
+
} else if (bits & U_SKIN8) {
|
|
6380
|
+
to.skinnum = this.stream.readByte();
|
|
6381
|
+
} else if (bits & U_SKIN16) {
|
|
6382
|
+
to.skinnum = this.stream.readShort();
|
|
6383
|
+
}
|
|
6384
|
+
if (bits & U_EFFECTS8 && bits & U_EFFECTS16) {
|
|
6385
|
+
to.effects = this.stream.readLong();
|
|
6386
|
+
} else if (bits & U_EFFECTS8) {
|
|
6387
|
+
to.effects = this.stream.readByte();
|
|
6388
|
+
} else if (bits & U_EFFECTS16) {
|
|
6389
|
+
to.effects = this.stream.readShort();
|
|
6390
|
+
}
|
|
6391
|
+
if (bits & U_RENDERFX8 && bits & U_RENDERFX16) {
|
|
6392
|
+
to.renderfx = this.stream.readLong();
|
|
6393
|
+
} else if (bits & U_RENDERFX8) {
|
|
6394
|
+
to.renderfx = this.stream.readByte();
|
|
6395
|
+
} else if (bits & U_RENDERFX16) {
|
|
6396
|
+
to.renderfx = this.stream.readShort();
|
|
6397
|
+
}
|
|
6398
|
+
if (bits & U_ORIGIN1) to.origin.x = this.stream.readCoord();
|
|
6399
|
+
if (bits & U_ORIGIN2) to.origin.y = this.stream.readCoord();
|
|
6400
|
+
if (bits & U_ORIGIN3) to.origin.z = this.stream.readCoord();
|
|
6401
|
+
if (bits & U_ANGLE1) to.angles.x = this.stream.readAngle();
|
|
6402
|
+
if (bits & U_ANGLE2) to.angles.y = this.stream.readAngle();
|
|
6403
|
+
if (bits & U_ANGLE3) to.angles.z = this.stream.readAngle();
|
|
6404
|
+
if (bits & U_OLDORIGIN) {
|
|
6405
|
+
this.stream.readPos(to.old_origin);
|
|
6406
|
+
}
|
|
6407
|
+
if (bits & U_SOUND) to.sound = this.stream.readByte();
|
|
6408
|
+
if (bits & U_EVENT) {
|
|
6409
|
+
to.event = this.stream.readByte();
|
|
6410
|
+
} else {
|
|
6411
|
+
to.event = 0;
|
|
6412
|
+
}
|
|
6413
|
+
if (bits & U_SOLID) to.solid = this.stream.readShort();
|
|
6414
|
+
}
|
|
6415
|
+
};
|
|
6416
|
+
|
|
6417
|
+
// src/demo/playback.ts
|
|
6418
|
+
var PlaybackState = /* @__PURE__ */ ((PlaybackState2) => {
|
|
6419
|
+
PlaybackState2[PlaybackState2["Stopped"] = 0] = "Stopped";
|
|
6420
|
+
PlaybackState2[PlaybackState2["Playing"] = 1] = "Playing";
|
|
6421
|
+
PlaybackState2[PlaybackState2["Paused"] = 2] = "Paused";
|
|
6422
|
+
PlaybackState2[PlaybackState2["Finished"] = 3] = "Finished";
|
|
6423
|
+
return PlaybackState2;
|
|
6424
|
+
})(PlaybackState || {});
|
|
6425
|
+
var DemoPlaybackController = class {
|
|
6426
|
+
// ms (10Hz default)
|
|
6427
|
+
constructor() {
|
|
6428
|
+
this.reader = null;
|
|
6429
|
+
this.state = 0 /* Stopped */;
|
|
6430
|
+
this.playbackSpeed = 1;
|
|
6431
|
+
// Timing
|
|
6432
|
+
this.accumulatedTime = 0;
|
|
6433
|
+
this.frameDuration = 100;
|
|
6434
|
+
}
|
|
6435
|
+
loadDemo(buffer) {
|
|
6436
|
+
this.reader = new DemoReader(buffer);
|
|
6437
|
+
this.state = 0 /* Stopped */;
|
|
6438
|
+
this.accumulatedTime = 0;
|
|
6439
|
+
}
|
|
6440
|
+
play() {
|
|
6441
|
+
if (this.reader) {
|
|
6442
|
+
this.state = 1 /* Playing */;
|
|
6443
|
+
}
|
|
6444
|
+
}
|
|
6445
|
+
pause() {
|
|
6446
|
+
if (this.state === 1 /* Playing */) {
|
|
6447
|
+
this.state = 2 /* Paused */;
|
|
6448
|
+
}
|
|
6449
|
+
}
|
|
6450
|
+
stop() {
|
|
6451
|
+
this.state = 0 /* Stopped */;
|
|
6452
|
+
if (this.reader) {
|
|
6453
|
+
this.reader.reset();
|
|
6454
|
+
}
|
|
6455
|
+
this.accumulatedTime = 0;
|
|
6456
|
+
}
|
|
6457
|
+
update(dt) {
|
|
6458
|
+
if (this.state !== 1 /* Playing */ || !this.reader) {
|
|
6459
|
+
return;
|
|
6460
|
+
}
|
|
6461
|
+
this.accumulatedTime += dt * 1e3 * this.playbackSpeed;
|
|
6462
|
+
while (this.accumulatedTime >= this.frameDuration) {
|
|
6463
|
+
if (!this.reader.hasMore()) {
|
|
6464
|
+
this.state = 3 /* Finished */;
|
|
6465
|
+
return;
|
|
6466
|
+
}
|
|
6467
|
+
const block = this.reader.readNextBlock();
|
|
6468
|
+
if (!block) {
|
|
6469
|
+
this.state = 3 /* Finished */;
|
|
6470
|
+
return;
|
|
6471
|
+
}
|
|
6472
|
+
const parser = new NetworkMessageParser(block.data);
|
|
6473
|
+
parser.parseMessage();
|
|
6474
|
+
this.accumulatedTime -= this.frameDuration;
|
|
6475
|
+
}
|
|
6476
|
+
}
|
|
6477
|
+
getState() {
|
|
6478
|
+
return this.state;
|
|
6479
|
+
}
|
|
6480
|
+
};
|
|
6481
|
+
|
|
5611
6482
|
// src/index.ts
|
|
5612
6483
|
function createEngine(imports) {
|
|
5613
6484
|
return {
|
|
@@ -5646,6 +6517,8 @@ function createEngine(imports) {
|
|
|
5646
6517
|
ConfigStringRegistry,
|
|
5647
6518
|
Cvar,
|
|
5648
6519
|
CvarRegistry,
|
|
6520
|
+
DemoPlaybackController,
|
|
6521
|
+
DemoReader,
|
|
5649
6522
|
EngineHost,
|
|
5650
6523
|
EngineRuntime,
|
|
5651
6524
|
FixedTimestepLoop,
|
|
@@ -5667,6 +6540,7 @@ function createEngine(imports) {
|
|
|
5667
6540
|
Md3Pipeline,
|
|
5668
6541
|
Md3SurfaceMesh,
|
|
5669
6542
|
MusicSystem,
|
|
6543
|
+
NetworkMessageParser,
|
|
5670
6544
|
PARTICLE_FRAGMENT_SHADER,
|
|
5671
6545
|
PARTICLE_VERTEX_SHADER,
|
|
5672
6546
|
PakArchive,
|
|
@@ -5677,6 +6551,7 @@ function createEngine(imports) {
|
|
|
5677
6551
|
PakValidator,
|
|
5678
6552
|
ParticleRenderer,
|
|
5679
6553
|
ParticleSystem,
|
|
6554
|
+
PlaybackState,
|
|
5680
6555
|
RERELEASE_KNOWN_PAKS,
|
|
5681
6556
|
SKYBOX_FRAGMENT_SHADER,
|
|
5682
6557
|
SKYBOX_VERTEX_SHADER,
|