@smoregg/sdk 1.2.0 → 2.0.0
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.
- package/dist/cjs/config.cjs.map +1 -1
- package/dist/cjs/controller.cjs +215 -145
- package/dist/cjs/controller.cjs.map +1 -1
- package/dist/cjs/screen.cjs +220 -178
- package/dist/cjs/screen.cjs.map +1 -1
- package/dist/cjs/testing.cjs +160 -151
- package/dist/cjs/testing.cjs.map +1 -1
- package/dist/esm/config.js.map +1 -1
- package/dist/esm/controller.js +216 -146
- package/dist/esm/controller.js.map +1 -1
- package/dist/esm/screen.js +221 -179
- package/dist/esm/screen.js.map +1 -1
- package/dist/esm/testing.js +160 -151
- package/dist/esm/testing.js.map +1 -1
- package/dist/types/config.d.ts +1 -2
- package/dist/types/config.d.ts.map +1 -1
- package/dist/types/controller.d.ts +22 -43
- package/dist/types/controller.d.ts.map +1 -1
- package/dist/types/index.d.ts +14 -14
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/screen.d.ts +26 -37
- package/dist/types/screen.d.ts.map +1 -1
- package/dist/types/testing.d.ts +16 -0
- package/dist/types/testing.d.ts.map +1 -1
- package/dist/types/types.d.ts +244 -338
- package/dist/types/types.d.ts.map +1 -1
- package/dist/umd/smore-sdk.umd.js +595 -474
- package/dist/umd/smore-sdk.umd.js.map +1 -1
- package/dist/umd/smore-sdk.umd.min.js +1 -1
- package/dist/umd/smore-sdk.umd.min.js.map +1 -1
- package/package.json +1 -1
- package/dist/cjs/SmoreHost.cjs +0 -306
- package/dist/cjs/SmoreHost.cjs.map +0 -1
- package/dist/cjs/SmorePlayer.cjs +0 -229
- package/dist/cjs/SmorePlayer.cjs.map +0 -1
- package/dist/cjs/components/DirectionPad.cjs +0 -68
- package/dist/cjs/components/DirectionPad.cjs.map +0 -1
- package/dist/cjs/components/DirectionPad.module.css.cjs +0 -12
- package/dist/cjs/components/DirectionPad.module.css.cjs.map +0 -1
- package/dist/cjs/components/HoldButton.cjs +0 -57
- package/dist/cjs/components/HoldButton.cjs.map +0 -1
- package/dist/cjs/components/HoldButton.module.css.cjs +0 -12
- package/dist/cjs/components/HoldButton.module.css.cjs.map +0 -1
- package/dist/cjs/components/IframeGameBridge.cjs +0 -115
- package/dist/cjs/components/IframeGameBridge.cjs.map +0 -1
- package/dist/cjs/components/SwipeArea.cjs +0 -58
- package/dist/cjs/components/SwipeArea.cjs.map +0 -1
- package/dist/cjs/components/SwipeArea.module.css.cjs +0 -12
- package/dist/cjs/components/SwipeArea.module.css.cjs.map +0 -1
- package/dist/cjs/components/TapButton.cjs +0 -58
- package/dist/cjs/components/TapButton.cjs.map +0 -1
- package/dist/cjs/components/TapButton.module.css.cjs +0 -12
- package/dist/cjs/components/TapButton.module.css.cjs.map +0 -1
- package/dist/cjs/context/RoomProvider.cjs +0 -118
- package/dist/cjs/context/RoomProvider.cjs.map +0 -1
- package/dist/cjs/hooks/useExternalGames.cjs +0 -49
- package/dist/cjs/hooks/useExternalGames.cjs.map +0 -1
- package/dist/cjs/hooks/useGameHost.cjs +0 -206
- package/dist/cjs/hooks/useGameHost.cjs.map +0 -1
- package/dist/cjs/hooks/useGamePlayer.cjs +0 -134
- package/dist/cjs/hooks/useGamePlayer.cjs.map +0 -1
- package/dist/cjs/iframe/index.cjs +0 -260
- package/dist/cjs/iframe/index.cjs.map +0 -1
- package/dist/cjs/node_modules/.pnpm/style-inject@0.3.0/node_modules/style-inject/dist/style-inject.es.cjs +0 -33
- package/dist/cjs/node_modules/.pnpm/style-inject@0.3.0/node_modules/style-inject/dist/style-inject.es.cjs.map +0 -1
- package/dist/cjs/server/index.cjs +0 -45
- package/dist/cjs/server/index.cjs.map +0 -1
- package/dist/cjs/transport/DirectTransport.cjs +0 -23
- package/dist/cjs/transport/DirectTransport.cjs.map +0 -1
- package/dist/cjs/utils/connectionMonitor.cjs +0 -77
- package/dist/cjs/utils/connectionMonitor.cjs.map +0 -1
- package/dist/cjs/utils/preloadAssets.cjs +0 -66
- package/dist/cjs/utils/preloadAssets.cjs.map +0 -1
- package/dist/cjs/utils/serverTime.cjs +0 -43
- package/dist/cjs/utils/serverTime.cjs.map +0 -1
- package/dist/esm/SmoreHost.js +0 -304
- package/dist/esm/SmoreHost.js.map +0 -1
- package/dist/esm/SmorePlayer.js +0 -227
- package/dist/esm/SmorePlayer.js.map +0 -1
- package/dist/esm/components/DirectionPad.js +0 -66
- package/dist/esm/components/DirectionPad.js.map +0 -1
- package/dist/esm/components/DirectionPad.module.css.js +0 -8
- package/dist/esm/components/DirectionPad.module.css.js.map +0 -1
- package/dist/esm/components/HoldButton.js +0 -55
- package/dist/esm/components/HoldButton.js.map +0 -1
- package/dist/esm/components/HoldButton.module.css.js +0 -8
- package/dist/esm/components/HoldButton.module.css.js.map +0 -1
- package/dist/esm/components/IframeGameBridge.js +0 -113
- package/dist/esm/components/IframeGameBridge.js.map +0 -1
- package/dist/esm/components/SwipeArea.js +0 -56
- package/dist/esm/components/SwipeArea.js.map +0 -1
- package/dist/esm/components/SwipeArea.module.css.js +0 -8
- package/dist/esm/components/SwipeArea.module.css.js.map +0 -1
- package/dist/esm/components/TapButton.js +0 -56
- package/dist/esm/components/TapButton.js.map +0 -1
- package/dist/esm/components/TapButton.module.css.js +0 -8
- package/dist/esm/components/TapButton.module.css.js.map +0 -1
- package/dist/esm/context/RoomProvider.js +0 -109
- package/dist/esm/context/RoomProvider.js.map +0 -1
- package/dist/esm/hooks/useExternalGames.js +0 -47
- package/dist/esm/hooks/useExternalGames.js.map +0 -1
- package/dist/esm/hooks/useGameHost.js +0 -204
- package/dist/esm/hooks/useGameHost.js.map +0 -1
- package/dist/esm/hooks/useGamePlayer.js +0 -132
- package/dist/esm/hooks/useGamePlayer.js.map +0 -1
- package/dist/esm/iframe/index.js +0 -257
- package/dist/esm/iframe/index.js.map +0 -1
- package/dist/esm/node_modules/.pnpm/style-inject@0.3.0/node_modules/style-inject/dist/style-inject.es.js +0 -29
- package/dist/esm/node_modules/.pnpm/style-inject@0.3.0/node_modules/style-inject/dist/style-inject.es.js.map +0 -1
- package/dist/esm/server/index.js +0 -43
- package/dist/esm/server/index.js.map +0 -1
- package/dist/esm/transport/DirectTransport.js +0 -21
- package/dist/esm/transport/DirectTransport.js.map +0 -1
- package/dist/esm/utils/connectionMonitor.js +0 -75
- package/dist/esm/utils/connectionMonitor.js.map +0 -1
- package/dist/esm/utils/preloadAssets.js +0 -63
- package/dist/esm/utils/preloadAssets.js.map +0 -1
- package/dist/esm/utils/serverTime.js +0 -41
- package/dist/esm/utils/serverTime.js.map +0 -1
- package/dist/types/SmoreHost.d.ts +0 -187
- package/dist/types/SmoreHost.d.ts.map +0 -1
- package/dist/types/SmorePlayer.d.ts +0 -146
- package/dist/types/SmorePlayer.d.ts.map +0 -1
- package/dist/types/components/DirectionPad.d.ts +0 -21
- package/dist/types/components/DirectionPad.d.ts.map +0 -1
- package/dist/types/components/HoldButton.d.ts +0 -22
- package/dist/types/components/HoldButton.d.ts.map +0 -1
- package/dist/types/components/IframeGameBridge.d.ts +0 -38
- package/dist/types/components/IframeGameBridge.d.ts.map +0 -1
- package/dist/types/components/SwipeArea.d.ts +0 -19
- package/dist/types/components/SwipeArea.d.ts.map +0 -1
- package/dist/types/components/TapButton.d.ts +0 -19
- package/dist/types/components/TapButton.d.ts.map +0 -1
- package/dist/types/components/index.d.ts +0 -6
- package/dist/types/components/index.d.ts.map +0 -1
- package/dist/types/context/RoomProvider.d.ts +0 -69
- package/dist/types/context/RoomProvider.d.ts.map +0 -1
- package/dist/types/context/index.d.ts +0 -3
- package/dist/types/context/index.d.ts.map +0 -1
- package/dist/types/dev/DevSimulator.d.ts +0 -31
- package/dist/types/dev/DevSimulator.d.ts.map +0 -1
- package/dist/types/dev/index.d.ts +0 -2
- package/dist/types/dev/index.d.ts.map +0 -1
- package/dist/types/hooks/index.d.ts +0 -7
- package/dist/types/hooks/index.d.ts.map +0 -1
- package/dist/types/hooks/useExternalGames.d.ts +0 -32
- package/dist/types/hooks/useExternalGames.d.ts.map +0 -1
- package/dist/types/hooks/useGameHost.d.ts +0 -67
- package/dist/types/hooks/useGameHost.d.ts.map +0 -1
- package/dist/types/hooks/useGamePlayer.d.ts +0 -55
- package/dist/types/hooks/useGamePlayer.d.ts.map +0 -1
- package/dist/types/iframe/IframeRoomProvider.d.ts +0 -31
- package/dist/types/iframe/IframeRoomProvider.d.ts.map +0 -1
- package/dist/types/iframe/index.d.ts +0 -18
- package/dist/types/iframe/index.d.ts.map +0 -1
- package/dist/types/iframe/vanilla-entry.d.ts +0 -7
- package/dist/types/iframe/vanilla-entry.d.ts.map +0 -1
- package/dist/types/iframe/vanilla.d.ts +0 -49
- package/dist/types/iframe/vanilla.d.ts.map +0 -1
- package/dist/types/server/createGameRelay.d.ts +0 -26
- package/dist/types/server/createGameRelay.d.ts.map +0 -1
- package/dist/types/server/index.d.ts +0 -3
- package/dist/types/server/index.d.ts.map +0 -1
- package/dist/types/utils/connectionMonitor.d.ts +0 -57
- package/dist/types/utils/connectionMonitor.d.ts.map +0 -1
- package/dist/types/utils/index.d.ts +0 -7
- package/dist/types/utils/index.d.ts.map +0 -1
- package/dist/types/utils/preloadAssets.d.ts +0 -29
- package/dist/types/utils/preloadAssets.d.ts.map +0 -1
- package/dist/types/utils/serverTime.d.ts +0 -28
- package/dist/types/utils/serverTime.d.ts.map +0 -1
- package/dist/umd/smore-sdk-iframe.umd.js +0 -266
- package/dist/umd/smore-sdk-iframe.umd.js.map +0 -1
- package/dist/umd/smore-sdk-iframe.umd.min.js +0 -2
- package/dist/umd/smore-sdk-iframe.umd.min.js.map +0 -1
- package/dist/umd/smore-sdk-vanilla.umd.js +0 -1275
- package/dist/umd/smore-sdk-vanilla.umd.js.map +0 -1
- package/dist/umd/smore-sdk-vanilla.umd.min.js +0 -2
- package/dist/umd/smore-sdk-vanilla.umd.min.js.map +0 -1
|
@@ -1,260 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
const SMORE_MSG_PREFIX = "smore:";
|
|
4
|
-
function isSmoreMessage(data) {
|
|
5
|
-
return data && typeof data === "object" && typeof data.type === "string" && data.type.startsWith(SMORE_MSG_PREFIX);
|
|
6
|
-
}
|
|
7
|
-
|
|
8
|
-
class PostMessageTransport {
|
|
9
|
-
handlers = /* @__PURE__ */ new Map();
|
|
10
|
-
ackCallbacks = /* @__PURE__ */ new Map();
|
|
11
|
-
ackCounter = 0;
|
|
12
|
-
parentOrigin;
|
|
13
|
-
boundMessageHandler;
|
|
14
|
-
constructor(parentOrigin = "*") {
|
|
15
|
-
this.parentOrigin = parentOrigin;
|
|
16
|
-
this.boundMessageHandler = this.handleMessage.bind(this);
|
|
17
|
-
window.addEventListener("message", this.boundMessageHandler);
|
|
18
|
-
}
|
|
19
|
-
emit(event, ...args) {
|
|
20
|
-
let data = args[0];
|
|
21
|
-
let ackId;
|
|
22
|
-
if (args.length >= 2 && typeof args[args.length - 1] === "function") {
|
|
23
|
-
data = args.length === 2 ? args[0] : args[0];
|
|
24
|
-
const callback = args[args.length - 1];
|
|
25
|
-
ackId = `ack_${++this.ackCounter}`;
|
|
26
|
-
this.ackCallbacks.set(ackId, callback);
|
|
27
|
-
}
|
|
28
|
-
window.parent.postMessage(
|
|
29
|
-
{ type: "smore:emit", payload: { event, data, ackId } },
|
|
30
|
-
this.parentOrigin
|
|
31
|
-
);
|
|
32
|
-
}
|
|
33
|
-
on(event, handler) {
|
|
34
|
-
let set = this.handlers.get(event);
|
|
35
|
-
if (!set) {
|
|
36
|
-
set = /* @__PURE__ */ new Set();
|
|
37
|
-
this.handlers.set(event, set);
|
|
38
|
-
}
|
|
39
|
-
set.add(handler);
|
|
40
|
-
}
|
|
41
|
-
off(event, handler) {
|
|
42
|
-
if (!handler) {
|
|
43
|
-
this.handlers.delete(event);
|
|
44
|
-
return;
|
|
45
|
-
}
|
|
46
|
-
this.handlers.get(event)?.delete(handler);
|
|
47
|
-
}
|
|
48
|
-
destroy() {
|
|
49
|
-
window.removeEventListener("message", this.boundMessageHandler);
|
|
50
|
-
this.handlers.clear();
|
|
51
|
-
this.ackCallbacks.clear();
|
|
52
|
-
}
|
|
53
|
-
handleMessage(e) {
|
|
54
|
-
if (this.parentOrigin !== "*" && e.origin !== this.parentOrigin) return;
|
|
55
|
-
const msg = e.data;
|
|
56
|
-
if (!isSmoreMessage(msg)) return;
|
|
57
|
-
if (msg.type === "smore:event") {
|
|
58
|
-
const { event, data } = msg.payload;
|
|
59
|
-
const set = this.handlers.get(event);
|
|
60
|
-
if (set) {
|
|
61
|
-
set.forEach((handler) => handler(data));
|
|
62
|
-
}
|
|
63
|
-
} else if (msg.type === "smore:ack") {
|
|
64
|
-
const { ackId, data } = msg.payload;
|
|
65
|
-
const cb = this.ackCallbacks.get(ackId);
|
|
66
|
-
if (cb) {
|
|
67
|
-
this.ackCallbacks.delete(ackId);
|
|
68
|
-
cb(data);
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
const EVENT_NAME_REGEX = /^[a-zA-Z]([a-zA-Z_-]*[a-zA-Z])?$/;
|
|
75
|
-
function validateEventName(event) {
|
|
76
|
-
if (!EVENT_NAME_REGEX.test(event)) {
|
|
77
|
-
console.error(
|
|
78
|
-
`[SDK] Invalid event name "${event}". Event names must:
|
|
79
|
-
- Only contain letters (a-z, A-Z), hyphens (-), and underscores (_)
|
|
80
|
-
- Start and end with a letter (no leading/trailing - or _)`
|
|
81
|
-
);
|
|
82
|
-
return false;
|
|
83
|
-
}
|
|
84
|
-
return true;
|
|
85
|
-
}
|
|
86
|
-
function createHostBridge(options) {
|
|
87
|
-
const { parentOrigin = "*", gameId, listeners, onPlayerJoin, onPlayerLeave, onReady, onCustomStateChange } = options;
|
|
88
|
-
let transport = null;
|
|
89
|
-
window.parent.postMessage({ type: "smore:ready" }, parentOrigin);
|
|
90
|
-
const messageHandler = (e) => {
|
|
91
|
-
if (parentOrigin !== "*" && e.origin !== parentOrigin) return;
|
|
92
|
-
const msg = e.data;
|
|
93
|
-
if (!isSmoreMessage(msg)) return;
|
|
94
|
-
if (msg.type === "smore:init") {
|
|
95
|
-
const { side, roomCode, players, leaderId } = msg.payload;
|
|
96
|
-
if (side !== "host") {
|
|
97
|
-
console.error("[HostBridge] Received init for wrong side:", side);
|
|
98
|
-
return;
|
|
99
|
-
}
|
|
100
|
-
transport = new PostMessageTransport(parentOrigin);
|
|
101
|
-
if (listeners) {
|
|
102
|
-
Object.keys(listeners).forEach((event) => {
|
|
103
|
-
validateEventName(event);
|
|
104
|
-
const handler = listeners[event];
|
|
105
|
-
transport.on(event, handler);
|
|
106
|
-
});
|
|
107
|
-
}
|
|
108
|
-
if (onPlayerJoin) {
|
|
109
|
-
transport.on("player:joined", (payload) => {
|
|
110
|
-
const playerIndex = payload.player?.playerIndex ?? payload.playerIndex;
|
|
111
|
-
if (playerIndex !== void 0) {
|
|
112
|
-
onPlayerJoin(playerIndex);
|
|
113
|
-
}
|
|
114
|
-
});
|
|
115
|
-
}
|
|
116
|
-
if (onPlayerLeave) {
|
|
117
|
-
transport.on("player:left", (payload) => {
|
|
118
|
-
const playerIndex = payload.player?.playerIndex ?? payload.playerIndex;
|
|
119
|
-
if (playerIndex !== void 0) {
|
|
120
|
-
onPlayerLeave(playerIndex);
|
|
121
|
-
}
|
|
122
|
-
});
|
|
123
|
-
}
|
|
124
|
-
if (onCustomStateChange) {
|
|
125
|
-
transport.on("smore:custom-state-change", (data) => {
|
|
126
|
-
if (data.playerIndex !== void 0) {
|
|
127
|
-
onCustomStateChange(data.playerIndex, data.state);
|
|
128
|
-
}
|
|
129
|
-
});
|
|
130
|
-
}
|
|
131
|
-
if (onReady) {
|
|
132
|
-
onReady({ roomCode, players, leaderId });
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
};
|
|
136
|
-
window.addEventListener("message", messageHandler);
|
|
137
|
-
return {
|
|
138
|
-
broadcast: (event, data) => {
|
|
139
|
-
if (!transport) {
|
|
140
|
-
console.warn("[HostBridge] Cannot broadcast before init");
|
|
141
|
-
return;
|
|
142
|
-
}
|
|
143
|
-
validateEventName(event);
|
|
144
|
-
transport.emit(event, data);
|
|
145
|
-
},
|
|
146
|
-
sendToPlayer: (playerIndex, event, data) => {
|
|
147
|
-
if (!transport) {
|
|
148
|
-
console.warn("[HostBridge] Cannot sendToPlayer before init");
|
|
149
|
-
return;
|
|
150
|
-
}
|
|
151
|
-
transport.emit(event, { targetPlayerIndex: playerIndex, ...data });
|
|
152
|
-
},
|
|
153
|
-
emitGameOver: (results) => {
|
|
154
|
-
if (!transport) {
|
|
155
|
-
console.warn("[HostBridge] Cannot emitGameOver before init");
|
|
156
|
-
return;
|
|
157
|
-
}
|
|
158
|
-
transport.emit("game-over", results);
|
|
159
|
-
},
|
|
160
|
-
setLoaded: () => {
|
|
161
|
-
window.parent.postMessage({ type: "smore:loaded" }, parentOrigin);
|
|
162
|
-
},
|
|
163
|
-
setCustomState: (state) => {
|
|
164
|
-
if (!transport) {
|
|
165
|
-
console.warn("[HostBridge] Cannot setCustomState before init");
|
|
166
|
-
return;
|
|
167
|
-
}
|
|
168
|
-
window.parent.postMessage(
|
|
169
|
-
{ type: "smore:emit", payload: { event: "smore:custom-state-change", data: { state } } },
|
|
170
|
-
parentOrigin
|
|
171
|
-
);
|
|
172
|
-
},
|
|
173
|
-
destroy: () => {
|
|
174
|
-
window.removeEventListener("message", messageHandler);
|
|
175
|
-
transport?.destroy();
|
|
176
|
-
transport = null;
|
|
177
|
-
}
|
|
178
|
-
};
|
|
179
|
-
}
|
|
180
|
-
function createPlayerBridge(options) {
|
|
181
|
-
const { parentOrigin = "*", gameId, listeners, onReady, onCustomStateChange } = options;
|
|
182
|
-
let transport = null;
|
|
183
|
-
window.parent.postMessage({ type: "smore:ready" }, parentOrigin);
|
|
184
|
-
const messageHandler = (e) => {
|
|
185
|
-
if (parentOrigin !== "*" && e.origin !== parentOrigin) return;
|
|
186
|
-
const msg = e.data;
|
|
187
|
-
if (!isSmoreMessage(msg)) return;
|
|
188
|
-
if (msg.type === "smore:init") {
|
|
189
|
-
const { side, roomCode, myIndex, isLeader } = msg.payload;
|
|
190
|
-
if (side !== "player") {
|
|
191
|
-
console.error("[PlayerBridge] Received init for wrong side:", side);
|
|
192
|
-
return;
|
|
193
|
-
}
|
|
194
|
-
if (myIndex === void 0) {
|
|
195
|
-
console.error("[PlayerBridge] Missing myIndex in init payload");
|
|
196
|
-
return;
|
|
197
|
-
}
|
|
198
|
-
transport = new PostMessageTransport(parentOrigin);
|
|
199
|
-
if (listeners) {
|
|
200
|
-
Object.keys(listeners).forEach((event) => {
|
|
201
|
-
validateEventName(event);
|
|
202
|
-
const handler = listeners[event];
|
|
203
|
-
transport.on(event, handler);
|
|
204
|
-
});
|
|
205
|
-
}
|
|
206
|
-
if (onCustomStateChange) {
|
|
207
|
-
transport.on("smore:custom-state-change", (data) => {
|
|
208
|
-
if (data.playerIndex !== void 0) {
|
|
209
|
-
onCustomStateChange(data.playerIndex, data.state);
|
|
210
|
-
}
|
|
211
|
-
});
|
|
212
|
-
}
|
|
213
|
-
if (onReady) {
|
|
214
|
-
onReady({ roomCode, isLeader: !!isLeader, myIndex });
|
|
215
|
-
}
|
|
216
|
-
}
|
|
217
|
-
};
|
|
218
|
-
window.addEventListener("message", messageHandler);
|
|
219
|
-
return {
|
|
220
|
-
emit: (event, data) => {
|
|
221
|
-
if (!transport) {
|
|
222
|
-
console.warn("[PlayerBridge] Cannot emit before init");
|
|
223
|
-
return;
|
|
224
|
-
}
|
|
225
|
-
validateEventName(event);
|
|
226
|
-
transport.emit(event, data);
|
|
227
|
-
},
|
|
228
|
-
onEvent: (event, handler) => {
|
|
229
|
-
if (!transport) {
|
|
230
|
-
console.warn("[PlayerBridge] Cannot onEvent before init");
|
|
231
|
-
return () => {
|
|
232
|
-
};
|
|
233
|
-
}
|
|
234
|
-
validateEventName(event);
|
|
235
|
-
transport.on(event, handler);
|
|
236
|
-
return () => {
|
|
237
|
-
transport?.off(event, handler);
|
|
238
|
-
};
|
|
239
|
-
},
|
|
240
|
-
setCustomState: (state) => {
|
|
241
|
-
if (!transport) {
|
|
242
|
-
console.warn("[PlayerBridge] Cannot setCustomState before init");
|
|
243
|
-
return;
|
|
244
|
-
}
|
|
245
|
-
window.parent.postMessage(
|
|
246
|
-
{ type: "smore:emit", payload: { event: "smore:custom-state-change", data: { state } } },
|
|
247
|
-
parentOrigin
|
|
248
|
-
);
|
|
249
|
-
},
|
|
250
|
-
destroy: () => {
|
|
251
|
-
window.removeEventListener("message", messageHandler);
|
|
252
|
-
transport?.destroy();
|
|
253
|
-
transport = null;
|
|
254
|
-
}
|
|
255
|
-
};
|
|
256
|
-
}
|
|
257
|
-
|
|
258
|
-
exports.createHostBridge = createHostBridge;
|
|
259
|
-
exports.createPlayerBridge = createPlayerBridge;
|
|
260
|
-
//# sourceMappingURL=index.cjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs","sources":["../../../src/transport/protocol.ts","../../../src/transport/PostMessageTransport.ts","../../../src/iframe/vanilla.ts"],"sourcesContent":["/**\n * postMessage protocol types for iframe ↔ parent communication.\n */\n\nexport const SMORE_MSG_PREFIX = 'smore:' as const;\n\nexport interface SmoreReadyMessage {\n type: 'smore:ready';\n}\n\nexport interface SmoreInitMessage {\n type: 'smore:init';\n payload: {\n side: 'host' | 'player';\n roomCode: string;\n players: any[];\n leaderId: string | null;\n myIndex?: number;\n isLeader?: boolean;\n };\n}\n\nexport interface SmoreEmitMessage {\n type: 'smore:emit';\n payload: {\n event: string;\n data?: any;\n ackId?: string;\n };\n}\n\nexport interface SmoreEventMessage {\n type: 'smore:event';\n payload: {\n event: string;\n data?: any;\n };\n}\n\nexport interface SmoreAckMessage {\n type: 'smore:ack';\n payload: {\n ackId: string;\n data?: any;\n };\n}\n\nexport interface SmoreUpdateMessage {\n type: 'smore:update';\n payload: {\n players?: any[];\n leaderId?: string | null;\n };\n}\n\nexport interface SmoreLoadedMessage {\n type: 'smore:loaded';\n}\n\nexport type SmoreMessage =\n | SmoreReadyMessage\n | SmoreInitMessage\n | SmoreEmitMessage\n | SmoreEventMessage\n | SmoreAckMessage\n | SmoreUpdateMessage\n | SmoreLoadedMessage;\n\nexport function isSmoreMessage(data: any): data is SmoreMessage {\n return data && typeof data === 'object' && typeof data.type === 'string' && data.type.startsWith(SMORE_MSG_PREFIX);\n}\n","/**\n * PostMessageTransport - Transport over window.postMessage for iframe-hosted games.\n *\n * Used inside an iframe. Sends `smore:emit` to parent and listens for `smore:event` from parent.\n */\n\nimport type { Transport, TransportEventHandler } from './types';\nimport type { SmoreEventMessage, SmoreAckMessage } from './protocol';\nimport { isSmoreMessage } from './protocol';\n\nexport class PostMessageTransport implements Transport {\n private handlers = new Map<string, Set<TransportEventHandler>>();\n private ackCallbacks = new Map<string, (...args: any[]) => void>();\n private ackCounter = 0;\n private parentOrigin: string;\n private boundMessageHandler: (e: MessageEvent) => void;\n\n constructor(parentOrigin: string = '*') {\n this.parentOrigin = parentOrigin;\n this.boundMessageHandler = this.handleMessage.bind(this);\n window.addEventListener('message', this.boundMessageHandler);\n }\n\n emit(event: string, ...args: any[]): void {\n // Detect if last arg is a callback (ack pattern)\n let data: any = args[0];\n let ackId: string | undefined;\n\n if (args.length >= 2 && typeof args[args.length - 1] === 'function') {\n data = args.length === 2 ? args[0] : args[0];\n const callback = args[args.length - 1];\n ackId = `ack_${++this.ackCounter}`;\n this.ackCallbacks.set(ackId, callback);\n }\n\n window.parent.postMessage(\n { type: 'smore:emit', payload: { event, data, ackId } },\n this.parentOrigin,\n );\n }\n\n on(event: string, handler: TransportEventHandler): void {\n let set = this.handlers.get(event);\n if (!set) {\n set = new Set();\n this.handlers.set(event, set);\n }\n set.add(handler);\n }\n\n off(event: string, handler?: TransportEventHandler): void {\n if (!handler) {\n this.handlers.delete(event);\n return;\n }\n this.handlers.get(event)?.delete(handler);\n }\n\n destroy(): void {\n window.removeEventListener('message', this.boundMessageHandler);\n this.handlers.clear();\n this.ackCallbacks.clear();\n }\n\n private handleMessage(e: MessageEvent): void {\n // Origin validation: only accept messages from the expected parent\n if (this.parentOrigin !== '*' && e.origin !== this.parentOrigin) return;\n\n const msg = e.data;\n if (!isSmoreMessage(msg)) return;\n\n if (msg.type === 'smore:event') {\n const { event, data } = (msg as SmoreEventMessage).payload;\n const set = this.handlers.get(event);\n if (set) {\n set.forEach((handler) => handler(data));\n }\n } else if (msg.type === 'smore:ack') {\n const { ackId, data } = (msg as SmoreAckMessage).payload;\n const cb = this.ackCallbacks.get(ackId);\n if (cb) {\n this.ackCallbacks.delete(ackId);\n cb(data);\n }\n }\n }\n}\n","/**\n * Vanilla JS bridge API for iframe-hosted games.\n * No React - pure JavaScript with PostMessage transport.\n */\n\nimport { PostMessageTransport } from '../transport/PostMessageTransport';\nimport { isSmoreMessage, type SmoreInitMessage } from '../transport/protocol';\n\n/**\n * Validates event name format.\n * Rules:\n * - Only English letters (a-z, A-Z), hyphens (-), and underscores (_) allowed\n * - Must start and end with a letter (no leading/trailing - or _)\n * - Colons are reserved for system prefix\n */\nconst EVENT_NAME_REGEX = /^[a-zA-Z]([a-zA-Z_-]*[a-zA-Z])?$/;\n\nfunction validateEventName(event: string): boolean {\n if (!EVENT_NAME_REGEX.test(event)) {\n console.error(\n `[SDK] Invalid event name \"${event}\". Event names must:\\n` +\n ` - Only contain letters (a-z, A-Z), hyphens (-), and underscores (_)\\n` +\n ` - Start and end with a letter (no leading/trailing - or _)`\n );\n return false;\n }\n return true;\n}\n\nexport interface HostBridgeOptions {\n parentOrigin?: string;\n gameId: string;\n listeners?: Record<string, (data: any) => void>;\n onPlayerJoin?: (playerIndex: number) => void;\n onPlayerLeave?: (playerIndex: number) => void;\n onReady?: (room: { roomCode: string; players: any[]; leaderId: string | null }) => void;\n /** Called when any device's custom state changes (AirConsole pattern) */\n onCustomStateChange?: (playerIndex: number, state: Record<string, any>) => void;\n}\n\nexport interface HostBridge {\n broadcast: (event: string, data?: any) => void;\n sendToPlayer: (playerIndex: number, event: string, data?: any) => void;\n emitGameOver: (results: any) => void;\n setLoaded: () => void;\n /** Set custom device state (AirConsole pattern) - merges with existing state */\n setCustomState: (state: Record<string, any>) => void;\n destroy: () => void;\n}\n\nexport interface PlayerBridgeOptions {\n parentOrigin?: string;\n gameId: string;\n listeners?: Record<string, (data: any) => void>;\n onReady?: (room: { roomCode: string; isLeader: boolean; myIndex: number }) => void;\n /** Called when any device's custom state changes (AirConsole pattern) */\n onCustomStateChange?: (playerIndex: number, state: Record<string, any>) => void;\n}\n\nexport interface PlayerBridge {\n emit: (event: string, data?: any) => void;\n onEvent: (event: string, handler: (data: any) => void) => () => void;\n /** Set custom device state (AirConsole pattern) - merges with existing state */\n setCustomState: (state: Record<string, any>) => void;\n destroy: () => void;\n}\n\nexport function createHostBridge(options: HostBridgeOptions): HostBridge {\n const { parentOrigin = '*', gameId, listeners, onPlayerJoin, onPlayerLeave, onReady, onCustomStateChange } = options;\n\n let transport: PostMessageTransport | null = null;\n let isInitialized = false;\n\n // Immediately signal ready to parent\n window.parent.postMessage({ type: 'smore:ready' }, parentOrigin);\n\n const messageHandler = (e: MessageEvent) => {\n if (parentOrigin !== '*' && e.origin !== parentOrigin) return;\n const msg = e.data;\n if (!isSmoreMessage(msg)) return;\n\n if (msg.type === 'smore:init') {\n const { side, roomCode, players, leaderId } = (msg as SmoreInitMessage).payload;\n\n if (side !== 'host') {\n console.error('[HostBridge] Received init for wrong side:', side);\n return;\n }\n\n // Create transport and wire up event handlers\n transport = new PostMessageTransport(parentOrigin);\n\n // Handle input events\n if (listeners) {\n Object.keys(listeners).forEach((event) => {\n validateEventName(event);\n const handler = listeners[event];\n transport!.on(event, handler);\n });\n }\n\n // Handle player join/leave events\n if (onPlayerJoin) {\n transport.on('player:joined', (payload: any) => {\n const playerIndex = payload.player?.playerIndex ?? payload.playerIndex;\n if (playerIndex !== undefined) {\n onPlayerJoin(playerIndex);\n }\n });\n }\n if (onPlayerLeave) {\n transport.on('player:left', (payload: any) => {\n const playerIndex = payload.player?.playerIndex ?? payload.playerIndex;\n if (playerIndex !== undefined) {\n onPlayerLeave(playerIndex);\n }\n });\n }\n\n // Handle custom device state changes (AirConsole pattern)\n if (onCustomStateChange) {\n transport.on('smore:custom-state-change', (data: { playerIndex?: number; state: Record<string, any> }) => {\n if (data.playerIndex !== undefined) {\n onCustomStateChange(data.playerIndex, data.state);\n }\n });\n }\n\n isInitialized = true;\n\n // Call onReady callback\n if (onReady) {\n onReady({ roomCode, players, leaderId });\n }\n }\n };\n\n window.addEventListener('message', messageHandler);\n\n return {\n broadcast: (event: string, data?: any) => {\n if (!transport) {\n console.warn('[HostBridge] Cannot broadcast before init');\n return;\n }\n validateEventName(event);\n transport.emit(event, data);\n },\n\n sendToPlayer: (playerIndex: number, event: string, data?: any) => {\n if (!transport) {\n console.warn('[HostBridge] Cannot sendToPlayer before init');\n return;\n }\n transport.emit(event, { targetPlayerIndex: playerIndex, ...data });\n },\n\n emitGameOver: (results: any) => {\n if (!transport) {\n console.warn('[HostBridge] Cannot emitGameOver before init');\n return;\n }\n transport.emit('game-over', results);\n },\n\n setLoaded: () => {\n window.parent.postMessage({ type: 'smore:loaded' }, parentOrigin);\n },\n\n setCustomState: (state: Record<string, any>) => {\n if (!transport) {\n console.warn('[HostBridge] Cannot setCustomState before init');\n return;\n }\n window.parent.postMessage(\n { type: 'smore:emit', payload: { event: 'smore:custom-state-change', data: { state } } },\n parentOrigin\n );\n },\n\n destroy: () => {\n window.removeEventListener('message', messageHandler);\n transport?.destroy();\n transport = null;\n isInitialized = false;\n },\n };\n}\n\nexport function createPlayerBridge(options: PlayerBridgeOptions): PlayerBridge {\n const { parentOrigin = '*', gameId, listeners, onReady, onCustomStateChange } = options;\n\n let transport: PostMessageTransport | null = null;\n let isInitialized = false;\n\n // Immediately signal ready to parent\n window.parent.postMessage({ type: 'smore:ready' }, parentOrigin);\n\n const messageHandler = (e: MessageEvent) => {\n if (parentOrigin !== '*' && e.origin !== parentOrigin) return;\n const msg = e.data;\n if (!isSmoreMessage(msg)) return;\n\n if (msg.type === 'smore:init') {\n const { side, roomCode, myIndex, isLeader } = (msg as SmoreInitMessage).payload;\n\n if (side !== 'player') {\n console.error('[PlayerBridge] Received init for wrong side:', side);\n return;\n }\n\n if (myIndex === undefined) {\n console.error('[PlayerBridge] Missing myIndex in init payload');\n return;\n }\n\n // Create transport and wire up listeners\n transport = new PostMessageTransport(parentOrigin);\n\n // Wire up game-specific event listeners\n if (listeners) {\n Object.keys(listeners).forEach((event) => {\n validateEventName(event);\n const handler = listeners[event];\n transport!.on(event, handler);\n });\n }\n\n // Handle custom device state changes (AirConsole pattern)\n if (onCustomStateChange) {\n transport!.on('smore:custom-state-change', (data: { playerIndex?: number; state: Record<string, any> }) => {\n if (data.playerIndex !== undefined) {\n onCustomStateChange(data.playerIndex, data.state);\n }\n });\n }\n\n isInitialized = true;\n\n // Call onReady callback\n if (onReady) {\n onReady({ roomCode, isLeader: !!isLeader, myIndex });\n }\n }\n };\n\n window.addEventListener('message', messageHandler);\n\n return {\n emit: (event: string, data?: any) => {\n if (!transport) {\n console.warn('[PlayerBridge] Cannot emit before init');\n return;\n }\n validateEventName(event);\n transport.emit(event, data);\n },\n\n onEvent: (event: string, handler: (data: any) => void) => {\n if (!transport) {\n console.warn('[PlayerBridge] Cannot onEvent before init');\n return () => {};\n }\n validateEventName(event);\n transport.on(event, handler);\n return () => {\n transport?.off(event, handler);\n };\n },\n\n setCustomState: (state: Record<string, any>) => {\n if (!transport) {\n console.warn('[PlayerBridge] Cannot setCustomState before init');\n return;\n }\n window.parent.postMessage(\n { type: 'smore:emit', payload: { event: 'smore:custom-state-change', data: { state } } },\n parentOrigin\n );\n },\n\n destroy: () => {\n window.removeEventListener('message', messageHandler);\n transport?.destroy();\n transport = null;\n isInitialized = false;\n },\n };\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
|
-
|
|
5
|
-
function styleInject(css, ref) {
|
|
6
|
-
if ( ref === void 0 ) ref = {};
|
|
7
|
-
var insertAt = ref.insertAt;
|
|
8
|
-
|
|
9
|
-
if (!css || typeof document === 'undefined') { return; }
|
|
10
|
-
|
|
11
|
-
var head = document.head || document.getElementsByTagName('head')[0];
|
|
12
|
-
var style = document.createElement('style');
|
|
13
|
-
style.type = 'text/css';
|
|
14
|
-
|
|
15
|
-
if (insertAt === 'top') {
|
|
16
|
-
if (head.firstChild) {
|
|
17
|
-
head.insertBefore(style, head.firstChild);
|
|
18
|
-
} else {
|
|
19
|
-
head.appendChild(style);
|
|
20
|
-
}
|
|
21
|
-
} else {
|
|
22
|
-
head.appendChild(style);
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
if (style.styleSheet) {
|
|
26
|
-
style.styleSheet.cssText = css;
|
|
27
|
-
} else {
|
|
28
|
-
style.appendChild(document.createTextNode(css));
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
exports.default = styleInject;
|
|
33
|
-
//# sourceMappingURL=style-inject.es.cjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"style-inject.es.cjs","sources":["../../../../../../../../../../node_modules/.pnpm/style-inject@0.3.0/node_modules/style-inject/dist/style-inject.es.js"],"sourcesContent":["function styleInject(css, ref) {\n if ( ref === void 0 ) ref = {};\n var insertAt = ref.insertAt;\n\n if (!css || typeof document === 'undefined') { return; }\n\n var head = document.head || document.getElementsByTagName('head')[0];\n var style = document.createElement('style');\n style.type = 'text/css';\n\n if (insertAt === 'top') {\n if (head.firstChild) {\n head.insertBefore(style, head.firstChild);\n } else {\n head.appendChild(style);\n }\n } else {\n head.appendChild(style);\n }\n\n if (style.styleSheet) {\n style.styleSheet.cssText = css;\n } else {\n style.appendChild(document.createTextNode(css));\n }\n}\n\nexport default styleInject;\n"],"names":[],"mappings":";;;;AAAA,SAAS,WAAW,CAAC,GAAG,EAAE,GAAG,EAAE;AAC/B,EAAE,KAAK,GAAG,KAAK,MAAM,GAAG,GAAG,GAAG,EAAE;AAChC,EAAE,IAAI,QAAQ,GAAG,GAAG,CAAC,QAAQ;;AAE7B,EAAE,IAAI,CAAC,GAAG,IAAI,OAAO,QAAQ,KAAK,WAAW,EAAE,EAAE,OAAO,CAAC;;AAEzD,EAAE,IAAI,IAAI,GAAG,QAAQ,CAAC,IAAI,IAAI,QAAQ,CAAC,oBAAoB,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;AACtE,EAAE,IAAI,KAAK,GAAG,QAAQ,CAAC,aAAa,CAAC,OAAO,CAAC;AAC7C,EAAE,KAAK,CAAC,IAAI,GAAG,UAAU;;AAEzB,EAAE,IAAI,QAAQ,KAAK,KAAK,EAAE;AAC1B,IAAI,IAAI,IAAI,CAAC,UAAU,EAAE;AACzB,MAAM,IAAI,CAAC,YAAY,CAAC,KAAK,EAAE,IAAI,CAAC,UAAU,CAAC;AAC/C,IAAI,CAAC,MAAM;AACX,MAAM,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC;AAC7B,IAAI;AACJ,EAAE,CAAC,MAAM;AACT,IAAI,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC;AAC3B,EAAE;;AAEF,EAAE,IAAI,KAAK,CAAC,UAAU,EAAE;AACxB,IAAI,KAAK,CAAC,UAAU,CAAC,OAAO,GAAG,GAAG;AAClC,EAAE,CAAC,MAAM;AACT,IAAI,KAAK,CAAC,WAAW,CAAC,QAAQ,CAAC,cAAc,CAAC,GAAG,CAAC,CAAC;AACnD,EAAE;AACF;;;;","x_google_ignoreList":[0]}
|
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
function createGameRelay(config) {
|
|
4
|
-
return function setupHandlers(io, socket, getRoomHostSocketId, getPlayerSocketId) {
|
|
5
|
-
const { gameId, playerToHost, hostBroadcast, hostToPlayer } = config;
|
|
6
|
-
playerToHost?.forEach(({ from, toHost, withAck }) => {
|
|
7
|
-
socket.on(from, (data, callback) => {
|
|
8
|
-
const roomCode = socket.roomCode;
|
|
9
|
-
if (!roomCode) {
|
|
10
|
-
if (withAck && callback) callback({ success: false, error: "No room" });
|
|
11
|
-
return;
|
|
12
|
-
}
|
|
13
|
-
const hostSocketId = getRoomHostSocketId(roomCode);
|
|
14
|
-
if (!hostSocketId) {
|
|
15
|
-
if (withAck && callback) callback({ success: false, error: "No host" });
|
|
16
|
-
return;
|
|
17
|
-
}
|
|
18
|
-
io.to(hostSocketId).emit(toHost || from, {
|
|
19
|
-
sessionId: socket.sessionId,
|
|
20
|
-
...data
|
|
21
|
-
});
|
|
22
|
-
if (withAck && callback) callback({ success: true });
|
|
23
|
-
});
|
|
24
|
-
});
|
|
25
|
-
hostBroadcast?.forEach(({ from, toPlayers }) => {
|
|
26
|
-
socket.on(from, (data) => {
|
|
27
|
-
const roomCode = socket.roomCode;
|
|
28
|
-
if (!roomCode) return;
|
|
29
|
-
socket.to(roomCode).emit(toPlayers || from, data);
|
|
30
|
-
});
|
|
31
|
-
});
|
|
32
|
-
hostToPlayer?.forEach(({ from, toPlayer }) => {
|
|
33
|
-
socket.on(from, (data) => {
|
|
34
|
-
if (!getPlayerSocketId) return;
|
|
35
|
-
const targetSocketId = getPlayerSocketId(data.sessionId);
|
|
36
|
-
if (!targetSocketId) return;
|
|
37
|
-
const { sessionId, ...rest } = data;
|
|
38
|
-
io.to(targetSocketId).emit(toPlayer || from, rest);
|
|
39
|
-
});
|
|
40
|
-
});
|
|
41
|
-
};
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
exports.createGameRelay = createGameRelay;
|
|
45
|
-
//# sourceMappingURL=index.cjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs","sources":["../../../src/server/createGameRelay.ts"],"sourcesContent":["import type { Server, Socket } from 'socket.io';\n\nexport interface RelayEvent {\n from: string;\n toHost?: string;\n withAck?: boolean;\n}\n\nexport interface BroadcastEvent {\n from: string;\n toPlayers?: string;\n}\n\nexport interface TargetedEvent {\n from: string;\n toPlayer?: string;\n}\n\nexport interface CreateGameRelayConfig {\n gameId: string;\n playerToHost?: RelayEvent[];\n hostBroadcast?: BroadcastEvent[];\n hostToPlayer?: TargetedEvent[];\n}\n\nexport type GameRelaySetup = (\n io: Server,\n socket: Socket & { sessionId?: string; roomCode?: string },\n getRoomHostSocketId: (roomCode: string) => string | null,\n getPlayerSocketId?: (sessionId: string) => string | null,\n) => void;\n\nexport function createGameRelay(config: CreateGameRelayConfig): GameRelaySetup {\n return function setupHandlers(io, socket, getRoomHostSocketId, getPlayerSocketId) {\n const { gameId, playerToHost, hostBroadcast, hostToPlayer } = config;\n\n // Player → Host relay\n playerToHost?.forEach(({ from, toHost, withAck }) => {\n socket.on(from, (data: any, callback?: Function) => {\n const roomCode = (socket as any).roomCode;\n if (!roomCode) {\n if (withAck && callback) callback({ success: false, error: 'No room' });\n return;\n }\n const hostSocketId = getRoomHostSocketId(roomCode);\n if (!hostSocketId) {\n if (withAck && callback) callback({ success: false, error: 'No host' });\n return;\n }\n io.to(hostSocketId).emit(toHost || from, {\n sessionId: (socket as any).sessionId,\n ...data,\n });\n if (withAck && callback) callback({ success: true });\n });\n });\n\n // Host → All Players broadcast\n hostBroadcast?.forEach(({ from, toPlayers }) => {\n socket.on(from, (data: any) => {\n const roomCode = (socket as any).roomCode;\n if (!roomCode) return;\n socket.to(roomCode).emit(toPlayers || from, data);\n });\n });\n\n // Host → Specific Player\n hostToPlayer?.forEach(({ from, toPlayer }) => {\n socket.on(from, (data: { sessionId: string; [key: string]: any }) => {\n if (!getPlayerSocketId) return;\n const targetSocketId = getPlayerSocketId(data.sessionId);\n if (!targetSocketId) return;\n const { sessionId, ...rest } = data;\n io.to(targetSocketId).emit(toPlayer || from, rest);\n });\n });\n };\n}\n"],"names":[],"mappings":";;AAgCO,SAAS,gBAAgB,MAAA,EAA+C;AAC7E,EAAA,OAAO,SAAS,aAAA,CAAc,EAAA,EAAI,MAAA,EAAQ,qBAAqB,iBAAA,EAAmB;AAChF,IAAA,MAAM,EAAE,MAAA,EAAQ,YAAA,EAAc,aAAA,EAAe,cAAa,GAAI,MAAA;AAG9D,IAAA,YAAA,EAAc,QAAQ,CAAC,EAAE,IAAA,EAAM,MAAA,EAAQ,SAAQ,KAAM;AACnD,MAAA,MAAA,CAAO,EAAA,CAAG,IAAA,EAAM,CAAC,IAAA,EAAW,QAAA,KAAwB;AAClD,QAAA,MAAM,WAAY,MAAA,CAAe,QAAA;AACjC,QAAA,IAAI,CAAC,QAAA,EAAU;AACb,UAAA,IAAI,OAAA,IAAW,UAAU,QAAA,CAAS,EAAE,SAAS,KAAA,EAAO,KAAA,EAAO,WAAW,CAAA;AACtE,UAAA;AAAA,QACF;AACA,QAAA,MAAM,YAAA,GAAe,oBAAoB,QAAQ,CAAA;AACjD,QAAA,IAAI,CAAC,YAAA,EAAc;AACjB,UAAA,IAAI,OAAA,IAAW,UAAU,QAAA,CAAS,EAAE,SAAS,KAAA,EAAO,KAAA,EAAO,WAAW,CAAA;AACtE,UAAA;AAAA,QACF;AACA,QAAA,EAAA,CAAG,EAAA,CAAG,YAAY,CAAA,CAAE,IAAA,CAAK,UAAU,IAAA,EAAM;AAAA,UACvC,WAAY,MAAA,CAAe,SAAA;AAAA,UAC3B,GAAG;AAAA,SACJ,CAAA;AACD,QAAA,IAAI,WAAW,QAAA,EAAU,QAAA,CAAS,EAAE,OAAA,EAAS,MAAM,CAAA;AAAA,MACrD,CAAC,CAAA;AAAA,IACH,CAAC,CAAA;AAGD,IAAA,aAAA,EAAe,OAAA,CAAQ,CAAC,EAAE,IAAA,EAAM,WAAU,KAAM;AAC9C,MAAA,MAAA,CAAO,EAAA,CAAG,IAAA,EAAM,CAAC,IAAA,KAAc;AAC7B,QAAA,MAAM,WAAY,MAAA,CAAe,QAAA;AACjC,QAAA,IAAI,CAAC,QAAA,EAAU;AACf,QAAA,MAAA,CAAO,GAAG,QAAQ,CAAA,CAAE,IAAA,CAAK,SAAA,IAAa,MAAM,IAAI,CAAA;AAAA,MAClD,CAAC,CAAA;AAAA,IACH,CAAC,CAAA;AAGD,IAAA,YAAA,EAAc,OAAA,CAAQ,CAAC,EAAE,IAAA,EAAM,UAAS,KAAM;AAC5C,MAAA,MAAA,CAAO,EAAA,CAAG,IAAA,EAAM,CAAC,IAAA,KAAoD;AACnE,QAAA,IAAI,CAAC,iBAAA,EAAmB;AACxB,QAAA,MAAM,cAAA,GAAiB,iBAAA,CAAkB,IAAA,CAAK,SAAS,CAAA;AACvD,QAAA,IAAI,CAAC,cAAA,EAAgB;AACrB,QAAA,MAAM,EAAE,SAAA,EAAW,GAAG,IAAA,EAAK,GAAI,IAAA;AAC/B,QAAA,EAAA,CAAG,GAAG,cAAc,CAAA,CAAE,IAAA,CAAK,QAAA,IAAY,MAAM,IAAI,CAAA;AAAA,MACnD,CAAC,CAAA;AAAA,IACH,CAAC,CAAA;AAAA,EACH,CAAA;AACF;;;;"}
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
class DirectTransport {
|
|
4
|
-
constructor(socket) {
|
|
5
|
-
this.socket = socket;
|
|
6
|
-
}
|
|
7
|
-
emit(event, ...args) {
|
|
8
|
-
this.socket.emit(event, ...args);
|
|
9
|
-
}
|
|
10
|
-
on(event, handler) {
|
|
11
|
-
this.socket.on(event, handler);
|
|
12
|
-
}
|
|
13
|
-
off(event, handler) {
|
|
14
|
-
if (handler) {
|
|
15
|
-
this.socket.off(event, handler);
|
|
16
|
-
} else {
|
|
17
|
-
this.socket.off(event);
|
|
18
|
-
}
|
|
19
|
-
}
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
exports.DirectTransport = DirectTransport;
|
|
23
|
-
//# sourceMappingURL=DirectTransport.cjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"DirectTransport.cjs","sources":["../../../src/transport/DirectTransport.ts"],"sourcesContent":["/**\n * DirectTransport - Wraps a Socket.IO socket as a Transport.\n * Used by bundled (internal) games. Behaviour is identical to using socket directly.\n */\n\nimport type { Socket } from 'socket.io-client';\nimport type { Transport, TransportEventHandler } from './types';\n\nexport class DirectTransport implements Transport {\n constructor(private socket: Socket) {}\n\n emit(event: string, ...args: unknown[]): void {\n this.socket.emit(event, ...args);\n }\n\n on(event: string, handler: TransportEventHandler): void {\n this.socket.on(event, handler);\n }\n\n off(event: string, handler?: TransportEventHandler): void {\n if (handler) {\n this.socket.off(event, handler);\n } else {\n this.socket.off(event);\n }\n }\n}\n"],"names":[],"mappings":";;AAQO,MAAM,eAAA,CAAqC;AAAA,EAChD,YAAoB,MAAA,EAAgB;AAAhB,IAAA,IAAA,CAAA,MAAA,GAAA,MAAA;AAAA,EAAiB;AAAA,EAErC,IAAA,CAAK,UAAkB,IAAA,EAAuB;AAC5C,IAAA,IAAA,CAAK,MAAA,CAAO,IAAA,CAAK,KAAA,EAAO,GAAG,IAAI,CAAA;AAAA,EACjC;AAAA,EAEA,EAAA,CAAG,OAAe,OAAA,EAAsC;AACtD,IAAA,IAAA,CAAK,MAAA,CAAO,EAAA,CAAG,KAAA,EAAO,OAAO,CAAA;AAAA,EAC/B;AAAA,EAEA,GAAA,CAAI,OAAe,OAAA,EAAuC;AACxD,IAAA,IAAI,OAAA,EAAS;AACX,MAAA,IAAA,CAAK,MAAA,CAAO,GAAA,CAAI,KAAA,EAAO,OAAO,CAAA;AAAA,IAChC,CAAA,MAAO;AACL,MAAA,IAAA,CAAK,MAAA,CAAO,IAAI,KAAK,CAAA;AAAA,IACvB;AAAA,EACF;AACF;;;;"}
|
|
@@ -1,77 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
function createConnectionMonitor(socket, options) {
|
|
4
|
-
const {
|
|
5
|
-
onPause,
|
|
6
|
-
onResume,
|
|
7
|
-
latencyThreshold = 2e3,
|
|
8
|
-
resumeCountdown = 3e3,
|
|
9
|
-
onCountdown
|
|
10
|
-
} = options;
|
|
11
|
-
let paused = false;
|
|
12
|
-
let latency = 0;
|
|
13
|
-
let pingInterval = null;
|
|
14
|
-
let resumeTimeout = null;
|
|
15
|
-
let countdownInterval = null;
|
|
16
|
-
const checkConnection = () => {
|
|
17
|
-
const start = Date.now();
|
|
18
|
-
socket.emit("ping", {}, () => {
|
|
19
|
-
latency = Date.now() - start;
|
|
20
|
-
if (latency > latencyThreshold && !paused) {
|
|
21
|
-
paused = true;
|
|
22
|
-
console.warn(`[ConnectionMonitor] High latency (${latency}ms), pausing`);
|
|
23
|
-
onPause();
|
|
24
|
-
} else if (latency <= latencyThreshold && paused) {
|
|
25
|
-
console.log(`[ConnectionMonitor] Connection restored, starting countdown`);
|
|
26
|
-
startResumeCountdown();
|
|
27
|
-
}
|
|
28
|
-
});
|
|
29
|
-
};
|
|
30
|
-
const startResumeCountdown = () => {
|
|
31
|
-
if (resumeTimeout) clearTimeout(resumeTimeout);
|
|
32
|
-
if (countdownInterval) clearInterval(countdownInterval);
|
|
33
|
-
let secondsLeft = Math.ceil(resumeCountdown / 1e3);
|
|
34
|
-
onCountdown?.(secondsLeft);
|
|
35
|
-
countdownInterval = setInterval(() => {
|
|
36
|
-
secondsLeft--;
|
|
37
|
-
if (secondsLeft > 0) {
|
|
38
|
-
onCountdown?.(secondsLeft);
|
|
39
|
-
}
|
|
40
|
-
}, 1e3);
|
|
41
|
-
resumeTimeout = setTimeout(() => {
|
|
42
|
-
if (countdownInterval) clearInterval(countdownInterval);
|
|
43
|
-
paused = false;
|
|
44
|
-
console.log(`[ConnectionMonitor] Resuming game`);
|
|
45
|
-
onResume();
|
|
46
|
-
}, resumeCountdown);
|
|
47
|
-
};
|
|
48
|
-
const handleDisconnect = () => {
|
|
49
|
-
if (!paused) {
|
|
50
|
-
paused = true;
|
|
51
|
-
console.warn("[ConnectionMonitor] Socket disconnected, pausing");
|
|
52
|
-
onPause();
|
|
53
|
-
}
|
|
54
|
-
};
|
|
55
|
-
const handleReconnect = () => {
|
|
56
|
-
console.log("[ConnectionMonitor] Socket reconnected");
|
|
57
|
-
checkConnection();
|
|
58
|
-
};
|
|
59
|
-
socket.on("disconnect", handleDisconnect);
|
|
60
|
-
socket.io.on("reconnect", handleReconnect);
|
|
61
|
-
pingInterval = setInterval(checkConnection, 5e3);
|
|
62
|
-
checkConnection();
|
|
63
|
-
return {
|
|
64
|
-
destroy: () => {
|
|
65
|
-
if (pingInterval) clearInterval(pingInterval);
|
|
66
|
-
if (resumeTimeout) clearTimeout(resumeTimeout);
|
|
67
|
-
if (countdownInterval) clearInterval(countdownInterval);
|
|
68
|
-
socket.off("disconnect", handleDisconnect);
|
|
69
|
-
socket.io.off("reconnect", handleReconnect);
|
|
70
|
-
},
|
|
71
|
-
isPaused: () => paused,
|
|
72
|
-
getLatency: () => latency
|
|
73
|
-
};
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
exports.createConnectionMonitor = createConnectionMonitor;
|
|
77
|
-
//# sourceMappingURL=connectionMonitor.cjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"connectionMonitor.cjs","sources":["../../../src/utils/connectionMonitor.ts"],"sourcesContent":["/**\n * Connection monitor for detecting unstable connections.\n * AirConsole pattern: onPause/onResume for connection issues.\n *\n * @example\n * ```typescript\n * const monitor = createConnectionMonitor(socket, {\n * onPause: () => {\n * pauseGame();\n * muteAudio();\n * },\n * onResume: () => {\n * resumeGame();\n * unmuteAudio();\n * },\n * onCountdown: (secondsLeft) => {\n * showCountdown(secondsLeft);\n * },\n * });\n *\n * // Later\n * monitor.destroy();\n * ```\n */\n\nimport type { Socket } from 'socket.io-client';\n\nexport interface ConnectionMonitorOptions {\n /** Called when connection becomes unstable or disconnects */\n onPause: () => void;\n /** Called after connection restores and countdown completes */\n onResume: () => void;\n /** Latency threshold to trigger pause (ms), default 2000 */\n latencyThreshold?: number;\n /** Resume countdown duration (ms), default 3000 */\n resumeCountdown?: number;\n /** Called during resume countdown with seconds remaining */\n onCountdown?: (secondsLeft: number) => void;\n}\n\nexport interface ConnectionMonitor {\n /** Clean up listeners and intervals */\n destroy: () => void;\n /** Check if currently paused */\n isPaused: () => boolean;\n /** Get current latency (ms) */\n getLatency: () => number;\n}\n\n/**\n * Creates a connection monitor that detects network issues and triggers pause/resume.\n *\n * Monitors both:\n * - Socket.IO disconnect/reconnect events\n * - High latency via periodic ping\n *\n * When connection is lost or latency exceeds threshold, calls onPause().\n * When connection restores, starts countdown and calls onResume() after delay.\n */\nexport function createConnectionMonitor(\n socket: Socket,\n options: ConnectionMonitorOptions\n): ConnectionMonitor {\n const {\n onPause,\n onResume,\n latencyThreshold = 2000,\n resumeCountdown = 3000,\n onCountdown,\n } = options;\n\n let paused = false;\n let latency = 0;\n let pingInterval: NodeJS.Timeout | null = null;\n let resumeTimeout: NodeJS.Timeout | null = null;\n let countdownInterval: NodeJS.Timeout | null = null;\n\n /**\n * Check latency via ping/pong.\n * If latency is too high and not already paused, pause.\n * If latency is good and paused, start resume countdown.\n */\n const checkConnection = () => {\n const start = Date.now();\n\n socket.emit('ping', {}, () => {\n latency = Date.now() - start;\n\n if (latency > latencyThreshold && !paused) {\n // Connection unstable\n paused = true;\n console.warn(`[ConnectionMonitor] High latency (${latency}ms), pausing`);\n onPause();\n } else if (latency <= latencyThreshold && paused) {\n // Connection restored - start countdown\n console.log(`[ConnectionMonitor] Connection restored, starting countdown`);\n startResumeCountdown();\n }\n });\n };\n\n /**\n * Start resume countdown after connection restores.\n * Calls onCountdown every second, then onResume at the end.\n */\n const startResumeCountdown = () => {\n // Clear any existing countdown\n if (resumeTimeout) clearTimeout(resumeTimeout);\n if (countdownInterval) clearInterval(countdownInterval);\n\n let secondsLeft = Math.ceil(resumeCountdown / 1000);\n onCountdown?.(secondsLeft);\n\n countdownInterval = setInterval(() => {\n secondsLeft--;\n if (secondsLeft > 0) {\n onCountdown?.(secondsLeft);\n }\n }, 1000);\n\n resumeTimeout = setTimeout(() => {\n if (countdownInterval) clearInterval(countdownInterval);\n paused = false;\n console.log(`[ConnectionMonitor] Resuming game`);\n onResume();\n }, resumeCountdown);\n };\n\n /**\n * Handle socket disconnect event.\n * Immediately pause if not already paused.\n */\n const handleDisconnect = () => {\n if (!paused) {\n paused = true;\n console.warn('[ConnectionMonitor] Socket disconnected, pausing');\n onPause();\n }\n };\n\n /**\n * Handle socket reconnect event.\n * Will trigger resume via latency check.\n */\n const handleReconnect = () => {\n console.log('[ConnectionMonitor] Socket reconnected');\n // Let latency check handle resume to avoid premature resume\n checkConnection();\n };\n\n // Register socket event listeners\n socket.on('disconnect', handleDisconnect);\n socket.io.on('reconnect', handleReconnect);\n\n // Start periodic latency check\n pingInterval = setInterval(checkConnection, 5000);\n checkConnection(); // Initial check\n\n return {\n destroy: () => {\n if (pingInterval) clearInterval(pingInterval);\n if (resumeTimeout) clearTimeout(resumeTimeout);\n if (countdownInterval) clearInterval(countdownInterval);\n socket.off('disconnect', handleDisconnect);\n socket.io.off('reconnect', handleReconnect);\n },\n isPaused: () => paused,\n getLatency: () => latency,\n };\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -1,66 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
async function preloadAssets(urls, options = {}) {
|
|
4
|
-
const { onProgress, timeout = 3e4 } = options;
|
|
5
|
-
const total = urls.length;
|
|
6
|
-
let loaded = 0;
|
|
7
|
-
const loadPromises = urls.map((url) => {
|
|
8
|
-
return new Promise((resolve, reject) => {
|
|
9
|
-
const timeoutId = setTimeout(() => {
|
|
10
|
-
reject(new Error(`Timeout loading: ${url}`));
|
|
11
|
-
}, timeout);
|
|
12
|
-
if (url.match(/\.(png|jpg|jpeg|gif|svg|webp)$/i)) {
|
|
13
|
-
const img = new Image();
|
|
14
|
-
img.onload = () => {
|
|
15
|
-
clearTimeout(timeoutId);
|
|
16
|
-
loaded++;
|
|
17
|
-
onProgress?.({ loaded, total, percent: loaded / total * 100, currentUrl: url });
|
|
18
|
-
resolve();
|
|
19
|
-
};
|
|
20
|
-
img.onerror = () => {
|
|
21
|
-
clearTimeout(timeoutId);
|
|
22
|
-
reject(new Error(`Failed to load image: ${url}`));
|
|
23
|
-
};
|
|
24
|
-
img.src = url;
|
|
25
|
-
} else if (url.match(/\.(mp3|wav|ogg|m4a)$/i)) {
|
|
26
|
-
const audio = new Audio();
|
|
27
|
-
audio.oncanplaythrough = () => {
|
|
28
|
-
clearTimeout(timeoutId);
|
|
29
|
-
loaded++;
|
|
30
|
-
onProgress?.({ loaded, total, percent: loaded / total * 100, currentUrl: url });
|
|
31
|
-
resolve();
|
|
32
|
-
};
|
|
33
|
-
audio.onerror = () => {
|
|
34
|
-
clearTimeout(timeoutId);
|
|
35
|
-
reject(new Error(`Failed to load audio: ${url}`));
|
|
36
|
-
};
|
|
37
|
-
audio.src = url;
|
|
38
|
-
audio.load();
|
|
39
|
-
} else {
|
|
40
|
-
fetch(url).then((res) => {
|
|
41
|
-
clearTimeout(timeoutId);
|
|
42
|
-
if (!res.ok) throw new Error(`HTTP ${res.status}`);
|
|
43
|
-
loaded++;
|
|
44
|
-
onProgress?.({ loaded, total, percent: loaded / total * 100, currentUrl: url });
|
|
45
|
-
resolve();
|
|
46
|
-
}).catch((err) => {
|
|
47
|
-
clearTimeout(timeoutId);
|
|
48
|
-
reject(new Error(`Failed to fetch: ${url} - ${err.message}`));
|
|
49
|
-
});
|
|
50
|
-
}
|
|
51
|
-
});
|
|
52
|
-
});
|
|
53
|
-
await Promise.all(loadPromises);
|
|
54
|
-
}
|
|
55
|
-
function preloadImage(url) {
|
|
56
|
-
return new Promise((resolve, reject) => {
|
|
57
|
-
const img = new Image();
|
|
58
|
-
img.onload = () => resolve(img);
|
|
59
|
-
img.onerror = () => reject(new Error(`Failed to load: ${url}`));
|
|
60
|
-
img.src = url;
|
|
61
|
-
});
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
exports.preloadAssets = preloadAssets;
|
|
65
|
-
exports.preloadImage = preloadImage;
|
|
66
|
-
//# sourceMappingURL=preloadAssets.cjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"preloadAssets.cjs","sources":["../../../src/utils/preloadAssets.ts"],"sourcesContent":["/**\n * Preload assets (images, audio, etc.) before game starts.\n * AirConsole best practice: load all resources before onReady.\n *\n * @example\n * ```typescript\n * await preloadAssets([\n * '/sprites/player.png',\n * '/audio/background.mp3',\n * ]);\n * bridge.setLoaded(); // Signal ready after preload\n * ```\n */\n\nexport interface PreloadProgress {\n loaded: number;\n total: number;\n percent: number;\n currentUrl: string;\n}\n\nexport interface PreloadOptions {\n onProgress?: (progress: PreloadProgress) => void;\n timeout?: number; // ms, default 30000\n}\n\nexport async function preloadAssets(\n urls: string[],\n options: PreloadOptions = {}\n): Promise<void> {\n const { onProgress, timeout = 30000 } = options;\n const total = urls.length;\n let loaded = 0;\n\n const loadPromises = urls.map((url) => {\n return new Promise<void>((resolve, reject) => {\n const timeoutId = setTimeout(() => {\n reject(new Error(`Timeout loading: ${url}`));\n }, timeout);\n\n if (url.match(/\\.(png|jpg|jpeg|gif|svg|webp)$/i)) {\n // Image\n const img = new Image();\n img.onload = () => {\n clearTimeout(timeoutId);\n loaded++;\n onProgress?.({ loaded, total, percent: (loaded / total) * 100, currentUrl: url });\n resolve();\n };\n img.onerror = () => {\n clearTimeout(timeoutId);\n reject(new Error(`Failed to load image: ${url}`));\n };\n img.src = url;\n } else if (url.match(/\\.(mp3|wav|ogg|m4a)$/i)) {\n // Audio\n const audio = new Audio();\n audio.oncanplaythrough = () => {\n clearTimeout(timeoutId);\n loaded++;\n onProgress?.({ loaded, total, percent: (loaded / total) * 100, currentUrl: url });\n resolve();\n };\n audio.onerror = () => {\n clearTimeout(timeoutId);\n reject(new Error(`Failed to load audio: ${url}`));\n };\n audio.src = url;\n audio.load();\n } else {\n // Generic fetch for other resources\n fetch(url)\n .then((res) => {\n clearTimeout(timeoutId);\n if (!res.ok) throw new Error(`HTTP ${res.status}`);\n loaded++;\n onProgress?.({ loaded, total, percent: (loaded / total) * 100, currentUrl: url });\n resolve();\n })\n .catch((err) => {\n clearTimeout(timeoutId);\n reject(new Error(`Failed to fetch: ${url} - ${err.message}`));\n });\n }\n });\n });\n\n await Promise.all(loadPromises);\n}\n\n/**\n * Preload a single image and return the Image element.\n */\nexport function preloadImage(url: string): Promise<HTMLImageElement> {\n return new Promise((resolve, reject) => {\n const img = new Image();\n img.onload = () => resolve(img);\n img.onerror = () => reject(new Error(`Failed to load: ${url}`));\n img.src = url;\n });\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
function createTimeSync(socket) {
|
|
4
|
-
let offset = 0;
|
|
5
|
-
let latency = 0;
|
|
6
|
-
let synced = false;
|
|
7
|
-
return {
|
|
8
|
-
sync: () => {
|
|
9
|
-
return new Promise((resolve, reject) => {
|
|
10
|
-
const requestTime = Date.now();
|
|
11
|
-
socket.emit("smore:time-sync", { requestTime }, (response) => {
|
|
12
|
-
if (!response?.success) {
|
|
13
|
-
reject(new Error("Time sync failed"));
|
|
14
|
-
return;
|
|
15
|
-
}
|
|
16
|
-
const responseTime = Date.now();
|
|
17
|
-
const roundTrip = responseTime - requestTime;
|
|
18
|
-
latency = roundTrip / 2;
|
|
19
|
-
const serverTimeAtResponse = response.serverTime + latency;
|
|
20
|
-
offset = serverTimeAtResponse - responseTime;
|
|
21
|
-
synced = true;
|
|
22
|
-
console.log(`[TimeSync] Synced. Offset: ${offset}ms, Latency: ${latency}ms`);
|
|
23
|
-
resolve();
|
|
24
|
-
});
|
|
25
|
-
setTimeout(() => {
|
|
26
|
-
if (!synced) reject(new Error("Time sync timeout"));
|
|
27
|
-
}, 5e3);
|
|
28
|
-
});
|
|
29
|
-
},
|
|
30
|
-
getServerTime: () => {
|
|
31
|
-
if (!synced) {
|
|
32
|
-
console.warn("[TimeSync] Not synced yet, returning local time");
|
|
33
|
-
return Date.now();
|
|
34
|
-
}
|
|
35
|
-
return Date.now() + offset;
|
|
36
|
-
},
|
|
37
|
-
getLatency: () => latency,
|
|
38
|
-
isSynced: () => synced
|
|
39
|
-
};
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
exports.createTimeSync = createTimeSync;
|
|
43
|
-
//# sourceMappingURL=serverTime.cjs.map
|