quake2ts 0.0.563 → 0.0.565

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.
@@ -30,6 +30,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
30
30
  // src/index.ts
31
31
  var index_exports = {};
32
32
  __export(index_exports, {
33
+ HandshakeStage: () => HandshakeStage,
33
34
  InputInjector: () => InputInjector,
34
35
  MockPointerLock: () => MockPointerLock,
35
36
  MockTransport: () => MockTransport,
@@ -42,15 +43,18 @@ __export(index_exports, {
42
43
  createBinaryWriterMock: () => createBinaryWriterMock,
43
44
  createControlledTimer: () => createControlledTimer,
44
45
  createCustomNetworkCondition: () => createCustomNetworkCondition,
46
+ createDeltaSnapshot: () => createDeltaSnapshot,
45
47
  createEntity: () => createEntity,
46
48
  createEntityStateFactory: () => createEntityStateFactory,
47
49
  createGameStateSnapshotFactory: () => createGameStateSnapshotFactory,
48
50
  createMockAudioContext: () => createMockAudioContext,
49
51
  createMockCanvas: () => createMockCanvas,
50
52
  createMockCanvasContext2D: () => createMockCanvasContext2D,
53
+ createMockConnection: () => createMockConnection,
51
54
  createMockEngine: () => createMockEngine,
52
55
  createMockGame: () => createMockGame,
53
56
  createMockGameState: () => createMockGameState,
57
+ createMockHandshake: () => createMockHandshake,
54
58
  createMockImage: () => createMockImage,
55
59
  createMockImageData: () => createMockImageData,
56
60
  createMockIndexedDB: () => createMockIndexedDB,
@@ -65,10 +69,13 @@ __export(index_exports, {
65
69
  createMockSessionStorage: () => createMockSessionStorage,
66
70
  createMockTransport: () => createMockTransport,
67
71
  createMockUDPSocket: () => createMockUDPSocket,
72
+ createMockUserInfo: () => createMockUserInfo,
68
73
  createMockWebGL2Context: () => createMockWebGL2Context,
74
+ createMultiplayerTestScenario: () => createMultiplayerTestScenario,
69
75
  createNetChanMock: () => createNetChanMock,
70
76
  createPlayerStateFactory: () => createPlayerStateFactory,
71
77
  createPlaywrightTestClient: () => createPlaywrightTestClient,
78
+ createServerSnapshot: () => createServerSnapshot,
72
79
  createSpawnContext: () => createSpawnContext,
73
80
  createStorageTestScenario: () => createStorageTestScenario,
74
81
  createTestContext: () => createTestContext,
@@ -82,16 +89,24 @@ __export(index_exports, {
82
89
  makeLeafModel: () => makeLeafModel,
83
90
  makeNode: () => makeNode,
84
91
  makePlane: () => makePlane,
92
+ serializeUserInfo: () => serializeUserInfo,
85
93
  setupBrowserEnvironment: () => setupBrowserEnvironment,
86
94
  setupMockAudioContext: () => setupMockAudioContext,
87
95
  setupNodeEnvironment: () => setupNodeEnvironment,
88
96
  simulateFrames: () => simulateFrames,
89
97
  simulateFramesWithMock: () => simulateFramesWithMock,
98
+ simulateHandshake: () => simulateHandshake,
90
99
  simulateNetworkCondition: () => simulateNetworkCondition,
100
+ simulatePlayerInput: () => simulatePlayerInput,
101
+ simulatePlayerJoin: () => simulatePlayerJoin,
102
+ simulatePlayerLeave: () => simulatePlayerLeave,
103
+ simulateServerTick: () => simulateServerTick,
104
+ simulateSnapshotDelivery: () => simulateSnapshotDelivery,
91
105
  stairTrace: () => import_shared3.stairTrace,
92
106
  teardownBrowserEnvironment: () => teardownBrowserEnvironment,
93
107
  teardownMockAudioContext: () => teardownMockAudioContext,
94
108
  throttleBandwidth: () => throttleBandwidth,
109
+ verifySnapshotConsistency: () => verifySnapshotConsistency,
95
110
  waitForGameReady: () => waitForGameReady
96
111
  });
97
112
  module.exports = __toCommonJS(index_exports);
@@ -698,6 +713,214 @@ function createMockServer(overrides) {
698
713
  };
699
714
  }
700
715
 
716
+ // src/server/mocks/connection.ts
717
+ var import_server2 = require("@quake2ts/server");
718
+ var HandshakeStage = /* @__PURE__ */ ((HandshakeStage2) => {
719
+ HandshakeStage2[HandshakeStage2["None"] = 0] = "None";
720
+ HandshakeStage2[HandshakeStage2["Challenge"] = 1] = "Challenge";
721
+ HandshakeStage2[HandshakeStage2["Connect"] = 2] = "Connect";
722
+ HandshakeStage2[HandshakeStage2["Info"] = 3] = "Info";
723
+ HandshakeStage2[HandshakeStage2["Active"] = 4] = "Active";
724
+ return HandshakeStage2;
725
+ })(HandshakeStage || {});
726
+ function serializeUserInfo(info) {
727
+ return Object.entries(info).reduce((acc, [key, value]) => {
728
+ if (value !== void 0) {
729
+ return `${acc}\\${key}\\${value}`;
730
+ }
731
+ return acc;
732
+ }, "");
733
+ }
734
+ function createMockUserInfo(overrides) {
735
+ return {
736
+ name: "Player",
737
+ skin: "male/grunt",
738
+ model: "male/grunt",
739
+ fov: 90,
740
+ hand: 0,
741
+ rate: 25e3,
742
+ msg: 1,
743
+ ...overrides
744
+ };
745
+ }
746
+ function createMockConnection(state = import_server2.ClientState.Connected, overrides) {
747
+ return createMockServerClient(0, {
748
+ state,
749
+ userInfo: serializeUserInfo(createMockUserInfo()),
750
+ challenge: Math.floor(Math.random() * 1e5),
751
+ ...overrides
752
+ });
753
+ }
754
+ function createMockHandshake(stage = 0 /* None */) {
755
+ return {
756
+ stage,
757
+ clientNum: -1,
758
+ challenge: 0,
759
+ qport: Math.floor(Math.random() * 65536)
760
+ };
761
+ }
762
+ async function simulateHandshake(client, server) {
763
+ const challenge = Math.floor(Math.random() * 1e5);
764
+ client.challenge = challenge;
765
+ if (server && server.clients) {
766
+ }
767
+ client.state = import_server2.ClientState.Connected;
768
+ client.state = import_server2.ClientState.Active;
769
+ return true;
770
+ }
771
+
772
+ // src/server/helpers/multiplayer.ts
773
+ var import_server3 = require("@quake2ts/server");
774
+ function createMultiplayerTestScenario(numPlayers = 2) {
775
+ const baseServer = createMockServerState();
776
+ const clients = [];
777
+ const entities = [];
778
+ const server = {
779
+ ...baseServer,
780
+ clients: new Array(numPlayers).fill(null),
781
+ entities: []
782
+ };
783
+ for (let i = 0; i < numPlayers; i++) {
784
+ const client = createMockServerClient(i, {
785
+ state: import_server3.ClientState.Active,
786
+ userInfo: serializeUserInfo(createMockUserInfo({ name: `Player${i}` }))
787
+ });
788
+ const entity = {
789
+ classname: "player",
790
+ s: { origin: { x: 0, y: 0, z: 0 }, number: i + 1 },
791
+ client
792
+ };
793
+ client.edict = entity;
794
+ server.clients[i] = client;
795
+ clients.push(client);
796
+ entities.push(entity);
797
+ }
798
+ server.entities = entities;
799
+ return {
800
+ server,
801
+ clients,
802
+ entities
803
+ };
804
+ }
805
+ async function simulatePlayerJoin(server, userInfo) {
806
+ const index = server.clients.findIndex((c) => !c || c.state === import_server3.ClientState.Free);
807
+ if (index === -1) {
808
+ throw new Error("Server full");
809
+ }
810
+ const client = createMockServerClient(index, {
811
+ state: import_server3.ClientState.Connected,
812
+ userInfo: serializeUserInfo(createMockUserInfo(userInfo))
813
+ });
814
+ server.clients[index] = client;
815
+ client.state = import_server3.ClientState.Active;
816
+ const entity = {
817
+ classname: "player",
818
+ s: { origin: { x: 0, y: 0, z: 0 }, number: index + 1 },
819
+ client
820
+ };
821
+ client.edict = entity;
822
+ if (server.entities && Array.isArray(server.entities)) {
823
+ server.entities[index + 1] = entity;
824
+ }
825
+ return client;
826
+ }
827
+ function simulatePlayerLeave(server, clientNum) {
828
+ const client = server.clients[clientNum];
829
+ if (client) {
830
+ client.state = import_server3.ClientState.Free;
831
+ client.edict = null;
832
+ }
833
+ }
834
+ function simulateServerTick(server, deltaTime = 0.1) {
835
+ server.time += deltaTime;
836
+ server.frame++;
837
+ server.clients.forEach((client) => {
838
+ if (client && client.state === import_server3.ClientState.Active) {
839
+ }
840
+ });
841
+ }
842
+ function simulatePlayerInput(client, input) {
843
+ const cmd = {
844
+ msec: 100,
845
+ buttons: 0,
846
+ angles: { x: 0, y: 0, z: 0 },
847
+ forwardmove: 0,
848
+ sidemove: 0,
849
+ upmove: 0,
850
+ sequence: client.lastCmd.sequence + 1,
851
+ lightlevel: 0,
852
+ impulse: 0,
853
+ ...input
854
+ };
855
+ client.lastCmd = cmd;
856
+ client.commandQueue.push(cmd);
857
+ client.commandCount++;
858
+ }
859
+
860
+ // src/server/helpers/snapshot.ts
861
+ function createServerSnapshot(serverState, clientNum) {
862
+ const visibleEntities = [];
863
+ if (serverState.baselines) {
864
+ serverState.baselines.forEach((ent, index) => {
865
+ if (ent && index !== clientNum + 1) {
866
+ visibleEntities.push({ ...ent });
867
+ }
868
+ });
869
+ }
870
+ return {
871
+ serverTime: serverState.time,
872
+ playerState: {
873
+ origin: { x: 0, y: 0, z: 0 },
874
+ viewangles: { x: 0, y: 0, z: 0 },
875
+ pm_type: 0
876
+ },
877
+ entities: visibleEntities
878
+ };
879
+ }
880
+ function createDeltaSnapshot(oldSnapshot, newSnapshot) {
881
+ const deltaEntities = [];
882
+ const removedEntities = [];
883
+ const oldMap = new Map(oldSnapshot.entities.map((e) => [e.number, e]));
884
+ const newMap = new Map(newSnapshot.entities.map((e) => [e.number, e]));
885
+ newSnapshot.entities.forEach((newEnt) => {
886
+ const oldEnt = oldMap.get(newEnt.number);
887
+ if (!oldEnt) {
888
+ deltaEntities.push(newEnt);
889
+ } else if (JSON.stringify(newEnt) !== JSON.stringify(oldEnt)) {
890
+ deltaEntities.push(newEnt);
891
+ }
892
+ });
893
+ oldSnapshot.entities.forEach((oldEnt) => {
894
+ if (!newMap.has(oldEnt.number)) {
895
+ removedEntities.push(oldEnt.number);
896
+ }
897
+ });
898
+ return {
899
+ snapshot: newSnapshot,
900
+ deltaEntities,
901
+ removedEntities
902
+ };
903
+ }
904
+ function verifySnapshotConsistency(snapshots) {
905
+ const report = { valid: true, errors: [] };
906
+ if (snapshots.length < 2) return report;
907
+ for (let i = 1; i < snapshots.length; i++) {
908
+ const prev = snapshots[i - 1];
909
+ const curr = snapshots[i];
910
+ if (curr.serverTime <= prev.serverTime) {
911
+ report.valid = false;
912
+ report.errors.push(`Snapshot ${i} has time ${curr.serverTime} <= prev ${prev.serverTime}`);
913
+ }
914
+ }
915
+ return report;
916
+ }
917
+ async function simulateSnapshotDelivery(snapshot, reliability = 1) {
918
+ if (Math.random() > reliability) {
919
+ return null;
920
+ }
921
+ return snapshot;
922
+ }
923
+
701
924
  // src/setup/browser.ts
702
925
  var import_jsdom = require("jsdom");
703
926
  var import_canvas = require("@napi-rs/canvas");
@@ -1764,6 +1987,7 @@ function createVisualTestScenario(page, sceneName) {
1764
1987
  }
1765
1988
  // Annotate the CommonJS export names for ESM import in node:
1766
1989
  0 && (module.exports = {
1990
+ HandshakeStage,
1767
1991
  InputInjector,
1768
1992
  MockPointerLock,
1769
1993
  MockTransport,
@@ -1776,15 +2000,18 @@ function createVisualTestScenario(page, sceneName) {
1776
2000
  createBinaryWriterMock,
1777
2001
  createControlledTimer,
1778
2002
  createCustomNetworkCondition,
2003
+ createDeltaSnapshot,
1779
2004
  createEntity,
1780
2005
  createEntityStateFactory,
1781
2006
  createGameStateSnapshotFactory,
1782
2007
  createMockAudioContext,
1783
2008
  createMockCanvas,
1784
2009
  createMockCanvasContext2D,
2010
+ createMockConnection,
1785
2011
  createMockEngine,
1786
2012
  createMockGame,
1787
2013
  createMockGameState,
2014
+ createMockHandshake,
1788
2015
  createMockImage,
1789
2016
  createMockImageData,
1790
2017
  createMockIndexedDB,
@@ -1799,10 +2026,13 @@ function createVisualTestScenario(page, sceneName) {
1799
2026
  createMockSessionStorage,
1800
2027
  createMockTransport,
1801
2028
  createMockUDPSocket,
2029
+ createMockUserInfo,
1802
2030
  createMockWebGL2Context,
2031
+ createMultiplayerTestScenario,
1803
2032
  createNetChanMock,
1804
2033
  createPlayerStateFactory,
1805
2034
  createPlaywrightTestClient,
2035
+ createServerSnapshot,
1806
2036
  createSpawnContext,
1807
2037
  createStorageTestScenario,
1808
2038
  createTestContext,
@@ -1816,16 +2046,24 @@ function createVisualTestScenario(page, sceneName) {
1816
2046
  makeLeafModel,
1817
2047
  makeNode,
1818
2048
  makePlane,
2049
+ serializeUserInfo,
1819
2050
  setupBrowserEnvironment,
1820
2051
  setupMockAudioContext,
1821
2052
  setupNodeEnvironment,
1822
2053
  simulateFrames,
1823
2054
  simulateFramesWithMock,
2055
+ simulateHandshake,
1824
2056
  simulateNetworkCondition,
2057
+ simulatePlayerInput,
2058
+ simulatePlayerJoin,
2059
+ simulatePlayerLeave,
2060
+ simulateServerTick,
2061
+ simulateSnapshotDelivery,
1825
2062
  stairTrace,
1826
2063
  teardownBrowserEnvironment,
1827
2064
  teardownMockAudioContext,
1828
2065
  throttleBandwidth,
2066
+ verifySnapshotConsistency,
1829
2067
  waitForGameReady
1830
2068
  });
1831
2069
  //# sourceMappingURL=index.cjs.map