quake2ts 0.0.543 → 0.0.544

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.
Files changed (27) hide show
  1. package/package.json +1 -1
  2. package/packages/client/dist/browser/index.global.js +17 -17
  3. package/packages/client/dist/browser/index.global.js.map +1 -1
  4. package/packages/client/dist/cjs/index.cjs +264 -6
  5. package/packages/client/dist/cjs/index.cjs.map +1 -1
  6. package/packages/client/dist/esm/index.js +264 -6
  7. package/packages/client/dist/esm/index.js.map +1 -1
  8. package/packages/client/dist/tsconfig.tsbuildinfo +1 -1
  9. package/packages/client/dist/types/effects-system.d.ts +1 -1
  10. package/packages/client/dist/types/effects-system.d.ts.map +1 -1
  11. package/packages/engine/dist/browser/index.global.js +15 -15
  12. package/packages/engine/dist/browser/index.global.js.map +1 -1
  13. package/packages/engine/dist/cjs/index.cjs +388 -46
  14. package/packages/engine/dist/cjs/index.cjs.map +1 -1
  15. package/packages/engine/dist/esm/index.js +384 -46
  16. package/packages/engine/dist/esm/index.js.map +1 -1
  17. package/packages/engine/dist/tsconfig.tsbuildinfo +1 -1
  18. package/packages/engine/dist/types/assets/visibilityAnalyzer.d.ts +17 -0
  19. package/packages/engine/dist/types/assets/visibilityAnalyzer.d.ts.map +1 -0
  20. package/packages/engine/dist/types/demo/parser.d.ts.map +1 -1
  21. package/packages/engine/dist/types/demo/writer.d.ts +13 -12
  22. package/packages/engine/dist/types/demo/writer.d.ts.map +1 -1
  23. package/packages/engine/dist/types/index.d.ts +1 -1
  24. package/packages/engine/dist/types/index.d.ts.map +1 -1
  25. package/packages/engine/dist/types/render/particleSystem.d.ts +16 -0
  26. package/packages/engine/dist/types/render/particleSystem.d.ts.map +1 -1
  27. package/packages/game/dist/tsconfig.tsbuildinfo +1 -1
@@ -3948,6 +3948,137 @@ function spawnSteam(context) {
3948
3948
  });
3949
3949
  }
3950
3950
  }
3951
+ function spawnRailTrail(context) {
3952
+ const { system, start, end } = context;
3953
+ const dx = end.x - start.x;
3954
+ const dy = end.y - start.y;
3955
+ const dz = end.z - start.z;
3956
+ const dist2 = Math.sqrt(dx * dx + dy * dy + dz * dz);
3957
+ if (dist2 < 1) return;
3958
+ const dir = { x: dx / dist2, y: dy / dist2, z: dz / dist2 };
3959
+ const step = 8;
3960
+ for (let d = 0; d < dist2; d += step) {
3961
+ const x = start.x + dir.x * d;
3962
+ const y = start.y + dir.y * d;
3963
+ const z = start.z + dir.z * d;
3964
+ system.spawn({
3965
+ position: { x, y, z },
3966
+ velocity: { x: 0, y: 0, z: 0 },
3967
+ // Static
3968
+ color: [0.4, 0.4, 1, 0.8],
3969
+ size: 2,
3970
+ lifetime: 0.6,
3971
+ blendMode: "additive",
3972
+ fade: true
3973
+ });
3974
+ const radius = 3;
3975
+ const theta = d * 0.5;
3976
+ system.spawn({
3977
+ position: {
3978
+ x: x + (system.rng.frandom() - 0.5) * 6,
3979
+ y: y + (system.rng.frandom() - 0.5) * 6,
3980
+ z: z + (system.rng.frandom() - 0.5) * 6
3981
+ },
3982
+ velocity: {
3983
+ x: (system.rng.frandom() - 0.5) * 10,
3984
+ y: (system.rng.frandom() - 0.5) * 10,
3985
+ z: (system.rng.frandom() - 0.5) * 10
3986
+ },
3987
+ color: [0.1, 0.1, 0.8, 0.6],
3988
+ size: 3,
3989
+ lifetime: 0.8 + system.rng.frandom() * 0.2,
3990
+ blendMode: "additive",
3991
+ fade: true
3992
+ });
3993
+ }
3994
+ }
3995
+ function spawnSparks(context) {
3996
+ const { system, origin, normal = { x: 0, y: 0, z: 1 }, count = 12, color = [1, 0.9, 0.2, 1] } = context;
3997
+ for (let i = 0; i < count; i++) {
3998
+ const speed = 100 + system.rng.frandom() * 200;
3999
+ const spread = 0.5;
4000
+ system.spawn({
4001
+ position: origin,
4002
+ velocity: {
4003
+ x: normal.x * speed + (system.rng.frandom() - 0.5) * 100 * spread,
4004
+ y: normal.y * speed + (system.rng.frandom() - 0.5) * 100 * spread,
4005
+ z: normal.z * speed + (system.rng.frandom() - 0.5) * 100 * spread
4006
+ },
4007
+ color,
4008
+ size: 1.5,
4009
+ lifetime: 0.3 + system.rng.frandom() * 0.2,
4010
+ gravity: 800,
4011
+ bounce: 0.5,
4012
+ damping: 1,
4013
+ blendMode: "additive",
4014
+ fade: true
4015
+ });
4016
+ }
4017
+ }
4018
+ function spawnBlasterImpact(context) {
4019
+ const { system, origin, normal = { x: 0, y: 0, z: 1 }, color = [1, 0.8, 0, 1] } = context;
4020
+ system.spawn({
4021
+ position: origin,
4022
+ velocity: { x: 0, y: 0, z: 0 },
4023
+ color,
4024
+ size: 8,
4025
+ lifetime: 0.2,
4026
+ blendMode: "additive",
4027
+ fade: true
4028
+ });
4029
+ for (let i = 0; i < 8; i++) {
4030
+ const speed = 150 + system.rng.frandom() * 150;
4031
+ system.spawn({
4032
+ position: origin,
4033
+ velocity: {
4034
+ x: normal.x * speed + (system.rng.frandom() - 0.5) * 120,
4035
+ y: normal.y * speed + (system.rng.frandom() - 0.5) * 120,
4036
+ z: normal.z * speed + (system.rng.frandom() - 0.5) * 120
4037
+ },
4038
+ color,
4039
+ size: 2,
4040
+ lifetime: 0.4 + system.rng.frandom() * 0.2,
4041
+ gravity: 400,
4042
+ blendMode: "additive",
4043
+ fade: true
4044
+ });
4045
+ }
4046
+ }
4047
+ function spawnBfgExplosion(context) {
4048
+ const { system, origin } = context;
4049
+ system.spawn({
4050
+ position: origin,
4051
+ velocity: { x: 0, y: 0, z: 0 },
4052
+ color: [0.2, 1, 0.2, 1],
4053
+ // Green
4054
+ size: 30,
4055
+ lifetime: 0.5,
4056
+ blendMode: "additive",
4057
+ fade: true
4058
+ });
4059
+ for (let i = 0; i < 60; i++) {
4060
+ const theta = system.rng.frandom() * Math.PI * 2;
4061
+ const phi = Math.acos(2 * system.rng.frandom() - 1);
4062
+ const speed = 300 + system.rng.frandom() * 400;
4063
+ const dir = {
4064
+ x: Math.sin(phi) * Math.cos(theta),
4065
+ y: Math.sin(phi) * Math.sin(theta),
4066
+ z: Math.cos(phi)
4067
+ };
4068
+ system.spawn({
4069
+ position: origin,
4070
+ velocity: { x: dir.x * speed, y: dir.y * speed, z: dir.z * speed },
4071
+ color: [0.2, 1, 0.2, 0.8],
4072
+ size: 4,
4073
+ lifetime: 1,
4074
+ gravity: 100,
4075
+ // Low gravity
4076
+ damping: 1,
4077
+ blendMode: "additive",
4078
+ fade: true
4079
+ });
4080
+ }
4081
+ }
3951
4082
  var DemoReader = class {
3952
4083
  constructor(buffer) {
3953
4084
  this.messageOffsets = [];
@@ -8613,6 +8744,32 @@ var BinaryStreamAdapter = class extends StreamingBuffer {
8613
8744
  throw new Error("peekBytes not implemented for BinaryStreamAdapter");
8614
8745
  }
8615
8746
  };
8747
+ var PROTO34_MAP = {
8748
+ 0: ServerCommand.bad,
8749
+ 1: ServerCommand.nop,
8750
+ 2: ServerCommand.disconnect,
8751
+ 3: ServerCommand.reconnect,
8752
+ 4: ServerCommand.download,
8753
+ 5: ServerCommand.frame,
8754
+ 6: ServerCommand.inventory,
8755
+ 7: ServerCommand.layout,
8756
+ 8: ServerCommand.muzzleflash,
8757
+ 9: ServerCommand.sound,
8758
+ 10: ServerCommand.print,
8759
+ 11: ServerCommand.stufftext,
8760
+ 12: ServerCommand.serverdata,
8761
+ 13: ServerCommand.configstring,
8762
+ 14: ServerCommand.spawnbaseline,
8763
+ 15: ServerCommand.centerprint,
8764
+ 16: ServerCommand.download,
8765
+ 17: ServerCommand.playerinfo,
8766
+ 18: ServerCommand.packetentities,
8767
+ 19: ServerCommand.deltapacketentities,
8768
+ 23: ServerCommand.temp_entity,
8769
+ // Wire 23 -> Enum 3 (TempEntity)
8770
+ 22: ServerCommand.muzzleflash2
8771
+ // Wire 22 -> Enum 2 (MuzzleFlash2)
8772
+ };
8616
8773
  var NetworkMessageParser = class _NetworkMessageParser {
8617
8774
  constructor(stream, handler, strictMode = false) {
8618
8775
  this.protocolVersion = 0;
@@ -8654,7 +8811,9 @@ var NetworkMessageParser = class _NetworkMessageParser {
8654
8811
  return ServerCommand.bad;
8655
8812
  }
8656
8813
  if (this.protocolVersion === 34) {
8657
- if (cmd <= ServerCommand.frame) return cmd;
8814
+ if (PROTO34_MAP[cmd] !== void 0) {
8815
+ return PROTO34_MAP[cmd];
8816
+ }
8658
8817
  return ServerCommand.bad;
8659
8818
  }
8660
8819
  return cmd;
@@ -9192,7 +9351,7 @@ var NetworkMessageParser = class _NetworkMessageParser {
9192
9351
  const playerState = this.parsePlayerState();
9193
9352
  let peCmd = this.stream.readByte();
9194
9353
  peCmd = this.translateCommand(peCmd);
9195
- if (peCmd !== ServerCommand.packetentities) {
9354
+ if (peCmd !== ServerCommand.packetentities && peCmd !== ServerCommand.deltapacketentities) {
9196
9355
  if (this.strictMode) throw new Error(`Expected svc_packetentities after svc_playerinfo, got ${peCmd}`);
9197
9356
  return;
9198
9357
  }
@@ -10393,6 +10552,47 @@ var DemoValidator = class {
10393
10552
  return { valid: true, version };
10394
10553
  }
10395
10554
  };
10555
+ var PROTO34_REVERSE_MAP = {
10556
+ [ServerCommand.bad]: 0,
10557
+ [ServerCommand.nop]: 1,
10558
+ [ServerCommand.disconnect]: 2,
10559
+ [ServerCommand.reconnect]: 3,
10560
+ // 4 is download? standard Q2 uses 4 for download sometimes, but let's stick to parser map (download=16).
10561
+ // Let's map download to 16.
10562
+ [ServerCommand.download]: 16,
10563
+ [ServerCommand.frame]: 5,
10564
+ [ServerCommand.inventory]: 6,
10565
+ [ServerCommand.layout]: 7,
10566
+ [ServerCommand.muzzleflash]: 8,
10567
+ [ServerCommand.sound]: 9,
10568
+ [ServerCommand.print]: 10,
10569
+ [ServerCommand.stufftext]: 11,
10570
+ [ServerCommand.serverdata]: 12,
10571
+ [ServerCommand.configstring]: 13,
10572
+ [ServerCommand.spawnbaseline]: 14,
10573
+ [ServerCommand.centerprint]: 15,
10574
+ // 16 is download
10575
+ [ServerCommand.playerinfo]: 17,
10576
+ [ServerCommand.packetentities]: 18,
10577
+ [ServerCommand.deltapacketentities]: 19,
10578
+ // Temp entity? Standard Q2 uses 9 for temp_entity?
10579
+ // But we mapped 9 to sound.
10580
+ // If we map temp_entity to 23 (arbitrary safe slot for internal tests) or assume standard Q2 layout:
10581
+ // Q2: svc_temp_entity = 9. svc_sound = 10.
10582
+ // My previous edit to parser.ts used 9->Sound, 10->Print.
10583
+ // I should check what I committed to `parser.ts` just now.
10584
+ // I committed: 9: Sound, 10: Print.
10585
+ // So Writer MUST MATCH Parser.
10586
+ // So if Parser says 9 is Sound, Writer must write Sound as 9.
10587
+ // But what about TempEntity?
10588
+ // Parser does NOT map any wire code to TempEntity in my recent edit (I commented out 23).
10589
+ // So TempEntity is currently broken for Protocol 34 unless I map it.
10590
+ // I will map TempEntity to 23 in both.
10591
+ [ServerCommand.temp_entity]: 23,
10592
+ // MuzzleFlash2?
10593
+ // I'll map it to 22 (arbitrary) just to have a value, or skip if unused.
10594
+ [ServerCommand.muzzleflash2]: 22
10595
+ };
10396
10596
  function applyEntityDelta(to, from) {
10397
10597
  const bits = from.bits;
10398
10598
  const bitsHigh = from.bitsHigh;
@@ -14899,7 +15099,7 @@ var ClientEffectSystem = class {
14899
15099
  this.playSound(null, entNum, soundName, volume, 1);
14900
15100
  }
14901
15101
  }
14902
- onTempEntity(type, pos, time, dir) {
15102
+ onTempEntity(type, pos, time, dir, pos2) {
14903
15103
  const particleSystem = this.engine.renderer?.particleSystem;
14904
15104
  switch (type) {
14905
15105
  case TempEntity2.GUNSHOT:
@@ -14955,10 +15155,9 @@ var ClientEffectSystem = class {
14955
15155
  this.addLight(void 0, pos, color, startRadius, 0, time + duration, speed);
14956
15156
  this.playSound(pos, 0, "weapons/bfg__x1b.wav", 1, 0.5);
14957
15157
  if (particleSystem) {
14958
- spawnExplosion({
15158
+ spawnBfgExplosion({
14959
15159
  system: particleSystem,
14960
15160
  origin: pos
14961
- // TODO: Make BFG explosion green/bigger
14962
15161
  });
14963
15162
  }
14964
15163
  }
@@ -14981,6 +15180,65 @@ var ClientEffectSystem = class {
14981
15180
  });
14982
15181
  }
14983
15182
  break;
15183
+ case TempEntity2.RAILTRAIL:
15184
+ if (particleSystem && pos2) {
15185
+ spawnRailTrail({
15186
+ system: particleSystem,
15187
+ start: pos,
15188
+ end: pos2
15189
+ });
15190
+ }
15191
+ break;
15192
+ case TempEntity2.BLASTER:
15193
+ if (particleSystem) {
15194
+ spawnBlasterImpact({
15195
+ system: particleSystem,
15196
+ origin: pos,
15197
+ color: [1, 1, 0, 1]
15198
+ // Yellow
15199
+ });
15200
+ }
15201
+ this.playSound(pos, 0, "weapons/lasthit.wav");
15202
+ break;
15203
+ case TempEntity2.BLUEHYPERBLASTER:
15204
+ if (particleSystem) {
15205
+ spawnBlasterImpact({
15206
+ system: particleSystem,
15207
+ origin: pos,
15208
+ color: [0, 0, 1, 1]
15209
+ // Blue
15210
+ });
15211
+ }
15212
+ this.playSound(pos, 0, "weapons/lasthit.wav");
15213
+ break;
15214
+ case TempEntity2.SPARKS:
15215
+ case TempEntity2.BULLET_SPARKS:
15216
+ case TempEntity2.WELDING_SPARKS:
15217
+ if (particleSystem) {
15218
+ spawnSparks({
15219
+ system: particleSystem,
15220
+ origin: pos,
15221
+ normal: dir || { x: 0, y: 0, z: 1 },
15222
+ count: 8,
15223
+ color: [1, 0.8, 0.2, 1]
15224
+ });
15225
+ }
15226
+ this.playSound(pos, 0, "world/spark1.wav");
15227
+ break;
15228
+ case TempEntity2.SHIELD_SPARKS:
15229
+ case TempEntity2.SCREEN_SPARKS:
15230
+ if (particleSystem) {
15231
+ spawnSparks({
15232
+ system: particleSystem,
15233
+ origin: pos,
15234
+ normal: dir || { x: 0, y: 0, z: 1 },
15235
+ count: 12,
15236
+ color: [0.5, 1, 0.5, 1]
15237
+ // Greenish for shield? Or classic spark color.
15238
+ });
15239
+ }
15240
+ this.playSound(pos, 0, "world/spark2.wav");
15241
+ break;
14984
15242
  }
14985
15243
  }
14986
15244
  };
@@ -16458,7 +16716,7 @@ function createClient(imports) {
16458
16716
  onTempEntity: (type, pos, pos2, dir, cnt, color, ent, srcEnt, destEnt) => {
16459
16717
  const time = demoPlayback.getCurrentTime() / 1e3;
16460
16718
  if (pos) {
16461
- effectSystem.onTempEntity(type, pos, time, dir);
16719
+ effectSystem.onTempEntity(type, pos, time, dir, pos2);
16462
16720
  }
16463
16721
  },
16464
16722
  onDamage: (indicators) => {