@remix-gg/sdk 0.7.0 → 0.8.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/index.d.ts +12 -86
- package/dist/index.js +195 -316
- package/dist/index.min.js +30 -114
- package/dist/index.min.js.map +3 -3
- package/dist/index.mjs +129 -255
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -1,237 +1,68 @@
|
|
|
1
|
-
var __defProp = Object.defineProperty;
|
|
2
|
-
var __defProps = Object.defineProperties;
|
|
3
|
-
var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
|
|
4
|
-
var __getOwnPropSymbols = Object.getOwnPropertySymbols;
|
|
5
|
-
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
-
var __propIsEnum = Object.prototype.propertyIsEnumerable;
|
|
7
|
-
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
8
|
-
var __spreadValues = (a, b) => {
|
|
9
|
-
for (var prop in b || (b = {}))
|
|
10
|
-
if (__hasOwnProp.call(b, prop))
|
|
11
|
-
__defNormalProp(a, prop, b[prop]);
|
|
12
|
-
if (__getOwnPropSymbols)
|
|
13
|
-
for (var prop of __getOwnPropSymbols(b)) {
|
|
14
|
-
if (__propIsEnum.call(b, prop))
|
|
15
|
-
__defNormalProp(a, prop, b[prop]);
|
|
16
|
-
}
|
|
17
|
-
return a;
|
|
18
|
-
};
|
|
19
|
-
var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
|
|
20
|
-
|
|
21
1
|
// src/index.ts
|
|
22
|
-
var ZERO_SAFE_AREA_INSET =
|
|
2
|
+
var ZERO_SAFE_AREA_INSET = {
|
|
23
3
|
top: 0,
|
|
24
4
|
right: 0,
|
|
25
5
|
bottom: 0,
|
|
26
6
|
left: 0
|
|
27
|
-
});
|
|
28
|
-
var createGameEventMessage = (type, data) => {
|
|
29
|
-
return { type: "game_event", event: { type, data } };
|
|
30
7
|
};
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
if (typeof event.type !== "string")
|
|
41
|
-
return null;
|
|
42
|
-
return event;
|
|
43
|
-
};
|
|
44
|
-
var READY_RESEND_INITIAL_DELAY_MS = 250;
|
|
45
|
-
var READY_RESEND_MAX_ATTEMPTS = 5;
|
|
46
|
-
var generateInstanceId = () => typeof crypto !== "undefined" && typeof crypto.randomUUID === "function" ? crypto.randomUUID() : Math.random().toString(36).slice(2);
|
|
47
|
-
var isBrowserGameClient = () => typeof window !== "undefined" && typeof window.addEventListener === "function" && typeof window.removeEventListener === "function";
|
|
48
|
-
var RemixSDK = class {
|
|
8
|
+
|
|
9
|
+
class RemixSDK {
|
|
10
|
+
isClient;
|
|
11
|
+
target = null;
|
|
12
|
+
eventListeners = new Map;
|
|
13
|
+
readyPromiseResolve = null;
|
|
14
|
+
purchasePromiseResolve = null;
|
|
15
|
+
_gameInfo;
|
|
16
|
+
_gameState;
|
|
49
17
|
constructor() {
|
|
50
|
-
this.
|
|
51
|
-
this.eventListeners = /* @__PURE__ */ new Map();
|
|
52
|
-
this.readyPromise = null;
|
|
53
|
-
this.readyPromiseResolve = null;
|
|
54
|
-
this.purchasePromiseResolvers = [];
|
|
55
|
-
this.readyResendTimer = null;
|
|
56
|
-
this.instanceId = generateInstanceId();
|
|
57
|
-
this._levelStars = Object.freeze({});
|
|
58
|
-
this.ready = () => {
|
|
59
|
-
if (this._gameInfo) {
|
|
60
|
-
return Promise.resolve(this._gameInfo);
|
|
61
|
-
}
|
|
62
|
-
if (!this.readyPromise) {
|
|
63
|
-
this.readyPromise = new Promise((resolve) => {
|
|
64
|
-
this.readyPromiseResolve = resolve;
|
|
65
|
-
});
|
|
66
|
-
}
|
|
67
|
-
return this.readyPromise;
|
|
68
|
-
};
|
|
69
|
-
this.purchase = (data) => {
|
|
70
|
-
this.sendMessage("purchase", data);
|
|
71
|
-
return new Promise((resolve) => {
|
|
72
|
-
this.purchasePromiseResolvers.push(resolve);
|
|
73
|
-
});
|
|
74
|
-
};
|
|
75
|
-
this.reportError = (data) => {
|
|
76
|
-
this.sendMessage("error", data);
|
|
77
|
-
};
|
|
78
|
-
this.hapticFeedback = (type) => {
|
|
79
|
-
this.sendMessage("haptic_feedback", type ? { type } : void 0);
|
|
80
|
-
};
|
|
81
|
-
this.hasItem = (item) => {
|
|
82
|
-
return this.getItemPurchaseCount(item) > 0;
|
|
83
|
-
};
|
|
84
|
-
this.getItemPurchaseCount = (item) => {
|
|
85
|
-
const inventoryItem = this.inventory.find((entry) => entry.slug === item);
|
|
86
|
-
return (inventoryItem == null ? void 0 : inventoryItem.quantity) || 0;
|
|
87
|
-
};
|
|
88
|
-
this.getShopItem = (slug) => {
|
|
89
|
-
return this.shopItems.find((item) => item.slug === slug);
|
|
90
|
-
};
|
|
91
|
-
this.singlePlayer = {
|
|
92
|
-
actions: {
|
|
93
|
-
ready: this.ready,
|
|
94
|
-
hapticFeedback: this.hapticFeedback,
|
|
95
|
-
reportError: this.reportError,
|
|
96
|
-
purchase: this.purchase,
|
|
97
|
-
gameOver: (data) => {
|
|
98
|
-
this.sendMessage("game_over", data);
|
|
99
|
-
},
|
|
100
|
-
saveGameState: (data) => {
|
|
101
|
-
this.sendMessage("save_game_state", data);
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
};
|
|
105
|
-
this.multiplayer = {
|
|
106
|
-
actions: __spreadProps(__spreadValues({}, this.singlePlayer.actions), {
|
|
107
|
-
gameOver: (data) => {
|
|
108
|
-
this.sendMessage("multiplayer_game_over", data);
|
|
109
|
-
},
|
|
110
|
-
refuteGameState: (data) => {
|
|
111
|
-
this.sendMessage("refute_game_state", data);
|
|
112
|
-
},
|
|
113
|
-
saveGameState: (data) => {
|
|
114
|
-
this.sendMessage("multiplayer_save_game_state", data);
|
|
115
|
-
}
|
|
116
|
-
})
|
|
117
|
-
};
|
|
118
|
-
this.handleMessage = (event) => {
|
|
119
|
-
if (event.source && event.source !== this.target)
|
|
120
|
-
return;
|
|
121
|
-
const gameEvent = parseGameEventMessage(event.data);
|
|
122
|
-
if (!gameEvent)
|
|
123
|
-
return;
|
|
124
|
-
this.emit(gameEvent.type, gameEvent.data);
|
|
125
|
-
};
|
|
126
|
-
this.sendMessage = (type, data) => {
|
|
127
|
-
if (!this.isClient || !this.target)
|
|
128
|
-
return;
|
|
129
|
-
const gameEvent = { type: "game_event", event: { type, data } };
|
|
130
|
-
this.target.postMessage(gameEvent, "*");
|
|
131
|
-
};
|
|
132
|
-
this.handleGlobalError = (event) => {
|
|
133
|
-
this.sendMessage("error", {
|
|
134
|
-
message: event.message || "Unknown error",
|
|
135
|
-
source: event.filename,
|
|
136
|
-
lineno: event.lineno,
|
|
137
|
-
colno: event.colno,
|
|
138
|
-
error: event.error,
|
|
139
|
-
stack: event.error instanceof Error ? event.error.stack : void 0
|
|
140
|
-
});
|
|
141
|
-
};
|
|
142
|
-
this.handleUnhandledRejection = (event) => {
|
|
143
|
-
const error = event.reason instanceof Error ? event.reason : new Error(String(event.reason));
|
|
144
|
-
this.sendMessage("error", {
|
|
145
|
-
message: error.message,
|
|
146
|
-
error,
|
|
147
|
-
stack: error.stack
|
|
148
|
-
});
|
|
149
|
-
};
|
|
150
|
-
this.isClient = isBrowserGameClient();
|
|
18
|
+
this.isClient = typeof window !== "undefined";
|
|
151
19
|
this.target = this.isClient ? window.parent : null;
|
|
152
20
|
if (this.isClient) {
|
|
153
21
|
window.addEventListener("message", this.handleMessage);
|
|
154
22
|
window.addEventListener("error", this.handleGlobalError);
|
|
155
23
|
window.addEventListener("unhandledrejection", this.handleUnhandledRejection);
|
|
156
|
-
this.sendMessage("ready",
|
|
157
|
-
this.scheduleReadyResend(1);
|
|
158
|
-
}
|
|
159
|
-
}
|
|
160
|
-
scheduleReadyResend(attempt) {
|
|
161
|
-
if (attempt > READY_RESEND_MAX_ATTEMPTS)
|
|
162
|
-
return;
|
|
163
|
-
this.readyResendTimer = setTimeout(
|
|
164
|
-
() => {
|
|
165
|
-
if (this._gameInfo)
|
|
166
|
-
return;
|
|
167
|
-
this.sendMessage("ready", { instanceId: this.instanceId });
|
|
168
|
-
this.scheduleReadyResend(attempt + 1);
|
|
169
|
-
},
|
|
170
|
-
READY_RESEND_INITIAL_DELAY_MS * 2 ** (attempt - 1)
|
|
171
|
-
);
|
|
172
|
-
}
|
|
173
|
-
cancelReadyResend() {
|
|
174
|
-
if (this.readyResendTimer !== null) {
|
|
175
|
-
clearTimeout(this.readyResendTimer);
|
|
176
|
-
this.readyResendTimer = null;
|
|
24
|
+
this.sendMessage("ready", undefined);
|
|
177
25
|
}
|
|
178
26
|
}
|
|
179
27
|
on(eventType, callback) {
|
|
180
|
-
var _a;
|
|
181
28
|
if (!this.eventListeners.has(eventType)) {
|
|
182
|
-
this.eventListeners.set(eventType,
|
|
29
|
+
this.eventListeners.set(eventType, new Set);
|
|
183
30
|
}
|
|
184
|
-
|
|
185
|
-
return () => this.off(eventType, callback);
|
|
31
|
+
this.eventListeners.get(eventType)?.add(callback);
|
|
186
32
|
}
|
|
187
33
|
off(eventType, callback) {
|
|
188
|
-
|
|
189
|
-
(_a = this.eventListeners.get(eventType)) == null ? void 0 : _a.delete(callback);
|
|
190
|
-
}
|
|
191
|
-
// explicitly named event listeners for better understanding and type safety;
|
|
192
|
-
// each returns an unsubscribe function
|
|
193
|
-
/**
|
|
194
|
-
* Listen for the host starting play: a replay after game over, or — for level
|
|
195
|
-
* games — a host-directed level via `data.levelIndex` (Studio continue/jump or
|
|
196
|
-
* the production next-level button). `data` may be omitted for a plain restart.
|
|
197
|
-
*/
|
|
198
|
-
onPlay(callback) {
|
|
199
|
-
return this.on("play_again", (data) => callback(data));
|
|
34
|
+
this.eventListeners.get(eventType)?.delete(callback);
|
|
200
35
|
}
|
|
201
|
-
/** @deprecated Use {@link onPlay}. Retained for backward compatibility. */
|
|
202
36
|
onPlayAgain(callback) {
|
|
203
|
-
|
|
37
|
+
this.on("play_again", () => callback());
|
|
204
38
|
}
|
|
205
39
|
onToggleMute(callback) {
|
|
206
|
-
|
|
40
|
+
this.on("toggle_mute", (data) => callback(data));
|
|
207
41
|
}
|
|
208
42
|
onGameStateUpdated(callback) {
|
|
209
|
-
|
|
43
|
+
this.on("game_state_updated", (data) => callback(data));
|
|
210
44
|
}
|
|
211
45
|
onGameInfo(callback) {
|
|
212
|
-
|
|
46
|
+
this.on("game_info", (data) => callback(data));
|
|
213
47
|
}
|
|
214
48
|
onPurchaseComplete(callback) {
|
|
215
|
-
|
|
49
|
+
this.on("purchase_complete", (data) => callback(data));
|
|
216
50
|
}
|
|
217
|
-
// end of explicitly named event listeners
|
|
218
51
|
setTarget(target) {
|
|
219
52
|
this.target = target;
|
|
220
53
|
}
|
|
221
54
|
get purchasedItems() {
|
|
222
|
-
|
|
223
|
-
return ((_a = this._gameInfo) == null ? void 0 : _a.player.purchasedItems) || [];
|
|
55
|
+
return this._gameInfo?.player.purchasedItems || [];
|
|
224
56
|
}
|
|
225
57
|
get inventory() {
|
|
226
|
-
const counts =
|
|
58
|
+
const counts = new Map;
|
|
227
59
|
for (const item of this.purchasedItems) {
|
|
228
60
|
counts.set(item, (counts.get(item) || 0) + 1);
|
|
229
61
|
}
|
|
230
62
|
return [...counts.entries()].map(([slug, quantity]) => ({ slug, quantity }));
|
|
231
63
|
}
|
|
232
64
|
get shopItems() {
|
|
233
|
-
|
|
234
|
-
return ((_a = this._gameInfo) == null ? void 0 : _a.shopItems) || [];
|
|
65
|
+
return this._gameInfo?.shopItems || [];
|
|
235
66
|
}
|
|
236
67
|
get gameInfo() {
|
|
237
68
|
return this._gameInfo;
|
|
@@ -240,63 +71,76 @@ var RemixSDK = class {
|
|
|
240
71
|
return this._gameState;
|
|
241
72
|
}
|
|
242
73
|
get players() {
|
|
243
|
-
|
|
244
|
-
return (_a = this._gameInfo) == null ? void 0 : _a.players;
|
|
74
|
+
return this._gameInfo?.players;
|
|
245
75
|
}
|
|
246
76
|
get player() {
|
|
247
|
-
|
|
248
|
-
return (_a = this._gameInfo) == null ? void 0 : _a.player;
|
|
77
|
+
return this._gameInfo?.player;
|
|
249
78
|
}
|
|
250
79
|
get isReady() {
|
|
251
80
|
return !!this._gameInfo;
|
|
252
81
|
}
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
return
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
return
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
82
|
+
ready = () => {
|
|
83
|
+
if (this._gameInfo) {
|
|
84
|
+
return Promise.resolve(this._gameInfo);
|
|
85
|
+
}
|
|
86
|
+
return new Promise((resolve) => {
|
|
87
|
+
this.readyPromiseResolve = resolve;
|
|
88
|
+
});
|
|
89
|
+
};
|
|
90
|
+
purchase = (data) => {
|
|
91
|
+
this.sendMessage("purchase", data);
|
|
92
|
+
return new Promise((resolve) => {
|
|
93
|
+
this.purchasePromiseResolve = resolve;
|
|
94
|
+
});
|
|
95
|
+
};
|
|
96
|
+
reportError = (data) => {
|
|
97
|
+
this.sendMessage("error", data);
|
|
98
|
+
};
|
|
99
|
+
hapticFeedback = (type) => {
|
|
100
|
+
this.sendMessage("haptic_feedback", type ? { type } : undefined);
|
|
101
|
+
};
|
|
102
|
+
hasItem = (item) => {
|
|
103
|
+
return this.getItemPurchaseCount(item) > 0;
|
|
104
|
+
};
|
|
105
|
+
getItemPurchaseCount = (item) => {
|
|
106
|
+
const inventoryItem = this.inventory.find((entry) => entry.slug === item);
|
|
107
|
+
return inventoryItem?.quantity || 0;
|
|
108
|
+
};
|
|
109
|
+
getShopItem = (slug) => {
|
|
110
|
+
return this.shopItems.find((item) => item.slug === slug);
|
|
111
|
+
};
|
|
112
|
+
singlePlayer = {
|
|
113
|
+
actions: {
|
|
114
|
+
ready: this.ready,
|
|
115
|
+
hapticFeedback: this.hapticFeedback,
|
|
116
|
+
reportError: this.reportError,
|
|
117
|
+
purchase: this.purchase,
|
|
118
|
+
gameOver: (data) => {
|
|
119
|
+
this.sendMessage("game_over", data);
|
|
120
|
+
},
|
|
121
|
+
saveGameState: (data) => {
|
|
122
|
+
this.sendMessage("save_game_state", data);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
};
|
|
126
|
+
multiplayer = {
|
|
127
|
+
actions: {
|
|
128
|
+
...this.singlePlayer.actions,
|
|
129
|
+
gameOver: (data) => {
|
|
130
|
+
this.sendMessage("multiplayer_game_over", data);
|
|
131
|
+
},
|
|
132
|
+
refuteGameState: (data) => {
|
|
133
|
+
this.sendMessage("refute_game_state", data);
|
|
134
|
+
},
|
|
135
|
+
saveGameState: (data) => {
|
|
136
|
+
this.sendMessage("multiplayer_save_game_state", data);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
};
|
|
285
140
|
emit(eventType, data) {
|
|
286
|
-
var _a, _b, _c;
|
|
287
141
|
if (eventType === "game_info") {
|
|
288
142
|
const eventData = data;
|
|
289
143
|
this._gameInfo = eventData;
|
|
290
|
-
const rawLevelStars = (_b = (_a = eventData.levelBased) == null ? void 0 : _a.progress) == null ? void 0 : _b.levelStars;
|
|
291
|
-
const levelStars = {};
|
|
292
|
-
if (rawLevelStars && typeof rawLevelStars === "object" && !Array.isArray(rawLevelStars)) {
|
|
293
|
-
for (const [key, starValue] of Object.entries(rawLevelStars)) {
|
|
294
|
-
if (starValue === 1 || starValue === 2 || starValue === 3)
|
|
295
|
-
levelStars[key] = starValue;
|
|
296
|
-
}
|
|
297
|
-
}
|
|
298
|
-
this._levelStars = Object.freeze(levelStars);
|
|
299
|
-
this.cancelReadyResend();
|
|
300
144
|
if (!this._gameState && eventData.initialGameState) {
|
|
301
145
|
this._gameState = eventData.initialGameState.gameState;
|
|
302
146
|
}
|
|
@@ -307,12 +151,12 @@ var RemixSDK = class {
|
|
|
307
151
|
}
|
|
308
152
|
if (eventType === "purchase_complete") {
|
|
309
153
|
const eventData = data;
|
|
310
|
-
if (eventData.success && eventData.item &&
|
|
154
|
+
if (eventData.success && eventData.item && this._gameInfo?.player) {
|
|
311
155
|
this.applyPurchaseToCurrentPlayer(eventData.item);
|
|
312
156
|
}
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
157
|
+
if (this.purchasePromiseResolve) {
|
|
158
|
+
this.purchasePromiseResolve(eventData);
|
|
159
|
+
this.purchasePromiseResolve = null;
|
|
316
160
|
}
|
|
317
161
|
}
|
|
318
162
|
if (eventType === "game_state_updated") {
|
|
@@ -327,27 +171,57 @@ var RemixSDK = class {
|
|
|
327
171
|
callback(data);
|
|
328
172
|
}
|
|
329
173
|
}
|
|
174
|
+
handleMessage = (event) => {
|
|
175
|
+
if (event.data?.type !== "game_event")
|
|
176
|
+
return;
|
|
177
|
+
this.emit(event.data.event.type, event.data.event.data);
|
|
178
|
+
};
|
|
179
|
+
sendMessage = (type, data) => {
|
|
180
|
+
if (!this.isClient || !this.target)
|
|
181
|
+
return;
|
|
182
|
+
const gameEvent = { type: "game_event", event: { type, data } };
|
|
183
|
+
this.target.postMessage(gameEvent, "*");
|
|
184
|
+
};
|
|
185
|
+
handleGlobalError = (event) => {
|
|
186
|
+
this.sendMessage("error", {
|
|
187
|
+
message: event.message || "Unknown error",
|
|
188
|
+
source: event.filename,
|
|
189
|
+
lineno: event.lineno,
|
|
190
|
+
colno: event.colno,
|
|
191
|
+
error: event.error
|
|
192
|
+
});
|
|
193
|
+
};
|
|
194
|
+
handleUnhandledRejection = (event) => {
|
|
195
|
+
const error = event.reason instanceof Error ? event.reason : new Error(String(event.reason));
|
|
196
|
+
this.sendMessage("error", {
|
|
197
|
+
message: error.message,
|
|
198
|
+
error
|
|
199
|
+
});
|
|
200
|
+
};
|
|
330
201
|
applyPurchaseToCurrentPlayer(item) {
|
|
331
202
|
if (!this._gameInfo)
|
|
332
203
|
return;
|
|
333
204
|
const currentPlayer = this._gameInfo.player;
|
|
334
205
|
currentPlayer.purchasedItems = [...currentPlayer.purchasedItems, item];
|
|
335
|
-
|
|
336
|
-
if (player
|
|
337
|
-
player
|
|
338
|
-
|
|
339
|
-
|
|
206
|
+
this._gameInfo.players = this._gameInfo.players.map((player) => {
|
|
207
|
+
if (player.id !== currentPlayer.id)
|
|
208
|
+
return player;
|
|
209
|
+
return {
|
|
210
|
+
...player,
|
|
211
|
+
purchasedItems: currentPlayer.purchasedItems
|
|
212
|
+
};
|
|
213
|
+
});
|
|
340
214
|
}
|
|
341
|
-
}
|
|
342
|
-
var sdk = new RemixSDK
|
|
343
|
-
if (
|
|
215
|
+
}
|
|
216
|
+
var sdk = new RemixSDK;
|
|
217
|
+
if (typeof window !== "undefined") {
|
|
344
218
|
window.FarcadeSDK = sdk;
|
|
345
219
|
window.RemixSDK = sdk;
|
|
346
220
|
}
|
|
347
221
|
export {
|
|
348
|
-
|
|
222
|
+
sdk,
|
|
349
223
|
ZERO_SAFE_AREA_INSET,
|
|
350
|
-
|
|
351
|
-
parseGameEventMessage,
|
|
352
|
-
sdk
|
|
224
|
+
RemixSDK
|
|
353
225
|
};
|
|
226
|
+
|
|
227
|
+
//# debugId=977CE63C2185488464756E2164756E21
|