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
@@ -2029,42 +2029,42 @@ function addReplayFrame(session, cmd, serverFrame, startTime) {
2029
2029
  });
2030
2030
  }
2031
2031
  var WATERJUMP_CLEAR = 8 | 16 | 32 | 1024;
2032
- var ServerCommand = /* @__PURE__ */ ((ServerCommand2) => {
2033
- ServerCommand2[ServerCommand2["bad"] = 0] = "bad";
2034
- ServerCommand2[ServerCommand2["muzzleflash"] = 1] = "muzzleflash";
2035
- ServerCommand2[ServerCommand2["muzzleflash2"] = 2] = "muzzleflash2";
2036
- ServerCommand2[ServerCommand2["temp_entity"] = 3] = "temp_entity";
2037
- ServerCommand2[ServerCommand2["layout"] = 4] = "layout";
2038
- ServerCommand2[ServerCommand2["inventory"] = 5] = "inventory";
2039
- ServerCommand2[ServerCommand2["nop"] = 6] = "nop";
2040
- ServerCommand2[ServerCommand2["disconnect"] = 7] = "disconnect";
2041
- ServerCommand2[ServerCommand2["reconnect"] = 8] = "reconnect";
2042
- ServerCommand2[ServerCommand2["sound"] = 9] = "sound";
2043
- ServerCommand2[ServerCommand2["print"] = 10] = "print";
2044
- ServerCommand2[ServerCommand2["stufftext"] = 11] = "stufftext";
2045
- ServerCommand2[ServerCommand2["serverdata"] = 12] = "serverdata";
2046
- ServerCommand2[ServerCommand2["configstring"] = 13] = "configstring";
2047
- ServerCommand2[ServerCommand2["spawnbaseline"] = 14] = "spawnbaseline";
2048
- ServerCommand2[ServerCommand2["centerprint"] = 15] = "centerprint";
2049
- ServerCommand2[ServerCommand2["download"] = 16] = "download";
2050
- ServerCommand2[ServerCommand2["playerinfo"] = 17] = "playerinfo";
2051
- ServerCommand2[ServerCommand2["packetentities"] = 18] = "packetentities";
2052
- ServerCommand2[ServerCommand2["deltapacketentities"] = 19] = "deltapacketentities";
2053
- ServerCommand2[ServerCommand2["frame"] = 20] = "frame";
2054
- ServerCommand2[ServerCommand2["splitclient"] = 21] = "splitclient";
2055
- ServerCommand2[ServerCommand2["configblast"] = 22] = "configblast";
2056
- ServerCommand2[ServerCommand2["spawnbaselineblast"] = 23] = "spawnbaselineblast";
2057
- ServerCommand2[ServerCommand2["level_restart"] = 24] = "level_restart";
2058
- ServerCommand2[ServerCommand2["damage"] = 25] = "damage";
2059
- ServerCommand2[ServerCommand2["locprint"] = 26] = "locprint";
2060
- ServerCommand2[ServerCommand2["fog"] = 27] = "fog";
2061
- ServerCommand2[ServerCommand2["waitingforplayers"] = 28] = "waitingforplayers";
2062
- ServerCommand2[ServerCommand2["bot_chat"] = 29] = "bot_chat";
2063
- ServerCommand2[ServerCommand2["poi"] = 30] = "poi";
2064
- ServerCommand2[ServerCommand2["help_path"] = 31] = "help_path";
2065
- ServerCommand2[ServerCommand2["muzzleflash3"] = 32] = "muzzleflash3";
2066
- ServerCommand2[ServerCommand2["achievement"] = 33] = "achievement";
2067
- return ServerCommand2;
2032
+ var ServerCommand = /* @__PURE__ */ ((ServerCommand22) => {
2033
+ ServerCommand22[ServerCommand22["bad"] = 0] = "bad";
2034
+ ServerCommand22[ServerCommand22["muzzleflash"] = 1] = "muzzleflash";
2035
+ ServerCommand22[ServerCommand22["muzzleflash2"] = 2] = "muzzleflash2";
2036
+ ServerCommand22[ServerCommand22["temp_entity"] = 3] = "temp_entity";
2037
+ ServerCommand22[ServerCommand22["layout"] = 4] = "layout";
2038
+ ServerCommand22[ServerCommand22["inventory"] = 5] = "inventory";
2039
+ ServerCommand22[ServerCommand22["nop"] = 6] = "nop";
2040
+ ServerCommand22[ServerCommand22["disconnect"] = 7] = "disconnect";
2041
+ ServerCommand22[ServerCommand22["reconnect"] = 8] = "reconnect";
2042
+ ServerCommand22[ServerCommand22["sound"] = 9] = "sound";
2043
+ ServerCommand22[ServerCommand22["print"] = 10] = "print";
2044
+ ServerCommand22[ServerCommand22["stufftext"] = 11] = "stufftext";
2045
+ ServerCommand22[ServerCommand22["serverdata"] = 12] = "serverdata";
2046
+ ServerCommand22[ServerCommand22["configstring"] = 13] = "configstring";
2047
+ ServerCommand22[ServerCommand22["spawnbaseline"] = 14] = "spawnbaseline";
2048
+ ServerCommand22[ServerCommand22["centerprint"] = 15] = "centerprint";
2049
+ ServerCommand22[ServerCommand22["download"] = 16] = "download";
2050
+ ServerCommand22[ServerCommand22["playerinfo"] = 17] = "playerinfo";
2051
+ ServerCommand22[ServerCommand22["packetentities"] = 18] = "packetentities";
2052
+ ServerCommand22[ServerCommand22["deltapacketentities"] = 19] = "deltapacketentities";
2053
+ ServerCommand22[ServerCommand22["frame"] = 20] = "frame";
2054
+ ServerCommand22[ServerCommand22["splitclient"] = 21] = "splitclient";
2055
+ ServerCommand22[ServerCommand22["configblast"] = 22] = "configblast";
2056
+ ServerCommand22[ServerCommand22["spawnbaselineblast"] = 23] = "spawnbaselineblast";
2057
+ ServerCommand22[ServerCommand22["level_restart"] = 24] = "level_restart";
2058
+ ServerCommand22[ServerCommand22["damage"] = 25] = "damage";
2059
+ ServerCommand22[ServerCommand22["locprint"] = 26] = "locprint";
2060
+ ServerCommand22[ServerCommand22["fog"] = 27] = "fog";
2061
+ ServerCommand22[ServerCommand22["waitingforplayers"] = 28] = "waitingforplayers";
2062
+ ServerCommand22[ServerCommand22["bot_chat"] = 29] = "bot_chat";
2063
+ ServerCommand22[ServerCommand22["poi"] = 30] = "poi";
2064
+ ServerCommand22[ServerCommand22["help_path"] = 31] = "help_path";
2065
+ ServerCommand22[ServerCommand22["muzzleflash3"] = 32] = "muzzleflash3";
2066
+ ServerCommand22[ServerCommand22["achievement"] = 33] = "achievement";
2067
+ return ServerCommand22;
2068
2068
  })(ServerCommand || {});
2069
2069
  var TempEntity = /* @__PURE__ */ ((TempEntity2) => {
2070
2070
  TempEntity2[TempEntity2["GUNSHOT"] = 0] = "GUNSHOT";
@@ -7069,6 +7069,13 @@ var U_OLDORIGIN = 1 << 24;
7069
7069
  var U_SKIN16 = 1 << 25;
7070
7070
  var U_SOUND2 = 1 << 26;
7071
7071
  var U_SOLID2 = 1 << 27;
7072
+ var U_SCALE = 1 << 28;
7073
+ var U_INSTANCE_BITS = 1 << 29;
7074
+ var U_LOOP_VOLUME = 1 << 30;
7075
+ var U_MOREBITS4 = 2147483648 | 0;
7076
+ var U_LOOP_ATTENUATION_HIGH = 1 << 0;
7077
+ var U_OWNER_HIGH = 1 << 1;
7078
+ var U_OLD_FRAME_HIGH = 1 << 2;
7072
7079
  var RECORD_CLIENT = 1;
7073
7080
  var RECORD_SERVER = 2;
7074
7081
  var RECORD_RELAY = 128;
@@ -7089,6 +7096,7 @@ var createEmptyEntityState = () => ({
7089
7096
  event: 0,
7090
7097
  solid: 0,
7091
7098
  bits: 0,
7099
+ bitsHigh: 0,
7092
7100
  alpha: 0,
7093
7101
  scale: 0,
7094
7102
  instanceBits: 0,
@@ -7391,13 +7399,13 @@ var NetworkMessageParser = class _NetworkMessageParser {
7391
7399
  args.push(this.stream.readString());
7392
7400
  }
7393
7401
  if (this.handler && this.handler.onLocPrint) {
7394
- this.handler.onLocPrint(flags, base);
7402
+ this.handler.onLocPrint(flags, base, args);
7395
7403
  }
7396
7404
  }
7397
7405
  parseWaitingForPlayers() {
7398
7406
  const count = this.stream.readByte();
7399
7407
  if (this.handler && this.handler.onWaitingForPlayers) {
7400
- this.handler.onWaitingForPlayers();
7408
+ this.handler.onWaitingForPlayers(count);
7401
7409
  }
7402
7410
  }
7403
7411
  parseBotChat() {
@@ -7432,6 +7440,9 @@ var NetworkMessageParser = class _NetworkMessageParser {
7432
7440
  }
7433
7441
  parseAchievement() {
7434
7442
  const idStr = this.stream.readString();
7443
+ if (this.handler && this.handler.onAchievement) {
7444
+ this.handler.onAchievement(idStr);
7445
+ }
7435
7446
  }
7436
7447
  parseDownload() {
7437
7448
  const size = this.stream.readShort();
@@ -7715,7 +7726,7 @@ var NetworkMessageParser = class _NetworkMessageParser {
7715
7726
  parseSpawnBaseline() {
7716
7727
  const bits = this.parseEntityBits();
7717
7728
  const entity = createEmptyEntityState();
7718
- this.parseDelta(createEmptyEntityState(), entity, bits.number, bits.bits);
7729
+ this.parseDelta(createEmptyEntityState(), entity, bits.number, bits.bits, bits.bitsHigh);
7719
7730
  if (this.handler) {
7720
7731
  this.handler.onSpawnBaseline(entity);
7721
7732
  }
@@ -7840,7 +7851,7 @@ var NetworkMessageParser = class _NetworkMessageParser {
7840
7851
  break;
7841
7852
  }
7842
7853
  const entity = createEmptyEntityState();
7843
- this.parseDelta(createEmptyEntityState(), entity, bits.number, bits.bits);
7854
+ this.parseDelta(createEmptyEntityState(), entity, bits.number, bits.bits, bits.bitsHigh);
7844
7855
  entities.push(entity);
7845
7856
  }
7846
7857
  return entities;
@@ -7856,15 +7867,20 @@ var NetworkMessageParser = class _NetworkMessageParser {
7856
7867
  if (total & U_MOREBITS3) {
7857
7868
  total |= this.stream.readByte() << 24;
7858
7869
  }
7870
+ let bitsHigh = 0;
7871
+ if (total & U_MOREBITS4) {
7872
+ const byte5 = this.stream.readByte();
7873
+ bitsHigh = byte5;
7874
+ }
7859
7875
  let number;
7860
7876
  if (total & U_NUMBER16) {
7861
7877
  number = this.stream.readShort();
7862
7878
  } else {
7863
7879
  number = this.stream.readByte();
7864
7880
  }
7865
- return { number, bits: total };
7881
+ return { number, bits: total, bitsHigh };
7866
7882
  }
7867
- parseDelta(from, to, number, bits) {
7883
+ parseDelta(from, to, number, bits, bitsHigh = 0) {
7868
7884
  to.number = from.number;
7869
7885
  to.modelindex = from.modelindex;
7870
7886
  to.modelindex2 = from.modelindex2;
@@ -7886,8 +7902,16 @@ var NetworkMessageParser = class _NetworkMessageParser {
7886
7902
  to.sound = from.sound;
7887
7903
  to.event = from.event;
7888
7904
  to.solid = from.solid;
7905
+ to.alpha = from.alpha;
7906
+ to.scale = from.scale;
7907
+ to.instanceBits = from.instanceBits;
7908
+ to.loopVolume = from.loopVolume;
7909
+ to.loopAttenuation = from.loopAttenuation;
7910
+ to.owner = from.owner;
7911
+ to.oldFrame = from.oldFrame;
7889
7912
  to.number = number;
7890
7913
  to.bits = bits;
7914
+ to.bitsHigh = bitsHigh;
7891
7915
  if (bits & U_MODEL5) to.modelindex = this.stream.readByte();
7892
7916
  if (bits & U_MODEL22) to.modelindex2 = this.stream.readByte();
7893
7917
  if (bits & U_MODEL32) to.modelindex3 = this.stream.readByte();
@@ -7931,6 +7955,13 @@ var NetworkMessageParser = class _NetworkMessageParser {
7931
7955
  to.event = 0;
7932
7956
  }
7933
7957
  if (bits & U_SOLID2) to.solid = this.stream.readShort();
7958
+ if (bits & U_ALPHA) to.alpha = this.stream.readByte() / 255;
7959
+ if (bits & U_SCALE) to.scale = this.stream.readFloat();
7960
+ if (bits & U_INSTANCE_BITS) to.instanceBits = this.stream.readLong();
7961
+ if (bits & U_LOOP_VOLUME) to.loopVolume = this.stream.readByte() / 255;
7962
+ if (bitsHigh & U_LOOP_ATTENUATION_HIGH) to.loopAttenuation = this.stream.readByte() / 255;
7963
+ if (bitsHigh & U_OWNER_HIGH) to.owner = this.stream.readShort();
7964
+ if (bitsHigh & U_OLD_FRAME_HIGH) to.oldFrame = this.stream.readShort();
7934
7965
  }
7935
7966
  };
7936
7967
  var PlaybackState = /* @__PURE__ */ ((PlaybackState2) => {
@@ -8016,6 +8047,170 @@ function angleMod(angle2) {
8016
8047
  const value = angle2 % 360;
8017
8048
  return value < 0 ? 360 + value : value;
8018
8049
  }
8050
+ var ANORMS2 = [
8051
+ [-0.525731, 0, 0.850651],
8052
+ [-0.442863, 0.238856, 0.864188],
8053
+ [-0.295242, 0, 0.955423],
8054
+ [-0.309017, 0.5, 0.809017],
8055
+ [-0.16246, 0.262866, 0.951056],
8056
+ [0, 0, 1],
8057
+ [0, 0.850651, 0.525731],
8058
+ [-0.147621, 0.716567, 0.681718],
8059
+ [0.147621, 0.716567, 0.681718],
8060
+ [0, 0.525731, 0.850651],
8061
+ [0.309017, 0.5, 0.809017],
8062
+ [0.525731, 0, 0.850651],
8063
+ [0.295242, 0, 0.955423],
8064
+ [0.442863, 0.238856, 0.864188],
8065
+ [0.16246, 0.262866, 0.951056],
8066
+ [-0.681718, 0.147621, 0.716567],
8067
+ [-0.809017, 0.309017, 0.5],
8068
+ [-0.587785, 0.425325, 0.688191],
8069
+ [-0.850651, 0.525731, 0],
8070
+ [-0.864188, 0.442863, 0.238856],
8071
+ [-0.716567, 0.681718, 0.147621],
8072
+ [-0.688191, 0.587785, 0.425325],
8073
+ [-0.5, 0.809017, 0.309017],
8074
+ [-0.238856, 0.864188, 0.442863],
8075
+ [-0.425325, 0.688191, 0.587785],
8076
+ [-0.716567, 0.681718, -0.147621],
8077
+ [-0.5, 0.809017, -0.309017],
8078
+ [-0.525731, 0.850651, 0],
8079
+ [0, 0.850651, -0.525731],
8080
+ [-0.238856, 0.864188, -0.442863],
8081
+ [0, 0.955423, -0.295242],
8082
+ [-0.262866, 0.951056, -0.16246],
8083
+ [0, 1, 0],
8084
+ [0, 0.955423, 0.295242],
8085
+ [-0.262866, 0.951056, 0.16246],
8086
+ [0.238856, 0.864188, 0.442863],
8087
+ [0.262866, 0.951056, 0.16246],
8088
+ [0.5, 0.809017, 0.309017],
8089
+ [0.238856, 0.864188, -0.442863],
8090
+ [0.262866, 0.951056, -0.16246],
8091
+ [0.5, 0.809017, -0.309017],
8092
+ [0.850651, 0.525731, 0],
8093
+ [0.716567, 0.681718, 0.147621],
8094
+ [0.716567, 0.681718, -0.147621],
8095
+ [0.525731, 0.850651, 0],
8096
+ [0.425325, 0.688191, 0.587785],
8097
+ [0.864188, 0.442863, 0.238856],
8098
+ [0.688191, 0.587785, 0.425325],
8099
+ [0.809017, 0.309017, 0.5],
8100
+ [0.681718, 0.147621, 0.716567],
8101
+ [0.587785, 0.425325, 0.688191],
8102
+ [0.955423, 0.295242, 0],
8103
+ [1, 0, 0],
8104
+ [0.951056, 0.16246, 0.262866],
8105
+ [0.850651, -0.525731, 0],
8106
+ [0.955423, -0.295242, 0],
8107
+ [0.864188, -0.442863, 0.238856],
8108
+ [0.951056, -0.16246, 0.262866],
8109
+ [0.809017, -0.309017, 0.5],
8110
+ [0.681718, -0.147621, 0.716567],
8111
+ [0.850651, 0, 0.525731],
8112
+ [0.864188, 0.442863, -0.238856],
8113
+ [0.809017, 0.309017, -0.5],
8114
+ [0.951056, 0.16246, -0.262866],
8115
+ [0.525731, 0, -0.850651],
8116
+ [0.681718, 0.147621, -0.716567],
8117
+ [0.681718, -0.147621, -0.716567],
8118
+ [0.850651, 0, -0.525731],
8119
+ [0.809017, -0.309017, -0.5],
8120
+ [0.864188, -0.442863, -0.238856],
8121
+ [0.951056, -0.16246, -0.262866],
8122
+ [0.147621, 0.716567, -0.681718],
8123
+ [0.309017, 0.5, -0.809017],
8124
+ [0.425325, 0.688191, -0.587785],
8125
+ [0.442863, 0.238856, -0.864188],
8126
+ [0.587785, 0.425325, -0.688191],
8127
+ [0.688191, 0.587785, -0.425325],
8128
+ [-0.147621, 0.716567, -0.681718],
8129
+ [-0.309017, 0.5, -0.809017],
8130
+ [0, 0.525731, -0.850651],
8131
+ [-0.525731, 0, -0.850651],
8132
+ [-0.442863, 0.238856, -0.864188],
8133
+ [-0.295242, 0, -0.955423],
8134
+ [-0.16246, 0.262866, -0.951056],
8135
+ [0, 0, -1],
8136
+ [0.295242, 0, -0.955423],
8137
+ [0.16246, 0.262866, -0.951056],
8138
+ [-0.442863, -0.238856, -0.864188],
8139
+ [-0.309017, -0.5, -0.809017],
8140
+ [-0.16246, -0.262866, -0.951056],
8141
+ [0, -0.850651, -0.525731],
8142
+ [-0.147621, -0.716567, -0.681718],
8143
+ [0.147621, -0.716567, -0.681718],
8144
+ [0, -0.525731, -0.850651],
8145
+ [0.309017, -0.5, -0.809017],
8146
+ [0.442863, -0.238856, -0.864188],
8147
+ [0.16246, -0.262866, -0.951056],
8148
+ [0.238856, -0.864188, -0.442863],
8149
+ [0.5, -0.809017, -0.309017],
8150
+ [0.425325, -0.688191, -0.587785],
8151
+ [0.716567, -0.681718, -0.147621],
8152
+ [0.688191, -0.587785, -0.425325],
8153
+ [0.587785, -0.425325, -0.688191],
8154
+ [0, -0.955423, -0.295242],
8155
+ [0, -1, 0],
8156
+ [0.262866, -0.951056, -0.16246],
8157
+ [0, -0.850651, 0.525731],
8158
+ [0, -0.955423, 0.295242],
8159
+ [0.238856, -0.864188, 0.442863],
8160
+ [0.262866, -0.951056, 0.16246],
8161
+ [0.5, -0.809017, 0.309017],
8162
+ [0.716567, -0.681718, 0.147621],
8163
+ [0.525731, -0.850651, 0],
8164
+ [-0.238856, -0.864188, -0.442863],
8165
+ [-0.5, -0.809017, -0.309017],
8166
+ [-0.262866, -0.951056, -0.16246],
8167
+ [-0.850651, -0.525731, 0],
8168
+ [-0.716567, -0.681718, -0.147621],
8169
+ [-0.716567, -0.681718, 0.147621],
8170
+ [-0.525731, -0.850651, 0],
8171
+ [-0.5, -0.809017, 0.309017],
8172
+ [-0.238856, -0.864188, 0.442863],
8173
+ [-0.262866, -0.951056, 0.16246],
8174
+ [-0.864188, -0.442863, 0.238856],
8175
+ [-0.809017, -0.309017, 0.5],
8176
+ [-0.688191, -0.587785, 0.425325],
8177
+ [-0.681718, -0.147621, 0.716567],
8178
+ [-0.442863, -0.238856, 0.864188],
8179
+ [-0.587785, -0.425325, 0.688191],
8180
+ [-0.309017, -0.5, 0.809017],
8181
+ [-0.147621, -0.716567, 0.681718],
8182
+ [-0.425325, -0.688191, 0.587785],
8183
+ [-0.16246, -0.262866, 0.951056],
8184
+ [0.442863, -0.238856, 0.864188],
8185
+ [0.16246, -0.262866, 0.951056],
8186
+ [0.309017, -0.5, 0.809017],
8187
+ [0.147621, -0.716567, 0.681718],
8188
+ [0, -0.525731, 0.850651],
8189
+ [0.425325, -0.688191, 0.587785],
8190
+ [0.587785, -0.425325, 0.688191],
8191
+ [0.688191, -0.587785, 0.425325],
8192
+ [-0.955423, 0.295242, 0],
8193
+ [-0.951056, 0.16246, 0.262866],
8194
+ [-1, 0, 0],
8195
+ [-0.850651, 0, 0.525731],
8196
+ [-0.955423, -0.295242, 0],
8197
+ [-0.951056, -0.16246, 0.262866],
8198
+ [-0.864188, 0.442863, -0.238856],
8199
+ [-0.951056, 0.16246, -0.262866],
8200
+ [-0.809017, 0.309017, -0.5],
8201
+ [-0.864188, -0.442863, -0.238856],
8202
+ [-0.951056, -0.16246, -0.262866],
8203
+ [-0.809017, -0.309017, -0.5],
8204
+ [-0.681718, 0.147621, -0.716567],
8205
+ [-0.681718, -0.147621, -0.716567],
8206
+ [-0.850651, 0, -0.525731],
8207
+ [-0.688191, 0.587785, -0.425325],
8208
+ [-0.587785, 0.425325, -0.688191],
8209
+ [-0.425325, 0.688191, -0.587785],
8210
+ [-0.425325, -0.688191, -0.587785],
8211
+ [-0.587785, -0.425325, -0.688191],
8212
+ [-0.688191, -0.587785, -0.425325]
8213
+ ];
8019
8214
  var CONTENTS_SOLID2 = 1 << 0;
8020
8215
  var CONTENTS_WINDOW2 = 1 << 1;
8021
8216
  var CONTENTS_AUX2 = 1 << 2;
@@ -8215,6 +8410,14 @@ function mouseDeltaToViewDelta(delta, options) {
8215
8410
  z: 0
8216
8411
  };
8217
8412
  }
8413
+ var ClientCommand = /* @__PURE__ */ ((ClientCommand2) => {
8414
+ ClientCommand2[ClientCommand2["bad"] = 0] = "bad";
8415
+ ClientCommand2[ClientCommand2["nop"] = 1] = "nop";
8416
+ ClientCommand2[ClientCommand2["move"] = 2] = "move";
8417
+ ClientCommand2[ClientCommand2["userinfo"] = 3] = "userinfo";
8418
+ ClientCommand2[ClientCommand2["stringcmd"] = 4] = "stringcmd";
8419
+ return ClientCommand2;
8420
+ })(ClientCommand || {});
8218
8421
  var MZ_BLASTER = 0;
8219
8422
  var MZ_MACHINEGUN = 1;
8220
8423
  var MZ_SHOTGUN = 2;
@@ -8442,7 +8645,7 @@ __export3(entityFlags_exports2, {
8442
8645
  U_MODEL2: () => U_MODEL23,
8443
8646
  U_MODEL3: () => U_MODEL33,
8444
8647
  U_MODEL4: () => U_MODEL43,
8445
- U_MOREBITS: () => U_MOREBITS4,
8648
+ U_MOREBITS: () => U_MOREBITS5,
8446
8649
  U_NUMBER: () => U_NUMBER2,
8447
8650
  U_ORIGIN1: () => U_ORIGIN13,
8448
8651
  U_ORIGIN2: () => U_ORIGIN23,
@@ -8468,11 +8671,216 @@ var U_EFFECTS2 = 1 << 11;
8468
8671
  var U_RENDERFX2 = 1 << 12;
8469
8672
  var U_SOLID3 = 1 << 13;
8470
8673
  var U_EVENT3 = 1 << 14;
8471
- var U_MOREBITS4 = 1 << 15;
8674
+ var U_MOREBITS5 = 1 << 15;
8472
8675
  var U_MODEL23 = 1 << 0;
8473
8676
  var U_MODEL33 = 1 << 1;
8474
8677
  var U_MODEL43 = 1 << 2;
8475
8678
  var U_REMOVE3 = 32768;
8679
+ var BinaryStream2 = class {
8680
+ constructor(buffer) {
8681
+ if (buffer instanceof Uint8Array) {
8682
+ this.view = new DataView(buffer.buffer, buffer.byteOffset, buffer.byteLength);
8683
+ } else {
8684
+ this.view = new DataView(buffer);
8685
+ }
8686
+ this.offset = 0;
8687
+ this.length = this.view.byteLength;
8688
+ }
8689
+ getPosition() {
8690
+ return this.offset;
8691
+ }
8692
+ seek(position) {
8693
+ if (position < 0 || position > this.length) {
8694
+ throw new Error(`Seek out of bounds: ${position} (length: ${this.length})`);
8695
+ }
8696
+ this.offset = position;
8697
+ }
8698
+ hasMore() {
8699
+ return this.offset < this.length;
8700
+ }
8701
+ readChar() {
8702
+ const value = this.view.getInt8(this.offset);
8703
+ this.offset += 1;
8704
+ return value;
8705
+ }
8706
+ readByte() {
8707
+ const value = this.view.getUint8(this.offset);
8708
+ this.offset += 1;
8709
+ return value;
8710
+ }
8711
+ readShort() {
8712
+ const value = this.view.getInt16(this.offset, true);
8713
+ this.offset += 2;
8714
+ return value;
8715
+ }
8716
+ readUShort() {
8717
+ const value = this.view.getUint16(this.offset, true);
8718
+ this.offset += 2;
8719
+ return value;
8720
+ }
8721
+ readLong() {
8722
+ const value = this.view.getInt32(this.offset, true);
8723
+ this.offset += 4;
8724
+ return value;
8725
+ }
8726
+ readULong() {
8727
+ const value = this.view.getUint32(this.offset, true);
8728
+ this.offset += 4;
8729
+ return value;
8730
+ }
8731
+ readFloat() {
8732
+ const value = this.view.getFloat32(this.offset, true);
8733
+ this.offset += 4;
8734
+ return value;
8735
+ }
8736
+ readString() {
8737
+ let str3 = "";
8738
+ while (this.offset < this.length) {
8739
+ const charCode = this.readChar();
8740
+ if (charCode === -1 || charCode === 0) {
8741
+ break;
8742
+ }
8743
+ str3 += String.fromCharCode(charCode);
8744
+ }
8745
+ return str3;
8746
+ }
8747
+ readStringLine() {
8748
+ let str3 = "";
8749
+ while (this.offset < this.length) {
8750
+ const charCode = this.readChar();
8751
+ if (charCode === -1 || charCode === 0 || charCode === 10) {
8752
+ break;
8753
+ }
8754
+ str3 += String.fromCharCode(charCode);
8755
+ }
8756
+ return str3;
8757
+ }
8758
+ readCoord() {
8759
+ return this.readShort() * (1 / 8);
8760
+ }
8761
+ readAngle() {
8762
+ return this.readChar() * (360 / 256);
8763
+ }
8764
+ readAngle16() {
8765
+ return this.readShort() * 360 / 65536;
8766
+ }
8767
+ readData(length2) {
8768
+ if (this.offset + length2 > this.length) {
8769
+ throw new Error(`Read out of bounds: ${this.offset + length2} (length: ${this.length})`);
8770
+ }
8771
+ const data = new Uint8Array(this.view.buffer, this.view.byteOffset + this.offset, length2);
8772
+ this.offset += length2;
8773
+ return new Uint8Array(data);
8774
+ }
8775
+ readPos(out) {
8776
+ out.x = this.readCoord();
8777
+ out.y = this.readCoord();
8778
+ out.z = this.readCoord();
8779
+ }
8780
+ readDir(out) {
8781
+ const b = this.readByte();
8782
+ if (b >= 162) {
8783
+ out.x = 0;
8784
+ out.y = 0;
8785
+ out.z = 0;
8786
+ return;
8787
+ }
8788
+ const norm = ANORMS2[b];
8789
+ out.x = norm[0];
8790
+ out.y = norm[1];
8791
+ out.z = norm[2];
8792
+ }
8793
+ };
8794
+ var NetworkMessageBuilder = class {
8795
+ constructor(initialSize = 1024) {
8796
+ this.buffer = new Uint8Array(initialSize);
8797
+ this.view = new DataView(this.buffer.buffer);
8798
+ this.offset = 0;
8799
+ }
8800
+ ensureCapacity(needed) {
8801
+ if (this.offset + needed > this.buffer.length) {
8802
+ const newSize = Math.max(this.buffer.length * 2, this.offset + needed);
8803
+ const newBuffer = new Uint8Array(newSize);
8804
+ newBuffer.set(this.buffer);
8805
+ this.buffer = newBuffer;
8806
+ this.view = new DataView(this.buffer.buffer);
8807
+ }
8808
+ }
8809
+ getData() {
8810
+ return this.buffer.slice(0, this.offset);
8811
+ }
8812
+ writeByte(value) {
8813
+ this.ensureCapacity(1);
8814
+ this.view.setUint8(this.offset, value);
8815
+ this.offset += 1;
8816
+ }
8817
+ writeChar(value) {
8818
+ this.ensureCapacity(1);
8819
+ this.view.setInt8(this.offset, value);
8820
+ this.offset += 1;
8821
+ }
8822
+ writeShort(value) {
8823
+ this.ensureCapacity(2);
8824
+ this.view.setInt16(this.offset, value, true);
8825
+ this.offset += 2;
8826
+ }
8827
+ writeUShort(value) {
8828
+ this.ensureCapacity(2);
8829
+ this.view.setUint16(this.offset, value, true);
8830
+ this.offset += 2;
8831
+ }
8832
+ writeLong(value) {
8833
+ this.ensureCapacity(4);
8834
+ this.view.setInt32(this.offset, value, true);
8835
+ this.offset += 4;
8836
+ }
8837
+ writeFloat(value) {
8838
+ this.ensureCapacity(4);
8839
+ this.view.setFloat32(this.offset, value, true);
8840
+ this.offset += 4;
8841
+ }
8842
+ writeString(value) {
8843
+ const len2 = value.length + 1;
8844
+ this.ensureCapacity(len2);
8845
+ for (let i = 0; i < value.length; i++) {
8846
+ this.view.setUint8(this.offset + i, value.charCodeAt(i));
8847
+ }
8848
+ this.view.setUint8(this.offset + value.length, 0);
8849
+ this.offset += len2;
8850
+ }
8851
+ writeData(data) {
8852
+ this.ensureCapacity(data.length);
8853
+ this.buffer.set(data, this.offset);
8854
+ this.offset += data.length;
8855
+ }
8856
+ writeCoord(value) {
8857
+ this.writeShort(Math.round(value * 8));
8858
+ }
8859
+ writeAngle(value) {
8860
+ this.writeByte(Math.round(value * 256 / 360) & 255);
8861
+ }
8862
+ writeAngle16(value) {
8863
+ this.writeShort(Math.round(value * 65536 / 360));
8864
+ }
8865
+ writeDir(x, y, z) {
8866
+ let best = 0;
8867
+ let bestDot = -999999;
8868
+ const len2 = Math.sqrt(x * x + y * y + z * z);
8869
+ if (len2 > 0) {
8870
+ x /= len2;
8871
+ y /= len2;
8872
+ z /= len2;
8873
+ for (let i = 0; i < 162; i++) {
8874
+ const dot2 = x * ANORMS2[i][0] + y * ANORMS2[i][1] + z * ANORMS2[i][2];
8875
+ if (dot2 > bestDot) {
8876
+ bestDot = dot2;
8877
+ best = i;
8878
+ }
8879
+ }
8880
+ }
8881
+ this.writeByte(best);
8882
+ }
8883
+ };
8476
8884
  var AmmoType2 = /* @__PURE__ */ ((AmmoType22) => {
8477
8885
  AmmoType22[AmmoType22["Bullets"] = 0] = "Bullets";
8478
8886
  AmmoType22[AmmoType22["Shells"] = 1] = "Shells";
@@ -9093,6 +9501,7 @@ var ClientNetworkHandler = class {
9093
9501
  }
9094
9502
  applyDelta(to, from) {
9095
9503
  const bits = from.bits;
9504
+ const bitsHigh = from.bitsHigh;
9096
9505
  to.number = from.number;
9097
9506
  if (bits & U_MODEL5) to.modelindex = from.modelindex;
9098
9507
  if (bits & U_MODEL22) to.modelindex2 = from.modelindex2;
@@ -9117,13 +9526,13 @@ var ClientNetworkHandler = class {
9117
9526
  if (bits & U_SOUND2) to.sound = from.sound;
9118
9527
  if (bits & U_EVENT2) to.event = from.event;
9119
9528
  if (bits & U_SOLID2) to.solid = from.solid;
9120
- if (from.alpha !== 0) to.alpha = from.alpha;
9121
- if (from.scale !== 0) to.scale = from.scale;
9122
- if (from.instanceBits !== 0) to.instanceBits = from.instanceBits;
9123
- if (from.loopVolume !== 0) to.loopVolume = from.loopVolume;
9124
- if (from.loopAttenuation !== 0) to.loopAttenuation = from.loopAttenuation;
9125
- if (from.owner !== 0) to.owner = from.owner;
9126
- if (from.oldFrame !== 0) to.oldFrame = from.oldFrame;
9529
+ if (bits & U_ALPHA) to.alpha = from.alpha;
9530
+ if (bits & U_SCALE) to.scale = from.scale;
9531
+ if (bits & U_INSTANCE_BITS) to.instanceBits = from.instanceBits;
9532
+ if (bits & U_LOOP_VOLUME) to.loopVolume = from.loopVolume;
9533
+ if (bitsHigh & U_LOOP_ATTENUATION_HIGH) to.loopAttenuation = from.loopAttenuation;
9534
+ if (bitsHigh & U_OWNER_HIGH) to.owner = from.owner;
9535
+ if (bitsHigh & U_OLD_FRAME_HIGH) to.oldFrame = from.oldFrame;
9127
9536
  }
9128
9537
  onCenterPrint(msg) {
9129
9538
  if (this.callbacks?.onCenterPrint) {
@@ -9239,11 +9648,16 @@ var ClientNetworkHandler = class {
9239
9648
  this.callbacks.onDamage(indicators);
9240
9649
  }
9241
9650
  }
9242
- // New Rerelease Handlers (Stubbed)
9651
+ onLocPrint(flags, base, args) {
9652
+ if (this.callbacks?.onLocPrint) {
9653
+ this.callbacks.onLocPrint(flags, base, args);
9654
+ }
9655
+ }
9656
+ // New Rerelease Handlers
9243
9657
  onLevelRestart() {
9244
9658
  if (this.callbacks?.onLevelRestart) this.callbacks.onLevelRestart();
9245
9659
  }
9246
- onWaitingForPlayers() {
9660
+ onWaitingForPlayers(count) {
9247
9661
  if (this.callbacks?.onWaitingForPlayers) this.callbacks.onWaitingForPlayers();
9248
9662
  }
9249
9663
  onDisconnect() {
@@ -9436,6 +9850,16 @@ var MainMenuFactory = class {
9436
9850
  this.menuSystem.pushMenu(this.createDifficultyMenu());
9437
9851
  }
9438
9852
  },
9853
+ {
9854
+ label: "Multiplayer",
9855
+ action: () => {
9856
+ if (this.options.multiplayerFactory) {
9857
+ this.menuSystem.pushMenu(this.options.multiplayerFactory.createMultiplayerMenu());
9858
+ } else {
9859
+ console.warn("Multiplayer factory not configured");
9860
+ }
9861
+ }
9862
+ },
9439
9863
  {
9440
9864
  label: "Load Game",
9441
9865
  action: () => {
@@ -10010,6 +10434,74 @@ var PauseMenuFactory = class {
10010
10434
  }
10011
10435
  };
10012
10436
 
10437
+ // src/ui/menu/multiplayer.ts
10438
+ var MultiplayerMenuFactory = class {
10439
+ constructor(menuSystem, connection) {
10440
+ this.menuSystem = menuSystem;
10441
+ this.connection = connection;
10442
+ }
10443
+ createMultiplayerMenu(initialAddress = "localhost:27910", status = "") {
10444
+ let address = initialAddress;
10445
+ const items = [];
10446
+ if (status) {
10447
+ items.push({
10448
+ label: status,
10449
+ action: () => {
10450
+ }
10451
+ // No-op
10452
+ });
10453
+ }
10454
+ items.push(
10455
+ {
10456
+ label: "Address: " + address,
10457
+ action: () => {
10458
+ if (typeof window !== "undefined") {
10459
+ const newAddr = window.prompt("Enter Server Address", address);
10460
+ if (newAddr) {
10461
+ address = newAddr;
10462
+ this.refreshMenu(address);
10463
+ }
10464
+ }
10465
+ }
10466
+ },
10467
+ {
10468
+ label: "Connect",
10469
+ action: () => {
10470
+ this.refreshMenu(address, "Connecting...");
10471
+ this.connection.connect("ws://" + address).then(() => {
10472
+ this.menuSystem.closeAll();
10473
+ }).catch((err2) => {
10474
+ console.error(err2);
10475
+ const failStatus = "Failed: " + (err2.message || "Unknown error");
10476
+ this.refreshMenu(address, failStatus);
10477
+ });
10478
+ }
10479
+ },
10480
+ {
10481
+ label: "Disconnect",
10482
+ action: () => {
10483
+ this.connection.disconnect();
10484
+ this.refreshMenu(address, "Disconnected");
10485
+ }
10486
+ },
10487
+ {
10488
+ label: "Back",
10489
+ action: () => {
10490
+ this.menuSystem.popMenu();
10491
+ }
10492
+ }
10493
+ );
10494
+ return {
10495
+ title: "Multiplayer",
10496
+ items
10497
+ };
10498
+ }
10499
+ refreshMenu(address, status = "") {
10500
+ this.menuSystem.popMenu();
10501
+ this.menuSystem.pushMenu(this.createMultiplayerMenu(address, status));
10502
+ }
10503
+ };
10504
+
10013
10505
  // src/ui/menu/render.ts
10014
10506
  function Draw_Menu(renderer, state, width, height) {
10015
10507
  if (!state.activeMenu) {
@@ -10288,6 +10780,233 @@ function buildRenderableEntities(latestEntities, previousEntities, alpha, config
10288
10780
  return renderables;
10289
10781
  }
10290
10782
 
10783
+ // src/net/browserWsDriver.ts
10784
+ var BrowserWebSocketNetDriver = class {
10785
+ constructor() {
10786
+ this.socket = null;
10787
+ this.messageCallback = null;
10788
+ this.closeCallback = null;
10789
+ this.errorCallback = null;
10790
+ }
10791
+ async connect(url) {
10792
+ return new Promise((resolve, reject) => {
10793
+ try {
10794
+ this.socket = new WebSocket(url);
10795
+ this.socket.binaryType = "arraybuffer";
10796
+ this.socket.onopen = () => {
10797
+ resolve();
10798
+ };
10799
+ this.socket.onerror = (event) => {
10800
+ const error = new Error("WebSocket connection error");
10801
+ if (this.errorCallback) {
10802
+ this.errorCallback(error);
10803
+ }
10804
+ reject(error);
10805
+ };
10806
+ this.socket.onclose = () => {
10807
+ if (this.closeCallback) {
10808
+ this.closeCallback();
10809
+ }
10810
+ this.socket = null;
10811
+ };
10812
+ this.socket.onmessage = (event) => {
10813
+ if (this.messageCallback) {
10814
+ if (event.data instanceof ArrayBuffer) {
10815
+ this.messageCallback(new Uint8Array(event.data));
10816
+ } else {
10817
+ console.warn("Received non-binary message from server");
10818
+ }
10819
+ }
10820
+ };
10821
+ } catch (e) {
10822
+ reject(e);
10823
+ }
10824
+ });
10825
+ }
10826
+ disconnect() {
10827
+ if (this.socket) {
10828
+ this.socket.close();
10829
+ this.socket = null;
10830
+ }
10831
+ }
10832
+ send(data) {
10833
+ if (this.socket && this.socket.readyState === WebSocket.OPEN) {
10834
+ this.socket.send(data);
10835
+ } else {
10836
+ console.warn("Attempted to send data on closed or connecting socket");
10837
+ }
10838
+ }
10839
+ onMessage(callback) {
10840
+ this.messageCallback = callback;
10841
+ }
10842
+ onClose(callback) {
10843
+ this.closeCallback = callback;
10844
+ }
10845
+ onError(callback) {
10846
+ this.errorCallback = callback;
10847
+ }
10848
+ isConnected() {
10849
+ return this.socket !== null && this.socket.readyState === WebSocket.OPEN;
10850
+ }
10851
+ };
10852
+
10853
+ // src/net/connection.ts
10854
+ var MultiplayerConnection = class {
10855
+ constructor(options) {
10856
+ this.state = 0 /* Disconnected */;
10857
+ this.parser = null;
10858
+ // Game State
10859
+ this.serverProtocol = 0;
10860
+ this.serverCount = 0;
10861
+ this.gameDir = "";
10862
+ this.playerNum = 0;
10863
+ this.levelName = "";
10864
+ this.configStrings = /* @__PURE__ */ new Map();
10865
+ this.baselines = /* @__PURE__ */ new Map();
10866
+ this.challenge = 0;
10867
+ this.connectPacketCount = 0;
10868
+ this.connectPacketTime = 0;
10869
+ this.driver = new BrowserWebSocketNetDriver();
10870
+ this.options = options;
10871
+ this.driver.onMessage((data) => this.handleMessage(data));
10872
+ this.driver.onClose(() => this.handleDisconnect());
10873
+ this.driver.onError((err2) => console.error("Network Error:", err2));
10874
+ }
10875
+ async connect(url) {
10876
+ if (this.state !== 0 /* Disconnected */) {
10877
+ this.disconnect();
10878
+ }
10879
+ console.log(`Connecting to ${url}...`);
10880
+ this.state = 1 /* Connecting */;
10881
+ try {
10882
+ await this.driver.connect(url);
10883
+ console.log("WebSocket connected.");
10884
+ this.state = 2 /* Challenge */;
10885
+ this.sendChallenge();
10886
+ } catch (e) {
10887
+ console.error("Connection failed:", e);
10888
+ this.state = 0 /* Disconnected */;
10889
+ throw e;
10890
+ }
10891
+ }
10892
+ disconnect() {
10893
+ if (this.state === 0 /* Disconnected */) return;
10894
+ this.driver.disconnect();
10895
+ this.state = 0 /* Disconnected */;
10896
+ this.configStrings.clear();
10897
+ this.baselines.clear();
10898
+ }
10899
+ sendCommand(cmd) {
10900
+ if (this.state !== 5 /* Active */) return;
10901
+ const builder = new NetworkMessageBuilder();
10902
+ builder.writeByte(ClientCommand.nop);
10903
+ this.driver.send(builder.getData());
10904
+ }
10905
+ handleMessage(data) {
10906
+ let buffer = data.buffer;
10907
+ if (buffer instanceof SharedArrayBuffer) {
10908
+ const newBuffer = new ArrayBuffer(data.byteLength);
10909
+ new Uint8Array(newBuffer).set(data);
10910
+ buffer = newBuffer;
10911
+ }
10912
+ const stream = new BinaryStream2(buffer);
10913
+ const sequence = stream.readLong();
10914
+ const sequenceAck = stream.readLong();
10915
+ this.parser = new NetworkMessageParser(stream, this);
10916
+ this.parser.parseMessage();
10917
+ }
10918
+ handleDisconnect() {
10919
+ console.log("Disconnected from server.");
10920
+ this.state = 0 /* Disconnected */;
10921
+ }
10922
+ sendChallenge() {
10923
+ const builder = new NetworkMessageBuilder();
10924
+ builder.writeByte(ClientCommand.stringcmd);
10925
+ builder.writeString("getchallenge");
10926
+ this.driver.send(builder.getData());
10927
+ }
10928
+ sendConnect(challenge) {
10929
+ const builder = new NetworkMessageBuilder();
10930
+ builder.writeByte(ClientCommand.stringcmd);
10931
+ const userinfo = `\\name\\${this.options.username}\\model\\${this.options.model}\\skin\\${this.options.skin}\\hand\\${this.options.hand ?? 0}\\fov\\${this.options.fov ?? 90}`;
10932
+ builder.writeString(`connect ${PROTOCOL_VERSION_RERELEASE} ${challenge} ${userinfo}`);
10933
+ this.driver.send(builder.getData());
10934
+ }
10935
+ isConnected() {
10936
+ return this.state === 5 /* Active */;
10937
+ }
10938
+ // ==================================================================================
10939
+ // NetworkMessageHandler Implementation
10940
+ // ==================================================================================
10941
+ onServerData(protocol, serverCount, attractLoop, gameDir, playerNum, levelName) {
10942
+ console.log(`Server Data: Protocol ${protocol}, Level ${levelName}`);
10943
+ this.serverProtocol = protocol;
10944
+ this.serverCount = serverCount;
10945
+ this.gameDir = gameDir;
10946
+ this.playerNum = playerNum;
10947
+ this.levelName = levelName;
10948
+ this.state = 3 /* Connected */;
10949
+ const builder = new NetworkMessageBuilder();
10950
+ builder.writeByte(ClientCommand.stringcmd);
10951
+ builder.writeString("new");
10952
+ this.driver.send(builder.getData());
10953
+ this.state = 4 /* Loading */;
10954
+ }
10955
+ onConfigString(index, str3) {
10956
+ this.configStrings.set(index, str3);
10957
+ }
10958
+ onSpawnBaseline(entity) {
10959
+ this.baselines.set(entity.number, entity);
10960
+ }
10961
+ onStuffText(msg) {
10962
+ console.log(`Server StuffText: ${msg}`);
10963
+ if (msg.startsWith("precache")) {
10964
+ this.finishLoading();
10965
+ }
10966
+ if (msg.startsWith("challenge ")) {
10967
+ const parts = msg.split(" ");
10968
+ if (parts.length > 1) {
10969
+ this.challenge = parseInt(parts[1], 10);
10970
+ this.sendConnect(this.challenge);
10971
+ }
10972
+ }
10973
+ }
10974
+ finishLoading() {
10975
+ console.log("Finished loading, sending begin...");
10976
+ const builder = new NetworkMessageBuilder();
10977
+ builder.writeByte(ClientCommand.stringcmd);
10978
+ builder.writeString("begin");
10979
+ this.driver.send(builder.getData());
10980
+ this.state = 5 /* Active */;
10981
+ }
10982
+ // Stubs for other handlers
10983
+ onFrame(frame) {
10984
+ }
10985
+ onCenterPrint(msg) {
10986
+ }
10987
+ onPrint(level, msg) {
10988
+ }
10989
+ onSound(flags, soundNum, volume, attenuation, offset, ent, pos) {
10990
+ }
10991
+ onTempEntity(type, pos, pos2, dir, cnt, color, ent, srcEnt, destEnt) {
10992
+ }
10993
+ onLayout(layout) {
10994
+ }
10995
+ onInventory(inventory) {
10996
+ }
10997
+ onMuzzleFlash(ent, weapon) {
10998
+ }
10999
+ onMuzzleFlash2(ent, weapon) {
11000
+ }
11001
+ onDisconnect() {
11002
+ this.disconnect();
11003
+ }
11004
+ onReconnect() {
11005
+ }
11006
+ onDownload(size, percent, data) {
11007
+ }
11008
+ };
11009
+
10291
11010
  // src/input/bindings.ts
10292
11011
  var DEFAULT_BINDINGS = [
10293
11012
  { code: "KeyW", command: "+forward" },
@@ -10824,6 +11543,21 @@ function createClient(imports) {
10824
11543
  };
10825
11544
  const cgameImport = createCGameImport(imports, stateProvider);
10826
11545
  const cg = GetCGameAPI(cgameImport);
11546
+ const multiplayer = new MultiplayerConnection({
11547
+ get username() {
11548
+ return imports.host?.cvars?.get("name")?.string || "Player";
11549
+ },
11550
+ get model() {
11551
+ return imports.host?.cvars?.get("model")?.string || "male";
11552
+ },
11553
+ get skin() {
11554
+ return imports.host?.cvars?.get("skin")?.string || "grunt";
11555
+ },
11556
+ get fov() {
11557
+ return fovValue;
11558
+ }
11559
+ });
11560
+ const multiplayerFactory = new MultiplayerMenuFactory(menuSystem, multiplayer);
10827
11561
  demoHandler.setCallbacks({
10828
11562
  onCenterPrint: (msg) => cg.ParseCenterPrint(msg, 0, false),
10829
11563
  onPrint: (level, msg) => cg.NotifyMessage(0, msg, false),
@@ -10886,6 +11620,22 @@ function createClient(imports) {
10886
11620
  menuSystem.pushMenu(pauseMenuFactory.createPauseMenu());
10887
11621
  }
10888
11622
  }, "Toggle the main/pause menu");
11623
+ imports.host.commands.register("connect", (args) => {
11624
+ if (args.length < 1) {
11625
+ console.log("usage: connect <address>");
11626
+ return;
11627
+ }
11628
+ const address = args[0];
11629
+ console.log(`Connecting to ${address}...`);
11630
+ multiplayer.connect(address).catch((e) => {
11631
+ console.error("Failed to connect:", e);
11632
+ errorDialog.show("Connection Failed", e instanceof Error ? e.message : "Unknown error");
11633
+ });
11634
+ }, "Connect to a multiplayer server");
11635
+ imports.host.commands.register("disconnect", () => {
11636
+ multiplayer.disconnect();
11637
+ console.log("Disconnected.");
11638
+ }, "Disconnect from server");
10889
11639
  if (imports.host.cvars) {
10890
11640
  imports.host.cvars.register({
10891
11641
  name: "fov",
@@ -10940,6 +11690,9 @@ function createClient(imports) {
10940
11690
  predict(command) {
10941
11691
  if (menuSystem.isActive()) {
10942
11692
  }
11693
+ if (multiplayer.isConnected()) {
11694
+ multiplayer.sendCommand(command);
11695
+ }
10943
11696
  return prediction.enqueueCommand(command);
10944
11697
  },
10945
11698
  handleInput(key, down) {
@@ -11004,6 +11757,7 @@ function createClient(imports) {
11004
11757
  ...options,
11005
11758
  optionsFactory: optsFactory,
11006
11759
  mapsFactory,
11760
+ multiplayerFactory,
11007
11761
  onSetDifficulty: (skill) => {
11008
11762
  if (imports.host?.cvars) {
11009
11763
  imports.host.cvars.setValue("skill", skill.toString());
@@ -11209,6 +11963,7 @@ function createClient(imports) {
11209
11963
  cg.ParseConfigString(index, value);
11210
11964
  },
11211
11965
  demoHandler,
11966
+ multiplayer,
11212
11967
  configStrings
11213
11968
  };
11214
11969
  return clientExports;