quake2ts 0.0.251 → 0.0.256

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 (47) 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 +808 -53
  5. package/packages/client/dist/cjs/index.cjs.map +1 -1
  6. package/packages/client/dist/esm/index.js +808 -53
  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/demo/handler.d.ts +3 -1
  10. package/packages/client/dist/types/demo/handler.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 +51 -6
  22. package/packages/engine/dist/cjs/index.cjs.map +1 -1
  23. package/packages/engine/dist/esm/index.js +44 -6
  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/demo/parser.d.ts +10 -2
  27. package/packages/engine/dist/types/demo/parser.d.ts.map +1 -1
  28. package/packages/engine/dist/types/index.d.ts +1 -1
  29. package/packages/engine/dist/types/index.d.ts.map +1 -1
  30. package/packages/game/dist/browser/index.global.js +2 -2
  31. package/packages/game/dist/browser/index.global.js.map +1 -1
  32. package/packages/game/dist/cjs/index.cjs.map +1 -1
  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/entities/projectiles/prox.d.ts.map +1 -1
  36. package/packages/shared/dist/browser/index.global.js +1 -1
  37. package/packages/shared/dist/browser/index.global.js.map +1 -1
  38. package/packages/shared/dist/cjs/index.cjs +94 -0
  39. package/packages/shared/dist/cjs/index.cjs.map +1 -1
  40. package/packages/shared/dist/esm/index.js +93 -0
  41. package/packages/shared/dist/esm/index.js.map +1 -1
  42. package/packages/shared/dist/tsconfig.tsbuildinfo +1 -1
  43. package/packages/shared/dist/types/io/index.d.ts +1 -0
  44. package/packages/shared/dist/types/io/index.d.ts.map +1 -1
  45. package/packages/shared/dist/types/io/messageBuilder.d.ts +21 -0
  46. package/packages/shared/dist/types/io/messageBuilder.d.ts.map +1 -0
  47. 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";
@@ -7100,6 +7100,13 @@ var U_OLDORIGIN = 1 << 24;
7100
7100
  var U_SKIN16 = 1 << 25;
7101
7101
  var U_SOUND2 = 1 << 26;
7102
7102
  var U_SOLID2 = 1 << 27;
7103
+ var U_SCALE = 1 << 28;
7104
+ var U_INSTANCE_BITS = 1 << 29;
7105
+ var U_LOOP_VOLUME = 1 << 30;
7106
+ var U_MOREBITS4 = 2147483648 | 0;
7107
+ var U_LOOP_ATTENUATION_HIGH = 1 << 0;
7108
+ var U_OWNER_HIGH = 1 << 1;
7109
+ var U_OLD_FRAME_HIGH = 1 << 2;
7103
7110
  var RECORD_CLIENT = 1;
7104
7111
  var RECORD_SERVER = 2;
7105
7112
  var RECORD_RELAY = 128;
@@ -7120,6 +7127,7 @@ var createEmptyEntityState = () => ({
7120
7127
  event: 0,
7121
7128
  solid: 0,
7122
7129
  bits: 0,
7130
+ bitsHigh: 0,
7123
7131
  alpha: 0,
7124
7132
  scale: 0,
7125
7133
  instanceBits: 0,
@@ -7422,13 +7430,13 @@ var NetworkMessageParser = class _NetworkMessageParser {
7422
7430
  args.push(this.stream.readString());
7423
7431
  }
7424
7432
  if (this.handler && this.handler.onLocPrint) {
7425
- this.handler.onLocPrint(flags, base);
7433
+ this.handler.onLocPrint(flags, base, args);
7426
7434
  }
7427
7435
  }
7428
7436
  parseWaitingForPlayers() {
7429
7437
  const count = this.stream.readByte();
7430
7438
  if (this.handler && this.handler.onWaitingForPlayers) {
7431
- this.handler.onWaitingForPlayers();
7439
+ this.handler.onWaitingForPlayers(count);
7432
7440
  }
7433
7441
  }
7434
7442
  parseBotChat() {
@@ -7463,6 +7471,9 @@ var NetworkMessageParser = class _NetworkMessageParser {
7463
7471
  }
7464
7472
  parseAchievement() {
7465
7473
  const idStr = this.stream.readString();
7474
+ if (this.handler && this.handler.onAchievement) {
7475
+ this.handler.onAchievement(idStr);
7476
+ }
7466
7477
  }
7467
7478
  parseDownload() {
7468
7479
  const size = this.stream.readShort();
@@ -7746,7 +7757,7 @@ var NetworkMessageParser = class _NetworkMessageParser {
7746
7757
  parseSpawnBaseline() {
7747
7758
  const bits = this.parseEntityBits();
7748
7759
  const entity = createEmptyEntityState();
7749
- this.parseDelta(createEmptyEntityState(), entity, bits.number, bits.bits);
7760
+ this.parseDelta(createEmptyEntityState(), entity, bits.number, bits.bits, bits.bitsHigh);
7750
7761
  if (this.handler) {
7751
7762
  this.handler.onSpawnBaseline(entity);
7752
7763
  }
@@ -7871,7 +7882,7 @@ var NetworkMessageParser = class _NetworkMessageParser {
7871
7882
  break;
7872
7883
  }
7873
7884
  const entity = createEmptyEntityState();
7874
- this.parseDelta(createEmptyEntityState(), entity, bits.number, bits.bits);
7885
+ this.parseDelta(createEmptyEntityState(), entity, bits.number, bits.bits, bits.bitsHigh);
7875
7886
  entities.push(entity);
7876
7887
  }
7877
7888
  return entities;
@@ -7887,15 +7898,20 @@ var NetworkMessageParser = class _NetworkMessageParser {
7887
7898
  if (total & U_MOREBITS3) {
7888
7899
  total |= this.stream.readByte() << 24;
7889
7900
  }
7901
+ let bitsHigh = 0;
7902
+ if (total & U_MOREBITS4) {
7903
+ const byte5 = this.stream.readByte();
7904
+ bitsHigh = byte5;
7905
+ }
7890
7906
  let number;
7891
7907
  if (total & U_NUMBER16) {
7892
7908
  number = this.stream.readShort();
7893
7909
  } else {
7894
7910
  number = this.stream.readByte();
7895
7911
  }
7896
- return { number, bits: total };
7912
+ return { number, bits: total, bitsHigh };
7897
7913
  }
7898
- parseDelta(from, to, number, bits) {
7914
+ parseDelta(from, to, number, bits, bitsHigh = 0) {
7899
7915
  to.number = from.number;
7900
7916
  to.modelindex = from.modelindex;
7901
7917
  to.modelindex2 = from.modelindex2;
@@ -7917,8 +7933,16 @@ var NetworkMessageParser = class _NetworkMessageParser {
7917
7933
  to.sound = from.sound;
7918
7934
  to.event = from.event;
7919
7935
  to.solid = from.solid;
7936
+ to.alpha = from.alpha;
7937
+ to.scale = from.scale;
7938
+ to.instanceBits = from.instanceBits;
7939
+ to.loopVolume = from.loopVolume;
7940
+ to.loopAttenuation = from.loopAttenuation;
7941
+ to.owner = from.owner;
7942
+ to.oldFrame = from.oldFrame;
7920
7943
  to.number = number;
7921
7944
  to.bits = bits;
7945
+ to.bitsHigh = bitsHigh;
7922
7946
  if (bits & U_MODEL5) to.modelindex = this.stream.readByte();
7923
7947
  if (bits & U_MODEL22) to.modelindex2 = this.stream.readByte();
7924
7948
  if (bits & U_MODEL32) to.modelindex3 = this.stream.readByte();
@@ -7962,6 +7986,13 @@ var NetworkMessageParser = class _NetworkMessageParser {
7962
7986
  to.event = 0;
7963
7987
  }
7964
7988
  if (bits & U_SOLID2) to.solid = this.stream.readShort();
7989
+ if (bits & U_ALPHA) to.alpha = this.stream.readByte() / 255;
7990
+ if (bits & U_SCALE) to.scale = this.stream.readFloat();
7991
+ if (bits & U_INSTANCE_BITS) to.instanceBits = this.stream.readLong();
7992
+ if (bits & U_LOOP_VOLUME) to.loopVolume = this.stream.readByte() / 255;
7993
+ if (bitsHigh & U_LOOP_ATTENUATION_HIGH) to.loopAttenuation = this.stream.readByte() / 255;
7994
+ if (bitsHigh & U_OWNER_HIGH) to.owner = this.stream.readShort();
7995
+ if (bitsHigh & U_OLD_FRAME_HIGH) to.oldFrame = this.stream.readShort();
7965
7996
  }
7966
7997
  };
7967
7998
  var PlaybackState = /* @__PURE__ */ ((PlaybackState2) => {
@@ -8047,6 +8078,170 @@ function angleMod(angle2) {
8047
8078
  const value = angle2 % 360;
8048
8079
  return value < 0 ? 360 + value : value;
8049
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
+ ];
8050
8245
  var CONTENTS_SOLID2 = 1 << 0;
8051
8246
  var CONTENTS_WINDOW2 = 1 << 1;
8052
8247
  var CONTENTS_AUX2 = 1 << 2;
@@ -8246,6 +8441,14 @@ function mouseDeltaToViewDelta(delta, options) {
8246
8441
  z: 0
8247
8442
  };
8248
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 || {});
8249
8452
  var MZ_BLASTER = 0;
8250
8453
  var MZ_MACHINEGUN = 1;
8251
8454
  var MZ_SHOTGUN = 2;
@@ -8473,7 +8676,7 @@ __export3(entityFlags_exports2, {
8473
8676
  U_MODEL2: () => U_MODEL23,
8474
8677
  U_MODEL3: () => U_MODEL33,
8475
8678
  U_MODEL4: () => U_MODEL43,
8476
- U_MOREBITS: () => U_MOREBITS4,
8679
+ U_MOREBITS: () => U_MOREBITS5,
8477
8680
  U_NUMBER: () => U_NUMBER2,
8478
8681
  U_ORIGIN1: () => U_ORIGIN13,
8479
8682
  U_ORIGIN2: () => U_ORIGIN23,
@@ -8499,11 +8702,216 @@ var U_EFFECTS2 = 1 << 11;
8499
8702
  var U_RENDERFX2 = 1 << 12;
8500
8703
  var U_SOLID3 = 1 << 13;
8501
8704
  var U_EVENT3 = 1 << 14;
8502
- var U_MOREBITS4 = 1 << 15;
8705
+ var U_MOREBITS5 = 1 << 15;
8503
8706
  var U_MODEL23 = 1 << 0;
8504
8707
  var U_MODEL33 = 1 << 1;
8505
8708
  var U_MODEL43 = 1 << 2;
8506
8709
  var U_REMOVE3 = 32768;
8710
+ var BinaryStream2 = class {
8711
+ constructor(buffer) {
8712
+ if (buffer instanceof Uint8Array) {
8713
+ this.view = new DataView(buffer.buffer, buffer.byteOffset, buffer.byteLength);
8714
+ } else {
8715
+ this.view = new DataView(buffer);
8716
+ }
8717
+ this.offset = 0;
8718
+ this.length = this.view.byteLength;
8719
+ }
8720
+ getPosition() {
8721
+ return this.offset;
8722
+ }
8723
+ seek(position) {
8724
+ if (position < 0 || position > this.length) {
8725
+ throw new Error(`Seek out of bounds: ${position} (length: ${this.length})`);
8726
+ }
8727
+ this.offset = position;
8728
+ }
8729
+ hasMore() {
8730
+ return this.offset < this.length;
8731
+ }
8732
+ readChar() {
8733
+ const value = this.view.getInt8(this.offset);
8734
+ this.offset += 1;
8735
+ return value;
8736
+ }
8737
+ readByte() {
8738
+ const value = this.view.getUint8(this.offset);
8739
+ this.offset += 1;
8740
+ return value;
8741
+ }
8742
+ readShort() {
8743
+ const value = this.view.getInt16(this.offset, true);
8744
+ this.offset += 2;
8745
+ return value;
8746
+ }
8747
+ readUShort() {
8748
+ const value = this.view.getUint16(this.offset, true);
8749
+ this.offset += 2;
8750
+ return value;
8751
+ }
8752
+ readLong() {
8753
+ const value = this.view.getInt32(this.offset, true);
8754
+ this.offset += 4;
8755
+ return value;
8756
+ }
8757
+ readULong() {
8758
+ const value = this.view.getUint32(this.offset, true);
8759
+ this.offset += 4;
8760
+ return value;
8761
+ }
8762
+ readFloat() {
8763
+ const value = this.view.getFloat32(this.offset, true);
8764
+ this.offset += 4;
8765
+ return value;
8766
+ }
8767
+ readString() {
8768
+ let str3 = "";
8769
+ while (this.offset < this.length) {
8770
+ const charCode = this.readChar();
8771
+ if (charCode === -1 || charCode === 0) {
8772
+ break;
8773
+ }
8774
+ str3 += String.fromCharCode(charCode);
8775
+ }
8776
+ return str3;
8777
+ }
8778
+ readStringLine() {
8779
+ let str3 = "";
8780
+ while (this.offset < this.length) {
8781
+ const charCode = this.readChar();
8782
+ if (charCode === -1 || charCode === 0 || charCode === 10) {
8783
+ break;
8784
+ }
8785
+ str3 += String.fromCharCode(charCode);
8786
+ }
8787
+ return str3;
8788
+ }
8789
+ readCoord() {
8790
+ return this.readShort() * (1 / 8);
8791
+ }
8792
+ readAngle() {
8793
+ return this.readChar() * (360 / 256);
8794
+ }
8795
+ readAngle16() {
8796
+ return this.readShort() * 360 / 65536;
8797
+ }
8798
+ readData(length2) {
8799
+ if (this.offset + length2 > this.length) {
8800
+ throw new Error(`Read out of bounds: ${this.offset + length2} (length: ${this.length})`);
8801
+ }
8802
+ const data = new Uint8Array(this.view.buffer, this.view.byteOffset + this.offset, length2);
8803
+ this.offset += length2;
8804
+ return new Uint8Array(data);
8805
+ }
8806
+ readPos(out) {
8807
+ out.x = this.readCoord();
8808
+ out.y = this.readCoord();
8809
+ out.z = this.readCoord();
8810
+ }
8811
+ readDir(out) {
8812
+ const b = this.readByte();
8813
+ if (b >= 162) {
8814
+ out.x = 0;
8815
+ out.y = 0;
8816
+ out.z = 0;
8817
+ return;
8818
+ }
8819
+ const norm = ANORMS2[b];
8820
+ out.x = norm[0];
8821
+ out.y = norm[1];
8822
+ out.z = norm[2];
8823
+ }
8824
+ };
8825
+ var NetworkMessageBuilder = class {
8826
+ constructor(initialSize = 1024) {
8827
+ this.buffer = new Uint8Array(initialSize);
8828
+ this.view = new DataView(this.buffer.buffer);
8829
+ this.offset = 0;
8830
+ }
8831
+ ensureCapacity(needed) {
8832
+ if (this.offset + needed > this.buffer.length) {
8833
+ const newSize = Math.max(this.buffer.length * 2, this.offset + needed);
8834
+ const newBuffer = new Uint8Array(newSize);
8835
+ newBuffer.set(this.buffer);
8836
+ this.buffer = newBuffer;
8837
+ this.view = new DataView(this.buffer.buffer);
8838
+ }
8839
+ }
8840
+ getData() {
8841
+ return this.buffer.slice(0, this.offset);
8842
+ }
8843
+ writeByte(value) {
8844
+ this.ensureCapacity(1);
8845
+ this.view.setUint8(this.offset, value);
8846
+ this.offset += 1;
8847
+ }
8848
+ writeChar(value) {
8849
+ this.ensureCapacity(1);
8850
+ this.view.setInt8(this.offset, value);
8851
+ this.offset += 1;
8852
+ }
8853
+ writeShort(value) {
8854
+ this.ensureCapacity(2);
8855
+ this.view.setInt16(this.offset, value, true);
8856
+ this.offset += 2;
8857
+ }
8858
+ writeUShort(value) {
8859
+ this.ensureCapacity(2);
8860
+ this.view.setUint16(this.offset, value, true);
8861
+ this.offset += 2;
8862
+ }
8863
+ writeLong(value) {
8864
+ this.ensureCapacity(4);
8865
+ this.view.setInt32(this.offset, value, true);
8866
+ this.offset += 4;
8867
+ }
8868
+ writeFloat(value) {
8869
+ this.ensureCapacity(4);
8870
+ this.view.setFloat32(this.offset, value, true);
8871
+ this.offset += 4;
8872
+ }
8873
+ writeString(value) {
8874
+ const len2 = value.length + 1;
8875
+ this.ensureCapacity(len2);
8876
+ for (let i = 0; i < value.length; i++) {
8877
+ this.view.setUint8(this.offset + i, value.charCodeAt(i));
8878
+ }
8879
+ this.view.setUint8(this.offset + value.length, 0);
8880
+ this.offset += len2;
8881
+ }
8882
+ writeData(data) {
8883
+ this.ensureCapacity(data.length);
8884
+ this.buffer.set(data, this.offset);
8885
+ this.offset += data.length;
8886
+ }
8887
+ writeCoord(value) {
8888
+ this.writeShort(Math.round(value * 8));
8889
+ }
8890
+ writeAngle(value) {
8891
+ this.writeByte(Math.round(value * 256 / 360) & 255);
8892
+ }
8893
+ writeAngle16(value) {
8894
+ this.writeShort(Math.round(value * 65536 / 360));
8895
+ }
8896
+ writeDir(x, y, z) {
8897
+ let best = 0;
8898
+ let bestDot = -999999;
8899
+ const len2 = Math.sqrt(x * x + y * y + z * z);
8900
+ if (len2 > 0) {
8901
+ x /= len2;
8902
+ y /= len2;
8903
+ z /= len2;
8904
+ for (let i = 0; i < 162; i++) {
8905
+ const dot2 = x * ANORMS2[i][0] + y * ANORMS2[i][1] + z * ANORMS2[i][2];
8906
+ if (dot2 > bestDot) {
8907
+ bestDot = dot2;
8908
+ best = i;
8909
+ }
8910
+ }
8911
+ }
8912
+ this.writeByte(best);
8913
+ }
8914
+ };
8507
8915
  var AmmoType2 = /* @__PURE__ */ ((AmmoType22) => {
8508
8916
  AmmoType22[AmmoType22["Bullets"] = 0] = "Bullets";
8509
8917
  AmmoType22[AmmoType22["Shells"] = 1] = "Shells";
@@ -9124,6 +9532,7 @@ var ClientNetworkHandler = class {
9124
9532
  }
9125
9533
  applyDelta(to, from) {
9126
9534
  const bits = from.bits;
9535
+ const bitsHigh = from.bitsHigh;
9127
9536
  to.number = from.number;
9128
9537
  if (bits & U_MODEL5) to.modelindex = from.modelindex;
9129
9538
  if (bits & U_MODEL22) to.modelindex2 = from.modelindex2;
@@ -9148,13 +9557,13 @@ var ClientNetworkHandler = class {
9148
9557
  if (bits & U_SOUND2) to.sound = from.sound;
9149
9558
  if (bits & U_EVENT2) to.event = from.event;
9150
9559
  if (bits & U_SOLID2) to.solid = from.solid;
9151
- if (from.alpha !== 0) to.alpha = from.alpha;
9152
- if (from.scale !== 0) to.scale = from.scale;
9153
- if (from.instanceBits !== 0) to.instanceBits = from.instanceBits;
9154
- if (from.loopVolume !== 0) to.loopVolume = from.loopVolume;
9155
- if (from.loopAttenuation !== 0) to.loopAttenuation = from.loopAttenuation;
9156
- if (from.owner !== 0) to.owner = from.owner;
9157
- if (from.oldFrame !== 0) to.oldFrame = from.oldFrame;
9560
+ if (bits & U_ALPHA) to.alpha = from.alpha;
9561
+ if (bits & U_SCALE) to.scale = from.scale;
9562
+ if (bits & U_INSTANCE_BITS) to.instanceBits = from.instanceBits;
9563
+ if (bits & U_LOOP_VOLUME) to.loopVolume = from.loopVolume;
9564
+ if (bitsHigh & U_LOOP_ATTENUATION_HIGH) to.loopAttenuation = from.loopAttenuation;
9565
+ if (bitsHigh & U_OWNER_HIGH) to.owner = from.owner;
9566
+ if (bitsHigh & U_OLD_FRAME_HIGH) to.oldFrame = from.oldFrame;
9158
9567
  }
9159
9568
  onCenterPrint(msg) {
9160
9569
  if (this.callbacks?.onCenterPrint) {
@@ -9270,11 +9679,16 @@ var ClientNetworkHandler = class {
9270
9679
  this.callbacks.onDamage(indicators);
9271
9680
  }
9272
9681
  }
9273
- // New Rerelease Handlers (Stubbed)
9682
+ onLocPrint(flags, base, args) {
9683
+ if (this.callbacks?.onLocPrint) {
9684
+ this.callbacks.onLocPrint(flags, base, args);
9685
+ }
9686
+ }
9687
+ // New Rerelease Handlers
9274
9688
  onLevelRestart() {
9275
9689
  if (this.callbacks?.onLevelRestart) this.callbacks.onLevelRestart();
9276
9690
  }
9277
- onWaitingForPlayers() {
9691
+ onWaitingForPlayers(count) {
9278
9692
  if (this.callbacks?.onWaitingForPlayers) this.callbacks.onWaitingForPlayers();
9279
9693
  }
9280
9694
  onDisconnect() {
@@ -9467,6 +9881,16 @@ var MainMenuFactory = class {
9467
9881
  this.menuSystem.pushMenu(this.createDifficultyMenu());
9468
9882
  }
9469
9883
  },
9884
+ {
9885
+ label: "Multiplayer",
9886
+ action: () => {
9887
+ if (this.options.multiplayerFactory) {
9888
+ this.menuSystem.pushMenu(this.options.multiplayerFactory.createMultiplayerMenu());
9889
+ } else {
9890
+ console.warn("Multiplayer factory not configured");
9891
+ }
9892
+ }
9893
+ },
9470
9894
  {
9471
9895
  label: "Load Game",
9472
9896
  action: () => {
@@ -10041,6 +10465,74 @@ var PauseMenuFactory = class {
10041
10465
  }
10042
10466
  };
10043
10467
 
10468
+ // src/ui/menu/multiplayer.ts
10469
+ var MultiplayerMenuFactory = class {
10470
+ constructor(menuSystem, connection) {
10471
+ this.menuSystem = menuSystem;
10472
+ this.connection = connection;
10473
+ }
10474
+ createMultiplayerMenu(initialAddress = "localhost:27910", status = "") {
10475
+ let address = initialAddress;
10476
+ const items = [];
10477
+ if (status) {
10478
+ items.push({
10479
+ label: status,
10480
+ action: () => {
10481
+ }
10482
+ // No-op
10483
+ });
10484
+ }
10485
+ items.push(
10486
+ {
10487
+ label: "Address: " + address,
10488
+ action: () => {
10489
+ if (typeof window !== "undefined") {
10490
+ const newAddr = window.prompt("Enter Server Address", address);
10491
+ if (newAddr) {
10492
+ address = newAddr;
10493
+ this.refreshMenu(address);
10494
+ }
10495
+ }
10496
+ }
10497
+ },
10498
+ {
10499
+ label: "Connect",
10500
+ action: () => {
10501
+ this.refreshMenu(address, "Connecting...");
10502
+ this.connection.connect("ws://" + address).then(() => {
10503
+ this.menuSystem.closeAll();
10504
+ }).catch((err2) => {
10505
+ console.error(err2);
10506
+ const failStatus = "Failed: " + (err2.message || "Unknown error");
10507
+ this.refreshMenu(address, failStatus);
10508
+ });
10509
+ }
10510
+ },
10511
+ {
10512
+ label: "Disconnect",
10513
+ action: () => {
10514
+ this.connection.disconnect();
10515
+ this.refreshMenu(address, "Disconnected");
10516
+ }
10517
+ },
10518
+ {
10519
+ label: "Back",
10520
+ action: () => {
10521
+ this.menuSystem.popMenu();
10522
+ }
10523
+ }
10524
+ );
10525
+ return {
10526
+ title: "Multiplayer",
10527
+ items
10528
+ };
10529
+ }
10530
+ refreshMenu(address, status = "") {
10531
+ this.menuSystem.popMenu();
10532
+ this.menuSystem.pushMenu(this.createMultiplayerMenu(address, status));
10533
+ }
10534
+ };
10535
+
10044
10536
  // src/ui/menu/render.ts
10045
10537
  function Draw_Menu(renderer, state, width, height) {
10046
10538
  if (!state.activeMenu) {
@@ -10319,6 +10811,233 @@ function buildRenderableEntities(latestEntities, previousEntities, alpha, config
10319
10811
  return renderables;
10320
10812
  }
10321
10813
 
10814
+ // src/net/browserWsDriver.ts
10815
+ var BrowserWebSocketNetDriver = class {
10816
+ constructor() {
10817
+ this.socket = null;
10818
+ this.messageCallback = null;
10819
+ this.closeCallback = null;
10820
+ this.errorCallback = null;
10821
+ }
10822
+ async connect(url) {
10823
+ return new Promise((resolve, reject) => {
10824
+ try {
10825
+ this.socket = new WebSocket(url);
10826
+ this.socket.binaryType = "arraybuffer";
10827
+ this.socket.onopen = () => {
10828
+ resolve();
10829
+ };
10830
+ this.socket.onerror = (event) => {
10831
+ const error = new Error("WebSocket connection error");
10832
+ if (this.errorCallback) {
10833
+ this.errorCallback(error);
10834
+ }
10835
+ reject(error);
10836
+ };
10837
+ this.socket.onclose = () => {
10838
+ if (this.closeCallback) {
10839
+ this.closeCallback();
10840
+ }
10841
+ this.socket = null;
10842
+ };
10843
+ this.socket.onmessage = (event) => {
10844
+ if (this.messageCallback) {
10845
+ if (event.data instanceof ArrayBuffer) {
10846
+ this.messageCallback(new Uint8Array(event.data));
10847
+ } else {
10848
+ console.warn("Received non-binary message from server");
10849
+ }
10850
+ }
10851
+ };
10852
+ } catch (e) {
10853
+ reject(e);
10854
+ }
10855
+ });
10856
+ }
10857
+ disconnect() {
10858
+ if (this.socket) {
10859
+ this.socket.close();
10860
+ this.socket = null;
10861
+ }
10862
+ }
10863
+ send(data) {
10864
+ if (this.socket && this.socket.readyState === WebSocket.OPEN) {
10865
+ this.socket.send(data);
10866
+ } else {
10867
+ console.warn("Attempted to send data on closed or connecting socket");
10868
+ }
10869
+ }
10870
+ onMessage(callback) {
10871
+ this.messageCallback = callback;
10872
+ }
10873
+ onClose(callback) {
10874
+ this.closeCallback = callback;
10875
+ }
10876
+ onError(callback) {
10877
+ this.errorCallback = callback;
10878
+ }
10879
+ isConnected() {
10880
+ return this.socket !== null && this.socket.readyState === WebSocket.OPEN;
10881
+ }
10882
+ };
10883
+
10884
+ // src/net/connection.ts
10885
+ var MultiplayerConnection = class {
10886
+ constructor(options) {
10887
+ this.state = 0 /* Disconnected */;
10888
+ this.parser = null;
10889
+ // Game State
10890
+ this.serverProtocol = 0;
10891
+ this.serverCount = 0;
10892
+ this.gameDir = "";
10893
+ this.playerNum = 0;
10894
+ this.levelName = "";
10895
+ this.configStrings = /* @__PURE__ */ new Map();
10896
+ this.baselines = /* @__PURE__ */ new Map();
10897
+ this.challenge = 0;
10898
+ this.connectPacketCount = 0;
10899
+ this.connectPacketTime = 0;
10900
+ this.driver = new BrowserWebSocketNetDriver();
10901
+ this.options = options;
10902
+ this.driver.onMessage((data) => this.handleMessage(data));
10903
+ this.driver.onClose(() => this.handleDisconnect());
10904
+ this.driver.onError((err2) => console.error("Network Error:", err2));
10905
+ }
10906
+ async connect(url) {
10907
+ if (this.state !== 0 /* Disconnected */) {
10908
+ this.disconnect();
10909
+ }
10910
+ console.log(`Connecting to ${url}...`);
10911
+ this.state = 1 /* Connecting */;
10912
+ try {
10913
+ await this.driver.connect(url);
10914
+ console.log("WebSocket connected.");
10915
+ this.state = 2 /* Challenge */;
10916
+ this.sendChallenge();
10917
+ } catch (e) {
10918
+ console.error("Connection failed:", e);
10919
+ this.state = 0 /* Disconnected */;
10920
+ throw e;
10921
+ }
10922
+ }
10923
+ disconnect() {
10924
+ if (this.state === 0 /* Disconnected */) return;
10925
+ this.driver.disconnect();
10926
+ this.state = 0 /* Disconnected */;
10927
+ this.configStrings.clear();
10928
+ this.baselines.clear();
10929
+ }
10930
+ sendCommand(cmd) {
10931
+ if (this.state !== 5 /* Active */) return;
10932
+ const builder = new NetworkMessageBuilder();
10933
+ builder.writeByte(ClientCommand.nop);
10934
+ this.driver.send(builder.getData());
10935
+ }
10936
+ handleMessage(data) {
10937
+ let buffer = data.buffer;
10938
+ if (buffer instanceof SharedArrayBuffer) {
10939
+ const newBuffer = new ArrayBuffer(data.byteLength);
10940
+ new Uint8Array(newBuffer).set(data);
10941
+ buffer = newBuffer;
10942
+ }
10943
+ const stream = new BinaryStream2(buffer);
10944
+ const sequence = stream.readLong();
10945
+ const sequenceAck = stream.readLong();
10946
+ this.parser = new NetworkMessageParser(stream, this);
10947
+ this.parser.parseMessage();
10948
+ }
10949
+ handleDisconnect() {
10950
+ console.log("Disconnected from server.");
10951
+ this.state = 0 /* Disconnected */;
10952
+ }
10953
+ sendChallenge() {
10954
+ const builder = new NetworkMessageBuilder();
10955
+ builder.writeByte(ClientCommand.stringcmd);
10956
+ builder.writeString("getchallenge");
10957
+ this.driver.send(builder.getData());
10958
+ }
10959
+ sendConnect(challenge) {
10960
+ const builder = new NetworkMessageBuilder();
10961
+ builder.writeByte(ClientCommand.stringcmd);
10962
+ const userinfo = `\\name\\${this.options.username}\\model\\${this.options.model}\\skin\\${this.options.skin}\\hand\\${this.options.hand ?? 0}\\fov\\${this.options.fov ?? 90}`;
10963
+ builder.writeString(`connect ${PROTOCOL_VERSION_RERELEASE} ${challenge} ${userinfo}`);
10964
+ this.driver.send(builder.getData());
10965
+ }
10966
+ isConnected() {
10967
+ return this.state === 5 /* Active */;
10968
+ }
10969
+ // ==================================================================================
10970
+ // NetworkMessageHandler Implementation
10971
+ // ==================================================================================
10972
+ onServerData(protocol, serverCount, attractLoop, gameDir, playerNum, levelName) {
10973
+ console.log(`Server Data: Protocol ${protocol}, Level ${levelName}`);
10974
+ this.serverProtocol = protocol;
10975
+ this.serverCount = serverCount;
10976
+ this.gameDir = gameDir;
10977
+ this.playerNum = playerNum;
10978
+ this.levelName = levelName;
10979
+ this.state = 3 /* Connected */;
10980
+ const builder = new NetworkMessageBuilder();
10981
+ builder.writeByte(ClientCommand.stringcmd);
10982
+ builder.writeString("new");
10983
+ this.driver.send(builder.getData());
10984
+ this.state = 4 /* Loading */;
10985
+ }
10986
+ onConfigString(index, str3) {
10987
+ this.configStrings.set(index, str3);
10988
+ }
10989
+ onSpawnBaseline(entity) {
10990
+ this.baselines.set(entity.number, entity);
10991
+ }
10992
+ onStuffText(msg) {
10993
+ console.log(`Server StuffText: ${msg}`);
10994
+ if (msg.startsWith("precache")) {
10995
+ this.finishLoading();
10996
+ }
10997
+ if (msg.startsWith("challenge ")) {
10998
+ const parts = msg.split(" ");
10999
+ if (parts.length > 1) {
11000
+ this.challenge = parseInt(parts[1], 10);
11001
+ this.sendConnect(this.challenge);
11002
+ }
11003
+ }
11004
+ }
11005
+ finishLoading() {
11006
+ console.log("Finished loading, sending begin...");
11007
+ const builder = new NetworkMessageBuilder();
11008
+ builder.writeByte(ClientCommand.stringcmd);
11009
+ builder.writeString("begin");
11010
+ this.driver.send(builder.getData());
11011
+ this.state = 5 /* Active */;
11012
+ }
11013
+ // Stubs for other handlers
11014
+ onFrame(frame) {
11015
+ }
11016
+ onCenterPrint(msg) {
11017
+ }
11018
+ onPrint(level, msg) {
11019
+ }
11020
+ onSound(flags, soundNum, volume, attenuation, offset, ent, pos) {
11021
+ }
11022
+ onTempEntity(type, pos, pos2, dir, cnt, color, ent, srcEnt, destEnt) {
11023
+ }
11024
+ onLayout(layout) {
11025
+ }
11026
+ onInventory(inventory) {
11027
+ }
11028
+ onMuzzleFlash(ent, weapon) {
11029
+ }
11030
+ onMuzzleFlash2(ent, weapon) {
11031
+ }
11032
+ onDisconnect() {
11033
+ this.disconnect();
11034
+ }
11035
+ onReconnect() {
11036
+ }
11037
+ onDownload(size, percent, data) {
11038
+ }
11039
+ };
11040
+
10322
11041
  // src/input/bindings.ts
10323
11042
  var DEFAULT_BINDINGS = [
10324
11043
  { code: "KeyW", command: "+forward" },
@@ -10852,6 +11571,21 @@ function createClient(imports) {
10852
11571
  };
10853
11572
  const cgameImport = createCGameImport(imports, stateProvider);
10854
11573
  const cg = (0, import_cgame2.GetCGameAPI)(cgameImport);
11574
+ const multiplayer = new MultiplayerConnection({
11575
+ get username() {
11576
+ return imports.host?.cvars?.get("name")?.string || "Player";
11577
+ },
11578
+ get model() {
11579
+ return imports.host?.cvars?.get("model")?.string || "male";
11580
+ },
11581
+ get skin() {
11582
+ return imports.host?.cvars?.get("skin")?.string || "grunt";
11583
+ },
11584
+ get fov() {
11585
+ return fovValue;
11586
+ }
11587
+ });
11588
+ const multiplayerFactory = new MultiplayerMenuFactory(menuSystem, multiplayer);
10855
11589
  demoHandler.setCallbacks({
10856
11590
  onCenterPrint: (msg) => cg.ParseCenterPrint(msg, 0, false),
10857
11591
  onPrint: (level, msg) => cg.NotifyMessage(0, msg, false),
@@ -10914,6 +11648,22 @@ function createClient(imports) {
10914
11648
  menuSystem.pushMenu(pauseMenuFactory.createPauseMenu());
10915
11649
  }
10916
11650
  }, "Toggle the main/pause menu");
11651
+ imports.host.commands.register("connect", (args) => {
11652
+ if (args.length < 1) {
11653
+ console.log("usage: connect <address>");
11654
+ return;
11655
+ }
11656
+ const address = args[0];
11657
+ console.log(`Connecting to ${address}...`);
11658
+ multiplayer.connect(address).catch((e) => {
11659
+ console.error("Failed to connect:", e);
11660
+ errorDialog.show("Connection Failed", e instanceof Error ? e.message : "Unknown error");
11661
+ });
11662
+ }, "Connect to a multiplayer server");
11663
+ imports.host.commands.register("disconnect", () => {
11664
+ multiplayer.disconnect();
11665
+ console.log("Disconnected.");
11666
+ }, "Disconnect from server");
10917
11667
  if (imports.host.cvars) {
10918
11668
  imports.host.cvars.register({
10919
11669
  name: "fov",
@@ -10968,6 +11718,9 @@ function createClient(imports) {
10968
11718
  predict(command) {
10969
11719
  if (menuSystem.isActive()) {
10970
11720
  }
11721
+ if (multiplayer.isConnected()) {
11722
+ multiplayer.sendCommand(command);
11723
+ }
10971
11724
  return prediction.enqueueCommand(command);
10972
11725
  },
10973
11726
  handleInput(key, down) {
@@ -11032,6 +11785,7 @@ function createClient(imports) {
11032
11785
  ...options,
11033
11786
  optionsFactory: optsFactory,
11034
11787
  mapsFactory,
11788
+ multiplayerFactory,
11035
11789
  onSetDifficulty: (skill) => {
11036
11790
  if (imports.host?.cvars) {
11037
11791
  imports.host.cvars.setValue("skill", skill.toString());
@@ -11237,6 +11991,7 @@ function createClient(imports) {
11237
11991
  cg.ParseConfigString(index, value);
11238
11992
  },
11239
11993
  demoHandler,
11994
+ multiplayer,
11240
11995
  configStrings
11241
11996
  };
11242
11997
  return clientExports;