quake2ts 0.0.254 → 0.0.257

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 (58) hide show
  1. package/package.json +1 -1
  2. package/packages/client/dist/browser/index.global.js +13 -13
  3. package/packages/client/dist/browser/index.global.js.map +1 -1
  4. package/packages/client/dist/cjs/index.cjs +770 -38
  5. package/packages/client/dist/cjs/index.cjs.map +1 -1
  6. package/packages/client/dist/esm/index.js +789 -57
  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/hud/icons.d.ts.map +1 -1
  10. package/packages/client/dist/types/hud/statusbar.d.ts.map +1 -1
  11. package/packages/client/dist/types/index.d.ts +3 -1
  12. package/packages/client/dist/types/index.d.ts.map +1 -1
  13. package/packages/client/dist/types/net/connection.d.ts +60 -0
  14. package/packages/client/dist/types/net/connection.d.ts.map +1 -0
  15. package/packages/client/dist/types/ui/menu/main.d.ts +2 -0
  16. package/packages/client/dist/types/ui/menu/main.d.ts.map +1 -1
  17. package/packages/client/dist/types/ui/menu/multiplayer.d.ts +11 -0
  18. package/packages/client/dist/types/ui/menu/multiplayer.d.ts.map +1 -0
  19. package/packages/engine/dist/browser/index.global.js +14 -14
  20. package/packages/engine/dist/browser/index.global.js.map +1 -1
  21. package/packages/engine/dist/cjs/index.cjs +2 -0
  22. package/packages/engine/dist/cjs/index.cjs.map +1 -1
  23. package/packages/engine/dist/esm/index.js +1 -0
  24. package/packages/engine/dist/esm/index.js.map +1 -1
  25. package/packages/engine/dist/tsconfig.tsbuildinfo +1 -1
  26. package/packages/engine/dist/types/index.d.ts +1 -1
  27. package/packages/engine/dist/types/index.d.ts.map +1 -1
  28. package/packages/game/dist/browser/index.global.js +2 -2
  29. package/packages/game/dist/browser/index.global.js.map +1 -1
  30. package/packages/game/dist/cjs/index.cjs +231 -208
  31. package/packages/game/dist/cjs/index.cjs.map +1 -1
  32. package/packages/game/dist/esm/index.js +230 -206
  33. package/packages/game/dist/esm/index.js.map +1 -1
  34. package/packages/game/dist/tsconfig.tsbuildinfo +1 -1
  35. package/packages/game/dist/types/combat/weapons/firing.d.ts.map +1 -1
  36. package/packages/game/dist/types/combat/weapons/projectSource.d.ts +28 -0
  37. package/packages/game/dist/types/combat/weapons/projectSource.d.ts.map +1 -0
  38. package/packages/game/dist/types/combat/weapons/rogue.d.ts +4 -4
  39. package/packages/game/dist/types/combat/weapons/rogue.d.ts.map +1 -1
  40. package/packages/game/dist/types/combat/weapons/state.d.ts +6 -0
  41. package/packages/game/dist/types/combat/weapons/state.d.ts.map +1 -1
  42. package/packages/game/dist/types/entities/playerStats.d.ts.map +1 -1
  43. package/packages/game/dist/types/inventory/ammo.d.ts.map +1 -1
  44. package/packages/game/dist/types/inventory/playerInventory.d.ts +91 -38
  45. package/packages/game/dist/types/inventory/playerInventory.d.ts.map +1 -1
  46. package/packages/shared/dist/browser/index.global.js +1 -1
  47. package/packages/shared/dist/browser/index.global.js.map +1 -1
  48. package/packages/shared/dist/cjs/index.cjs +101 -2
  49. package/packages/shared/dist/cjs/index.cjs.map +1 -1
  50. package/packages/shared/dist/esm/index.js +100 -2
  51. package/packages/shared/dist/esm/index.js.map +1 -1
  52. package/packages/shared/dist/tsconfig.tsbuildinfo +1 -1
  53. package/packages/shared/dist/types/io/index.d.ts +1 -0
  54. package/packages/shared/dist/types/io/index.d.ts.map +1 -1
  55. package/packages/shared/dist/types/io/messageBuilder.d.ts +21 -0
  56. package/packages/shared/dist/types/io/messageBuilder.d.ts.map +1 -0
  57. package/packages/shared/dist/types/protocol/stats.d.ts.map +1 -1
  58. package/packages/tools/dist/tsconfig.tsbuildinfo +1 -1
@@ -2060,42 +2060,42 @@ function addReplayFrame(session, cmd, serverFrame, startTime) {
2060
2060
  });
2061
2061
  }
2062
2062
  var WATERJUMP_CLEAR = 8 | 16 | 32 | 1024;
2063
- var ServerCommand = /* @__PURE__ */ ((ServerCommand2) => {
2064
- ServerCommand2[ServerCommand2["bad"] = 0] = "bad";
2065
- ServerCommand2[ServerCommand2["muzzleflash"] = 1] = "muzzleflash";
2066
- ServerCommand2[ServerCommand2["muzzleflash2"] = 2] = "muzzleflash2";
2067
- ServerCommand2[ServerCommand2["temp_entity"] = 3] = "temp_entity";
2068
- ServerCommand2[ServerCommand2["layout"] = 4] = "layout";
2069
- ServerCommand2[ServerCommand2["inventory"] = 5] = "inventory";
2070
- ServerCommand2[ServerCommand2["nop"] = 6] = "nop";
2071
- ServerCommand2[ServerCommand2["disconnect"] = 7] = "disconnect";
2072
- ServerCommand2[ServerCommand2["reconnect"] = 8] = "reconnect";
2073
- ServerCommand2[ServerCommand2["sound"] = 9] = "sound";
2074
- ServerCommand2[ServerCommand2["print"] = 10] = "print";
2075
- ServerCommand2[ServerCommand2["stufftext"] = 11] = "stufftext";
2076
- ServerCommand2[ServerCommand2["serverdata"] = 12] = "serverdata";
2077
- ServerCommand2[ServerCommand2["configstring"] = 13] = "configstring";
2078
- ServerCommand2[ServerCommand2["spawnbaseline"] = 14] = "spawnbaseline";
2079
- ServerCommand2[ServerCommand2["centerprint"] = 15] = "centerprint";
2080
- ServerCommand2[ServerCommand2["download"] = 16] = "download";
2081
- ServerCommand2[ServerCommand2["playerinfo"] = 17] = "playerinfo";
2082
- ServerCommand2[ServerCommand2["packetentities"] = 18] = "packetentities";
2083
- ServerCommand2[ServerCommand2["deltapacketentities"] = 19] = "deltapacketentities";
2084
- ServerCommand2[ServerCommand2["frame"] = 20] = "frame";
2085
- ServerCommand2[ServerCommand2["splitclient"] = 21] = "splitclient";
2086
- ServerCommand2[ServerCommand2["configblast"] = 22] = "configblast";
2087
- ServerCommand2[ServerCommand2["spawnbaselineblast"] = 23] = "spawnbaselineblast";
2088
- ServerCommand2[ServerCommand2["level_restart"] = 24] = "level_restart";
2089
- ServerCommand2[ServerCommand2["damage"] = 25] = "damage";
2090
- ServerCommand2[ServerCommand2["locprint"] = 26] = "locprint";
2091
- ServerCommand2[ServerCommand2["fog"] = 27] = "fog";
2092
- ServerCommand2[ServerCommand2["waitingforplayers"] = 28] = "waitingforplayers";
2093
- ServerCommand2[ServerCommand2["bot_chat"] = 29] = "bot_chat";
2094
- ServerCommand2[ServerCommand2["poi"] = 30] = "poi";
2095
- ServerCommand2[ServerCommand2["help_path"] = 31] = "help_path";
2096
- ServerCommand2[ServerCommand2["muzzleflash3"] = 32] = "muzzleflash3";
2097
- ServerCommand2[ServerCommand2["achievement"] = 33] = "achievement";
2098
- return ServerCommand2;
2063
+ var ServerCommand = /* @__PURE__ */ ((ServerCommand22) => {
2064
+ ServerCommand22[ServerCommand22["bad"] = 0] = "bad";
2065
+ ServerCommand22[ServerCommand22["muzzleflash"] = 1] = "muzzleflash";
2066
+ ServerCommand22[ServerCommand22["muzzleflash2"] = 2] = "muzzleflash2";
2067
+ ServerCommand22[ServerCommand22["temp_entity"] = 3] = "temp_entity";
2068
+ ServerCommand22[ServerCommand22["layout"] = 4] = "layout";
2069
+ ServerCommand22[ServerCommand22["inventory"] = 5] = "inventory";
2070
+ ServerCommand22[ServerCommand22["nop"] = 6] = "nop";
2071
+ ServerCommand22[ServerCommand22["disconnect"] = 7] = "disconnect";
2072
+ ServerCommand22[ServerCommand22["reconnect"] = 8] = "reconnect";
2073
+ ServerCommand22[ServerCommand22["sound"] = 9] = "sound";
2074
+ ServerCommand22[ServerCommand22["print"] = 10] = "print";
2075
+ ServerCommand22[ServerCommand22["stufftext"] = 11] = "stufftext";
2076
+ ServerCommand22[ServerCommand22["serverdata"] = 12] = "serverdata";
2077
+ ServerCommand22[ServerCommand22["configstring"] = 13] = "configstring";
2078
+ ServerCommand22[ServerCommand22["spawnbaseline"] = 14] = "spawnbaseline";
2079
+ ServerCommand22[ServerCommand22["centerprint"] = 15] = "centerprint";
2080
+ ServerCommand22[ServerCommand22["download"] = 16] = "download";
2081
+ ServerCommand22[ServerCommand22["playerinfo"] = 17] = "playerinfo";
2082
+ ServerCommand22[ServerCommand22["packetentities"] = 18] = "packetentities";
2083
+ ServerCommand22[ServerCommand22["deltapacketentities"] = 19] = "deltapacketentities";
2084
+ ServerCommand22[ServerCommand22["frame"] = 20] = "frame";
2085
+ ServerCommand22[ServerCommand22["splitclient"] = 21] = "splitclient";
2086
+ ServerCommand22[ServerCommand22["configblast"] = 22] = "configblast";
2087
+ ServerCommand22[ServerCommand22["spawnbaselineblast"] = 23] = "spawnbaselineblast";
2088
+ ServerCommand22[ServerCommand22["level_restart"] = 24] = "level_restart";
2089
+ ServerCommand22[ServerCommand22["damage"] = 25] = "damage";
2090
+ ServerCommand22[ServerCommand22["locprint"] = 26] = "locprint";
2091
+ ServerCommand22[ServerCommand22["fog"] = 27] = "fog";
2092
+ ServerCommand22[ServerCommand22["waitingforplayers"] = 28] = "waitingforplayers";
2093
+ ServerCommand22[ServerCommand22["bot_chat"] = 29] = "bot_chat";
2094
+ ServerCommand22[ServerCommand22["poi"] = 30] = "poi";
2095
+ ServerCommand22[ServerCommand22["help_path"] = 31] = "help_path";
2096
+ ServerCommand22[ServerCommand22["muzzleflash3"] = 32] = "muzzleflash3";
2097
+ ServerCommand22[ServerCommand22["achievement"] = 33] = "achievement";
2098
+ return ServerCommand22;
2099
2099
  })(ServerCommand || {});
2100
2100
  var TempEntity = /* @__PURE__ */ ((TempEntity2) => {
2101
2101
  TempEntity2[TempEntity2["GUNSHOT"] = 0] = "GUNSHOT";
@@ -8078,6 +8078,170 @@ function angleMod(angle2) {
8078
8078
  const value = angle2 % 360;
8079
8079
  return value < 0 ? 360 + value : value;
8080
8080
  }
8081
+ var ANORMS2 = [
8082
+ [-0.525731, 0, 0.850651],
8083
+ [-0.442863, 0.238856, 0.864188],
8084
+ [-0.295242, 0, 0.955423],
8085
+ [-0.309017, 0.5, 0.809017],
8086
+ [-0.16246, 0.262866, 0.951056],
8087
+ [0, 0, 1],
8088
+ [0, 0.850651, 0.525731],
8089
+ [-0.147621, 0.716567, 0.681718],
8090
+ [0.147621, 0.716567, 0.681718],
8091
+ [0, 0.525731, 0.850651],
8092
+ [0.309017, 0.5, 0.809017],
8093
+ [0.525731, 0, 0.850651],
8094
+ [0.295242, 0, 0.955423],
8095
+ [0.442863, 0.238856, 0.864188],
8096
+ [0.16246, 0.262866, 0.951056],
8097
+ [-0.681718, 0.147621, 0.716567],
8098
+ [-0.809017, 0.309017, 0.5],
8099
+ [-0.587785, 0.425325, 0.688191],
8100
+ [-0.850651, 0.525731, 0],
8101
+ [-0.864188, 0.442863, 0.238856],
8102
+ [-0.716567, 0.681718, 0.147621],
8103
+ [-0.688191, 0.587785, 0.425325],
8104
+ [-0.5, 0.809017, 0.309017],
8105
+ [-0.238856, 0.864188, 0.442863],
8106
+ [-0.425325, 0.688191, 0.587785],
8107
+ [-0.716567, 0.681718, -0.147621],
8108
+ [-0.5, 0.809017, -0.309017],
8109
+ [-0.525731, 0.850651, 0],
8110
+ [0, 0.850651, -0.525731],
8111
+ [-0.238856, 0.864188, -0.442863],
8112
+ [0, 0.955423, -0.295242],
8113
+ [-0.262866, 0.951056, -0.16246],
8114
+ [0, 1, 0],
8115
+ [0, 0.955423, 0.295242],
8116
+ [-0.262866, 0.951056, 0.16246],
8117
+ [0.238856, 0.864188, 0.442863],
8118
+ [0.262866, 0.951056, 0.16246],
8119
+ [0.5, 0.809017, 0.309017],
8120
+ [0.238856, 0.864188, -0.442863],
8121
+ [0.262866, 0.951056, -0.16246],
8122
+ [0.5, 0.809017, -0.309017],
8123
+ [0.850651, 0.525731, 0],
8124
+ [0.716567, 0.681718, 0.147621],
8125
+ [0.716567, 0.681718, -0.147621],
8126
+ [0.525731, 0.850651, 0],
8127
+ [0.425325, 0.688191, 0.587785],
8128
+ [0.864188, 0.442863, 0.238856],
8129
+ [0.688191, 0.587785, 0.425325],
8130
+ [0.809017, 0.309017, 0.5],
8131
+ [0.681718, 0.147621, 0.716567],
8132
+ [0.587785, 0.425325, 0.688191],
8133
+ [0.955423, 0.295242, 0],
8134
+ [1, 0, 0],
8135
+ [0.951056, 0.16246, 0.262866],
8136
+ [0.850651, -0.525731, 0],
8137
+ [0.955423, -0.295242, 0],
8138
+ [0.864188, -0.442863, 0.238856],
8139
+ [0.951056, -0.16246, 0.262866],
8140
+ [0.809017, -0.309017, 0.5],
8141
+ [0.681718, -0.147621, 0.716567],
8142
+ [0.850651, 0, 0.525731],
8143
+ [0.864188, 0.442863, -0.238856],
8144
+ [0.809017, 0.309017, -0.5],
8145
+ [0.951056, 0.16246, -0.262866],
8146
+ [0.525731, 0, -0.850651],
8147
+ [0.681718, 0.147621, -0.716567],
8148
+ [0.681718, -0.147621, -0.716567],
8149
+ [0.850651, 0, -0.525731],
8150
+ [0.809017, -0.309017, -0.5],
8151
+ [0.864188, -0.442863, -0.238856],
8152
+ [0.951056, -0.16246, -0.262866],
8153
+ [0.147621, 0.716567, -0.681718],
8154
+ [0.309017, 0.5, -0.809017],
8155
+ [0.425325, 0.688191, -0.587785],
8156
+ [0.442863, 0.238856, -0.864188],
8157
+ [0.587785, 0.425325, -0.688191],
8158
+ [0.688191, 0.587785, -0.425325],
8159
+ [-0.147621, 0.716567, -0.681718],
8160
+ [-0.309017, 0.5, -0.809017],
8161
+ [0, 0.525731, -0.850651],
8162
+ [-0.525731, 0, -0.850651],
8163
+ [-0.442863, 0.238856, -0.864188],
8164
+ [-0.295242, 0, -0.955423],
8165
+ [-0.16246, 0.262866, -0.951056],
8166
+ [0, 0, -1],
8167
+ [0.295242, 0, -0.955423],
8168
+ [0.16246, 0.262866, -0.951056],
8169
+ [-0.442863, -0.238856, -0.864188],
8170
+ [-0.309017, -0.5, -0.809017],
8171
+ [-0.16246, -0.262866, -0.951056],
8172
+ [0, -0.850651, -0.525731],
8173
+ [-0.147621, -0.716567, -0.681718],
8174
+ [0.147621, -0.716567, -0.681718],
8175
+ [0, -0.525731, -0.850651],
8176
+ [0.309017, -0.5, -0.809017],
8177
+ [0.442863, -0.238856, -0.864188],
8178
+ [0.16246, -0.262866, -0.951056],
8179
+ [0.238856, -0.864188, -0.442863],
8180
+ [0.5, -0.809017, -0.309017],
8181
+ [0.425325, -0.688191, -0.587785],
8182
+ [0.716567, -0.681718, -0.147621],
8183
+ [0.688191, -0.587785, -0.425325],
8184
+ [0.587785, -0.425325, -0.688191],
8185
+ [0, -0.955423, -0.295242],
8186
+ [0, -1, 0],
8187
+ [0.262866, -0.951056, -0.16246],
8188
+ [0, -0.850651, 0.525731],
8189
+ [0, -0.955423, 0.295242],
8190
+ [0.238856, -0.864188, 0.442863],
8191
+ [0.262866, -0.951056, 0.16246],
8192
+ [0.5, -0.809017, 0.309017],
8193
+ [0.716567, -0.681718, 0.147621],
8194
+ [0.525731, -0.850651, 0],
8195
+ [-0.238856, -0.864188, -0.442863],
8196
+ [-0.5, -0.809017, -0.309017],
8197
+ [-0.262866, -0.951056, -0.16246],
8198
+ [-0.850651, -0.525731, 0],
8199
+ [-0.716567, -0.681718, -0.147621],
8200
+ [-0.716567, -0.681718, 0.147621],
8201
+ [-0.525731, -0.850651, 0],
8202
+ [-0.5, -0.809017, 0.309017],
8203
+ [-0.238856, -0.864188, 0.442863],
8204
+ [-0.262866, -0.951056, 0.16246],
8205
+ [-0.864188, -0.442863, 0.238856],
8206
+ [-0.809017, -0.309017, 0.5],
8207
+ [-0.688191, -0.587785, 0.425325],
8208
+ [-0.681718, -0.147621, 0.716567],
8209
+ [-0.442863, -0.238856, 0.864188],
8210
+ [-0.587785, -0.425325, 0.688191],
8211
+ [-0.309017, -0.5, 0.809017],
8212
+ [-0.147621, -0.716567, 0.681718],
8213
+ [-0.425325, -0.688191, 0.587785],
8214
+ [-0.16246, -0.262866, 0.951056],
8215
+ [0.442863, -0.238856, 0.864188],
8216
+ [0.16246, -0.262866, 0.951056],
8217
+ [0.309017, -0.5, 0.809017],
8218
+ [0.147621, -0.716567, 0.681718],
8219
+ [0, -0.525731, 0.850651],
8220
+ [0.425325, -0.688191, 0.587785],
8221
+ [0.587785, -0.425325, 0.688191],
8222
+ [0.688191, -0.587785, 0.425325],
8223
+ [-0.955423, 0.295242, 0],
8224
+ [-0.951056, 0.16246, 0.262866],
8225
+ [-1, 0, 0],
8226
+ [-0.850651, 0, 0.525731],
8227
+ [-0.955423, -0.295242, 0],
8228
+ [-0.951056, -0.16246, 0.262866],
8229
+ [-0.864188, 0.442863, -0.238856],
8230
+ [-0.951056, 0.16246, -0.262866],
8231
+ [-0.809017, 0.309017, -0.5],
8232
+ [-0.864188, -0.442863, -0.238856],
8233
+ [-0.951056, -0.16246, -0.262866],
8234
+ [-0.809017, -0.309017, -0.5],
8235
+ [-0.681718, 0.147621, -0.716567],
8236
+ [-0.681718, -0.147621, -0.716567],
8237
+ [-0.850651, 0, -0.525731],
8238
+ [-0.688191, 0.587785, -0.425325],
8239
+ [-0.587785, 0.425325, -0.688191],
8240
+ [-0.425325, 0.688191, -0.587785],
8241
+ [-0.425325, -0.688191, -0.587785],
8242
+ [-0.587785, -0.425325, -0.688191],
8243
+ [-0.688191, -0.587785, -0.425325]
8244
+ ];
8081
8245
  var CONTENTS_SOLID2 = 1 << 0;
8082
8246
  var CONTENTS_WINDOW2 = 1 << 1;
8083
8247
  var CONTENTS_AUX2 = 1 << 2;
@@ -8277,6 +8441,14 @@ function mouseDeltaToViewDelta(delta, options) {
8277
8441
  z: 0
8278
8442
  };
8279
8443
  }
8444
+ var ClientCommand = /* @__PURE__ */ ((ClientCommand2) => {
8445
+ ClientCommand2[ClientCommand2["bad"] = 0] = "bad";
8446
+ ClientCommand2[ClientCommand2["nop"] = 1] = "nop";
8447
+ ClientCommand2[ClientCommand2["move"] = 2] = "move";
8448
+ ClientCommand2[ClientCommand2["userinfo"] = 3] = "userinfo";
8449
+ ClientCommand2[ClientCommand2["stringcmd"] = 4] = "stringcmd";
8450
+ return ClientCommand2;
8451
+ })(ClientCommand || {});
8280
8452
  var MZ_BLASTER = 0;
8281
8453
  var MZ_MACHINEGUN = 1;
8282
8454
  var MZ_SHOTGUN = 2;
@@ -8432,7 +8604,16 @@ var POWERUP_STAT_MAP = {
8432
8604
  "enviro_suit"
8433
8605
  /* EnviroSuit */
8434
8606
  ]: 9,
8435
- // 10 is POWERUP_ADRENALINE (not in PowerupId?)
8607
+ [
8608
+ "bandolier"
8609
+ /* Bandolier */
8610
+ ]: 10,
8611
+ // Placeholder/Map mismatch handling?
8612
+ [
8613
+ "ammo_pack"
8614
+ /* AmmoPack */
8615
+ ]: 10,
8616
+ // Original reused indices or had gaps?
8436
8617
  [
8437
8618
  "ir_goggles"
8438
8619
  /* IRGoggles */
@@ -8480,7 +8661,12 @@ var POWERUP_STAT_MAP = {
8480
8661
  [
8481
8662
  "tech_regeneration"
8482
8663
  /* TechRegeneration */
8483
- ]: 22
8664
+ ]: 22,
8665
+ // Add missing mappings to avoid runtime lookups failing for new types
8666
+ [
8667
+ "tag_token"
8668
+ /* TagToken */
8669
+ ]: -1
8484
8670
  };
8485
8671
  function G_GetPowerupStat(stats, powerupId) {
8486
8672
  let index;
@@ -8535,6 +8721,211 @@ var U_MODEL23 = 1 << 0;
8535
8721
  var U_MODEL33 = 1 << 1;
8536
8722
  var U_MODEL43 = 1 << 2;
8537
8723
  var U_REMOVE3 = 32768;
8724
+ var BinaryStream2 = class {
8725
+ constructor(buffer) {
8726
+ if (buffer instanceof Uint8Array) {
8727
+ this.view = new DataView(buffer.buffer, buffer.byteOffset, buffer.byteLength);
8728
+ } else {
8729
+ this.view = new DataView(buffer);
8730
+ }
8731
+ this.offset = 0;
8732
+ this.length = this.view.byteLength;
8733
+ }
8734
+ getPosition() {
8735
+ return this.offset;
8736
+ }
8737
+ seek(position) {
8738
+ if (position < 0 || position > this.length) {
8739
+ throw new Error(`Seek out of bounds: ${position} (length: ${this.length})`);
8740
+ }
8741
+ this.offset = position;
8742
+ }
8743
+ hasMore() {
8744
+ return this.offset < this.length;
8745
+ }
8746
+ readChar() {
8747
+ const value = this.view.getInt8(this.offset);
8748
+ this.offset += 1;
8749
+ return value;
8750
+ }
8751
+ readByte() {
8752
+ const value = this.view.getUint8(this.offset);
8753
+ this.offset += 1;
8754
+ return value;
8755
+ }
8756
+ readShort() {
8757
+ const value = this.view.getInt16(this.offset, true);
8758
+ this.offset += 2;
8759
+ return value;
8760
+ }
8761
+ readUShort() {
8762
+ const value = this.view.getUint16(this.offset, true);
8763
+ this.offset += 2;
8764
+ return value;
8765
+ }
8766
+ readLong() {
8767
+ const value = this.view.getInt32(this.offset, true);
8768
+ this.offset += 4;
8769
+ return value;
8770
+ }
8771
+ readULong() {
8772
+ const value = this.view.getUint32(this.offset, true);
8773
+ this.offset += 4;
8774
+ return value;
8775
+ }
8776
+ readFloat() {
8777
+ const value = this.view.getFloat32(this.offset, true);
8778
+ this.offset += 4;
8779
+ return value;
8780
+ }
8781
+ readString() {
8782
+ let str3 = "";
8783
+ while (this.offset < this.length) {
8784
+ const charCode = this.readChar();
8785
+ if (charCode === -1 || charCode === 0) {
8786
+ break;
8787
+ }
8788
+ str3 += String.fromCharCode(charCode);
8789
+ }
8790
+ return str3;
8791
+ }
8792
+ readStringLine() {
8793
+ let str3 = "";
8794
+ while (this.offset < this.length) {
8795
+ const charCode = this.readChar();
8796
+ if (charCode === -1 || charCode === 0 || charCode === 10) {
8797
+ break;
8798
+ }
8799
+ str3 += String.fromCharCode(charCode);
8800
+ }
8801
+ return str3;
8802
+ }
8803
+ readCoord() {
8804
+ return this.readShort() * (1 / 8);
8805
+ }
8806
+ readAngle() {
8807
+ return this.readChar() * (360 / 256);
8808
+ }
8809
+ readAngle16() {
8810
+ return this.readShort() * 360 / 65536;
8811
+ }
8812
+ readData(length2) {
8813
+ if (this.offset + length2 > this.length) {
8814
+ throw new Error(`Read out of bounds: ${this.offset + length2} (length: ${this.length})`);
8815
+ }
8816
+ const data = new Uint8Array(this.view.buffer, this.view.byteOffset + this.offset, length2);
8817
+ this.offset += length2;
8818
+ return new Uint8Array(data);
8819
+ }
8820
+ readPos(out) {
8821
+ out.x = this.readCoord();
8822
+ out.y = this.readCoord();
8823
+ out.z = this.readCoord();
8824
+ }
8825
+ readDir(out) {
8826
+ const b = this.readByte();
8827
+ if (b >= 162) {
8828
+ out.x = 0;
8829
+ out.y = 0;
8830
+ out.z = 0;
8831
+ return;
8832
+ }
8833
+ const norm = ANORMS2[b];
8834
+ out.x = norm[0];
8835
+ out.y = norm[1];
8836
+ out.z = norm[2];
8837
+ }
8838
+ };
8839
+ var NetworkMessageBuilder = class {
8840
+ constructor(initialSize = 1024) {
8841
+ this.buffer = new Uint8Array(initialSize);
8842
+ this.view = new DataView(this.buffer.buffer);
8843
+ this.offset = 0;
8844
+ }
8845
+ ensureCapacity(needed) {
8846
+ if (this.offset + needed > this.buffer.length) {
8847
+ const newSize = Math.max(this.buffer.length * 2, this.offset + needed);
8848
+ const newBuffer = new Uint8Array(newSize);
8849
+ newBuffer.set(this.buffer);
8850
+ this.buffer = newBuffer;
8851
+ this.view = new DataView(this.buffer.buffer);
8852
+ }
8853
+ }
8854
+ getData() {
8855
+ return this.buffer.slice(0, this.offset);
8856
+ }
8857
+ writeByte(value) {
8858
+ this.ensureCapacity(1);
8859
+ this.view.setUint8(this.offset, value);
8860
+ this.offset += 1;
8861
+ }
8862
+ writeChar(value) {
8863
+ this.ensureCapacity(1);
8864
+ this.view.setInt8(this.offset, value);
8865
+ this.offset += 1;
8866
+ }
8867
+ writeShort(value) {
8868
+ this.ensureCapacity(2);
8869
+ this.view.setInt16(this.offset, value, true);
8870
+ this.offset += 2;
8871
+ }
8872
+ writeUShort(value) {
8873
+ this.ensureCapacity(2);
8874
+ this.view.setUint16(this.offset, value, true);
8875
+ this.offset += 2;
8876
+ }
8877
+ writeLong(value) {
8878
+ this.ensureCapacity(4);
8879
+ this.view.setInt32(this.offset, value, true);
8880
+ this.offset += 4;
8881
+ }
8882
+ writeFloat(value) {
8883
+ this.ensureCapacity(4);
8884
+ this.view.setFloat32(this.offset, value, true);
8885
+ this.offset += 4;
8886
+ }
8887
+ writeString(value) {
8888
+ const len2 = value.length + 1;
8889
+ this.ensureCapacity(len2);
8890
+ for (let i = 0; i < value.length; i++) {
8891
+ this.view.setUint8(this.offset + i, value.charCodeAt(i));
8892
+ }
8893
+ this.view.setUint8(this.offset + value.length, 0);
8894
+ this.offset += len2;
8895
+ }
8896
+ writeData(data) {
8897
+ this.ensureCapacity(data.length);
8898
+ this.buffer.set(data, this.offset);
8899
+ this.offset += data.length;
8900
+ }
8901
+ writeCoord(value) {
8902
+ this.writeShort(Math.round(value * 8));
8903
+ }
8904
+ writeAngle(value) {
8905
+ this.writeByte(Math.round(value * 256 / 360) & 255);
8906
+ }
8907
+ writeAngle16(value) {
8908
+ this.writeShort(Math.round(value * 65536 / 360));
8909
+ }
8910
+ writeDir(x, y, z) {
8911
+ let best = 0;
8912
+ let bestDot = -999999;
8913
+ const len2 = Math.sqrt(x * x + y * y + z * z);
8914
+ if (len2 > 0) {
8915
+ x /= len2;
8916
+ y /= len2;
8917
+ z /= len2;
8918
+ for (let i = 0; i < 162; i++) {
8919
+ const dot2 = x * ANORMS2[i][0] + y * ANORMS2[i][1] + z * ANORMS2[i][2];
8920
+ if (dot2 > bestDot) {
8921
+ bestDot = dot2;
8922
+ best = i;
8923
+ }
8924
+ }
8925
+ }
8926
+ this.writeByte(best);
8927
+ }
8928
+ };
8538
8929
  var AmmoType2 = /* @__PURE__ */ ((AmmoType22) => {
8539
8930
  AmmoType22[AmmoType22["Bullets"] = 0] = "Bullets";
8540
8931
  AmmoType22[AmmoType22["Shells"] = 1] = "Shells";
@@ -9504,6 +9895,16 @@ var MainMenuFactory = class {
9504
9895
  this.menuSystem.pushMenu(this.createDifficultyMenu());
9505
9896
  }
9506
9897
  },
9898
+ {
9899
+ label: "Multiplayer",
9900
+ action: () => {
9901
+ if (this.options.multiplayerFactory) {
9902
+ this.menuSystem.pushMenu(this.options.multiplayerFactory.createMultiplayerMenu());
9903
+ } else {
9904
+ console.warn("Multiplayer factory not configured");
9905
+ }
9906
+ }
9907
+ },
9507
9908
  {
9508
9909
  label: "Load Game",
9509
9910
  action: () => {
@@ -10078,6 +10479,74 @@ var PauseMenuFactory = class {
10078
10479
  }
10079
10480
  };
10080
10481
 
10482
+ // src/ui/menu/multiplayer.ts
10483
+ var MultiplayerMenuFactory = class {
10484
+ constructor(menuSystem, connection) {
10485
+ this.menuSystem = menuSystem;
10486
+ this.connection = connection;
10487
+ }
10488
+ createMultiplayerMenu(initialAddress = "localhost:27910", status = "") {
10489
+ let address = initialAddress;
10490
+ const items = [];
10491
+ if (status) {
10492
+ items.push({
10493
+ label: status,
10494
+ action: () => {
10495
+ }
10496
+ // No-op
10497
+ });
10498
+ }
10499
+ items.push(
10500
+ {
10501
+ label: "Address: " + address,
10502
+ action: () => {
10503
+ if (typeof window !== "undefined") {
10504
+ const newAddr = window.prompt("Enter Server Address", address);
10505
+ if (newAddr) {
10506
+ address = newAddr;
10507
+ this.refreshMenu(address);
10508
+ }
10509
+ }
10510
+ }
10511
+ },
10512
+ {
10513
+ label: "Connect",
10514
+ action: () => {
10515
+ this.refreshMenu(address, "Connecting...");
10516
+ this.connection.connect("ws://" + address).then(() => {
10517
+ this.menuSystem.closeAll();
10518
+ }).catch((err2) => {
10519
+ console.error(err2);
10520
+ const failStatus = "Failed: " + (err2.message || "Unknown error");
10521
+ this.refreshMenu(address, failStatus);
10522
+ });
10523
+ }
10524
+ },
10525
+ {
10526
+ label: "Disconnect",
10527
+ action: () => {
10528
+ this.connection.disconnect();
10529
+ this.refreshMenu(address, "Disconnected");
10530
+ }
10531
+ },
10532
+ {
10533
+ label: "Back",
10534
+ action: () => {
10535
+ this.menuSystem.popMenu();
10536
+ }
10537
+ }
10538
+ );
10539
+ return {
10540
+ title: "Multiplayer",
10541
+ items
10542
+ };
10543
+ }
10544
+ refreshMenu(address, status = "") {
10545
+ this.menuSystem.popMenu();
10546
+ this.menuSystem.pushMenu(this.createMultiplayerMenu(address, status));
10547
+ }
10548
+ };
10549
+
10081
10550
  // src/ui/menu/render.ts
10082
10551
  function Draw_Menu(renderer, state, width, height) {
10083
10552
  if (!state.activeMenu) {
@@ -10356,6 +10825,233 @@ function buildRenderableEntities(latestEntities, previousEntities, alpha, config
10356
10825
  return renderables;
10357
10826
  }
10358
10827
 
10828
+ // src/net/browserWsDriver.ts
10829
+ var BrowserWebSocketNetDriver = class {
10830
+ constructor() {
10831
+ this.socket = null;
10832
+ this.messageCallback = null;
10833
+ this.closeCallback = null;
10834
+ this.errorCallback = null;
10835
+ }
10836
+ async connect(url) {
10837
+ return new Promise((resolve, reject) => {
10838
+ try {
10839
+ this.socket = new WebSocket(url);
10840
+ this.socket.binaryType = "arraybuffer";
10841
+ this.socket.onopen = () => {
10842
+ resolve();
10843
+ };
10844
+ this.socket.onerror = (event) => {
10845
+ const error = new Error("WebSocket connection error");
10846
+ if (this.errorCallback) {
10847
+ this.errorCallback(error);
10848
+ }
10849
+ reject(error);
10850
+ };
10851
+ this.socket.onclose = () => {
10852
+ if (this.closeCallback) {
10853
+ this.closeCallback();
10854
+ }
10855
+ this.socket = null;
10856
+ };
10857
+ this.socket.onmessage = (event) => {
10858
+ if (this.messageCallback) {
10859
+ if (event.data instanceof ArrayBuffer) {
10860
+ this.messageCallback(new Uint8Array(event.data));
10861
+ } else {
10862
+ console.warn("Received non-binary message from server");
10863
+ }
10864
+ }
10865
+ };
10866
+ } catch (e) {
10867
+ reject(e);
10868
+ }
10869
+ });
10870
+ }
10871
+ disconnect() {
10872
+ if (this.socket) {
10873
+ this.socket.close();
10874
+ this.socket = null;
10875
+ }
10876
+ }
10877
+ send(data) {
10878
+ if (this.socket && this.socket.readyState === WebSocket.OPEN) {
10879
+ this.socket.send(data);
10880
+ } else {
10881
+ console.warn("Attempted to send data on closed or connecting socket");
10882
+ }
10883
+ }
10884
+ onMessage(callback) {
10885
+ this.messageCallback = callback;
10886
+ }
10887
+ onClose(callback) {
10888
+ this.closeCallback = callback;
10889
+ }
10890
+ onError(callback) {
10891
+ this.errorCallback = callback;
10892
+ }
10893
+ isConnected() {
10894
+ return this.socket !== null && this.socket.readyState === WebSocket.OPEN;
10895
+ }
10896
+ };
10897
+
10898
+ // src/net/connection.ts
10899
+ var MultiplayerConnection = class {
10900
+ constructor(options) {
10901
+ this.state = 0 /* Disconnected */;
10902
+ this.parser = null;
10903
+ // Game State
10904
+ this.serverProtocol = 0;
10905
+ this.serverCount = 0;
10906
+ this.gameDir = "";
10907
+ this.playerNum = 0;
10908
+ this.levelName = "";
10909
+ this.configStrings = /* @__PURE__ */ new Map();
10910
+ this.baselines = /* @__PURE__ */ new Map();
10911
+ this.challenge = 0;
10912
+ this.connectPacketCount = 0;
10913
+ this.connectPacketTime = 0;
10914
+ this.driver = new BrowserWebSocketNetDriver();
10915
+ this.options = options;
10916
+ this.driver.onMessage((data) => this.handleMessage(data));
10917
+ this.driver.onClose(() => this.handleDisconnect());
10918
+ this.driver.onError((err2) => console.error("Network Error:", err2));
10919
+ }
10920
+ async connect(url) {
10921
+ if (this.state !== 0 /* Disconnected */) {
10922
+ this.disconnect();
10923
+ }
10924
+ console.log(`Connecting to ${url}...`);
10925
+ this.state = 1 /* Connecting */;
10926
+ try {
10927
+ await this.driver.connect(url);
10928
+ console.log("WebSocket connected.");
10929
+ this.state = 2 /* Challenge */;
10930
+ this.sendChallenge();
10931
+ } catch (e) {
10932
+ console.error("Connection failed:", e);
10933
+ this.state = 0 /* Disconnected */;
10934
+ throw e;
10935
+ }
10936
+ }
10937
+ disconnect() {
10938
+ if (this.state === 0 /* Disconnected */) return;
10939
+ this.driver.disconnect();
10940
+ this.state = 0 /* Disconnected */;
10941
+ this.configStrings.clear();
10942
+ this.baselines.clear();
10943
+ }
10944
+ sendCommand(cmd) {
10945
+ if (this.state !== 5 /* Active */) return;
10946
+ const builder = new NetworkMessageBuilder();
10947
+ builder.writeByte(ClientCommand.nop);
10948
+ this.driver.send(builder.getData());
10949
+ }
10950
+ handleMessage(data) {
10951
+ let buffer = data.buffer;
10952
+ if (buffer instanceof SharedArrayBuffer) {
10953
+ const newBuffer = new ArrayBuffer(data.byteLength);
10954
+ new Uint8Array(newBuffer).set(data);
10955
+ buffer = newBuffer;
10956
+ }
10957
+ const stream = new BinaryStream2(buffer);
10958
+ const sequence = stream.readLong();
10959
+ const sequenceAck = stream.readLong();
10960
+ this.parser = new NetworkMessageParser(stream, this);
10961
+ this.parser.parseMessage();
10962
+ }
10963
+ handleDisconnect() {
10964
+ console.log("Disconnected from server.");
10965
+ this.state = 0 /* Disconnected */;
10966
+ }
10967
+ sendChallenge() {
10968
+ const builder = new NetworkMessageBuilder();
10969
+ builder.writeByte(ClientCommand.stringcmd);
10970
+ builder.writeString("getchallenge");
10971
+ this.driver.send(builder.getData());
10972
+ }
10973
+ sendConnect(challenge) {
10974
+ const builder = new NetworkMessageBuilder();
10975
+ builder.writeByte(ClientCommand.stringcmd);
10976
+ const userinfo = `\\name\\${this.options.username}\\model\\${this.options.model}\\skin\\${this.options.skin}\\hand\\${this.options.hand ?? 0}\\fov\\${this.options.fov ?? 90}`;
10977
+ builder.writeString(`connect ${PROTOCOL_VERSION_RERELEASE} ${challenge} ${userinfo}`);
10978
+ this.driver.send(builder.getData());
10979
+ }
10980
+ isConnected() {
10981
+ return this.state === 5 /* Active */;
10982
+ }
10983
+ // ==================================================================================
10984
+ // NetworkMessageHandler Implementation
10985
+ // ==================================================================================
10986
+ onServerData(protocol, serverCount, attractLoop, gameDir, playerNum, levelName) {
10987
+ console.log(`Server Data: Protocol ${protocol}, Level ${levelName}`);
10988
+ this.serverProtocol = protocol;
10989
+ this.serverCount = serverCount;
10990
+ this.gameDir = gameDir;
10991
+ this.playerNum = playerNum;
10992
+ this.levelName = levelName;
10993
+ this.state = 3 /* Connected */;
10994
+ const builder = new NetworkMessageBuilder();
10995
+ builder.writeByte(ClientCommand.stringcmd);
10996
+ builder.writeString("new");
10997
+ this.driver.send(builder.getData());
10998
+ this.state = 4 /* Loading */;
10999
+ }
11000
+ onConfigString(index, str3) {
11001
+ this.configStrings.set(index, str3);
11002
+ }
11003
+ onSpawnBaseline(entity) {
11004
+ this.baselines.set(entity.number, entity);
11005
+ }
11006
+ onStuffText(msg) {
11007
+ console.log(`Server StuffText: ${msg}`);
11008
+ if (msg.startsWith("precache")) {
11009
+ this.finishLoading();
11010
+ }
11011
+ if (msg.startsWith("challenge ")) {
11012
+ const parts = msg.split(" ");
11013
+ if (parts.length > 1) {
11014
+ this.challenge = parseInt(parts[1], 10);
11015
+ this.sendConnect(this.challenge);
11016
+ }
11017
+ }
11018
+ }
11019
+ finishLoading() {
11020
+ console.log("Finished loading, sending begin...");
11021
+ const builder = new NetworkMessageBuilder();
11022
+ builder.writeByte(ClientCommand.stringcmd);
11023
+ builder.writeString("begin");
11024
+ this.driver.send(builder.getData());
11025
+ this.state = 5 /* Active */;
11026
+ }
11027
+ // Stubs for other handlers
11028
+ onFrame(frame) {
11029
+ }
11030
+ onCenterPrint(msg) {
11031
+ }
11032
+ onPrint(level, msg) {
11033
+ }
11034
+ onSound(flags, soundNum, volume, attenuation, offset, ent, pos) {
11035
+ }
11036
+ onTempEntity(type, pos, pos2, dir, cnt, color, ent, srcEnt, destEnt) {
11037
+ }
11038
+ onLayout(layout) {
11039
+ }
11040
+ onInventory(inventory) {
11041
+ }
11042
+ onMuzzleFlash(ent, weapon) {
11043
+ }
11044
+ onMuzzleFlash2(ent, weapon) {
11045
+ }
11046
+ onDisconnect() {
11047
+ this.disconnect();
11048
+ }
11049
+ onReconnect() {
11050
+ }
11051
+ onDownload(size, percent, data) {
11052
+ }
11053
+ };
11054
+
10359
11055
  // src/input/bindings.ts
10360
11056
  var DEFAULT_BINDINGS = [
10361
11057
  { code: "KeyW", command: "+forward" },
@@ -10889,6 +11585,21 @@ function createClient(imports) {
10889
11585
  };
10890
11586
  const cgameImport = createCGameImport(imports, stateProvider);
10891
11587
  const cg = (0, import_cgame2.GetCGameAPI)(cgameImport);
11588
+ const multiplayer = new MultiplayerConnection({
11589
+ get username() {
11590
+ return imports.host?.cvars?.get("name")?.string || "Player";
11591
+ },
11592
+ get model() {
11593
+ return imports.host?.cvars?.get("model")?.string || "male";
11594
+ },
11595
+ get skin() {
11596
+ return imports.host?.cvars?.get("skin")?.string || "grunt";
11597
+ },
11598
+ get fov() {
11599
+ return fovValue;
11600
+ }
11601
+ });
11602
+ const multiplayerFactory = new MultiplayerMenuFactory(menuSystem, multiplayer);
10892
11603
  demoHandler.setCallbacks({
10893
11604
  onCenterPrint: (msg) => cg.ParseCenterPrint(msg, 0, false),
10894
11605
  onPrint: (level, msg) => cg.NotifyMessage(0, msg, false),
@@ -10951,6 +11662,22 @@ function createClient(imports) {
10951
11662
  menuSystem.pushMenu(pauseMenuFactory.createPauseMenu());
10952
11663
  }
10953
11664
  }, "Toggle the main/pause menu");
11665
+ imports.host.commands.register("connect", (args) => {
11666
+ if (args.length < 1) {
11667
+ console.log("usage: connect <address>");
11668
+ return;
11669
+ }
11670
+ const address = args[0];
11671
+ console.log(`Connecting to ${address}...`);
11672
+ multiplayer.connect(address).catch((e) => {
11673
+ console.error("Failed to connect:", e);
11674
+ errorDialog.show("Connection Failed", e instanceof Error ? e.message : "Unknown error");
11675
+ });
11676
+ }, "Connect to a multiplayer server");
11677
+ imports.host.commands.register("disconnect", () => {
11678
+ multiplayer.disconnect();
11679
+ console.log("Disconnected.");
11680
+ }, "Disconnect from server");
10954
11681
  if (imports.host.cvars) {
10955
11682
  imports.host.cvars.register({
10956
11683
  name: "fov",
@@ -11005,6 +11732,9 @@ function createClient(imports) {
11005
11732
  predict(command) {
11006
11733
  if (menuSystem.isActive()) {
11007
11734
  }
11735
+ if (multiplayer.isConnected()) {
11736
+ multiplayer.sendCommand(command);
11737
+ }
11008
11738
  return prediction.enqueueCommand(command);
11009
11739
  },
11010
11740
  handleInput(key, down) {
@@ -11069,6 +11799,7 @@ function createClient(imports) {
11069
11799
  ...options,
11070
11800
  optionsFactory: optsFactory,
11071
11801
  mapsFactory,
11802
+ multiplayerFactory,
11072
11803
  onSetDifficulty: (skill) => {
11073
11804
  if (imports.host?.cvars) {
11074
11805
  imports.host.cvars.setValue("skill", skill.toString());
@@ -11274,6 +12005,7 @@ function createClient(imports) {
11274
12005
  cg.ParseConfigString(index, value);
11275
12006
  },
11276
12007
  demoHandler,
12008
+ multiplayer,
11277
12009
  configStrings
11278
12010
  };
11279
12011
  return clientExports;