@quake2ts/engine 0.0.753 → 0.0.756

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/dist/esm/index.js CHANGED
@@ -1,5 +1,5 @@
1
- import { ServerCommand, SURF_NONE, CvarFlags, ConfigStringIndex, MAX_CONFIGSTRINGS, MAX_MODELS, MAX_SOUNDS, MAX_IMAGES, MAX_LIGHTSTYLES, MAX_SHADOW_LIGHTS, MAX_ITEMS, MAX_CLIENTS, MAX_GENERAL, MAX_SOUND_CHANNELS, SoundChannel, ZERO_VEC3, ATTN_NONE, attenuationToDistanceMultiplier, SOUND_FULLVOLUME, calculateMaxAudibleDistance, lengthVec3, subtractVec3, RAD2DEG, DEG2RAD, normalizeVec3 as normalizeVec3$1, mat4FromBasis, BinaryStream, ANORMS, TempEntity, BinaryWriter, NetChan, crc8, CMD_BACKUP, ClientCommand, writeUserCommand, NetworkMessageBuilder, SURF_FLOWING, SURF_WARP, SURF_SKY, SURF_TRANS33, SURF_TRANS66, configStringSize, CS_MAX_STRING_LENGTH, transformPointMat4 } from '@quake2ts/shared';
2
- export { ATTN_IDLE, ATTN_LOOP_NONE, ATTN_NONE, ATTN_NORM, ATTN_STATIC, MAX_SOUND_CHANNELS, SOUND_FULLVOLUME, SOUND_LOOP_ATTENUATE, SoundChannel, attenuationToDistanceMultiplier, calculateMaxAudibleDistance } from '@quake2ts/shared';
1
+ import { ServerCommand, SURF_NONE, CvarFlags, ConfigStringIndex, MAX_CONFIGSTRINGS, MAX_MODELS, MAX_SOUNDS, MAX_IMAGES, MAX_LIGHTSTYLES, MAX_SHADOW_LIGHTS, MAX_ITEMS, MAX_CLIENTS, MAX_GENERAL, MAX_SOUND_CHANNELS, SoundChannel, ZERO_VEC3, ATTN_NONE, attenuationToDistanceMultiplier, SOUND_FULLVOLUME, calculateMaxAudibleDistance, lengthVec3, subtractVec3, RAD2DEG, DEG2RAD, normalizeVec3 as normalizeVec3$1, mat4FromBasis, BinaryStream, ANORMS, TempEntity, U_REMOVE, BinaryWriter, U_MOREBITS1, U_MOREBITS2, U_MOREBITS3, U_MOREBITS4, U_MODEL, U_MODEL2, U_MODEL3, U_MODEL4, U_FRAME8, U_FRAME16, U_SKIN8, U_SKIN16, U_EFFECTS8, U_EFFECTS16, U_RENDERFX8, U_RENDERFX16, U_ORIGIN1, U_ORIGIN2, U_ORIGIN3, U_ANGLE1, U_ANGLE2, U_ANGLE3, U_SOUND, U_EVENT, U_SOLID, U_ALPHA, U_SCALE, U_INSTANCE_BITS, U_LOOP_VOLUME, U_LOOP_ATTENUATION_HIGH, U_OWNER_HIGH, U_OLD_FRAME_HIGH, U_OLDORIGIN, NetChan, crc8, CMD_BACKUP, ClientCommand, writeUserCommand, NetworkMessageBuilder, SURF_FLOWING, SURF_WARP, SURF_SKY, SURF_TRANS33, SURF_TRANS66, configStringSize, CS_MAX_STRING_LENGTH, transformPointMat4, U_NUMBER16 } from '@quake2ts/shared';
2
+ export { ATTN_IDLE, ATTN_LOOP_NONE, ATTN_NONE, ATTN_NORM, ATTN_STATIC, MAX_SOUND_CHANNELS, SOUND_FULLVOLUME, SOUND_LOOP_ATTENUATE, SoundChannel, U_ALPHA, U_ANGLE1, U_ANGLE2, U_ANGLE3, U_EFFECTS16, U_EFFECTS8, U_EVENT, U_FRAME16, U_FRAME8, U_INSTANCE_BITS, U_LOOP_ATTENUATION_HIGH, U_LOOP_VOLUME, U_MODEL, U_MODEL2, U_MODEL3, U_MODEL4, U_OLDORIGIN, U_OLD_FRAME_HIGH, U_ORIGIN1, U_ORIGIN2, U_ORIGIN3, U_OWNER_HIGH, U_REMOVE, U_RENDERFX16, U_RENDERFX8, U_SCALE, U_SKIN16, U_SKIN8, U_SOLID, U_SOUND, attenuationToDistanceMultiplier, calculateMaxAudibleDistance } from '@quake2ts/shared';
3
3
  import { OggVorbisDecoder } from '@wasm-audio-decoders/ogg-vorbis';
4
4
  import { vec3, mat4 } from 'gl-matrix';
5
5
 
@@ -12010,46 +12010,7 @@ _StreamingBuffer.INITIAL_SIZE = 64 * 1024;
12010
12010
  _StreamingBuffer.MAX_STRING_LENGTH = 2048;
12011
12011
  var StreamingBuffer = _StreamingBuffer;
12012
12012
 
12013
- // src/demo/parser.ts
12014
- var PROTOCOL_VERSION_RERELEASE = 2023;
12015
- var U_ORIGIN1 = 1 << 0;
12016
- var U_ORIGIN2 = 1 << 1;
12017
- var U_ANGLE2 = 1 << 2;
12018
- var U_ANGLE3 = 1 << 3;
12019
- var U_FRAME8 = 1 << 4;
12020
- var U_EVENT = 1 << 5;
12021
- var U_REMOVE = 1 << 6;
12022
- var U_MOREBITS1 = 1 << 7;
12023
- var U_NUMBER16 = 1 << 8;
12024
- var U_ORIGIN3 = 1 << 9;
12025
- var U_ANGLE1 = 1 << 10;
12026
- var U_MODEL = 1 << 11;
12027
- var U_RENDERFX8 = 1 << 12;
12028
- var U_ALPHA = 1 << 13;
12029
- var U_EFFECTS8 = 1 << 14;
12030
- var U_MOREBITS2 = 1 << 15;
12031
- var U_SKIN8 = 1 << 16;
12032
- var U_FRAME16 = 1 << 17;
12033
- var U_RENDERFX16 = 1 << 18;
12034
- var U_EFFECTS16 = 1 << 19;
12035
- var U_MODEL2 = 1 << 20;
12036
- var U_MODEL3 = 1 << 21;
12037
- var U_MODEL4 = 1 << 22;
12038
- var U_MOREBITS3 = 1 << 23;
12039
- var U_OLDORIGIN = 1 << 24;
12040
- var U_SKIN16 = 1 << 25;
12041
- var U_SOUND = 1 << 26;
12042
- var U_SOLID = 1 << 27;
12043
- var U_SCALE = 1 << 28;
12044
- var U_INSTANCE_BITS = 1 << 29;
12045
- var U_LOOP_VOLUME = 1 << 30;
12046
- var U_MOREBITS4 = 2147483648 | 0;
12047
- var U_LOOP_ATTENUATION_HIGH = 1 << 0;
12048
- var U_OWNER_HIGH = 1 << 1;
12049
- var U_OLD_FRAME_HIGH = 1 << 2;
12050
- var RECORD_CLIENT = 1;
12051
- var RECORD_SERVER = 2;
12052
- var RECORD_RELAY = 128;
12013
+ // src/demo/state.ts
12053
12014
  var createEmptyEntityState = () => ({
12054
12015
  number: 0,
12055
12016
  modelindex: 0,
@@ -12101,6 +12062,575 @@ var createEmptyProtocolPlayerState = () => ({
12101
12062
  team_id: 0,
12102
12063
  watertype: 0
12103
12064
  });
12065
+
12066
+ // src/demo/protocol/quake2.ts
12067
+ var PROTO34_MAP = {
12068
+ 0: ServerCommand.bad,
12069
+ 1: ServerCommand.nop,
12070
+ 2: ServerCommand.disconnect,
12071
+ 3: ServerCommand.reconnect,
12072
+ 4: ServerCommand.download,
12073
+ 5: ServerCommand.frame,
12074
+ 6: ServerCommand.inventory,
12075
+ 7: ServerCommand.layout,
12076
+ 8: ServerCommand.muzzleflash,
12077
+ 9: ServerCommand.temp_entity,
12078
+ 10: ServerCommand.sound,
12079
+ 11: ServerCommand.print,
12080
+ 12: ServerCommand.stufftext,
12081
+ 13: ServerCommand.serverdata,
12082
+ 14: ServerCommand.configstring,
12083
+ 15: ServerCommand.spawnbaseline,
12084
+ 16: ServerCommand.centerprint,
12085
+ 17: ServerCommand.playerinfo,
12086
+ 18: ServerCommand.packetentities,
12087
+ 19: ServerCommand.deltapacketentities,
12088
+ 20: ServerCommand.muzzleflash2
12089
+ };
12090
+ var Quake2ProtocolHandler = class {
12091
+ constructor() {
12092
+ this.protocolVersion = 34;
12093
+ }
12094
+ translateCommand(cmd) {
12095
+ if (PROTO34_MAP[cmd] !== void 0) {
12096
+ return PROTO34_MAP[cmd];
12097
+ }
12098
+ return ServerCommand.bad;
12099
+ }
12100
+ parseServerData(stream) {
12101
+ const protocol = stream.readLong();
12102
+ const serverCount = stream.readLong();
12103
+ const attractLoop = stream.readByte();
12104
+ const gameDir = stream.readString();
12105
+ const playerNum = stream.readShort();
12106
+ const levelName = stream.readString();
12107
+ return {
12108
+ protocol,
12109
+ serverCount,
12110
+ attractLoop,
12111
+ gameDir,
12112
+ playerNum,
12113
+ levelName
12114
+ };
12115
+ }
12116
+ parseEntityBits(stream) {
12117
+ let total = stream.readByte();
12118
+ if (total & U_MOREBITS1) total |= stream.readByte() << 8;
12119
+ if (total & U_MOREBITS2) total |= stream.readByte() << 16;
12120
+ if (total & U_MOREBITS3) total |= stream.readByte() << 24;
12121
+ let number;
12122
+ if (total & U_NUMBER16) number = stream.readShort();
12123
+ else number = stream.readByte();
12124
+ return { number, bits: total, bitsHigh: 0 };
12125
+ }
12126
+ parseDelta(from, to, number, bits, bitsHigh, stream) {
12127
+ to.number = from.number;
12128
+ to.modelindex = from.modelindex;
12129
+ to.modelindex2 = from.modelindex2;
12130
+ to.modelindex3 = from.modelindex3;
12131
+ to.modelindex4 = from.modelindex4;
12132
+ to.frame = from.frame;
12133
+ to.skinnum = from.skinnum;
12134
+ to.effects = from.effects;
12135
+ to.renderfx = from.renderfx;
12136
+ to.origin.x = from.origin.x;
12137
+ to.origin.y = from.origin.y;
12138
+ to.origin.z = from.origin.z;
12139
+ to.old_origin.x = from.origin.x;
12140
+ to.old_origin.y = from.origin.y;
12141
+ to.old_origin.z = from.origin.z;
12142
+ to.angles.x = from.angles.x;
12143
+ to.angles.y = from.angles.y;
12144
+ to.angles.z = from.angles.z;
12145
+ to.sound = from.sound;
12146
+ to.event = from.event;
12147
+ to.solid = from.solid;
12148
+ to.number = number;
12149
+ to.bits = bits;
12150
+ if (bits & U_MODEL) to.modelindex = stream.readByte();
12151
+ if (bits & U_MODEL2) to.modelindex2 = stream.readByte();
12152
+ if (bits & U_MODEL3) to.modelindex3 = stream.readByte();
12153
+ if (bits & U_MODEL4) to.modelindex4 = stream.readByte();
12154
+ if (bits & U_FRAME8) to.frame = stream.readByte();
12155
+ if (bits & U_FRAME16) to.frame = stream.readShort();
12156
+ if (bits & U_SKIN8 && bits & U_SKIN16) to.skinnum = stream.readLong();
12157
+ else if (bits & U_SKIN8) to.skinnum = stream.readByte();
12158
+ else if (bits & U_SKIN16) to.skinnum = stream.readShort();
12159
+ if (bits & U_EFFECTS8 && bits & U_EFFECTS16) to.effects = stream.readLong();
12160
+ else if (bits & U_EFFECTS8) to.effects = stream.readByte();
12161
+ else if (bits & U_EFFECTS16) to.effects = stream.readShort();
12162
+ if (bits & U_RENDERFX8 && bits & U_RENDERFX16) to.renderfx = stream.readLong();
12163
+ else if (bits & U_RENDERFX8) to.renderfx = stream.readByte();
12164
+ else if (bits & U_RENDERFX16) to.renderfx = stream.readShort();
12165
+ if (bits & U_ORIGIN1) to.origin.x = stream.readShort() * 0.125;
12166
+ if (bits & U_ORIGIN2) to.origin.y = stream.readShort() * 0.125;
12167
+ if (bits & U_ORIGIN3) to.origin.z = stream.readShort() * 0.125;
12168
+ if (bits & U_ANGLE1) to.angles.x = stream.readByte() * (360 / 256);
12169
+ if (bits & U_ANGLE2) to.angles.y = stream.readByte() * (360 / 256);
12170
+ if (bits & U_ANGLE3) to.angles.z = stream.readByte() * (360 / 256);
12171
+ if (bits & U_OLDORIGIN) {
12172
+ to.old_origin.x = stream.readShort() * 0.125;
12173
+ to.old_origin.y = stream.readShort() * 0.125;
12174
+ to.old_origin.z = stream.readShort() * 0.125;
12175
+ }
12176
+ if (bits & U_SOUND) to.sound = stream.readByte();
12177
+ if (bits & U_EVENT) to.event = stream.readByte();
12178
+ else to.event = 0;
12179
+ if (bits & U_SOLID) to.solid = stream.readShort();
12180
+ }
12181
+ parsePlayerState(stream) {
12182
+ const ps = createEmptyProtocolPlayerState();
12183
+ const flags = stream.readShort();
12184
+ if (flags & 1) ps.pm_type = stream.readByte();
12185
+ if (flags & 2) {
12186
+ ps.origin.x = stream.readShort() * 0.125;
12187
+ ps.origin.y = stream.readShort() * 0.125;
12188
+ ps.origin.z = stream.readShort() * 0.125;
12189
+ }
12190
+ if (flags & 4) {
12191
+ ps.velocity.x = stream.readShort() * 0.125;
12192
+ ps.velocity.y = stream.readShort() * 0.125;
12193
+ ps.velocity.z = stream.readShort() * 0.125;
12194
+ }
12195
+ if (flags & 8) ps.pm_time = stream.readByte();
12196
+ if (flags & 16) ps.pm_flags = stream.readByte();
12197
+ if (flags & 32) ps.gravity = stream.readShort();
12198
+ if (flags & 64) {
12199
+ ps.delta_angles.x = stream.readShort() * (180 / 32768);
12200
+ ps.delta_angles.y = stream.readShort() * (180 / 32768);
12201
+ ps.delta_angles.z = stream.readShort() * (180 / 32768);
12202
+ }
12203
+ if (flags & 128) {
12204
+ ps.viewoffset.x = (stream.readByte() << 24 >> 24) * 0.25;
12205
+ ps.viewoffset.y = (stream.readByte() << 24 >> 24) * 0.25;
12206
+ ps.viewoffset.z = (stream.readByte() << 24 >> 24) * 0.25;
12207
+ }
12208
+ if (flags & 256) {
12209
+ ps.viewangles.x = stream.readShort() * (360 / 65536);
12210
+ ps.viewangles.y = stream.readShort() * (360 / 65536);
12211
+ ps.viewangles.z = stream.readShort() * (360 / 65536);
12212
+ }
12213
+ if (flags & 512) {
12214
+ ps.kick_angles.x = (stream.readByte() << 24 >> 24) * 0.25;
12215
+ ps.kick_angles.y = (stream.readByte() << 24 >> 24) * 0.25;
12216
+ ps.kick_angles.z = (stream.readByte() << 24 >> 24) * 0.25;
12217
+ }
12218
+ if (flags & 4096) ps.gun_index = stream.readByte();
12219
+ if (flags & 8192) {
12220
+ ps.gun_frame = stream.readByte();
12221
+ ps.gun_offset.x = (stream.readByte() << 24 >> 24) * 0.25;
12222
+ ps.gun_offset.y = (stream.readByte() << 24 >> 24) * 0.25;
12223
+ ps.gun_offset.z = (stream.readByte() << 24 >> 24) * 0.25;
12224
+ ps.gun_angles.x = (stream.readByte() << 24 >> 24) * 0.25;
12225
+ ps.gun_angles.y = (stream.readByte() << 24 >> 24) * 0.25;
12226
+ ps.gun_angles.z = (stream.readByte() << 24 >> 24) * 0.25;
12227
+ }
12228
+ if (flags & 1024) {
12229
+ ps.blend[0] = stream.readByte();
12230
+ ps.blend[1] = stream.readByte();
12231
+ ps.blend[2] = stream.readByte();
12232
+ ps.blend[3] = stream.readByte();
12233
+ }
12234
+ if (flags & 2048) ps.fov = stream.readByte();
12235
+ if (flags & 16384) ps.rdflags = stream.readByte();
12236
+ if (flags & 32768) ps.watertype = stream.readByte();
12237
+ const statbits = stream.readLong();
12238
+ for (let i = 0; i < 32; i++) {
12239
+ if (statbits & 1 << i) ps.stats[i] = stream.readShort();
12240
+ }
12241
+ return ps;
12242
+ }
12243
+ };
12244
+ var PROTOCOL_VERSION_RERELEASE = 2023;
12245
+ var RereleaseProtocolHandler = class {
12246
+ constructor() {
12247
+ this.protocolVersion = PROTOCOL_VERSION_RERELEASE;
12248
+ }
12249
+ translateCommand(cmd) {
12250
+ return cmd;
12251
+ }
12252
+ parseServerData(stream) {
12253
+ const protocol = stream.readLong();
12254
+ const spawnCount = stream.readLong();
12255
+ const demoType = stream.readByte();
12256
+ const tickRate = stream.readByte();
12257
+ const gameDir = stream.readString();
12258
+ let playerNum = stream.readShort();
12259
+ if (playerNum === -2) {
12260
+ const numSplits = stream.readShort();
12261
+ for (let i = 0; i < numSplits; i++) stream.readShort();
12262
+ playerNum = 0;
12263
+ } else if (playerNum === -1) {
12264
+ playerNum = -1;
12265
+ }
12266
+ const levelName = stream.readString();
12267
+ return {
12268
+ protocol,
12269
+ serverCount: spawnCount,
12270
+ // Map spawnCount to serverCount interface
12271
+ spawnCount,
12272
+ attractLoop: 0,
12273
+ // Not used in rerelease
12274
+ gameDir,
12275
+ playerNum,
12276
+ levelName,
12277
+ tickRate,
12278
+ demoType
12279
+ };
12280
+ }
12281
+ parseEntityBits(stream) {
12282
+ let total = stream.readByte();
12283
+ if (total & U_MOREBITS1) total |= stream.readByte() << 8;
12284
+ if (total & U_MOREBITS2) total |= stream.readByte() << 16;
12285
+ if (total & U_MOREBITS3) total |= stream.readByte() << 24;
12286
+ let bitsHigh = 0;
12287
+ if (total & U_MOREBITS4) bitsHigh = stream.readByte();
12288
+ let number;
12289
+ if (total & U_NUMBER16) number = stream.readShort();
12290
+ else number = stream.readByte();
12291
+ return { number, bits: total, bitsHigh };
12292
+ }
12293
+ parseDelta(from, to, number, bits, bitsHigh, stream) {
12294
+ Object.assign(to, from);
12295
+ to.origin = { ...from.origin };
12296
+ to.old_origin = { ...from.old_origin };
12297
+ to.angles = { ...from.angles };
12298
+ to.number = number;
12299
+ to.bits = bits;
12300
+ to.bitsHigh = bitsHigh;
12301
+ if (bits & U_MODEL) to.modelindex = stream.readByte();
12302
+ if (bits & U_MODEL2) to.modelindex2 = stream.readByte();
12303
+ if (bits & U_MODEL3) to.modelindex3 = stream.readByte();
12304
+ if (bits & U_MODEL4) to.modelindex4 = stream.readByte();
12305
+ if (bits & U_FRAME8) to.frame = stream.readByte();
12306
+ if (bits & U_FRAME16) to.frame = stream.readShort();
12307
+ if (bits & U_SKIN8 && bits & U_SKIN16) to.skinnum = stream.readLong();
12308
+ else if (bits & U_SKIN8) to.skinnum = stream.readByte();
12309
+ else if (bits & U_SKIN16) to.skinnum = stream.readShort();
12310
+ if (bits & U_EFFECTS8 && bits & U_EFFECTS16) to.effects = stream.readLong();
12311
+ else if (bits & U_EFFECTS8) to.effects = stream.readByte();
12312
+ else if (bits & U_EFFECTS16) to.effects = stream.readShort();
12313
+ if (bits & U_RENDERFX8 && bits & U_RENDERFX16) to.renderfx = stream.readLong();
12314
+ else if (bits & U_RENDERFX8) to.renderfx = stream.readByte();
12315
+ else if (bits & U_RENDERFX16) to.renderfx = stream.readShort();
12316
+ if (bits & U_ORIGIN1) to.origin.x = stream.readShort() * 0.125;
12317
+ if (bits & U_ORIGIN2) to.origin.y = stream.readShort() * 0.125;
12318
+ if (bits & U_ORIGIN3) to.origin.z = stream.readShort() * 0.125;
12319
+ if (bits & U_ANGLE1) to.angles.x = stream.readByte() * (360 / 256);
12320
+ if (bits & U_ANGLE2) to.angles.y = stream.readByte() * (360 / 256);
12321
+ if (bits & U_ANGLE3) to.angles.z = stream.readByte() * (360 / 256);
12322
+ if (bits & U_OLDORIGIN) {
12323
+ to.old_origin.x = stream.readShort() * 0.125;
12324
+ to.old_origin.y = stream.readShort() * 0.125;
12325
+ to.old_origin.z = stream.readShort() * 0.125;
12326
+ }
12327
+ if (bits & U_SOUND) to.sound = stream.readByte();
12328
+ if (bits & U_EVENT) to.event = stream.readByte();
12329
+ else to.event = 0;
12330
+ if (bits & U_SOLID) to.solid = stream.readShort();
12331
+ if (bits & U_ALPHA) to.alpha = stream.readByte() / 255;
12332
+ if (bits & U_SCALE) to.scale = stream.readFloat();
12333
+ if (bits & U_INSTANCE_BITS) to.instanceBits = stream.readLong();
12334
+ if (bits & U_LOOP_VOLUME) to.loopVolume = stream.readByte() / 255;
12335
+ if (bitsHigh & U_LOOP_ATTENUATION_HIGH) to.loopAttenuation = stream.readByte() / 255;
12336
+ if (bitsHigh & U_OWNER_HIGH) to.owner = stream.readShort();
12337
+ if (bitsHigh & U_OLD_FRAME_HIGH) to.oldFrame = stream.readShort();
12338
+ }
12339
+ parsePlayerState(stream) {
12340
+ const ps = createEmptyProtocolPlayerState();
12341
+ const flags = stream.readShort();
12342
+ if (flags & 1) ps.pm_type = stream.readByte();
12343
+ if (flags & 2) {
12344
+ ps.origin.x = stream.readShort() * 0.125;
12345
+ ps.origin.y = stream.readShort() * 0.125;
12346
+ ps.origin.z = stream.readShort() * 0.125;
12347
+ }
12348
+ if (flags & 4) {
12349
+ ps.velocity.x = stream.readShort() * 0.125;
12350
+ ps.velocity.y = stream.readShort() * 0.125;
12351
+ ps.velocity.z = stream.readShort() * 0.125;
12352
+ }
12353
+ if (flags & 8) ps.pm_time = stream.readByte();
12354
+ if (flags & 16) ps.pm_flags = stream.readByte();
12355
+ if (flags & 32) ps.gravity = stream.readShort();
12356
+ if (flags & 64) {
12357
+ ps.delta_angles.x = stream.readShort() * (180 / 32768);
12358
+ ps.delta_angles.y = stream.readShort() * (180 / 32768);
12359
+ ps.delta_angles.z = stream.readShort() * (180 / 32768);
12360
+ }
12361
+ if (flags & 128) {
12362
+ ps.viewoffset.x = (stream.readByte() << 24 >> 24) * 0.25;
12363
+ ps.viewoffset.y = (stream.readByte() << 24 >> 24) * 0.25;
12364
+ ps.viewoffset.z = (stream.readByte() << 24 >> 24) * 0.25;
12365
+ }
12366
+ if (flags & 256) {
12367
+ ps.viewangles.x = stream.readShort() * (360 / 65536);
12368
+ ps.viewangles.y = stream.readShort() * (360 / 65536);
12369
+ ps.viewangles.z = stream.readShort() * (360 / 65536);
12370
+ }
12371
+ if (flags & 512) {
12372
+ ps.kick_angles.x = (stream.readByte() << 24 >> 24) * 0.25;
12373
+ ps.kick_angles.y = (stream.readByte() << 24 >> 24) * 0.25;
12374
+ ps.kick_angles.z = (stream.readByte() << 24 >> 24) * 0.25;
12375
+ }
12376
+ if (flags & 4096) ps.gun_index = stream.readByte();
12377
+ if (flags & 8192) {
12378
+ ps.gun_frame = stream.readByte();
12379
+ ps.gun_offset.x = (stream.readByte() << 24 >> 24) * 0.25;
12380
+ ps.gun_offset.y = (stream.readByte() << 24 >> 24) * 0.25;
12381
+ ps.gun_offset.z = (stream.readByte() << 24 >> 24) * 0.25;
12382
+ ps.gun_angles.x = (stream.readByte() << 24 >> 24) * 0.25;
12383
+ ps.gun_angles.y = (stream.readByte() << 24 >> 24) * 0.25;
12384
+ ps.gun_angles.z = (stream.readByte() << 24 >> 24) * 0.25;
12385
+ }
12386
+ if (flags & 1024) {
12387
+ ps.blend[0] = stream.readByte();
12388
+ ps.blend[1] = stream.readByte();
12389
+ ps.blend[2] = stream.readByte();
12390
+ ps.blend[3] = stream.readByte();
12391
+ }
12392
+ if (flags & 2048) ps.fov = stream.readByte();
12393
+ if (flags & 16384) ps.rdflags = stream.readByte();
12394
+ if (flags & 32768) ps.watertype = stream.readByte();
12395
+ const statbits = stream.readLong();
12396
+ for (let i = 0; i < 32; i++) {
12397
+ if (statbits & 1 << i) ps.stats[i] = stream.readShort();
12398
+ }
12399
+ return ps;
12400
+ }
12401
+ };
12402
+ var LegacyProtocolHandler = class {
12403
+ constructor(version = 0) {
12404
+ this.protocolVersion = version;
12405
+ }
12406
+ translateCommand(cmd) {
12407
+ return cmd;
12408
+ }
12409
+ parseServerData(stream) {
12410
+ const protocol = stream.readLong();
12411
+ const serverCount = stream.readLong();
12412
+ const attractLoop = stream.readByte();
12413
+ const gameDir = stream.readString();
12414
+ const playerNum = stream.readShort();
12415
+ const levelName = stream.readString();
12416
+ return {
12417
+ protocol,
12418
+ serverCount,
12419
+ attractLoop,
12420
+ gameDir,
12421
+ playerNum,
12422
+ levelName
12423
+ };
12424
+ }
12425
+ parseEntityBits(stream) {
12426
+ let total = stream.readByte();
12427
+ if (total & U_MOREBITS1) total |= stream.readByte() << 8;
12428
+ if (total & U_MOREBITS2) total |= stream.readByte() << 16;
12429
+ if (total & U_MOREBITS3) total |= stream.readByte() << 24;
12430
+ let number;
12431
+ if (total & U_NUMBER16) number = stream.readShort();
12432
+ else number = stream.readByte();
12433
+ return { number, bits: total, bitsHigh: 0 };
12434
+ }
12435
+ parseDelta(from, to, number, bits, bitsHigh, stream) {
12436
+ to.number = from.number;
12437
+ to.modelindex = from.modelindex;
12438
+ to.modelindex2 = from.modelindex2;
12439
+ to.modelindex3 = from.modelindex3;
12440
+ to.modelindex4 = from.modelindex4;
12441
+ to.frame = from.frame;
12442
+ to.skinnum = from.skinnum;
12443
+ to.effects = from.effects;
12444
+ to.renderfx = from.renderfx;
12445
+ to.origin.x = from.origin.x;
12446
+ to.origin.y = from.origin.y;
12447
+ to.origin.z = from.origin.z;
12448
+ to.old_origin.x = from.origin.x;
12449
+ to.old_origin.y = from.origin.y;
12450
+ to.old_origin.z = from.origin.z;
12451
+ to.angles.x = from.angles.x;
12452
+ to.angles.y = from.angles.y;
12453
+ to.angles.z = from.angles.z;
12454
+ to.sound = from.sound;
12455
+ to.event = from.event;
12456
+ to.solid = from.solid;
12457
+ to.number = number;
12458
+ to.bits = bits;
12459
+ if (bits & U_MODEL) to.modelindex = stream.readByte();
12460
+ if (bits & U_MODEL2) to.modelindex2 = stream.readByte();
12461
+ if (bits & U_MODEL3) to.modelindex3 = stream.readByte();
12462
+ if (bits & U_MODEL4) to.modelindex4 = stream.readByte();
12463
+ if (bits & U_FRAME8) to.frame = stream.readByte();
12464
+ if (bits & U_FRAME16) to.frame = stream.readShort();
12465
+ if (bits & U_SKIN8 && bits & U_SKIN16) to.skinnum = stream.readLong();
12466
+ else if (bits & U_SKIN8) to.skinnum = stream.readByte();
12467
+ else if (bits & U_SKIN16) to.skinnum = stream.readShort();
12468
+ if (bits & U_EFFECTS8 && bits & U_EFFECTS16) to.effects = stream.readLong();
12469
+ else if (bits & U_EFFECTS8) to.effects = stream.readByte();
12470
+ else if (bits & U_EFFECTS16) to.effects = stream.readShort();
12471
+ if (bits & U_RENDERFX8 && bits & U_RENDERFX16) to.renderfx = stream.readLong();
12472
+ else if (bits & U_RENDERFX8) to.renderfx = stream.readByte();
12473
+ else if (bits & U_RENDERFX16) to.renderfx = stream.readShort();
12474
+ if (bits & U_ORIGIN1) to.origin.x = stream.readShort() * 0.125;
12475
+ if (bits & U_ORIGIN2) to.origin.y = stream.readShort() * 0.125;
12476
+ if (bits & U_ORIGIN3) to.origin.z = stream.readShort() * 0.125;
12477
+ if (bits & U_ANGLE1) to.angles.x = stream.readByte() * (360 / 256);
12478
+ if (bits & U_ANGLE2) to.angles.y = stream.readByte() * (360 / 256);
12479
+ if (bits & U_ANGLE3) to.angles.z = stream.readByte() * (360 / 256);
12480
+ if (bits & U_OLDORIGIN) {
12481
+ to.old_origin.x = stream.readShort() * 0.125;
12482
+ to.old_origin.y = stream.readShort() * 0.125;
12483
+ to.old_origin.z = stream.readShort() * 0.125;
12484
+ }
12485
+ if (bits & U_SOUND) to.sound = stream.readByte();
12486
+ if (bits & U_EVENT) to.event = stream.readByte();
12487
+ else to.event = 0;
12488
+ if (bits & U_SOLID) to.solid = stream.readShort();
12489
+ }
12490
+ parsePlayerState(stream) {
12491
+ const ps = createEmptyProtocolPlayerState();
12492
+ const flags = stream.readShort();
12493
+ if (flags & 1) ps.pm_type = stream.readByte();
12494
+ if (flags & 2) {
12495
+ ps.origin.x = stream.readShort() * 0.125;
12496
+ ps.origin.y = stream.readShort() * 0.125;
12497
+ ps.origin.z = stream.readShort() * 0.125;
12498
+ }
12499
+ if (flags & 4) {
12500
+ ps.velocity.x = stream.readShort() * 0.125;
12501
+ ps.velocity.y = stream.readShort() * 0.125;
12502
+ ps.velocity.z = stream.readShort() * 0.125;
12503
+ }
12504
+ if (flags & 8) ps.pm_time = stream.readByte();
12505
+ if (flags & 16) ps.pm_flags = stream.readByte();
12506
+ if (flags & 32) ps.gravity = stream.readShort();
12507
+ if (flags & 64) {
12508
+ ps.delta_angles.x = stream.readShort() * (180 / 32768);
12509
+ ps.delta_angles.y = stream.readShort() * (180 / 32768);
12510
+ ps.delta_angles.z = stream.readShort() * (180 / 32768);
12511
+ }
12512
+ if (flags & 128) {
12513
+ ps.viewoffset.x = (stream.readByte() << 24 >> 24) * 0.25;
12514
+ ps.viewoffset.y = (stream.readByte() << 24 >> 24) * 0.25;
12515
+ ps.viewoffset.z = (stream.readByte() << 24 >> 24) * 0.25;
12516
+ }
12517
+ if (flags & 256) {
12518
+ ps.viewangles.x = stream.readShort() * (360 / 65536);
12519
+ ps.viewangles.y = stream.readShort() * (360 / 65536);
12520
+ ps.viewangles.z = stream.readShort() * (360 / 65536);
12521
+ }
12522
+ if (flags & 512) {
12523
+ ps.kick_angles.x = (stream.readByte() << 24 >> 24) * 0.25;
12524
+ ps.kick_angles.y = (stream.readByte() << 24 >> 24) * 0.25;
12525
+ ps.kick_angles.z = (stream.readByte() << 24 >> 24) * 0.25;
12526
+ }
12527
+ if (flags & 4096) ps.gun_index = stream.readByte();
12528
+ if (flags & 8192) {
12529
+ ps.gun_frame = stream.readByte();
12530
+ ps.gun_offset.x = (stream.readByte() << 24 >> 24) * 0.25;
12531
+ ps.gun_offset.y = (stream.readByte() << 24 >> 24) * 0.25;
12532
+ ps.gun_offset.z = (stream.readByte() << 24 >> 24) * 0.25;
12533
+ ps.gun_angles.x = (stream.readByte() << 24 >> 24) * 0.25;
12534
+ ps.gun_angles.y = (stream.readByte() << 24 >> 24) * 0.25;
12535
+ ps.gun_angles.z = (stream.readByte() << 24 >> 24) * 0.25;
12536
+ }
12537
+ if (flags & 1024) {
12538
+ ps.blend[0] = stream.readByte();
12539
+ ps.blend[1] = stream.readByte();
12540
+ ps.blend[2] = stream.readByte();
12541
+ ps.blend[3] = stream.readByte();
12542
+ }
12543
+ if (flags & 2048) ps.fov = stream.readByte();
12544
+ if (flags & 16384) ps.rdflags = stream.readByte();
12545
+ if (flags & 32768) ps.watertype = stream.readByte();
12546
+ const statbits = stream.readLong();
12547
+ for (let i = 0; i < 32; i++) {
12548
+ if (statbits & 1 << i) ps.stats[i] = stream.readShort();
12549
+ }
12550
+ return ps;
12551
+ }
12552
+ };
12553
+ var BootstrapProtocolHandler = class {
12554
+ constructor() {
12555
+ this.protocolVersion = 0;
12556
+ }
12557
+ // We assume standard Q2 opcodes for bootstrap to find serverdata
12558
+ // but we can also check for legacy serverdata (12 vs 13 vs 7)
12559
+ translateCommand(cmd) {
12560
+ if (cmd === 7) return ServerCommand.serverdata;
12561
+ if (cmd === 12) return ServerCommand.serverdata;
12562
+ if (cmd === 13) return ServerCommand.serverdata;
12563
+ if (cmd === ServerCommand.stufftext) return ServerCommand.stufftext;
12564
+ return ServerCommand.bad;
12565
+ }
12566
+ parseServerData(stream) {
12567
+ const protocol = stream.readLong();
12568
+ if (protocol === PROTOCOL_VERSION_RERELEASE) {
12569
+ const spawnCount = stream.readLong();
12570
+ const demoType = stream.readByte();
12571
+ const tickRate = stream.readByte();
12572
+ const gameDir = stream.readString();
12573
+ let playerNum = stream.readShort();
12574
+ if (playerNum === -2) {
12575
+ const numSplits = stream.readShort();
12576
+ for (let i = 0; i < numSplits; i++) stream.readShort();
12577
+ playerNum = 0;
12578
+ } else if (playerNum === -1) {
12579
+ playerNum = -1;
12580
+ }
12581
+ const levelName = stream.readString();
12582
+ return {
12583
+ protocol,
12584
+ serverCount: spawnCount,
12585
+ spawnCount,
12586
+ attractLoop: 0,
12587
+ gameDir,
12588
+ playerNum,
12589
+ levelName,
12590
+ tickRate,
12591
+ demoType
12592
+ };
12593
+ } else {
12594
+ const serverCount = stream.readLong();
12595
+ const attractLoop = stream.readByte();
12596
+ const gameDir = stream.readString();
12597
+ const playerNum = stream.readShort();
12598
+ const levelName = stream.readString();
12599
+ return {
12600
+ protocol,
12601
+ serverCount,
12602
+ attractLoop,
12603
+ gameDir,
12604
+ playerNum,
12605
+ levelName
12606
+ };
12607
+ }
12608
+ }
12609
+ parseEntityBits(stream) {
12610
+ throw new Error("Bootstrap handler cannot parse entities");
12611
+ }
12612
+ parseDelta(from, to, number, bits, bitsHigh, stream) {
12613
+ throw new Error("Bootstrap handler cannot parse delta");
12614
+ }
12615
+ parsePlayerState(stream) {
12616
+ throw new Error("Bootstrap handler cannot parse player state");
12617
+ }
12618
+ };
12619
+ function createProtocolHandler(version) {
12620
+ if (version === 0) {
12621
+ return new BootstrapProtocolHandler();
12622
+ }
12623
+ if (version === PROTOCOL_VERSION_RERELEASE) {
12624
+ return new RereleaseProtocolHandler();
12625
+ }
12626
+ if (version === 34) {
12627
+ return new Quake2ProtocolHandler();
12628
+ }
12629
+ return new LegacyProtocolHandler(version);
12630
+ }
12631
+ var RECORD_CLIENT = 1;
12632
+ var RECORD_SERVER = 2;
12633
+ var RECORD_RELAY = 128;
12104
12634
  var BinaryStreamAdapter = class extends StreamingBuffer {
12105
12635
  constructor(stream) {
12106
12636
  super(0);
@@ -12138,38 +12668,11 @@ var BinaryStreamAdapter = class extends StreamingBuffer {
12138
12668
  throw new Error("peekBytes not implemented for BinaryStreamAdapter");
12139
12669
  }
12140
12670
  };
12141
- var PROTO34_MAP = {
12142
- 0: ServerCommand.bad,
12143
- 1: ServerCommand.nop,
12144
- 2: ServerCommand.disconnect,
12145
- 3: ServerCommand.reconnect,
12146
- 4: ServerCommand.download,
12147
- 5: ServerCommand.frame,
12148
- 6: ServerCommand.inventory,
12149
- 7: ServerCommand.layout,
12150
- 8: ServerCommand.muzzleflash,
12151
- 9: ServerCommand.sound,
12152
- 10: ServerCommand.print,
12153
- 11: ServerCommand.stufftext,
12154
- 12: ServerCommand.serverdata,
12155
- 13: ServerCommand.configstring,
12156
- 14: ServerCommand.spawnbaseline,
12157
- 15: ServerCommand.centerprint,
12158
- 16: ServerCommand.download,
12159
- 17: ServerCommand.playerinfo,
12160
- 18: ServerCommand.packetentities,
12161
- 19: ServerCommand.deltapacketentities,
12162
- 23: ServerCommand.temp_entity,
12163
- // Wire 23 -> Enum 3 (TempEntity)
12164
- 22: ServerCommand.muzzleflash2
12165
- // Wire 22 -> Enum 2 (MuzzleFlash2)
12166
- };
12167
12671
  var NetworkMessageParser = class _NetworkMessageParser {
12168
12672
  constructor(stream, handler, strictMode = false) {
12169
- this.protocolVersion = 0;
12170
- this.isDemo = RECORD_CLIENT;
12171
12673
  this.strictMode = false;
12172
12674
  this.errorCount = 0;
12675
+ this.isDemo = RECORD_CLIENT;
12173
12676
  if (stream instanceof BinaryStream) {
12174
12677
  this.stream = new BinaryStreamAdapter(stream);
12175
12678
  } else {
@@ -12177,41 +12680,19 @@ var NetworkMessageParser = class _NetworkMessageParser {
12177
12680
  }
12178
12681
  this.handler = handler;
12179
12682
  this.strictMode = strictMode;
12683
+ this.protocolHandler = new BootstrapProtocolHandler();
12180
12684
  }
12181
12685
  setProtocolVersion(version) {
12182
- this.protocolVersion = version;
12686
+ if (this.protocolHandler.protocolVersion !== version) {
12687
+ this.protocolHandler = createProtocolHandler(version);
12688
+ }
12183
12689
  }
12184
12690
  getProtocolVersion() {
12185
- return this.protocolVersion;
12691
+ return this.protocolHandler.protocolVersion;
12186
12692
  }
12187
12693
  getErrorCount() {
12188
12694
  return this.errorCount;
12189
12695
  }
12190
- translateCommand(cmd) {
12191
- if (this.protocolVersion === 0) {
12192
- if (cmd === 7) return ServerCommand.serverdata;
12193
- if (cmd === 12) return ServerCommand.serverdata;
12194
- return cmd;
12195
- }
12196
- if (this.protocolVersion === PROTOCOL_VERSION_RERELEASE) {
12197
- return cmd;
12198
- }
12199
- if (this.protocolVersion === 25 || this.protocolVersion === 26) {
12200
- if (cmd === 0) return ServerCommand.bad;
12201
- const translated = cmd + 5;
12202
- if (translated >= ServerCommand.nop && translated <= ServerCommand.frame) {
12203
- return translated;
12204
- }
12205
- return ServerCommand.bad;
12206
- }
12207
- if (this.protocolVersion === 34) {
12208
- if (PROTO34_MAP[cmd] !== void 0) {
12209
- return PROTO34_MAP[cmd];
12210
- }
12211
- return ServerCommand.bad;
12212
- }
12213
- return cmd;
12214
- }
12215
12696
  parseMessage() {
12216
12697
  while (this.stream.hasBytes(1)) {
12217
12698
  const startPos = this.stream.getReadPosition();
@@ -12220,9 +12701,16 @@ var NetworkMessageParser = class _NetworkMessageParser {
12220
12701
  cmd = this.stream.readByte();
12221
12702
  if (cmd === -1) break;
12222
12703
  const originalCmd = cmd;
12223
- cmd = this.translateCommand(cmd);
12224
- switch (cmd) {
12704
+ const translatedCmd = this.protocolHandler.translateCommand(cmd);
12705
+ switch (translatedCmd) {
12225
12706
  case ServerCommand.bad:
12707
+ if (originalCmd === 0) {
12708
+ return;
12709
+ }
12710
+ const errorMsg = `Unknown server command: ${originalCmd} (translated: ${translatedCmd}) at offset ${startPos} (Protocol: ${this.getProtocolVersion()})`;
12711
+ if (this.strictMode) throw new Error(errorMsg);
12712
+ console.warn(errorMsg);
12713
+ this.errorCount++;
12226
12714
  return;
12227
12715
  case ServerCommand.nop:
12228
12716
  break;
@@ -12323,9 +12811,9 @@ var NetworkMessageParser = class _NetworkMessageParser {
12323
12811
  this.parseAchievement();
12324
12812
  break;
12325
12813
  default:
12326
- const errorMsg = `Unknown server command: ${originalCmd} (translated: ${cmd}) at offset ${startPos}`;
12327
- if (this.strictMode) throw new Error(errorMsg);
12328
- console.warn(errorMsg);
12814
+ const errorMsgDef = `Unknown server command: ${originalCmd} (translated: ${translatedCmd}) at offset ${startPos}`;
12815
+ if (this.strictMode) throw new Error(errorMsgDef);
12816
+ console.warn(errorMsgDef);
12329
12817
  this.errorCount++;
12330
12818
  return;
12331
12819
  }
@@ -12339,7 +12827,7 @@ var NetworkMessageParser = class _NetworkMessageParser {
12339
12827
  }
12340
12828
  return;
12341
12829
  }
12342
- const context = `offset ${startPos}, cmd ${cmd}, protocol ${this.protocolVersion}`;
12830
+ const context = `offset ${startPos}, cmd ${cmd}, protocol ${this.getProtocolVersion()}`;
12343
12831
  console.warn(`Error parsing command ${cmd} (${context}): ${errMsg}`);
12344
12832
  this.errorCount++;
12345
12833
  if (this.strictMode) throw e;
@@ -12392,31 +12880,24 @@ var NetworkMessageParser = class _NetworkMessageParser {
12392
12880
  if (this.handler) this.handler.onCenterPrint(centerMsg);
12393
12881
  }
12394
12882
  parseServerData() {
12395
- this.protocolVersion = this.stream.readLong();
12396
- if (this.protocolVersion === PROTOCOL_VERSION_RERELEASE) {
12397
- const spawnCount = this.stream.readLong();
12398
- const demoType = this.stream.readByte();
12399
- this.isDemo = demoType;
12400
- const tickRate = this.stream.readByte();
12401
- const gameDir = this.stream.readString();
12402
- let playerNum = this.stream.readShort();
12403
- if (playerNum === -2) {
12404
- const numSplits = this.stream.readShort();
12405
- for (let i = 0; i < numSplits; i++) this.stream.readShort();
12406
- playerNum = 0;
12407
- } else if (playerNum === -1) {
12408
- playerNum = -1;
12409
- }
12410
- const levelName = this.stream.readString();
12411
- if (this.handler) this.handler.onServerData(this.protocolVersion, spawnCount, 0, gameDir, playerNum, levelName, tickRate, demoType);
12883
+ const data = this.protocolHandler.parseServerData(this.stream);
12884
+ this.setProtocolVersion(data.protocol);
12885
+ if (this.handler) {
12886
+ this.handler.onServerData(
12887
+ data.protocol,
12888
+ data.serverCount,
12889
+ data.attractLoop,
12890
+ data.gameDir,
12891
+ data.playerNum,
12892
+ data.levelName,
12893
+ data.tickRate,
12894
+ data.demoType
12895
+ );
12896
+ }
12897
+ if (data.protocol === PROTOCOL_VERSION_RERELEASE) {
12898
+ this.isDemo = data.demoType ?? RECORD_CLIENT;
12412
12899
  } else {
12413
- const serverCount = this.stream.readLong();
12414
- const attractLoop = this.stream.readByte();
12415
- this.isDemo = attractLoop;
12416
- const gameDir = this.stream.readString();
12417
- const playerNum = this.stream.readShort();
12418
- const levelName = this.stream.readString();
12419
- if (this.handler) this.handler.onServerData(this.protocolVersion, serverCount, attractLoop, gameDir, playerNum, levelName);
12900
+ this.isDemo = data.attractLoop;
12420
12901
  }
12421
12902
  }
12422
12903
  parseConfigString() {
@@ -12452,7 +12933,7 @@ var NetworkMessageParser = class _NetworkMessageParser {
12452
12933
  const decompressed = pako.inflate(compressedData);
12453
12934
  const blastStream = new BinaryStream(decompressed.buffer);
12454
12935
  const blastParser = new _NetworkMessageParser(blastStream, this.handler, this.strictMode);
12455
- blastParser.setProtocolVersion(this.protocolVersion);
12936
+ blastParser.setProtocolVersion(this.getProtocolVersion());
12456
12937
  while (blastStream.hasMore()) {
12457
12938
  blastParser.parseSpawnBaseline();
12458
12939
  }
@@ -12648,7 +13129,7 @@ var NetworkMessageParser = class _NetworkMessageParser {
12648
13129
  color = this.stream.readByte();
12649
13130
  break;
12650
13131
  case TempEntity.BLUEHYPERBLASTER:
12651
- if (this.protocolVersion >= 32) {
13132
+ if (this.getProtocolVersion() >= 32) {
12652
13133
  this.readPos(pos);
12653
13134
  this.readPos(pos2);
12654
13135
  } else {
@@ -12657,7 +13138,7 @@ var NetworkMessageParser = class _NetworkMessageParser {
12657
13138
  }
12658
13139
  break;
12659
13140
  case TempEntity.GREENBLOOD:
12660
- if (this.protocolVersion >= 32) {
13141
+ if (this.getProtocolVersion() >= 32) {
12661
13142
  this.readPos(pos);
12662
13143
  this.readDir(dir);
12663
13144
  } else {
@@ -12722,29 +13203,29 @@ var NetworkMessageParser = class _NetworkMessageParser {
12722
13203
  if (this.handler) this.handler.onTempEntity(type, pos, pos2, dir, cnt, color, ent, srcEnt, destEnt);
12723
13204
  }
12724
13205
  parseSpawnBaseline() {
12725
- const bits = this.parseEntityBits();
13206
+ const bits = this.protocolHandler.parseEntityBits(this.stream);
12726
13207
  const entity = createEmptyEntityState();
12727
- this.parseDelta(createEmptyEntityState(), entity, bits.number, bits.bits, bits.bitsHigh);
13208
+ this.protocolHandler.parseDelta(createEmptyEntityState(), entity, bits.number, bits.bits, bits.bitsHigh, this.stream);
12728
13209
  if (this.handler) this.handler.onSpawnBaseline(entity);
12729
13210
  }
12730
13211
  parseFrame() {
12731
13212
  const serverFrame = this.stream.readLong();
12732
13213
  const deltaFrame = this.stream.readLong();
12733
13214
  let surpressCount = 0;
12734
- if (this.protocolVersion !== 26 && this.protocolVersion !== 25) {
13215
+ if (this.getProtocolVersion() !== 26 && this.getProtocolVersion() !== 25) {
12735
13216
  surpressCount = this.stream.readByte();
12736
13217
  }
12737
13218
  const areaBytes = this.stream.readByte();
12738
13219
  const areaBits = this.stream.readData(areaBytes);
12739
13220
  let piCmd = this.stream.readByte();
12740
- piCmd = this.translateCommand(piCmd);
13221
+ piCmd = this.protocolHandler.translateCommand(piCmd);
12741
13222
  if (piCmd !== ServerCommand.playerinfo) {
12742
13223
  if (this.strictMode) throw new Error(`Expected svc_playerinfo after svc_frame, got ${piCmd}`);
12743
13224
  return;
12744
13225
  }
12745
13226
  const playerState = this.parsePlayerState();
12746
13227
  let peCmd = this.stream.readByte();
12747
- peCmd = this.translateCommand(peCmd);
13228
+ peCmd = this.protocolHandler.translateCommand(peCmd);
12748
13229
  if (peCmd !== ServerCommand.packetentities && peCmd !== ServerCommand.deltapacketentities) {
12749
13230
  if (this.strictMode) throw new Error(`Expected svc_packetentities after svc_playerinfo, got ${peCmd}`);
12750
13231
  return;
@@ -12766,64 +13247,7 @@ var NetworkMessageParser = class _NetworkMessageParser {
12766
13247
  });
12767
13248
  }
12768
13249
  parsePlayerState() {
12769
- const ps = createEmptyProtocolPlayerState();
12770
- const flags = this.stream.readShort();
12771
- if (flags & 1) ps.pm_type = this.stream.readByte();
12772
- if (flags & 2) {
12773
- ps.origin.x = this.readCoord();
12774
- ps.origin.y = this.readCoord();
12775
- ps.origin.z = this.readCoord();
12776
- }
12777
- if (flags & 4) {
12778
- ps.velocity.x = this.readCoord();
12779
- ps.velocity.y = this.readCoord();
12780
- ps.velocity.z = this.readCoord();
12781
- }
12782
- if (flags & 8) ps.pm_time = this.stream.readByte();
12783
- if (flags & 16) ps.pm_flags = this.stream.readByte();
12784
- if (flags & 32) ps.gravity = this.stream.readShort();
12785
- if (flags & 64) {
12786
- ps.delta_angles.x = this.stream.readShort() * (180 / 32768);
12787
- ps.delta_angles.y = this.stream.readShort() * (180 / 32768);
12788
- ps.delta_angles.z = this.stream.readShort() * (180 / 32768);
12789
- }
12790
- if (flags & 128) {
12791
- ps.viewoffset.x = (this.stream.readByte() << 24 >> 24) * 0.25;
12792
- ps.viewoffset.y = (this.stream.readByte() << 24 >> 24) * 0.25;
12793
- ps.viewoffset.z = (this.stream.readByte() << 24 >> 24) * 0.25;
12794
- }
12795
- if (flags & 256) {
12796
- ps.viewangles.x = this.readAngle16();
12797
- ps.viewangles.y = this.readAngle16();
12798
- ps.viewangles.z = this.readAngle16();
12799
- }
12800
- if (flags & 512) {
12801
- ps.kick_angles.x = (this.stream.readByte() << 24 >> 24) * 0.25;
12802
- ps.kick_angles.y = (this.stream.readByte() << 24 >> 24) * 0.25;
12803
- ps.kick_angles.z = (this.stream.readByte() << 24 >> 24) * 0.25;
12804
- }
12805
- if (flags & 4096) ps.gun_index = this.stream.readByte();
12806
- if (flags & 8192) {
12807
- ps.gun_frame = this.stream.readByte();
12808
- ps.gun_offset.x = (this.stream.readByte() << 24 >> 24) * 0.25;
12809
- ps.gun_offset.y = (this.stream.readByte() << 24 >> 24) * 0.25;
12810
- ps.gun_offset.z = (this.stream.readByte() << 24 >> 24) * 0.25;
12811
- ps.gun_angles.x = (this.stream.readByte() << 24 >> 24) * 0.25;
12812
- ps.gun_angles.y = (this.stream.readByte() << 24 >> 24) * 0.25;
12813
- ps.gun_angles.z = (this.stream.readByte() << 24 >> 24) * 0.25;
12814
- }
12815
- if (flags & 1024) {
12816
- ps.blend[0] = this.stream.readByte();
12817
- ps.blend[1] = this.stream.readByte();
12818
- ps.blend[2] = this.stream.readByte();
12819
- ps.blend[3] = this.stream.readByte();
12820
- }
12821
- if (flags & 2048) ps.fov = this.stream.readByte();
12822
- if (flags & 16384) ps.rdflags = this.stream.readByte();
12823
- if (flags & 32768) ps.watertype = this.stream.readByte();
12824
- const statbits = this.stream.readLong();
12825
- for (let i = 0; i < 32; i++) if (statbits & 1 << i) ps.stats[i] = this.stream.readShort();
12826
- return ps;
13250
+ return this.protocolHandler.parsePlayerState(this.stream);
12827
13251
  }
12828
13252
  parsePacketEntities(delta) {
12829
13253
  const entities = this.collectPacketEntities();
@@ -12840,103 +13264,20 @@ var NetworkMessageParser = class _NetworkMessageParser {
12840
13264
  collectPacketEntities() {
12841
13265
  const entities = [];
12842
13266
  while (true) {
12843
- const bits = this.parseEntityBits();
13267
+ const bits = this.protocolHandler.parseEntityBits(this.stream);
12844
13268
  if (bits.bits & U_REMOVE) {
12845
13269
  if (bits.number === 0) break;
12846
13270
  continue;
12847
13271
  }
12848
13272
  const entity = createEmptyEntityState();
12849
- const forceParse = bits.number === 0 && !(bits.bits & U_MOREBITS1);
12850
- if (bits.number !== 0 || forceParse) {
12851
- this.parseDelta(createEmptyEntityState(), entity, bits.number, bits.bits, bits.bitsHigh);
13273
+ if (bits.number === 0) {
13274
+ break;
12852
13275
  }
12853
- if (bits.number === 0) break;
13276
+ this.protocolHandler.parseDelta(createEmptyEntityState(), entity, bits.number, bits.bits, bits.bitsHigh, this.stream);
12854
13277
  entities.push(entity);
12855
13278
  }
12856
13279
  return entities;
12857
13280
  }
12858
- parseEntityBits() {
12859
- let total = this.stream.readByte();
12860
- if (total & U_MOREBITS1) total |= this.stream.readByte() << 8;
12861
- if (total & U_MOREBITS2) total |= this.stream.readByte() << 16;
12862
- if (total & U_MOREBITS3) total |= this.stream.readByte() << 24;
12863
- let bitsHigh = 0;
12864
- if (this.protocolVersion === PROTOCOL_VERSION_RERELEASE) {
12865
- if (total & U_MOREBITS4) bitsHigh = this.stream.readByte();
12866
- }
12867
- let number;
12868
- if (total & U_NUMBER16) number = this.stream.readShort();
12869
- else number = this.stream.readByte();
12870
- return { number, bits: total, bitsHigh };
12871
- }
12872
- parseDelta(from, to, number, bits, bitsHigh = 0) {
12873
- to.number = from.number;
12874
- to.modelindex = from.modelindex;
12875
- to.modelindex2 = from.modelindex2;
12876
- to.modelindex3 = from.modelindex3;
12877
- to.modelindex4 = from.modelindex4;
12878
- to.frame = from.frame;
12879
- to.skinnum = from.skinnum;
12880
- to.effects = from.effects;
12881
- to.renderfx = from.renderfx;
12882
- to.origin.x = from.origin.x;
12883
- to.origin.y = from.origin.y;
12884
- to.origin.z = from.origin.z;
12885
- to.old_origin.x = from.origin.x;
12886
- to.old_origin.y = from.origin.y;
12887
- to.old_origin.z = from.origin.z;
12888
- to.angles.x = from.angles.x;
12889
- to.angles.y = from.angles.y;
12890
- to.angles.z = from.angles.z;
12891
- to.sound = from.sound;
12892
- to.event = from.event;
12893
- to.solid = from.solid;
12894
- to.alpha = from.alpha;
12895
- to.scale = from.scale;
12896
- to.instanceBits = from.instanceBits;
12897
- to.loopVolume = from.loopVolume;
12898
- to.loopAttenuation = from.loopAttenuation;
12899
- to.owner = from.owner;
12900
- to.oldFrame = from.oldFrame;
12901
- to.number = number;
12902
- to.bits = bits;
12903
- to.bitsHigh = bitsHigh;
12904
- if (bits & U_MODEL) to.modelindex = this.stream.readByte();
12905
- if (bits & U_MODEL2) to.modelindex2 = this.stream.readByte();
12906
- if (bits & U_MODEL3) to.modelindex3 = this.stream.readByte();
12907
- if (bits & U_MODEL4) to.modelindex4 = this.stream.readByte();
12908
- if (bits & U_FRAME8) to.frame = this.stream.readByte();
12909
- if (bits & U_FRAME16) to.frame = this.stream.readShort();
12910
- if (bits & U_SKIN8 && bits & U_SKIN16) to.skinnum = this.stream.readLong();
12911
- else if (bits & U_SKIN8) to.skinnum = this.stream.readByte();
12912
- else if (bits & U_SKIN16) to.skinnum = this.stream.readShort();
12913
- if (bits & U_EFFECTS8 && bits & U_EFFECTS16) to.effects = this.stream.readLong();
12914
- else if (bits & U_EFFECTS8) to.effects = this.stream.readByte();
12915
- else if (bits & U_EFFECTS16) to.effects = this.stream.readShort();
12916
- if (bits & U_RENDERFX8 && bits & U_RENDERFX16) to.renderfx = this.stream.readLong();
12917
- else if (bits & U_RENDERFX8) to.renderfx = this.stream.readByte();
12918
- else if (bits & U_RENDERFX16) to.renderfx = this.stream.readShort();
12919
- if (bits & U_ORIGIN1) to.origin.x = this.readCoord();
12920
- if (bits & U_ORIGIN2) to.origin.y = this.readCoord();
12921
- if (bits & U_ORIGIN3) to.origin.z = this.readCoord();
12922
- if (bits & U_ANGLE1) to.angles.x = this.readAngle();
12923
- if (bits & U_ANGLE2) to.angles.y = this.readAngle();
12924
- if (bits & U_ANGLE3) to.angles.z = this.readAngle();
12925
- if (bits & U_OLDORIGIN) this.readPos(to.old_origin);
12926
- if (bits & U_SOUND) to.sound = this.stream.readByte();
12927
- if (bits & U_EVENT) to.event = this.stream.readByte();
12928
- else to.event = 0;
12929
- if (bits & U_SOLID) to.solid = this.stream.readShort();
12930
- if (this.protocolVersion === PROTOCOL_VERSION_RERELEASE) {
12931
- if (bits & U_ALPHA) to.alpha = this.stream.readByte() / 255;
12932
- if (bits & U_SCALE) to.scale = this.stream.readFloat();
12933
- if (bits & U_INSTANCE_BITS) to.instanceBits = this.stream.readLong();
12934
- if (bits & U_LOOP_VOLUME) to.loopVolume = this.stream.readByte() / 255;
12935
- if (bitsHigh & U_LOOP_ATTENUATION_HIGH) to.loopAttenuation = this.stream.readByte() / 255;
12936
- if (bitsHigh & U_OWNER_HIGH) to.owner = this.stream.readShort();
12937
- if (bitsHigh & U_OLD_FRAME_HIGH) to.oldFrame = this.stream.readShort();
12938
- }
12939
- }
12940
13281
  };
12941
13282
 
12942
13283
  // src/demo/analysis.ts
@@ -13202,12 +13543,12 @@ var DemoCameraMode = /* @__PURE__ */ ((DemoCameraMode2) => {
13202
13543
  })(DemoCameraMode || {});
13203
13544
 
13204
13545
  // src/demo/playback.ts
13205
- var PlaybackState = /* @__PURE__ */ ((PlaybackState3) => {
13206
- PlaybackState3[PlaybackState3["Stopped"] = 0] = "Stopped";
13207
- PlaybackState3[PlaybackState3["Playing"] = 1] = "Playing";
13208
- PlaybackState3[PlaybackState3["Paused"] = 2] = "Paused";
13209
- PlaybackState3[PlaybackState3["Finished"] = 3] = "Finished";
13210
- return PlaybackState3;
13546
+ var PlaybackState = /* @__PURE__ */ ((PlaybackState2) => {
13547
+ PlaybackState2[PlaybackState2["Stopped"] = 0] = "Stopped";
13548
+ PlaybackState2[PlaybackState2["Playing"] = 1] = "Playing";
13549
+ PlaybackState2[PlaybackState2["Paused"] = 2] = "Paused";
13550
+ PlaybackState2[PlaybackState2["Finished"] = 3] = "Finished";
13551
+ return PlaybackState2;
13211
13552
  })(PlaybackState || {});
13212
13553
  var createNoOpHandler = () => ({
13213
13554
  onServerData: () => {
@@ -13928,66 +14269,63 @@ var DemoRecorder = class {
13928
14269
  return this.isRecording;
13929
14270
  }
13930
14271
  };
13931
- var PROTO34_REVERSE_MAP = {
13932
- [ServerCommand.bad]: 0,
13933
- [ServerCommand.nop]: 1,
13934
- [ServerCommand.disconnect]: 2,
13935
- [ServerCommand.reconnect]: 3,
13936
- // 4 is download? standard Q2 uses 4 for download sometimes, but let's stick to parser map (download=16).
13937
- // Let's map download to 16.
13938
- [ServerCommand.download]: 16,
13939
- [ServerCommand.frame]: 5,
13940
- [ServerCommand.inventory]: 6,
13941
- [ServerCommand.layout]: 7,
13942
- [ServerCommand.muzzleflash]: 8,
13943
- [ServerCommand.sound]: 9,
13944
- [ServerCommand.print]: 10,
13945
- [ServerCommand.stufftext]: 11,
13946
- [ServerCommand.serverdata]: 12,
13947
- [ServerCommand.configstring]: 13,
13948
- [ServerCommand.spawnbaseline]: 14,
13949
- [ServerCommand.centerprint]: 15,
13950
- // 16 is download
13951
- [ServerCommand.playerinfo]: 17,
13952
- [ServerCommand.packetentities]: 18,
13953
- [ServerCommand.deltapacketentities]: 19,
13954
- // Temp entity? Standard Q2 uses 9 for temp_entity?
13955
- // But we mapped 9 to sound.
13956
- // If we map temp_entity to 23 (arbitrary safe slot for internal tests) or assume standard Q2 layout:
13957
- // Q2: svc_temp_entity = 9. svc_sound = 10.
13958
- // My previous edit to parser.ts used 9->Sound, 10->Print.
13959
- // I should check what I committed to `parser.ts` just now.
13960
- // I committed: 9: Sound, 10: Print.
13961
- // So Writer MUST MATCH Parser.
13962
- // So if Parser says 9 is Sound, Writer must write Sound as 9.
13963
- // But what about TempEntity?
13964
- // Parser does NOT map any wire code to TempEntity in my recent edit (I commented out 23).
13965
- // So TempEntity is currently broken for Protocol 34 unless I map it.
13966
- // I will map TempEntity to 23 in both.
13967
- [ServerCommand.temp_entity]: 23,
13968
- // MuzzleFlash2?
13969
- // I'll map it to 22 (arbitrary) just to have a value, or skip if unused.
13970
- [ServerCommand.muzzleflash2]: 22
13971
- };
13972
14272
  var MessageWriter = class {
13973
- constructor() {
13974
- this.writer = new BinaryWriter();
14273
+ constructor(writer, protocol = 34) {
14274
+ this.writer = writer || new BinaryWriter(new Uint8Array(64 * 1024));
14275
+ this.protocol = protocol;
13975
14276
  }
13976
14277
  getData() {
13977
14278
  return this.writer.getData();
13978
14279
  }
13979
- writeCommand(cmd, protocolVersion = 0) {
13980
- if (protocolVersion === 34) {
13981
- const translated = PROTO34_REVERSE_MAP[cmd];
13982
- if (translated !== void 0) {
13983
- this.writer.writeByte(translated);
13984
- return;
14280
+ getOpcode(cmd) {
14281
+ if (this.protocol === 34) {
14282
+ switch (cmd) {
14283
+ case ServerCommand.serverdata:
14284
+ return 13;
14285
+ case ServerCommand.frame:
14286
+ return 5;
14287
+ case ServerCommand.playerinfo:
14288
+ return 17;
14289
+ case ServerCommand.packetentities:
14290
+ return 18;
14291
+ case ServerCommand.deltapacketentities:
14292
+ return 19;
14293
+ case ServerCommand.print:
14294
+ return 11;
14295
+ case ServerCommand.centerprint:
14296
+ return 16;
14297
+ case ServerCommand.stufftext:
14298
+ return 12;
14299
+ case ServerCommand.sound:
14300
+ return 10;
14301
+ case ServerCommand.temp_entity:
14302
+ return 9;
14303
+ case ServerCommand.configstring:
14304
+ return 14;
14305
+ case ServerCommand.spawnbaseline:
14306
+ return 15;
14307
+ case ServerCommand.layout:
14308
+ return 7;
14309
+ case ServerCommand.inventory:
14310
+ return 6;
14311
+ case ServerCommand.muzzleflash:
14312
+ return 8;
14313
+ case ServerCommand.muzzleflash2:
14314
+ return 20;
13985
14315
  }
13986
14316
  }
13987
- this.writer.writeByte(cmd);
14317
+ return cmd;
14318
+ }
14319
+ writeCommand(cmd, protocol) {
14320
+ const proto = protocol ?? this.protocol;
14321
+ if (proto === 34 || proto === 0) {
14322
+ this.writer.writeByte(this.getOpcode(cmd));
14323
+ } else {
14324
+ this.writer.writeByte(cmd);
14325
+ }
13988
14326
  }
13989
14327
  writeServerData(protocol, serverCount, attractLoop, gameDir, playerNum, levelName) {
13990
- this.writeCommand(ServerCommand.serverdata, protocol);
14328
+ this.writeCommand(ServerCommand.serverdata);
13991
14329
  this.writer.writeLong(protocol);
13992
14330
  this.writer.writeLong(serverCount);
13993
14331
  this.writer.writeByte(attractLoop);
@@ -13995,222 +14333,70 @@ var MessageWriter = class {
13995
14333
  this.writer.writeShort(playerNum);
13996
14334
  this.writer.writeString(levelName);
13997
14335
  }
13998
- writeServerDataRerelease(protocol, spawnCount, demoType, tickRate, gameDir, playerNum, levelName) {
13999
- this.writeCommand(ServerCommand.serverdata, protocol);
14000
- this.writer.writeLong(protocol);
14001
- this.writer.writeLong(spawnCount);
14002
- this.writer.writeByte(demoType);
14003
- this.writer.writeByte(tickRate);
14004
- this.writer.writeString(gameDir);
14005
- this.writer.writeShort(playerNum);
14006
- this.writer.writeString(levelName);
14007
- }
14008
- writeConfigString(index, str, protocolVersion = 0) {
14009
- this.writeCommand(ServerCommand.configstring, protocolVersion);
14336
+ writeConfigString(index, str) {
14337
+ this.writeCommand(ServerCommand.configstring);
14010
14338
  this.writer.writeShort(index);
14011
14339
  this.writer.writeString(str);
14012
14340
  }
14013
- writeSpawnBaseline(entity, protocolVersion) {
14014
- this.writeCommand(ServerCommand.spawnbaseline, protocolVersion);
14015
- this.writeEntityState(entity, null, true, protocolVersion);
14016
- }
14017
- writeStuffText(text, protocolVersion = 0) {
14018
- this.writeCommand(ServerCommand.stufftext, protocolVersion);
14341
+ writeStuffText(text) {
14342
+ this.writeCommand(ServerCommand.stufftext);
14019
14343
  this.writer.writeString(text);
14020
14344
  }
14021
- writeCenterPrint(text, protocolVersion = 0) {
14022
- this.writeCommand(ServerCommand.centerprint, protocolVersion);
14023
- this.writer.writeString(text);
14345
+ writeCenterPrint(msg) {
14346
+ this.writeCommand(ServerCommand.centerprint);
14347
+ this.writer.writeString(msg);
14024
14348
  }
14025
- writePrint(level, text, protocolVersion = 0) {
14026
- this.writeCommand(ServerCommand.print, protocolVersion);
14349
+ writePrint(level, msg) {
14350
+ this.writeCommand(ServerCommand.print);
14027
14351
  this.writer.writeByte(level);
14028
- this.writer.writeString(text);
14352
+ this.writer.writeString(msg);
14029
14353
  }
14030
- writeLayout(layout, protocolVersion = 0) {
14031
- this.writeCommand(ServerCommand.layout, protocolVersion);
14354
+ writeLayout(layout) {
14355
+ this.writeCommand(ServerCommand.layout);
14032
14356
  this.writer.writeString(layout);
14033
14357
  }
14034
- writeInventory(inventory, protocolVersion = 0) {
14035
- this.writeCommand(ServerCommand.inventory, protocolVersion);
14036
- for (let i = 0; i < 256; i++) {
14037
- this.writer.writeShort(inventory[i] || 0);
14358
+ writeInventory(inventory) {
14359
+ this.writeCommand(ServerCommand.inventory);
14360
+ for (const count of inventory) {
14361
+ this.writer.writeShort(count);
14362
+ }
14363
+ for (let i = inventory.length; i < 256; i++) {
14364
+ this.writer.writeShort(0);
14038
14365
  }
14039
14366
  }
14040
- writeMuzzleFlash(ent, weapon, protocolVersion = 0) {
14041
- this.writeCommand(ServerCommand.muzzleflash, protocolVersion);
14367
+ writeMuzzleFlash(ent, weapon) {
14368
+ this.writeCommand(ServerCommand.muzzleflash);
14042
14369
  this.writer.writeShort(ent);
14043
14370
  this.writer.writeByte(weapon);
14044
14371
  }
14045
- writeMuzzleFlash2(ent, weapon, protocolVersion = 0) {
14046
- this.writeCommand(ServerCommand.muzzleflash2, protocolVersion);
14372
+ writeMuzzleFlash2(ent, weapon) {
14373
+ this.writeCommand(ServerCommand.muzzleflash2);
14047
14374
  this.writer.writeShort(ent);
14048
14375
  this.writer.writeByte(weapon);
14049
14376
  }
14050
- writeTempEntity(type, pos, pos2, dir, cnt, color, ent, srcEnt, destEnt, protocolVersion = 0) {
14051
- this.writeCommand(ServerCommand.temp_entity, protocolVersion);
14052
- this.writer.writeByte(type);
14053
- switch (type) {
14054
- case TempEntity.EXPLOSION1:
14055
- case TempEntity.EXPLOSION2:
14056
- case TempEntity.ROCKET_EXPLOSION:
14057
- case TempEntity.GRENADE_EXPLOSION:
14058
- case TempEntity.ROCKET_EXPLOSION_WATER:
14059
- case TempEntity.GRENADE_EXPLOSION_WATER:
14060
- case TempEntity.BFG_EXPLOSION:
14061
- case TempEntity.BFG_BIGEXPLOSION:
14062
- case TempEntity.BOSSTPORT:
14063
- case TempEntity.PLASMA_EXPLOSION:
14064
- case TempEntity.PLAIN_EXPLOSION:
14065
- case TempEntity.CHAINFIST_SMOKE:
14066
- case TempEntity.TRACKER_EXPLOSION:
14067
- case TempEntity.TELEPORT_EFFECT:
14068
- case TempEntity.DBALL_GOAL:
14069
- case TempEntity.NUKEBLAST:
14070
- case TempEntity.WIDOWSPLASH:
14071
- case TempEntity.EXPLOSION1_BIG:
14072
- case TempEntity.EXPLOSION1_NP:
14073
- this.writer.writePos(pos);
14074
- break;
14075
- case TempEntity.GUNSHOT:
14076
- case TempEntity.BLOOD:
14077
- case TempEntity.BLASTER:
14078
- case TempEntity.SHOTGUN:
14079
- case TempEntity.SPARKS:
14080
- case TempEntity.BULLET_SPARKS:
14081
- case TempEntity.SCREEN_SPARKS:
14082
- case TempEntity.SHIELD_SPARKS:
14083
- case TempEntity.BLASTER2:
14084
- case TempEntity.FLECHETTE:
14085
- case TempEntity.MOREBLOOD:
14086
- case TempEntity.ELECTRIC_SPARKS:
14087
- case TempEntity.HEATBEAM_SPARKS:
14088
- case TempEntity.HEATBEAM_STEAM:
14089
- this.writer.writePos(pos);
14090
- this.writer.writeDir(dir || { x: 0, y: 0, z: 0 });
14091
- break;
14092
- case TempEntity.SPLASH:
14093
- case TempEntity.LASER_SPARKS:
14094
- case TempEntity.WELDING_SPARKS:
14095
- case TempEntity.TUNNEL_SPARKS:
14096
- this.writer.writeByte(cnt || 0);
14097
- this.writer.writePos(pos);
14098
- this.writer.writeDir(dir || { x: 0, y: 0, z: 0 });
14099
- this.writer.writeByte(color || 0);
14100
- break;
14101
- case TempEntity.BLUEHYPERBLASTER:
14102
- if (protocolVersion >= 32) {
14103
- this.writer.writePos(pos);
14104
- this.writer.writePos(pos2 || { x: 0, y: 0, z: 0 });
14105
- } else {
14106
- this.writer.writePos(pos);
14107
- this.writer.writeDir(dir || { x: 0, y: 0, z: 0 });
14108
- }
14109
- break;
14110
- case TempEntity.GREENBLOOD:
14111
- if (protocolVersion >= 32) {
14112
- this.writer.writePos(pos);
14113
- this.writer.writeDir(dir || { x: 0, y: 0, z: 0 });
14114
- } else {
14115
- this.writer.writePos(pos);
14116
- this.writer.writePos(pos2 || { x: 0, y: 0, z: 0 });
14117
- }
14118
- break;
14119
- case TempEntity.RAILTRAIL:
14120
- case TempEntity.BUBBLETRAIL:
14121
- case TempEntity.BFG_LASER:
14122
- case TempEntity.DEBUGTRAIL:
14123
- case TempEntity.BUBBLETRAIL2:
14124
- this.writer.writePos(pos);
14125
- this.writer.writePos(pos2 || { x: 0, y: 0, z: 0 });
14126
- break;
14127
- case TempEntity.PARASITE_ATTACK:
14128
- case TempEntity.MEDIC_CABLE_ATTACK:
14129
- this.writer.writeShort(ent || 0);
14130
- this.writer.writePos(pos);
14131
- this.writer.writePos(pos2 || { x: 0, y: 0, z: 0 });
14132
- break;
14133
- case TempEntity.GRAPPLE_CABLE:
14134
- this.writer.writeShort(ent || 0);
14135
- this.writer.writePos(pos);
14136
- this.writer.writePos(pos2 || { x: 0, y: 0, z: 0 });
14137
- this.writer.writePos(dir || { x: 0, y: 0, z: 0 });
14138
- break;
14139
- case TempEntity.LIGHTNING:
14140
- this.writer.writeShort(srcEnt || 0);
14141
- this.writer.writeShort(destEnt || 0);
14142
- this.writer.writePos(pos);
14143
- this.writer.writePos(pos2 || { x: 0, y: 0, z: 0 });
14144
- break;
14145
- case TempEntity.FLASHLIGHT:
14146
- this.writer.writePos(pos);
14147
- this.writer.writeShort(ent || 0);
14148
- break;
14149
- case TempEntity.FORCEWALL:
14150
- this.writer.writePos(pos);
14151
- this.writer.writePos(pos2 || { x: 0, y: 0, z: 0 });
14152
- this.writer.writeByte(color || 0);
14153
- break;
14154
- case TempEntity.STEAM:
14155
- this.writer.writeShort(-1);
14156
- this.writer.writeByte(cnt || 0);
14157
- this.writer.writePos(pos);
14158
- this.writer.writeDir(dir || { x: 0, y: 0, z: 0 });
14159
- this.writer.writeByte(color || 0);
14160
- this.writer.writeShort(0);
14161
- break;
14162
- case TempEntity.WIDOWBEAMOUT:
14163
- this.writer.writeShort(0);
14164
- // ent
14165
- // Fallthrough
14166
- case TempEntity.HEATBEAM:
14167
- case TempEntity.MONSTER_HEATBEAM:
14168
- this.writer.writeShort(ent || 0);
14169
- this.writer.writePos(pos);
14170
- this.writer.writePos(pos2 || { x: 0, y: 0, z: 0 });
14171
- this.writer.writeDir(dir || { x: 0, y: 0, z: 0 });
14172
- break;
14173
- default:
14174
- console.warn(`writeTempEntity: Unhandled type ${type}`);
14175
- break;
14176
- }
14177
- }
14178
- writeSound(mask, soundNum, volume, attenuation, offset, ent, pos, protocolVersion = 0) {
14179
- this.writeCommand(ServerCommand.sound, protocolVersion);
14377
+ writeSound(mask, soundNum, volume, attenuation, offset, ent, pos, protocol) {
14378
+ this.writeCommand(ServerCommand.sound);
14180
14379
  this.writer.writeByte(mask);
14181
14380
  this.writer.writeByte(soundNum);
14182
- if (mask & 1) this.writer.writeByte(volume || 0);
14183
- if (mask & 2) this.writer.writeByte(attenuation || 0);
14184
- if (mask & 16) this.writer.writeByte(offset || 0);
14185
- if (mask & 8) this.writer.writeShort(ent || 0);
14186
- if (mask & 4 && pos) {
14381
+ if (mask & 1) this.writer.writeByte(volume);
14382
+ if (mask & 2) this.writer.writeByte(attenuation);
14383
+ if (mask & 16) this.writer.writeByte(offset);
14384
+ if (mask & 8) this.writer.writeShort(ent);
14385
+ if (mask & 4) {
14187
14386
  this.writer.writeCoord(pos.x);
14188
14387
  this.writer.writeCoord(pos.y);
14189
14388
  this.writer.writeCoord(pos.z);
14190
14389
  }
14191
14390
  }
14192
- writeDisconnect(protocolVersion = 0) {
14193
- this.writeCommand(ServerCommand.disconnect, protocolVersion);
14194
- }
14195
- writeReconnect(protocolVersion = 0) {
14196
- this.writeCommand(ServerCommand.reconnect, protocolVersion);
14197
- }
14198
- writeFrame(frame, protocolVersion) {
14199
- this.writeCommand(ServerCommand.frame, protocolVersion);
14200
- this.writer.writeLong(frame.serverFrame);
14201
- this.writer.writeLong(frame.deltaFrame);
14202
- if (protocolVersion !== 25 && protocolVersion !== 26) {
14203
- this.writer.writeByte(frame.surpressCount);
14204
- }
14205
- this.writer.writeByte(frame.areaBytes);
14206
- if (frame.areaBytes > 0) {
14207
- this.writer.writeBytes(frame.areaBits);
14391
+ writeTempEntity(type, pos, pos2, dir, cnt, color, ent, srcEnt, destEnt) {
14392
+ this.writeCommand(ServerCommand.temp_entity);
14393
+ this.writer.writeByte(type);
14394
+ if (pos) {
14395
+ this.writer.writePos(pos);
14208
14396
  }
14209
- this.writeCommand(ServerCommand.playerinfo, protocolVersion);
14210
- this.writePlayerState(frame.playerState);
14211
- this.writePacketEntities(frame.packetEntities.entities, frame.packetEntities.delta, protocolVersion);
14212
14397
  }
14213
14398
  writePlayerState(ps) {
14399
+ this.writeCommand(ServerCommand.playerinfo);
14214
14400
  let flags = 0;
14215
14401
  if (ps.pm_type !== 0) flags |= 1;
14216
14402
  if (ps.origin.x !== 0 || ps.origin.y !== 0 || ps.origin.z !== 0) flags |= 2;
@@ -14222,55 +14408,56 @@ var MessageWriter = class {
14222
14408
  if (ps.viewoffset.x !== 0 || ps.viewoffset.y !== 0 || ps.viewoffset.z !== 0) flags |= 128;
14223
14409
  if (ps.viewangles.x !== 0 || ps.viewangles.y !== 0 || ps.viewangles.z !== 0) flags |= 256;
14224
14410
  if (ps.kick_angles.x !== 0 || ps.kick_angles.y !== 0 || ps.kick_angles.z !== 0) flags |= 512;
14225
- if (ps.blend[0] !== 0 || ps.blend[1] !== 0 || ps.blend[2] !== 0 || ps.blend[3] !== 0) flags |= 1024;
14226
14411
  if (ps.gun_index !== 0) flags |= 4096;
14227
14412
  if (ps.gun_frame !== 0 || ps.gun_offset.x !== 0 || ps.gun_offset.y !== 0 || ps.gun_offset.z !== 0 || ps.gun_angles.x !== 0 || ps.gun_angles.y !== 0 || ps.gun_angles.z !== 0) flags |= 8192;
14413
+ if (ps.blend[0] !== 0 || ps.blend[1] !== 0 || ps.blend[2] !== 0 || ps.blend[3] !== 0) flags |= 1024;
14228
14414
  if (ps.fov !== 0) flags |= 2048;
14229
14415
  if (ps.rdflags !== 0) flags |= 16384;
14416
+ if (ps.watertype !== 0) flags |= 32768;
14230
14417
  this.writer.writeShort(flags);
14231
14418
  if (flags & 1) this.writer.writeByte(ps.pm_type);
14232
14419
  if (flags & 2) {
14233
- this.writer.writeCoord(ps.origin.x);
14234
- this.writer.writeCoord(ps.origin.y);
14235
- this.writer.writeCoord(ps.origin.z);
14420
+ this.writer.writeShort(ps.origin.x / 0.125);
14421
+ this.writer.writeShort(ps.origin.y / 0.125);
14422
+ this.writer.writeShort(ps.origin.z / 0.125);
14236
14423
  }
14237
14424
  if (flags & 4) {
14238
- this.writer.writeCoord(ps.velocity.x);
14239
- this.writer.writeCoord(ps.velocity.y);
14240
- this.writer.writeCoord(ps.velocity.z);
14425
+ this.writer.writeShort(ps.velocity.x / 0.125);
14426
+ this.writer.writeShort(ps.velocity.y / 0.125);
14427
+ this.writer.writeShort(ps.velocity.z / 0.125);
14241
14428
  }
14242
14429
  if (flags & 8) this.writer.writeByte(ps.pm_time);
14243
14430
  if (flags & 16) this.writer.writeByte(ps.pm_flags);
14244
14431
  if (flags & 32) this.writer.writeShort(ps.gravity);
14245
14432
  if (flags & 64) {
14246
- this.writer.writeShort(Math.round(ps.delta_angles.x * (32768 / 180)));
14247
- this.writer.writeShort(Math.round(ps.delta_angles.y * (32768 / 180)));
14248
- this.writer.writeShort(Math.round(ps.delta_angles.z * (32768 / 180)));
14433
+ this.writer.writeShort(ps.delta_angles.x / (180 / 32768));
14434
+ this.writer.writeShort(ps.delta_angles.y / (180 / 32768));
14435
+ this.writer.writeShort(ps.delta_angles.z / (180 / 32768));
14249
14436
  }
14250
14437
  if (flags & 128) {
14251
- this.writer.writeChar(Math.round(ps.viewoffset.x * 4));
14252
- this.writer.writeChar(Math.round(ps.viewoffset.y * 4));
14253
- this.writer.writeChar(Math.round(ps.viewoffset.z * 4));
14438
+ this.writer.writeByte(ps.viewoffset.x / 0.25);
14439
+ this.writer.writeByte(ps.viewoffset.y / 0.25);
14440
+ this.writer.writeByte(ps.viewoffset.z / 0.25);
14254
14441
  }
14255
14442
  if (flags & 256) {
14256
- this.writer.writeAngle16(ps.viewangles.x);
14257
- this.writer.writeAngle16(ps.viewangles.y);
14258
- this.writer.writeAngle16(ps.viewangles.z);
14443
+ this.writer.writeShort(ps.viewangles.x / (360 / 65536));
14444
+ this.writer.writeShort(ps.viewangles.y / (360 / 65536));
14445
+ this.writer.writeShort(ps.viewangles.z / (360 / 65536));
14259
14446
  }
14260
14447
  if (flags & 512) {
14261
- this.writer.writeChar(Math.round(ps.kick_angles.x * 4));
14262
- this.writer.writeChar(Math.round(ps.kick_angles.y * 4));
14263
- this.writer.writeChar(Math.round(ps.kick_angles.z * 4));
14448
+ this.writer.writeByte(ps.kick_angles.x / 0.25);
14449
+ this.writer.writeByte(ps.kick_angles.y / 0.25);
14450
+ this.writer.writeByte(ps.kick_angles.z / 0.25);
14264
14451
  }
14265
14452
  if (flags & 4096) this.writer.writeByte(ps.gun_index);
14266
14453
  if (flags & 8192) {
14267
14454
  this.writer.writeByte(ps.gun_frame);
14268
- this.writer.writeChar(Math.round(ps.gun_offset.x * 4));
14269
- this.writer.writeChar(Math.round(ps.gun_offset.y * 4));
14270
- this.writer.writeChar(Math.round(ps.gun_offset.z * 4));
14271
- this.writer.writeChar(Math.round(ps.gun_angles.x * 4));
14272
- this.writer.writeChar(Math.round(ps.gun_angles.y * 4));
14273
- this.writer.writeChar(Math.round(ps.gun_angles.z * 4));
14455
+ this.writer.writeByte(ps.gun_offset.x / 0.25);
14456
+ this.writer.writeByte(ps.gun_offset.y / 0.25);
14457
+ this.writer.writeByte(ps.gun_offset.z / 0.25);
14458
+ this.writer.writeByte(ps.gun_angles.x / 0.25);
14459
+ this.writer.writeByte(ps.gun_angles.y / 0.25);
14460
+ this.writer.writeByte(ps.gun_angles.z / 0.25);
14274
14461
  }
14275
14462
  if (flags & 1024) {
14276
14463
  this.writer.writeByte(ps.blend[0]);
@@ -14280,6 +14467,7 @@ var MessageWriter = class {
14280
14467
  }
14281
14468
  if (flags & 2048) this.writer.writeByte(ps.fov);
14282
14469
  if (flags & 16384) this.writer.writeByte(ps.rdflags);
14470
+ if (flags & 32768) this.writer.writeByte(ps.watertype);
14283
14471
  let statbits = 0;
14284
14472
  for (let i = 0; i < 32; i++) {
14285
14473
  if (ps.stats[i] !== 0) statbits |= 1 << i;
@@ -14289,110 +14477,119 @@ var MessageWriter = class {
14289
14477
  if (statbits & 1 << i) this.writer.writeShort(ps.stats[i]);
14290
14478
  }
14291
14479
  }
14292
- writePacketEntities(entities, delta, protocolVersion) {
14293
- this.writeCommand(delta ? ServerCommand.deltapacketentities : ServerCommand.packetentities, protocolVersion);
14480
+ writePacketEntities(entities, delta, protocol) {
14481
+ this.writeCommand(delta ? ServerCommand.deltapacketentities : ServerCommand.packetentities);
14294
14482
  for (const ent of entities) {
14295
- const force = !delta;
14296
- this.writeEntityState(ent, null, force, protocolVersion);
14483
+ this.writeDeltaEntity(createEmptyEntityState(), ent, true);
14297
14484
  }
14298
14485
  this.writer.writeShort(0);
14299
14486
  }
14300
- writeEntityState(to, from, force, protocolVersion) {
14487
+ writeFrame(frame, protocol) {
14488
+ this.writeCommand(ServerCommand.frame);
14489
+ this.writer.writeLong(frame.serverFrame);
14490
+ this.writer.writeLong(frame.deltaFrame);
14491
+ if (protocol !== 26 && protocol !== 25) {
14492
+ this.writer.writeByte(frame.surpressCount);
14493
+ }
14494
+ this.writer.writeByte(frame.areaBytes);
14495
+ this.writer.writeBytes(frame.areaBits);
14496
+ this.writePlayerState(frame.playerState);
14497
+ this.writePacketEntities(frame.packetEntities.entities, frame.packetEntities.delta, protocol);
14498
+ }
14499
+ writeDeltaEntity(from, to, force) {
14301
14500
  let bits = 0;
14302
14501
  let bitsHigh = 0;
14303
- if (to.bits !== 0 && !force) {
14304
- bits = to.bits;
14305
- bitsHigh = to.bitsHigh;
14306
- } else {
14307
- if (to.modelindex !== 0) bits |= U_MODEL;
14308
- if (to.modelindex2 !== 0) bits |= U_MODEL2;
14309
- if (to.modelindex3 !== 0) bits |= U_MODEL3;
14310
- if (to.modelindex4 !== 0) bits |= U_MODEL4;
14311
- if (to.frame !== 0) {
14312
- if (to.frame >= 256) bits |= U_FRAME16;
14313
- else bits |= U_FRAME8;
14314
- }
14315
- if (to.skinnum !== 0) {
14316
- if (to.skinnum >= 256) bits |= U_SKIN16;
14317
- else bits |= U_SKIN8;
14318
- }
14319
- if (to.effects !== 0) {
14320
- if (to.effects >= 256) bits |= U_EFFECTS16;
14321
- else bits |= U_EFFECTS8;
14322
- }
14323
- if (to.renderfx !== 0) {
14324
- if (to.renderfx >= 256) bits |= U_RENDERFX16;
14325
- else bits |= U_RENDERFX8;
14326
- }
14502
+ if (to.modelindex !== from.modelindex || force) bits |= U_MODEL;
14503
+ if (to.modelindex2 !== from.modelindex2 || force) bits |= U_MODEL2;
14504
+ if (to.modelindex3 !== from.modelindex3 || force) bits |= U_MODEL3;
14505
+ if (to.modelindex4 !== from.modelindex4 || force) bits |= U_MODEL4;
14506
+ if (to.frame !== from.frame || force) {
14507
+ if (to.frame >= 256) bits |= U_FRAME16;
14508
+ else bits |= U_FRAME8;
14509
+ }
14510
+ if (to.skinnum !== from.skinnum || force) {
14511
+ if (to.skinnum >= 256) bits |= U_SKIN16;
14512
+ else bits |= U_SKIN8;
14513
+ }
14514
+ if (to.effects !== from.effects || force) {
14515
+ if (to.effects >= 256) bits |= U_EFFECTS16;
14516
+ else bits |= U_EFFECTS8;
14517
+ }
14518
+ if (to.renderfx !== from.renderfx || force) {
14519
+ if (to.renderfx >= 256) bits |= U_RENDERFX16;
14520
+ else bits |= U_RENDERFX8;
14521
+ }
14522
+ if (to.origin.x !== from.origin.x || force) {
14327
14523
  if (to.origin.x !== 0) bits |= U_ORIGIN1;
14524
+ }
14525
+ if (to.origin.y !== from.origin.y || force) {
14328
14526
  if (to.origin.y !== 0) bits |= U_ORIGIN2;
14527
+ }
14528
+ if (to.origin.z !== from.origin.z || force) {
14329
14529
  if (to.origin.z !== 0) bits |= U_ORIGIN3;
14530
+ }
14531
+ if (to.angles.x !== from.angles.x || force) {
14330
14532
  if (to.angles.x !== 0) bits |= U_ANGLE1;
14533
+ }
14534
+ if (to.angles.y !== from.angles.y || force) {
14331
14535
  if (to.angles.y !== 0) bits |= U_ANGLE2;
14536
+ }
14537
+ if (to.angles.z !== from.angles.z || force) {
14332
14538
  if (to.angles.z !== 0) bits |= U_ANGLE3;
14333
- if (to.old_origin.x !== 0 || to.old_origin.y !== 0 || to.old_origin.z !== 0) bits |= U_OLDORIGIN;
14334
- if (to.sound !== 0) bits |= U_SOUND;
14335
- if (to.event !== 0) bits |= U_EVENT;
14336
- if (to.solid !== 0) bits |= U_SOLID;
14337
- if (protocolVersion >= 2023) {
14338
- if (to.alpha !== 0) bits |= U_ALPHA;
14339
- if (to.scale !== 0) bits |= U_SCALE;
14340
- if (to.instanceBits !== 0) bits |= U_INSTANCE_BITS;
14341
- if (to.loopVolume !== 0) bits |= U_LOOP_VOLUME;
14342
- if (to.loopAttenuation !== 0) bitsHigh |= U_LOOP_ATTENUATION_HIGH;
14343
- if (to.owner !== 0) bitsHigh |= U_OWNER_HIGH;
14344
- if (to.oldFrame !== 0) bitsHigh |= U_OLD_FRAME_HIGH;
14345
- }
14346
- if (to.number >= 256) bits |= U_NUMBER16;
14347
- }
14348
- if (bitsHigh !== 0) bits |= U_MOREBITS4;
14349
- if ((bits & 4278190080) !== 0) bits |= U_MOREBITS3;
14350
- if ((bits & 16711680) !== 0) bits |= U_MOREBITS2;
14351
- if ((bits & 65280) !== 0) bits |= U_MOREBITS1;
14539
+ }
14540
+ if (to.sound !== from.sound || force) bits |= U_SOUND;
14541
+ if (to.event !== from.event || force) bits |= U_EVENT;
14542
+ if (to.solid !== from.solid || force) bits |= U_SOLID;
14543
+ if (this.protocol !== 34) {
14544
+ if (to.alpha !== from.alpha || force) bits |= U_ALPHA;
14545
+ if (to.scale !== from.scale || force) bits |= U_SCALE;
14546
+ if (to.instanceBits !== from.instanceBits || force) bits |= U_INSTANCE_BITS;
14547
+ if (to.loopVolume !== from.loopVolume || force) bits |= U_LOOP_VOLUME;
14548
+ if (to.loopAttenuation !== from.loopAttenuation || force) bitsHigh |= U_LOOP_ATTENUATION_HIGH;
14549
+ if (to.owner !== from.owner || force) bitsHigh |= U_OWNER_HIGH;
14550
+ if (to.oldFrame !== from.oldFrame || force) bitsHigh |= U_OLD_FRAME_HIGH;
14551
+ }
14552
+ if (bitsHigh > 0) bits |= U_MOREBITS4;
14553
+ if (bits & 4278190080) bits |= U_MOREBITS3;
14554
+ if (bits & 4294901760) bits |= U_MOREBITS2;
14555
+ if (bits & 4294967040) bits |= U_MOREBITS1;
14352
14556
  this.writer.writeByte(bits & 255);
14353
14557
  if (bits & U_MOREBITS1) this.writer.writeByte(bits >> 8 & 255);
14354
14558
  if (bits & U_MOREBITS2) this.writer.writeByte(bits >> 16 & 255);
14355
14559
  if (bits & U_MOREBITS3) this.writer.writeByte(bits >> 24 & 255);
14356
- if (protocolVersion >= 2023 && bits & U_MOREBITS4) {
14357
- this.writer.writeByte(bitsHigh & 255);
14560
+ if (bits & U_MOREBITS4) this.writer.writeByte(bitsHigh & 255);
14561
+ if (to.number >= 256) {
14562
+ this.writer.writeShort(to.number);
14563
+ } else {
14564
+ this.writer.writeByte(to.number);
14358
14565
  }
14359
- if (bits & U_NUMBER16) this.writer.writeShort(to.number);
14360
- else this.writer.writeByte(to.number);
14361
14566
  if (bits & U_MODEL) this.writer.writeByte(to.modelindex);
14362
14567
  if (bits & U_MODEL2) this.writer.writeByte(to.modelindex2);
14363
14568
  if (bits & U_MODEL3) this.writer.writeByte(to.modelindex3);
14364
14569
  if (bits & U_MODEL4) this.writer.writeByte(to.modelindex4);
14365
14570
  if (bits & U_FRAME8) this.writer.writeByte(to.frame);
14366
14571
  if (bits & U_FRAME16) this.writer.writeShort(to.frame);
14367
- if (bits & U_SKIN8 && bits & U_SKIN16) this.writer.writeLong(to.skinnum);
14368
- else if (bits & U_SKIN8) this.writer.writeByte(to.skinnum);
14369
- else if (bits & U_SKIN16) this.writer.writeShort(to.skinnum);
14370
- if (bits & U_EFFECTS8 && bits & U_EFFECTS16) this.writer.writeLong(to.effects);
14371
- else if (bits & U_EFFECTS8) this.writer.writeByte(to.effects);
14372
- else if (bits & U_EFFECTS16) this.writer.writeShort(to.effects);
14373
- if (bits & U_RENDERFX8 && bits & U_RENDERFX16) this.writer.writeLong(to.renderfx);
14374
- else if (bits & U_RENDERFX8) this.writer.writeByte(to.renderfx);
14375
- else if (bits & U_RENDERFX16) this.writer.writeShort(to.renderfx);
14572
+ if (bits & U_SKIN8) this.writer.writeByte(to.skinnum);
14573
+ if (bits & U_SKIN16) this.writer.writeShort(to.skinnum);
14574
+ if (bits & U_EFFECTS8) this.writer.writeByte(to.effects);
14575
+ if (bits & U_EFFECTS16) this.writer.writeShort(to.effects);
14576
+ if (bits & U_RENDERFX8) this.writer.writeByte(to.renderfx);
14577
+ if (bits & U_RENDERFX16) this.writer.writeShort(to.renderfx);
14376
14578
  if (bits & U_ORIGIN1) this.writer.writeCoord(to.origin.x);
14377
14579
  if (bits & U_ORIGIN2) this.writer.writeCoord(to.origin.y);
14378
14580
  if (bits & U_ORIGIN3) this.writer.writeCoord(to.origin.z);
14379
14581
  if (bits & U_ANGLE1) this.writer.writeAngle(to.angles.x);
14380
14582
  if (bits & U_ANGLE2) this.writer.writeAngle(to.angles.y);
14381
14583
  if (bits & U_ANGLE3) this.writer.writeAngle(to.angles.z);
14382
- if (bits & U_OLDORIGIN) {
14383
- this.writer.writeCoord(to.old_origin.x);
14384
- this.writer.writeCoord(to.old_origin.y);
14385
- this.writer.writeCoord(to.old_origin.z);
14386
- }
14387
- if (bits & U_SOUND) this.writer.writeByte(to.sound);
14388
- if (bits & U_EVENT) this.writer.writeByte(to.event);
14584
+ if (bits & U_SOUND) this.writer.writeByte(to.sound ?? 0);
14585
+ if (bits & U_EVENT) this.writer.writeByte(to.event ?? 0);
14389
14586
  if (bits & U_SOLID) this.writer.writeShort(to.solid);
14390
- if (protocolVersion >= 2023) {
14391
- if (bits & U_ALPHA) this.writer.writeByte(Math.round(to.alpha * 255));
14587
+ if (this.protocol !== 34) {
14588
+ if (bits & U_ALPHA) this.writer.writeByte(to.alpha * 255);
14392
14589
  if (bits & U_SCALE) this.writer.writeFloat(to.scale);
14393
14590
  if (bits & U_INSTANCE_BITS) this.writer.writeLong(to.instanceBits);
14394
- if (bits & U_LOOP_VOLUME) this.writer.writeByte(Math.round(to.loopVolume * 255));
14395
- if (bitsHigh & U_LOOP_ATTENUATION_HIGH) this.writer.writeByte(Math.round(to.loopAttenuation * 255));
14591
+ if (bits & U_LOOP_VOLUME) this.writer.writeByte(to.loopVolume * 255);
14592
+ if (bitsHigh & U_LOOP_ATTENUATION_HIGH) this.writer.writeByte(to.loopAttenuation * 255);
14396
14593
  if (bitsHigh & U_OWNER_HIGH) this.writer.writeShort(to.owner);
14397
14594
  if (bitsHigh & U_OLD_FRAME_HIGH) this.writer.writeShort(to.oldFrame);
14398
14595
  }
@@ -14429,294 +14626,210 @@ var DemoValidator = class {
14429
14626
  return { valid: true, version };
14430
14627
  }
14431
14628
  };
14432
- var DemoWriter = class {
14433
- constructor() {
14434
- this.writer = new BinaryWriter();
14435
- }
14436
- writeBlock(data) {
14437
- this.writer.writeLong(data.byteLength);
14438
- this.writer.writeBytes(data);
14439
- }
14440
- writeEOF() {
14441
- this.writer.writeLong(-1);
14442
- }
14443
- getData() {
14444
- return this.writer.getData();
14445
- }
14446
- };
14447
-
14448
- // src/demo/delta.ts
14449
- function applyEntityDelta(to, from) {
14450
- const bits = from.bits;
14451
- const bitsHigh = from.bitsHigh;
14452
- to.number = from.number;
14453
- if (bits & U_MODEL) to.modelindex = from.modelindex;
14454
- if (bits & U_MODEL2) to.modelindex2 = from.modelindex2;
14455
- if (bits & U_MODEL3) to.modelindex3 = from.modelindex3;
14456
- if (bits & U_MODEL4) to.modelindex4 = from.modelindex4;
14457
- if (bits & U_FRAME8) to.frame = from.frame;
14458
- if (bits & U_FRAME16) to.frame = from.frame;
14459
- if (bits & U_SKIN8 || bits & U_SKIN16) to.skinnum = from.skinnum;
14460
- if (bits & U_EFFECTS8 || bits & U_EFFECTS16) to.effects = from.effects;
14461
- if (bits & U_RENDERFX8 || bits & U_RENDERFX16) to.renderfx = from.renderfx;
14462
- if (bits & U_ORIGIN1) to.origin.x = from.origin.x;
14463
- if (bits & U_ORIGIN2) to.origin.y = from.origin.y;
14464
- if (bits & U_ORIGIN3) to.origin.z = from.origin.z;
14465
- if (bits & U_ANGLE1) to.angles.x = from.angles.x;
14466
- if (bits & U_ANGLE2) to.angles.y = from.angles.y;
14467
- if (bits & U_ANGLE3) to.angles.z = from.angles.z;
14468
- if (bits & U_OLDORIGIN) {
14469
- to.old_origin.x = from.old_origin.x;
14470
- to.old_origin.y = from.old_origin.y;
14471
- to.old_origin.z = from.old_origin.z;
14472
- }
14473
- if (bits & U_SOUND) to.sound = from.sound;
14474
- if (bits & U_EVENT) to.event = from.event;
14475
- if (bits & U_SOLID) to.solid = from.solid;
14476
- if (bits & U_ALPHA) to.alpha = from.alpha;
14477
- if (bits & U_SCALE) to.scale = from.scale;
14478
- if (bits & U_INSTANCE_BITS) to.instanceBits = from.instanceBits;
14479
- if (bits & U_LOOP_VOLUME) to.loopVolume = from.loopVolume;
14480
- if (bitsHigh & U_LOOP_ATTENUATION_HIGH) to.loopAttenuation = from.loopAttenuation;
14481
- if (bitsHigh & U_OWNER_HIGH) to.owner = from.owner;
14482
- if (bitsHigh & U_OLD_FRAME_HIGH) to.oldFrame = from.oldFrame;
14483
- }
14484
14629
 
14485
14630
  // src/demo/clipper.ts
14486
14631
  var DemoClipper = class {
14487
- /**
14488
- * Extracts a raw clip from a demo between two offsets.
14489
- * Simply copies the message blocks.
14490
- */
14491
- extractClip(demo, start, end, controller) {
14492
- const reader = new DemoReader(demo.buffer);
14493
- const startFrame = start.type === "frame" ? start.frame : controller.timeToFrame(start.seconds);
14494
- const endFrame = end.type === "frame" ? end.frame : controller.timeToFrame(end.seconds);
14495
- if (!reader.seekToMessage(startFrame)) {
14496
- throw new Error(`Start frame ${startFrame} out of bounds`);
14497
- }
14498
- const startByteOffset = reader.getOffset();
14499
- let endByteOffset = demo.byteLength;
14500
- if (reader.seekToMessage(endFrame + 1)) {
14501
- endByteOffset = reader.getOffset();
14502
- }
14503
- const clipData = demo.slice(startByteOffset, endByteOffset);
14504
- const result = new Uint8Array(clipData.length + 4);
14505
- result.set(clipData);
14506
- const view = new DataView(result.buffer);
14507
- view.setInt32(clipData.length, -1, true);
14508
- return result;
14509
- }
14510
- extractDemoRange(demo, startFrame, endFrame) {
14511
- const controller = new DemoPlaybackController();
14512
- controller.loadDemo(demo.buffer);
14513
- return this.extractClip(demo, { type: "frame", frame: startFrame }, { type: "frame", frame: endFrame }, controller);
14632
+ constructor(buffer) {
14633
+ this.frames = [];
14634
+ this.configStrings = /* @__PURE__ */ new Map();
14635
+ this.baselines = /* @__PURE__ */ new Map();
14636
+ this.currentEntities = /* @__PURE__ */ new Map();
14637
+ if (buffer) {
14638
+ const sb = new StreamingBuffer(buffer.byteLength);
14639
+ sb.append(new Uint8Array(buffer));
14640
+ sb.setReadPosition(0);
14641
+ this.parser = new NetworkMessageParser(sb, this);
14642
+ } else {
14643
+ this.parser = new NetworkMessageParser(new StreamingBuffer(), this);
14644
+ }
14514
14645
  }
14515
- /**
14516
- * Captures the world state at a specific offset by playing the demo up to that point.
14517
- */
14518
- async captureWorldState(demo, atOffset) {
14519
- const controller = new DemoPlaybackController();
14520
- controller.loadDemo(demo.buffer);
14521
- const state = {
14522
- serverData: {
14523
- protocol: 0,
14524
- serverCount: 0,
14525
- attractLoop: 0,
14526
- gameDir: "",
14527
- playerNum: 0,
14528
- levelName: ""
14529
- },
14530
- configStrings: /* @__PURE__ */ new Map(),
14531
- entityBaselines: /* @__PURE__ */ new Map(),
14532
- playerState: createEmptyProtocolPlayerState(),
14533
- currentEntities: /* @__PURE__ */ new Map(),
14534
- currentFrameNumber: 0
14535
- };
14536
- const handler = {
14537
- onServerData: (protocol, serverCount, attractLoop, gameDir, playerNum, levelName, tickRate, demoType) => {
14538
- state.serverData = { protocol, serverCount, attractLoop, gameDir, playerNum, levelName, tickRate, demoType };
14539
- },
14540
- onConfigString: (index, str) => {
14541
- state.configStrings.set(index, str);
14542
- },
14543
- onSpawnBaseline: (entity) => {
14544
- state.entityBaselines.set(entity.number, { ...entity });
14545
- },
14546
- onFrame: (frame) => {
14547
- state.playerState = { ...frame.playerState };
14548
- state.currentFrameNumber = frame.serverFrame;
14549
- if (!frame.packetEntities.delta) {
14550
- state.currentEntities.clear();
14551
- }
14552
- const newEntities = /* @__PURE__ */ new Map();
14553
- if (frame.packetEntities.delta) {
14554
- for (const [key, val] of state.currentEntities) {
14555
- newEntities.set(key, val);
14556
- }
14557
- }
14558
- for (const deltaEnt of frame.packetEntities.entities) {
14559
- if (deltaEnt.bits & U_REMOVE) {
14560
- newEntities.delete(deltaEnt.number);
14561
- continue;
14562
- }
14563
- let prev = newEntities.get(deltaEnt.number);
14564
- if (!prev) {
14565
- const baseline = state.entityBaselines.get(deltaEnt.number);
14566
- if (baseline) {
14567
- prev = { ...baseline };
14568
- } else {
14569
- prev = createEmptyEntityState();
14570
- prev.number = deltaEnt.number;
14571
- }
14572
- } else {
14573
- prev = { ...prev };
14646
+ // Implementation of extractClip matching api.ts usage: extractClip(demoData, start, end, controller)
14647
+ extractClip(demoData, start, end, controller) {
14648
+ const reader = new DemoReader(demoData.buffer);
14649
+ const outputParts = [];
14650
+ let totalLength = 0;
14651
+ const startFrame = start.frame ?? -1;
14652
+ const endFrame = end.frame ?? Number.MAX_SAFE_INTEGER;
14653
+ let currentProtocol = 0;
14654
+ let blockIndex = 0;
14655
+ while (reader.nextBlock()) {
14656
+ const block = reader.getBlock();
14657
+ const blockData = block.data;
14658
+ let keepBlock = false;
14659
+ let frameNum = -1;
14660
+ let parsedSuccessfully = false;
14661
+ const probeHandler = {
14662
+ onServerData: (protocol) => {
14663
+ currentProtocol = protocol;
14664
+ keepBlock = true;
14665
+ parsedSuccessfully = true;
14666
+ },
14667
+ onConfigString: () => {
14668
+ keepBlock = true;
14669
+ parsedSuccessfully = true;
14670
+ },
14671
+ onSpawnBaseline: () => {
14672
+ keepBlock = true;
14673
+ parsedSuccessfully = true;
14674
+ },
14675
+ onFrame: (f) => {
14676
+ frameNum = f.serverFrame;
14677
+ parsedSuccessfully = true;
14678
+ if (frameNum >= startFrame && frameNum <= endFrame) {
14679
+ keepBlock = true;
14574
14680
  }
14575
- applyEntityDelta(prev, deltaEnt);
14576
- newEntities.set(deltaEnt.number, prev);
14681
+ },
14682
+ onCenterPrint: () => {
14683
+ parsedSuccessfully = true;
14684
+ },
14685
+ onStuffText: () => {
14686
+ parsedSuccessfully = true;
14687
+ },
14688
+ onPrint: () => {
14689
+ parsedSuccessfully = true;
14690
+ },
14691
+ onSound: () => {
14692
+ parsedSuccessfully = true;
14693
+ },
14694
+ onTempEntity: () => {
14695
+ parsedSuccessfully = true;
14696
+ },
14697
+ onLayout: () => {
14698
+ parsedSuccessfully = true;
14699
+ },
14700
+ onInventory: () => {
14701
+ parsedSuccessfully = true;
14702
+ },
14703
+ onMuzzleFlash: () => {
14704
+ parsedSuccessfully = true;
14705
+ },
14706
+ onMuzzleFlash2: () => {
14707
+ parsedSuccessfully = true;
14708
+ },
14709
+ onDisconnect: () => {
14710
+ parsedSuccessfully = true;
14711
+ },
14712
+ onReconnect: () => {
14713
+ parsedSuccessfully = true;
14714
+ },
14715
+ onDownload: () => {
14716
+ parsedSuccessfully = true;
14577
14717
  }
14578
- state.currentEntities = newEntities;
14579
- },
14580
- onCenterPrint: () => {
14581
- },
14582
- onStuffText: () => {
14583
- },
14584
- onPrint: () => {
14585
- },
14586
- onSound: () => {
14587
- },
14588
- onTempEntity: () => {
14589
- },
14590
- onLayout: () => {
14591
- },
14592
- onInventory: () => {
14593
- },
14594
- onMuzzleFlash: () => {
14595
- },
14596
- onMuzzleFlash2: () => {
14597
- },
14598
- onDisconnect: () => {
14599
- },
14600
- onReconnect: () => {
14601
- },
14602
- onDownload: () => {
14603
- }
14604
- };
14605
- controller.setHandler(handler);
14606
- const targetFrame = atOffset.type === "frame" ? atOffset.frame : controller.timeToFrame(atOffset.seconds);
14607
- controller.seek(targetFrame);
14608
- return state;
14609
- }
14610
- extractStandaloneClip(demo, start, end, worldState) {
14611
- const demoWriter = new DemoWriter();
14612
- const headerWriter = new MessageWriter();
14613
- const controller = new DemoPlaybackController();
14614
- controller.loadDemo(demo.buffer);
14615
- const startFrame = start.type === "frame" ? start.frame : controller.timeToFrame(start.seconds);
14616
- const endFrame = end.type === "frame" ? end.frame : controller.timeToFrame(end.seconds);
14617
- const { serverData } = worldState;
14618
- if (serverData.protocol >= 2023) {
14619
- headerWriter.writeServerDataRerelease(
14620
- serverData.protocol,
14621
- serverData.serverCount,
14622
- serverData.demoType || 0,
14623
- serverData.tickRate || 10,
14624
- serverData.gameDir,
14625
- serverData.playerNum,
14626
- serverData.levelName
14627
- );
14628
- } else {
14629
- headerWriter.writeServerData(
14630
- serverData.protocol,
14631
- serverData.serverCount,
14632
- serverData.attractLoop,
14633
- serverData.gameDir,
14634
- serverData.playerNum,
14635
- serverData.levelName
14636
- );
14637
- }
14638
- for (const [index, str] of worldState.configStrings) {
14639
- headerWriter.writeConfigString(index, str, serverData.protocol);
14640
- }
14641
- for (const entity of worldState.entityBaselines.values()) {
14642
- headerWriter.writeSpawnBaseline(entity, serverData.protocol);
14643
- }
14644
- const entities = Array.from(worldState.currentEntities.values());
14645
- const frame0 = {
14646
- serverFrame: 0,
14647
- // Rebase to 0
14648
- deltaFrame: -1,
14649
- surpressCount: 0,
14650
- areaBytes: 0,
14651
- areaBits: new Uint8Array(0),
14652
- // TODO: capture area bits?
14653
- playerState: worldState.playerState,
14654
- packetEntities: {
14655
- delta: false,
14656
- entities
14657
- // These are full entity states, writeFrame will handle them
14718
+ };
14719
+ const sb = new StreamingBuffer(blockData.getLength());
14720
+ sb.append(blockData.readData(blockData.getLength()));
14721
+ sb.setReadPosition(0);
14722
+ blockData.seek(0);
14723
+ const probeParser = new NetworkMessageParser(sb, probeHandler);
14724
+ if (currentProtocol > 0) probeParser.setProtocolVersion(currentProtocol);
14725
+ try {
14726
+ probeParser.parseMessage();
14727
+ } catch (e) {
14658
14728
  }
14659
- };
14660
- headerWriter.writeFrame(frame0, serverData.protocol);
14661
- demoWriter.writeBlock(headerWriter.getData());
14662
- const frameMap = /* @__PURE__ */ new Map();
14663
- frameMap.set(startFrame, 0);
14664
- const reader = new DemoReader(demo.buffer);
14665
- if (reader.seekToMessage(startFrame + 1)) {
14666
- let messageIndex = startFrame + 1;
14667
- while (messageIndex <= endFrame && reader.nextBlock()) {
14668
- const block = reader.getBlock();
14669
- const blockStream = block.data;
14670
- const blockWriter = new MessageWriter();
14671
- const passthroughHandler = {
14672
- onServerData: () => {
14673
- },
14674
- onConfigString: (idx, str) => blockWriter.writeConfigString(idx, str, serverData.protocol),
14675
- onSpawnBaseline: (ent) => blockWriter.writeSpawnBaseline(ent, serverData.protocol),
14676
- onCenterPrint: (msg) => blockWriter.writeCenterPrint(msg, serverData.protocol),
14677
- onStuffText: (txt) => blockWriter.writeStuffText(txt, serverData.protocol),
14678
- onPrint: (lvl, msg) => blockWriter.writePrint(lvl, msg, serverData.protocol),
14679
- onSound: (mask, s, v, a, o, e, p) => blockWriter.writeSound(mask, s, v, a, o, e, p, serverData.protocol),
14680
- onLayout: (l) => blockWriter.writeLayout(l, serverData.protocol),
14681
- onInventory: (inv) => blockWriter.writeInventory(inv, serverData.protocol),
14682
- onMuzzleFlash: (ent, w) => blockWriter.writeMuzzleFlash(ent, w, serverData.protocol),
14683
- onMuzzleFlash2: (ent, w) => blockWriter.writeMuzzleFlash2(ent, w, serverData.protocol),
14684
- onTempEntity: (t, p, p2, d, c, clr, e, s, de) => blockWriter.writeTempEntity(t, p, p2, d, c, clr, e, s, de, serverData.protocol),
14685
- onDisconnect: () => blockWriter.writeDisconnect(serverData.protocol),
14686
- onReconnect: () => blockWriter.writeReconnect(serverData.protocol),
14687
- onDownload: () => {
14688
- },
14689
- // Stub for download
14690
- onFrame: (frame) => {
14691
- const oldSeq = frame.serverFrame;
14692
- const oldDelta = frame.deltaFrame;
14693
- const newSeq = messageIndex - startFrame;
14694
- let newDelta = -1;
14695
- if (frameMap.has(oldDelta)) {
14696
- newDelta = frameMap.get(oldDelta);
14697
- } else {
14698
- frame.packetEntities.delta = false;
14699
- }
14700
- frameMap.set(oldSeq, newSeq);
14701
- frame.serverFrame = newSeq;
14702
- frame.deltaFrame = newDelta;
14703
- blockWriter.writeFrame(frame, serverData.protocol);
14704
- }
14705
- };
14706
- const blockParser = new NetworkMessageParser(blockStream, passthroughHandler, false);
14707
- blockParser.setProtocolVersion(serverData.protocol);
14708
- blockParser.parseMessage();
14709
- const blockData = blockWriter.getData();
14710
- if (blockData.byteLength > 0) {
14711
- demoWriter.writeBlock(blockData);
14729
+ if (!parsedSuccessfully) {
14730
+ if (blockIndex >= startFrame && blockIndex <= endFrame) {
14731
+ keepBlock = true;
14712
14732
  }
14713
- messageIndex++;
14714
14733
  }
14734
+ if (keepBlock) {
14735
+ const blockHeader = new Uint8Array(4);
14736
+ const view = new DataView(blockHeader.buffer);
14737
+ view.setUint32(0, blockData.getLength(), true);
14738
+ outputParts.push(blockHeader);
14739
+ const data = blockData.readData(blockData.getLength());
14740
+ outputParts.push(data);
14741
+ totalLength += 4 + data.length;
14742
+ }
14743
+ blockIndex++;
14744
+ }
14745
+ const eof = new Uint8Array(4);
14746
+ new DataView(eof.buffer).setInt32(0, -1, true);
14747
+ outputParts.push(eof);
14748
+ totalLength += 4;
14749
+ const result = new Uint8Array(totalLength);
14750
+ let offset = 0;
14751
+ for (const part of outputParts) {
14752
+ result.set(part, offset);
14753
+ offset += part.length;
14715
14754
  }
14716
- demoWriter.writeEOF();
14717
- return demoWriter.getData();
14755
+ return result;
14756
+ }
14757
+ extractDemoRange(demoData, startFrame, endFrame) {
14758
+ return this.extractClip(demoData, { frame: startFrame }, { frame: endFrame });
14759
+ }
14760
+ // Implement interface methods
14761
+ onServerData(protocol, serverCount, attractLoop, gameDir, playerNum, levelName) {
14762
+ this.serverData = { protocol, serverCount, attractLoop, gameDir, playerNum, levelName };
14763
+ }
14764
+ onConfigString(index, str) {
14765
+ this.configStrings.set(index, str);
14766
+ }
14767
+ onSpawnBaseline(entity) {
14768
+ this.baselines.set(entity.number, entity);
14769
+ }
14770
+ onFrame(frame) {
14771
+ this.frames.push(frame);
14772
+ }
14773
+ onCenterPrint(msg) {
14774
+ }
14775
+ onStuffText(msg) {
14776
+ }
14777
+ onPrint(level, msg) {
14778
+ }
14779
+ onSound(flags, soundNum, volume, attenuation, offset, ent, pos) {
14780
+ }
14781
+ onTempEntity(type, pos, pos2, dir, cnt, color, ent, srcEnt, destEnt) {
14782
+ }
14783
+ onLayout(layout) {
14784
+ }
14785
+ onInventory(inventory) {
14786
+ }
14787
+ onMuzzleFlash(ent, weapon) {
14788
+ }
14789
+ onMuzzleFlash2(ent, weapon) {
14790
+ }
14791
+ onDisconnect() {
14792
+ }
14793
+ onReconnect() {
14794
+ }
14795
+ onDownload(size, percent, data) {
14718
14796
  }
14719
14797
  };
14798
+ function applyEntityDelta(target, delta) {
14799
+ const bits = delta.bits;
14800
+ target.bits = bits;
14801
+ target.number = delta.number;
14802
+ if (bits & U_MODEL) target.modelindex = delta.modelindex;
14803
+ if (bits & U_MODEL2) target.modelindex2 = delta.modelindex2;
14804
+ if (bits & U_MODEL3) target.modelindex3 = delta.modelindex3;
14805
+ if (bits & U_MODEL4) target.modelindex4 = delta.modelindex4;
14806
+ if (bits & U_FRAME8) target.frame = delta.frame;
14807
+ if (bits & U_FRAME16) target.frame = delta.frame;
14808
+ if (bits & U_SKIN8) target.skinnum = delta.skinnum;
14809
+ if (bits & U_SKIN16) target.skinnum = delta.skinnum;
14810
+ if (bits & U_EFFECTS8) target.effects = delta.effects;
14811
+ if (bits & U_EFFECTS16) target.effects = delta.effects;
14812
+ if (bits & U_RENDERFX8) target.renderfx = delta.renderfx;
14813
+ if (bits & U_RENDERFX16) target.renderfx = delta.renderfx;
14814
+ if (bits & U_ORIGIN1) target.origin.x = delta.origin.x;
14815
+ if (bits & U_ORIGIN2) target.origin.y = delta.origin.y;
14816
+ if (bits & U_ORIGIN3) target.origin.z = delta.origin.z;
14817
+ if (bits & U_ANGLE1) target.angles.x = delta.angles.x;
14818
+ if (bits & U_ANGLE2) target.angles.y = delta.angles.y;
14819
+ if (bits & U_ANGLE3) target.angles.z = delta.angles.z;
14820
+ if (bits & U_OLDORIGIN) {
14821
+ target.old_origin.x = delta.old_origin.x;
14822
+ target.old_origin.y = delta.old_origin.y;
14823
+ target.old_origin.z = delta.old_origin.z;
14824
+ }
14825
+ if (bits & U_SOUND) target.sound = delta.sound;
14826
+ if (bits & U_EVENT) target.event = delta.event;
14827
+ if (bits & U_SOLID) target.solid = delta.solid;
14828
+ if (bits & U_ALPHA) target.alpha = delta.alpha;
14829
+ if (bits & U_SCALE) target.scale = delta.scale;
14830
+ if (bits & U_INSTANCE_BITS) target.instanceBits = delta.instanceBits;
14831
+ if (bits & U_LOOP_VOLUME) target.loopVolume = delta.loopVolume;
14832
+ }
14720
14833
 
14721
14834
  // src/assets/fileType.ts
14722
14835
  var FileType = /* @__PURE__ */ ((FileType2) => {
@@ -15597,6 +15710,6 @@ pako/dist/pako.esm.mjs:
15597
15710
  (*! pako 2.1.0 https://github.com/nodeca/pako @license (MIT AND Zlib) *)
15598
15711
  */
15599
15712
 
15600
- export { AssetDependencyError, AssetDependencyTracker, AssetManager, AssetPreviewGenerator, AudioApi, AudioContextController, AudioOcclusion, AudioRegistry, AudioRegistryError, AudioSystem, BSP_SURFACE_FRAGMENT_SOURCE, BSP_SURFACE_VERTEX_SOURCE, BSP_VERTEX_LAYOUT, BspLoader, BspParseError, BspSurfacePipeline, Camera, ClientConnection, Command, CommandRegistry, ConfigStringRegistry, ConnectionState, Cvar, CvarRegistry, DemoAnalyzer, DemoCameraMode, DemoClipper, DemoEventType, DemoPlaybackController, DemoReader, DemoRecorder, DemoValidator, DynamicLightManager, EngineHost, EngineRuntime, FileType, FixedTimestepLoop, Framebuffer, IndexBuffer, LruCache, MD2_FRAGMENT_SHADER, MD2_VERTEX_SHADER, MD3_FRAGMENT_SHADER, MD3_VERTEX_SHADER, MapAnalyzer, Md2Loader, Md2MeshBuffers, Md2ParseError, Md2Pipeline, Md3Loader, Md3ModelMesh, Md3ParseError, Md3Pipeline, Md3SurfaceMesh, MessageWriter, MusicSystem, NetworkMessageParser, PARTICLE_FRAGMENT_SHADER, PARTICLE_VERTEX_SHADER, PROTOCOL_VERSION_RERELEASE, PakArchive, PakIndexStore, PakIngestionError, PakParseError, PakValidationError, PakValidator, PakWriter, ParticleRenderer, ParticleSystem, PlaybackState, RERELEASE_KNOWN_PAKS, ResourceLoadTracker, ResourceType, SKYBOX_FRAGMENT_SHADER, SKYBOX_VERTEX_SHADER, ShaderProgram, SkyboxPipeline, SoundPrecache, SoundRegistry, SpriteLoader, SpriteParseError, SpriteRenderer, StreamingPakArchive, Texture2D, TextureCache, TextureCubeMap, TgaParseError, U_ALPHA, U_ANGLE1, U_ANGLE2, U_ANGLE3, U_EFFECTS16, U_EFFECTS8, U_EVENT, U_FRAME16, U_FRAME8, U_INSTANCE_BITS, U_LOOP_ATTENUATION_HIGH, U_LOOP_VOLUME, U_MODEL, U_MODEL2, U_MODEL3, U_MODEL4, U_OLDORIGIN, U_OLD_FRAME_HIGH, U_ORIGIN1, U_ORIGIN2, U_ORIGIN3, U_OWNER_HIGH, U_REMOVE, U_RENDERFX16, U_RENDERFX8, U_SCALE, U_SKIN16, U_SKIN8, U_SOLID, U_SOUND, VertexArray, VertexBuffer, VirtualFileSystem, advanceAnimation, applyEntityDelta, applySurfaceState, boxIntersectsFrustum, buildBspGeometry, buildMd2Geometry, buildMd2VertexData, buildMd3SurfaceGeometry, buildMd3VertexData, calculatePakChecksum, captureRenderTarget, computeFrameBlend, computeSkyScroll, createAnimationState, createAudioGraph, createBspSurfaces, createEmptyEntityState, createEmptyProtocolPlayerState, createEngine, createEngineRuntime, createFaceLightmap, createHeadlessRenderTarget, createInitialChannels, createOcclusionResolver, createProgramFromSources, createWebGLContext, createWebGPUContext, decodeOgg, deriveSurfaceRenderState, detectFileType, extractFrustumPlanes, filesToPakSources, findLeafForPoint, gatherVisibleFaces, groupMd2Animations, ingestPakFiles, ingestPaks, interpolateMd3Tag, interpolateVec3, isBinaryFile, isTextFile, parseBsp, parseEntLump, parseMd2, parseMd3, parsePcx, parseSprite, parseTga, parseWal, parseWalTexture, parseWav, pcxToRgba, pickChannel, preparePcxTexture, queryCapabilities, removeViewTranslation, resolveLightStyles, serializeEntLump, spawnBfgExplosion, spawnBlasterImpact, spawnBlood, spawnBulletImpact, spawnExplosion, spawnMuzzleFlash, spawnRailTrail, spawnSparks, spawnSplash, spawnSteam, spawnTeleportFlash, spawnTrail, validateEntity, walToRgba, wireDropTarget, wireFileInput };
15713
+ export { AssetDependencyError, AssetDependencyTracker, AssetManager, AssetPreviewGenerator, AudioApi, AudioContextController, AudioOcclusion, AudioRegistry, AudioRegistryError, AudioSystem, BSP_SURFACE_FRAGMENT_SOURCE, BSP_SURFACE_VERTEX_SOURCE, BSP_VERTEX_LAYOUT, BspLoader, BspParseError, BspSurfacePipeline, Camera, ClientConnection, Command, CommandRegistry, ConfigStringRegistry, ConnectionState, Cvar, CvarRegistry, DemoAnalyzer, DemoCameraMode, DemoClipper, DemoEventType, DemoPlaybackController, DemoReader, DemoRecorder, DemoValidator, DynamicLightManager, EngineHost, EngineRuntime, FileType, FixedTimestepLoop, Framebuffer, IndexBuffer, LruCache, MD2_FRAGMENT_SHADER, MD2_VERTEX_SHADER, MD3_FRAGMENT_SHADER, MD3_VERTEX_SHADER, MapAnalyzer, Md2Loader, Md2MeshBuffers, Md2ParseError, Md2Pipeline, Md3Loader, Md3ModelMesh, Md3ParseError, Md3Pipeline, Md3SurfaceMesh, MessageWriter, MusicSystem, NetworkMessageParser, PARTICLE_FRAGMENT_SHADER, PARTICLE_VERTEX_SHADER, PROTOCOL_VERSION_RERELEASE, PakArchive, PakIndexStore, PakIngestionError, PakParseError, PakValidationError, PakValidator, PakWriter, ParticleRenderer, ParticleSystem, PlaybackState, RERELEASE_KNOWN_PAKS, ResourceLoadTracker, ResourceType, SKYBOX_FRAGMENT_SHADER, SKYBOX_VERTEX_SHADER, ShaderProgram, SkyboxPipeline, SoundPrecache, SoundRegistry, SpriteLoader, SpriteParseError, SpriteRenderer, StreamingPakArchive, Texture2D, TextureCache, TextureCubeMap, TgaParseError, VertexArray, VertexBuffer, VirtualFileSystem, advanceAnimation, applyEntityDelta, applySurfaceState, boxIntersectsFrustum, buildBspGeometry, buildMd2Geometry, buildMd2VertexData, buildMd3SurfaceGeometry, buildMd3VertexData, calculatePakChecksum, captureRenderTarget, computeFrameBlend, computeSkyScroll, createAnimationState, createAudioGraph, createBspSurfaces, createEmptyEntityState, createEmptyProtocolPlayerState, createEngine, createEngineRuntime, createFaceLightmap, createHeadlessRenderTarget, createInitialChannels, createOcclusionResolver, createProgramFromSources, createWebGLContext, createWebGPUContext, decodeOgg, deriveSurfaceRenderState, detectFileType, extractFrustumPlanes, filesToPakSources, findLeafForPoint, gatherVisibleFaces, groupMd2Animations, ingestPakFiles, ingestPaks, interpolateMd3Tag, interpolateVec3, isBinaryFile, isTextFile, parseBsp, parseEntLump, parseMd2, parseMd3, parsePcx, parseSprite, parseTga, parseWal, parseWalTexture, parseWav, pcxToRgba, pickChannel, preparePcxTexture, queryCapabilities, removeViewTranslation, resolveLightStyles, serializeEntLump, spawnBfgExplosion, spawnBlasterImpact, spawnBlood, spawnBulletImpact, spawnExplosion, spawnMuzzleFlash, spawnRailTrail, spawnSparks, spawnSplash, spawnSteam, spawnTeleportFlash, spawnTrail, validateEntity, walToRgba, wireDropTarget, wireFileInput };
15601
15714
  //# sourceMappingURL=index.js.map
15602
15715
  //# sourceMappingURL=index.js.map