@bountyboard/arcade-sdk 1.1.0 → 1.3.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/AGENTS.md +22 -10
- package/CHANGELOG.md +73 -0
- package/README.md +378 -85
- package/dist/{chunk-OWOESH4X.js → chunk-PYW5F45R.js} +384 -10
- package/dist/chunk-PYW5F45R.js.map +1 -0
- package/dist/global-sdk.d.ts +100 -3
- package/dist/global.js +482 -48
- package/dist/index.cjs +383 -9
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +1 -1
- package/dist/multiplayer.cjs +481 -48
- package/dist/multiplayer.cjs.map +1 -1
- package/dist/multiplayer.d.cts +2 -2
- package/dist/multiplayer.d.ts +2 -2
- package/dist/multiplayer.js +88 -29
- package/dist/multiplayer.js.map +1 -1
- package/dist/{types-Cq8p7ZkC.d.cts → types-B5bqWnHH.d.cts} +99 -4
- package/dist/{types-Cq8p7ZkC.d.ts → types-B5bqWnHH.d.ts} +99 -4
- package/docs/external-authoritative-servers.md +265 -0
- package/docs/llms.txt +800 -0
- package/docs/relay-rooms.md +134 -0
- package/package.json +2 -1
- package/dist/chunk-OWOESH4X.js.map +0 -1
|
@@ -3,6 +3,316 @@ var VERSION = 1;
|
|
|
3
3
|
var SDK_MESSAGE_SOURCE = "bb-arcade";
|
|
4
4
|
var HOST_MESSAGE_SOURCE = "bb-arcade-host";
|
|
5
5
|
|
|
6
|
+
// src/storage.ts
|
|
7
|
+
var FLUSH_DELAY_MS = 400;
|
|
8
|
+
var ENVELOPE_TAG = "__bbArcadeStorage";
|
|
9
|
+
var ENVELOPE_VERSION = 1;
|
|
10
|
+
function hasOwn(target, key) {
|
|
11
|
+
return Object.prototype.hasOwnProperty.call(target, key);
|
|
12
|
+
}
|
|
13
|
+
function emptyMap() {
|
|
14
|
+
return /* @__PURE__ */ Object.create(null);
|
|
15
|
+
}
|
|
16
|
+
function storageError(code) {
|
|
17
|
+
const err = new Error(code);
|
|
18
|
+
err.code = code;
|
|
19
|
+
return err;
|
|
20
|
+
}
|
|
21
|
+
function parseEnvelope(raw) {
|
|
22
|
+
if (raw == null) return { ls: {}, app: null };
|
|
23
|
+
if (raw.charAt(0) !== "{") return { ls: {}, app: raw };
|
|
24
|
+
let parsed;
|
|
25
|
+
try {
|
|
26
|
+
parsed = JSON.parse(raw);
|
|
27
|
+
} catch (err) {
|
|
28
|
+
return { ls: {}, app: raw };
|
|
29
|
+
}
|
|
30
|
+
if (!parsed || typeof parsed !== "object") return { ls: {}, app: raw };
|
|
31
|
+
const record = parsed;
|
|
32
|
+
if (record[ENVELOPE_TAG] !== ENVELOPE_VERSION) return { ls: {}, app: raw };
|
|
33
|
+
const ls = emptyMap();
|
|
34
|
+
const source = record.ls;
|
|
35
|
+
if (source && typeof source === "object") {
|
|
36
|
+
const entries = source;
|
|
37
|
+
for (const key in entries) {
|
|
38
|
+
if (hasOwn(entries, key) && typeof entries[key] === "string") {
|
|
39
|
+
ls[key] = entries[key];
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
return { ls, app: typeof record.app === "string" ? record.app : null };
|
|
44
|
+
}
|
|
45
|
+
function buildEnvelope(ls, app) {
|
|
46
|
+
const envelope = {};
|
|
47
|
+
envelope[ENVELOPE_TAG] = ENVELOPE_VERSION;
|
|
48
|
+
envelope.ls = ls;
|
|
49
|
+
envelope.app = app;
|
|
50
|
+
return JSON.stringify(envelope);
|
|
51
|
+
}
|
|
52
|
+
function quotaError() {
|
|
53
|
+
try {
|
|
54
|
+
return new DOMException("Cloud save quota exceeded", "QuotaExceededError");
|
|
55
|
+
} catch (err) {
|
|
56
|
+
const fallback = new Error("Cloud save quota exceeded");
|
|
57
|
+
fallback.name = "QuotaExceededError";
|
|
58
|
+
return fallback;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
var RESERVED = {
|
|
62
|
+
getItem: true,
|
|
63
|
+
setItem: true,
|
|
64
|
+
removeItem: true,
|
|
65
|
+
clear: true,
|
|
66
|
+
key: true,
|
|
67
|
+
length: true
|
|
68
|
+
};
|
|
69
|
+
function createStorageShim(backend = {}) {
|
|
70
|
+
const map = emptyMap();
|
|
71
|
+
const localWrites = emptyMap();
|
|
72
|
+
function keys() {
|
|
73
|
+
return Object.keys(map);
|
|
74
|
+
}
|
|
75
|
+
function changed() {
|
|
76
|
+
if (backend.onChange) backend.onChange();
|
|
77
|
+
}
|
|
78
|
+
const api = {
|
|
79
|
+
getItem: function(key) {
|
|
80
|
+
const name = String(key);
|
|
81
|
+
return hasOwn(map, name) ? map[name] : null;
|
|
82
|
+
},
|
|
83
|
+
setItem: function(key, value) {
|
|
84
|
+
const name = String(key);
|
|
85
|
+
const next = String(value);
|
|
86
|
+
if (backend.wouldOverflow && backend.wouldOverflow(name, next)) throw quotaError();
|
|
87
|
+
map[name] = next;
|
|
88
|
+
localWrites[name] = true;
|
|
89
|
+
changed();
|
|
90
|
+
},
|
|
91
|
+
removeItem: function(key) {
|
|
92
|
+
const name = String(key);
|
|
93
|
+
localWrites[name] = true;
|
|
94
|
+
if (!hasOwn(map, name)) return;
|
|
95
|
+
delete map[name];
|
|
96
|
+
changed();
|
|
97
|
+
},
|
|
98
|
+
clear: function() {
|
|
99
|
+
const existing = keys();
|
|
100
|
+
for (let i = 0; i < existing.length; i++) {
|
|
101
|
+
delete map[existing[i]];
|
|
102
|
+
localWrites[existing[i]] = true;
|
|
103
|
+
}
|
|
104
|
+
changed();
|
|
105
|
+
},
|
|
106
|
+
key: function(index) {
|
|
107
|
+
const existing = keys();
|
|
108
|
+
const at = Number(index);
|
|
109
|
+
return at >= 0 && at < existing.length ? existing[at] : null;
|
|
110
|
+
},
|
|
111
|
+
get length() {
|
|
112
|
+
return keys().length;
|
|
113
|
+
}
|
|
114
|
+
};
|
|
115
|
+
const storage = new Proxy(api, {
|
|
116
|
+
get(target, prop, receiver) {
|
|
117
|
+
if (typeof prop !== "string") return Reflect.get(target, prop, receiver);
|
|
118
|
+
if (hasOwn(RESERVED, prop)) return Reflect.get(target, prop, receiver);
|
|
119
|
+
return hasOwn(map, prop) ? map[prop] : void 0;
|
|
120
|
+
},
|
|
121
|
+
set(target, prop, value) {
|
|
122
|
+
if (typeof prop !== "string" || hasOwn(RESERVED, prop)) return true;
|
|
123
|
+
api.setItem(prop, value);
|
|
124
|
+
return true;
|
|
125
|
+
},
|
|
126
|
+
has(target, prop) {
|
|
127
|
+
if (typeof prop !== "string") return Reflect.has(target, prop);
|
|
128
|
+
return hasOwn(RESERVED, prop) || hasOwn(map, prop);
|
|
129
|
+
},
|
|
130
|
+
deleteProperty(target, prop) {
|
|
131
|
+
if (typeof prop === "string" && !hasOwn(RESERVED, prop)) api.removeItem(prop);
|
|
132
|
+
return true;
|
|
133
|
+
},
|
|
134
|
+
ownKeys() {
|
|
135
|
+
return keys();
|
|
136
|
+
},
|
|
137
|
+
getOwnPropertyDescriptor(target, prop) {
|
|
138
|
+
if (typeof prop !== "string" || !hasOwn(map, prop)) return void 0;
|
|
139
|
+
return { value: map[prop], writable: true, enumerable: true, configurable: true };
|
|
140
|
+
}
|
|
141
|
+
});
|
|
142
|
+
return {
|
|
143
|
+
storage,
|
|
144
|
+
entries: function() {
|
|
145
|
+
const copy = emptyMap();
|
|
146
|
+
const existing = keys();
|
|
147
|
+
for (let i = 0; i < existing.length; i++) copy[existing[i]] = map[existing[i]];
|
|
148
|
+
return copy;
|
|
149
|
+
},
|
|
150
|
+
hydrate: function(values) {
|
|
151
|
+
for (const key in values) {
|
|
152
|
+
if (hasOwn(values, key) && !hasOwn(localWrites, key)) map[key] = values[key];
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
function settled(promise) {
|
|
158
|
+
return promise.then(
|
|
159
|
+
function() {
|
|
160
|
+
},
|
|
161
|
+
function() {
|
|
162
|
+
}
|
|
163
|
+
);
|
|
164
|
+
}
|
|
165
|
+
function installSessionStorageShim() {
|
|
166
|
+
if (nativeStorageWorks("sessionStorage")) return;
|
|
167
|
+
try {
|
|
168
|
+
Object.defineProperty(window, "sessionStorage", {
|
|
169
|
+
value: createStorageShim().storage,
|
|
170
|
+
configurable: true
|
|
171
|
+
});
|
|
172
|
+
} catch (err) {
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
function nativeStorageWorks(area) {
|
|
176
|
+
try {
|
|
177
|
+
const store = window[area];
|
|
178
|
+
if (!store) return false;
|
|
179
|
+
const probe = "__bb_arcade_probe__";
|
|
180
|
+
store.setItem(probe, "1");
|
|
181
|
+
store.removeItem(probe);
|
|
182
|
+
return true;
|
|
183
|
+
} catch (err) {
|
|
184
|
+
return false;
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
function createStorageController(options) {
|
|
188
|
+
let shim = null;
|
|
189
|
+
let mode = "native";
|
|
190
|
+
let appBlob = null;
|
|
191
|
+
let hydration = null;
|
|
192
|
+
let flushTimer = null;
|
|
193
|
+
let inFlight = Promise.resolve();
|
|
194
|
+
let dirty = false;
|
|
195
|
+
let hydrated = false;
|
|
196
|
+
function serialize() {
|
|
197
|
+
return buildEnvelope(shim ? shim.entries() : {}, appBlob);
|
|
198
|
+
}
|
|
199
|
+
function hydrateFromCloud() {
|
|
200
|
+
hydration = options.load().then(
|
|
201
|
+
function(raw) {
|
|
202
|
+
const envelope = parseEnvelope(raw);
|
|
203
|
+
if (shim) shim.hydrate(envelope.ls);
|
|
204
|
+
if (appBlob === null) appBlob = envelope.app;
|
|
205
|
+
hydrated = true;
|
|
206
|
+
return mode;
|
|
207
|
+
},
|
|
208
|
+
function(err) {
|
|
209
|
+
const code = err && err.code;
|
|
210
|
+
if (code === "unsupported" || code === "unauthenticated") mode = "memory";
|
|
211
|
+
return mode;
|
|
212
|
+
}
|
|
213
|
+
);
|
|
214
|
+
return hydration;
|
|
215
|
+
}
|
|
216
|
+
function wouldOverflow(key, value) {
|
|
217
|
+
if (!shim) return false;
|
|
218
|
+
const next = shim.entries();
|
|
219
|
+
next[key] = value;
|
|
220
|
+
return options.byteLength(buildEnvelope(next, appBlob)) > options.maxBytes;
|
|
221
|
+
}
|
|
222
|
+
function persist() {
|
|
223
|
+
return whenHydrated().then(function() {
|
|
224
|
+
if (mode === "memory") return;
|
|
225
|
+
if (hydrated) return options.save(serialize());
|
|
226
|
+
return hydrateFromCloud().then(function() {
|
|
227
|
+
if (mode === "memory") return;
|
|
228
|
+
if (!hydrated) throw storageError("error");
|
|
229
|
+
return options.save(serialize());
|
|
230
|
+
});
|
|
231
|
+
}).then(void 0, function(err) {
|
|
232
|
+
dirty = true;
|
|
233
|
+
throw err;
|
|
234
|
+
});
|
|
235
|
+
}
|
|
236
|
+
function flushNow() {
|
|
237
|
+
if (flushTimer !== null) {
|
|
238
|
+
clearTimeout(flushTimer);
|
|
239
|
+
flushTimer = null;
|
|
240
|
+
}
|
|
241
|
+
dirty = false;
|
|
242
|
+
const next = inFlight.then(persist, persist);
|
|
243
|
+
inFlight = settled(next);
|
|
244
|
+
return next;
|
|
245
|
+
}
|
|
246
|
+
function scheduleFlush() {
|
|
247
|
+
dirty = true;
|
|
248
|
+
if (flushTimer !== null) return;
|
|
249
|
+
flushTimer = setTimeout(function() {
|
|
250
|
+
flushTimer = null;
|
|
251
|
+
void settled(flushNow());
|
|
252
|
+
}, FLUSH_DELAY_MS);
|
|
253
|
+
}
|
|
254
|
+
function whenHydrated() {
|
|
255
|
+
return hydration ? hydration : Promise.resolve(mode);
|
|
256
|
+
}
|
|
257
|
+
function attachUnloadFlush() {
|
|
258
|
+
const flushIfDirty = function() {
|
|
259
|
+
if (dirty) void settled(flushNow());
|
|
260
|
+
};
|
|
261
|
+
try {
|
|
262
|
+
window.addEventListener("pagehide", flushIfDirty);
|
|
263
|
+
window.addEventListener("visibilitychange", function() {
|
|
264
|
+
if (document.visibilityState === "hidden") flushIfDirty();
|
|
265
|
+
});
|
|
266
|
+
} catch (err) {
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
function install() {
|
|
270
|
+
if (shim) return mode;
|
|
271
|
+
installSessionStorageShim();
|
|
272
|
+
if (nativeStorageWorks("localStorage")) {
|
|
273
|
+
mode = "native";
|
|
274
|
+
return mode;
|
|
275
|
+
}
|
|
276
|
+
const handle = createStorageShim({ onChange: scheduleFlush, wouldOverflow });
|
|
277
|
+
try {
|
|
278
|
+
Object.defineProperty(window, "localStorage", {
|
|
279
|
+
value: handle.storage,
|
|
280
|
+
configurable: true
|
|
281
|
+
});
|
|
282
|
+
} catch (err) {
|
|
283
|
+
return mode;
|
|
284
|
+
}
|
|
285
|
+
shim = handle;
|
|
286
|
+
mode = "cloud";
|
|
287
|
+
attachUnloadFlush();
|
|
288
|
+
void hydrateFromCloud();
|
|
289
|
+
return mode;
|
|
290
|
+
}
|
|
291
|
+
return {
|
|
292
|
+
install,
|
|
293
|
+
active: function() {
|
|
294
|
+
return shim !== null;
|
|
295
|
+
},
|
|
296
|
+
ready: function() {
|
|
297
|
+
return whenHydrated();
|
|
298
|
+
},
|
|
299
|
+
flush: function() {
|
|
300
|
+
if (!shim && appBlob === null) return Promise.resolve();
|
|
301
|
+
return flushNow();
|
|
302
|
+
},
|
|
303
|
+
writeApp: function(blob) {
|
|
304
|
+
if (options.byteLength(buildEnvelope(shim ? shim.entries() : {}, blob)) > options.maxBytes) {
|
|
305
|
+
return Promise.reject(storageError("too_large"));
|
|
306
|
+
}
|
|
307
|
+
appBlob = blob;
|
|
308
|
+
return flushNow();
|
|
309
|
+
},
|
|
310
|
+
get mode() {
|
|
311
|
+
return mode;
|
|
312
|
+
}
|
|
313
|
+
};
|
|
314
|
+
}
|
|
315
|
+
|
|
6
316
|
// src/core.ts
|
|
7
317
|
var BOUNTY_BOARD_URL = "https://www.bountyboard.gg/arcade";
|
|
8
318
|
var ADSENSE_CLIENT_ID = "ca-pub-7727110228190547";
|
|
@@ -10,6 +320,8 @@ var AD_PLACEMENT_SRC = "https://pagead2.googlesyndication.com/pagead/js/adsbygoo
|
|
|
10
320
|
var AD_PLACEMENT_SCRIPT_ID = "bb-arcade-h5-ads";
|
|
11
321
|
var DEFAULT_AD_LOAD_TIMEOUT_MS = 6e3;
|
|
12
322
|
var SAVE_TIMEOUT_MS = 15e3;
|
|
323
|
+
var LOCK_TIMEOUT_MS = 5e3;
|
|
324
|
+
var MAX_SAVE_BYTES = 1024 * 1024;
|
|
13
325
|
var INIT_CONFIG_GRACE_MS = 1500;
|
|
14
326
|
var DEFAULT_ALLOW = [
|
|
15
327
|
"bountyboard.gg",
|
|
@@ -34,6 +346,14 @@ function cleanText(value, fallback, max) {
|
|
|
34
346
|
if (typeof value !== "string") return fallback || "";
|
|
35
347
|
return value.replace(/[^\w:.-]+/g, "_").slice(0, max || 80) || fallback || "";
|
|
36
348
|
}
|
|
349
|
+
var cachedTextEncoder = null;
|
|
350
|
+
function utf8ByteLength(value) {
|
|
351
|
+
if (typeof TextEncoder !== "undefined") {
|
|
352
|
+
cachedTextEncoder = cachedTextEncoder || new TextEncoder();
|
|
353
|
+
return cachedTextEncoder.encode(value).length;
|
|
354
|
+
}
|
|
355
|
+
return new Blob([value]).size;
|
|
356
|
+
}
|
|
37
357
|
function toBoolean(value) {
|
|
38
358
|
return value === true || value === "true" || value === "1";
|
|
39
359
|
}
|
|
@@ -153,13 +473,14 @@ function createBBArcade() {
|
|
|
153
473
|
};
|
|
154
474
|
let hostConfigReceived = false;
|
|
155
475
|
let hostPlayer = null;
|
|
476
|
+
const playerChangeHandlers = [];
|
|
156
477
|
let blocked = false;
|
|
157
478
|
const pending = {};
|
|
158
479
|
let seq = 0;
|
|
159
480
|
function post(type, score, extra) {
|
|
160
481
|
if (blocked) return;
|
|
161
482
|
const message = { source: SDK_MESSAGE_SOURCE, v: VERSION, type };
|
|
162
|
-
if (typeof score === "number" && isFinite(score)) message.score = Math.
|
|
483
|
+
if (typeof score === "number" && isFinite(score)) message.score = Math.trunc(score);
|
|
163
484
|
if (extra && typeof extra === "object") {
|
|
164
485
|
const fields = extra;
|
|
165
486
|
for (const key in fields) {
|
|
@@ -180,7 +501,7 @@ function createBBArcade() {
|
|
|
180
501
|
return true;
|
|
181
502
|
}
|
|
182
503
|
}
|
|
183
|
-
function request(type, payload) {
|
|
504
|
+
function request(type, payload, timeoutMs = SAVE_TIMEOUT_MS) {
|
|
184
505
|
return new Promise(function(resolve, reject) {
|
|
185
506
|
if (blocked) return reject(sdkError("error"));
|
|
186
507
|
if (!isEmbedded()) return reject(sdkError("unsupported"));
|
|
@@ -190,7 +511,7 @@ function createBBArcade() {
|
|
|
190
511
|
delete pending[requestId];
|
|
191
512
|
reject(sdkError("error"));
|
|
192
513
|
}
|
|
193
|
-
},
|
|
514
|
+
}, timeoutMs);
|
|
194
515
|
pending[requestId] = { resolve, reject, timer };
|
|
195
516
|
try {
|
|
196
517
|
window.parent.postMessage(
|
|
@@ -282,7 +603,7 @@ function createBBArcade() {
|
|
|
282
603
|
if (!hostnameAllowed(origin, allow)) blockHost(options);
|
|
283
604
|
return;
|
|
284
605
|
}
|
|
285
|
-
request("host").then(
|
|
606
|
+
request("host", void 0, LOCK_TIMEOUT_MS).then(
|
|
286
607
|
function(res) {
|
|
287
608
|
const r = res;
|
|
288
609
|
if (!hostnameAllowed(r && r.origin, allow)) blockHost(options);
|
|
@@ -306,7 +627,7 @@ function createBBArcade() {
|
|
|
306
627
|
lockToHostBestEffort(opts, allow);
|
|
307
628
|
return;
|
|
308
629
|
}
|
|
309
|
-
request("host_attest").then(
|
|
630
|
+
request("host_attest", void 0, LOCK_TIMEOUT_MS).then(
|
|
310
631
|
function(res) {
|
|
311
632
|
const r = res;
|
|
312
633
|
if (!r || !r.attestation) {
|
|
@@ -368,7 +689,15 @@ function createBBArcade() {
|
|
|
368
689
|
if (msg.source !== HOST_MESSAGE_SOURCE || msg.type !== "config") return;
|
|
369
690
|
hostConfigReceived = true;
|
|
370
691
|
if (msg.player !== void 0) {
|
|
371
|
-
|
|
692
|
+
const nextPlayer = sanitizePlayer(msg.player);
|
|
693
|
+
const changed = nextPlayer === null ? hostPlayer !== null : hostPlayer === null || nextPlayer.name !== hostPlayer.name || nextPlayer.avatarUrl !== hostPlayer.avatarUrl;
|
|
694
|
+
hostPlayer = nextPlayer;
|
|
695
|
+
if (changed) {
|
|
696
|
+
const snapshot = nextPlayer ? { name: nextPlayer.name, avatarUrl: nextPlayer.avatarUrl } : null;
|
|
697
|
+
for (let i = 0; i < playerChangeHandlers.length; i++) {
|
|
698
|
+
safeCall(playerChangeHandlers[i], snapshot);
|
|
699
|
+
}
|
|
700
|
+
}
|
|
372
701
|
}
|
|
373
702
|
const rewardedAds = msg.rewardedAds;
|
|
374
703
|
if (rewardedAds && typeof rewardedAds === "object") {
|
|
@@ -500,6 +829,7 @@ function createBBArcade() {
|
|
|
500
829
|
let resolved = false;
|
|
501
830
|
let status = "unavailable";
|
|
502
831
|
let rewardOffered = false;
|
|
832
|
+
let adShown = false;
|
|
503
833
|
const waitTimer = setTimeout(function() {
|
|
504
834
|
if (rewardOffered || resolved) return;
|
|
505
835
|
const timeout = Object.assign(
|
|
@@ -544,6 +874,7 @@ function createBBArcade() {
|
|
|
544
874
|
}
|
|
545
875
|
post("rewarded_ad", void 0, Object.assign({ event: "started" }, base));
|
|
546
876
|
try {
|
|
877
|
+
adShown = true;
|
|
547
878
|
showAdFn();
|
|
548
879
|
} catch (err) {
|
|
549
880
|
const showError = Object.assign(
|
|
@@ -593,7 +924,13 @@ function createBBArcade() {
|
|
|
593
924
|
},
|
|
594
925
|
adBreakDone: function(placementInfo) {
|
|
595
926
|
if (resolved) return;
|
|
596
|
-
const result = rewardOffered || status !== "unavailable" ? {
|
|
927
|
+
const result = rewardOffered || status !== "unavailable" ? {
|
|
928
|
+
// A reward was offered but the ad never reached the screen
|
|
929
|
+
// (the game retained show() and let the break lapse): the
|
|
930
|
+
// break is over without a view, so resolve 'dismissed',
|
|
931
|
+
// not the non-terminal-looking 'ready'.
|
|
932
|
+
status: status === "ready" && !adShown ? "dismissed" : status
|
|
933
|
+
} : { status: "unavailable", error: "no_rewarded_ad" };
|
|
597
934
|
if (placementInfo && typeof placementInfo === "object") {
|
|
598
935
|
result.breakStatus = cleanText(
|
|
599
936
|
placementInfo.breakStatus
|
|
@@ -764,6 +1101,16 @@ function createBBArcade() {
|
|
|
764
1101
|
if (!hostnameAllowed(event.origin, DEFAULT_ALLOW)) return;
|
|
765
1102
|
applyHostConfig(event.data);
|
|
766
1103
|
});
|
|
1104
|
+
const storage = createStorageController({
|
|
1105
|
+
save: function(blob) {
|
|
1106
|
+
return request("save", blob);
|
|
1107
|
+
},
|
|
1108
|
+
load: function() {
|
|
1109
|
+
return request("load");
|
|
1110
|
+
},
|
|
1111
|
+
byteLength: utf8ByteLength,
|
|
1112
|
+
maxBytes: MAX_SAVE_BYTES
|
|
1113
|
+
});
|
|
767
1114
|
const sdk = {
|
|
768
1115
|
lockToHost,
|
|
769
1116
|
init,
|
|
@@ -796,12 +1143,29 @@ function createBBArcade() {
|
|
|
796
1143
|
prepareRewardedBreak: prepareRewardedAd,
|
|
797
1144
|
rewardedBreak,
|
|
798
1145
|
save: function(blob) {
|
|
799
|
-
|
|
1146
|
+
const data = String(blob);
|
|
1147
|
+
if (utf8ByteLength(data) > MAX_SAVE_BYTES) {
|
|
1148
|
+
return Promise.reject(sdkError("too_large"));
|
|
1149
|
+
}
|
|
1150
|
+
if (storage.active()) return storage.writeApp(data);
|
|
1151
|
+
return request("save", data);
|
|
800
1152
|
},
|
|
801
1153
|
load: function() {
|
|
802
|
-
return request("load")
|
|
1154
|
+
return request("load").then(function(raw) {
|
|
1155
|
+
return parseEnvelope(raw).app;
|
|
1156
|
+
});
|
|
803
1157
|
},
|
|
1158
|
+
storage,
|
|
804
1159
|
getPlayer,
|
|
1160
|
+
onPlayerChange: function(handler) {
|
|
1161
|
+
if (typeof handler !== "function") return function() {
|
|
1162
|
+
};
|
|
1163
|
+
playerChangeHandlers.push(handler);
|
|
1164
|
+
return function() {
|
|
1165
|
+
const idx = playerChangeHandlers.indexOf(handler);
|
|
1166
|
+
if (idx !== -1) playerChangeHandlers.splice(idx, 1);
|
|
1167
|
+
};
|
|
1168
|
+
},
|
|
805
1169
|
getVariant: function(key, variants) {
|
|
806
1170
|
const sorted = Array.isArray(variants) ? variants.slice().sort() : [];
|
|
807
1171
|
const fallback = sorted.length > 0 ? sorted[0] : null;
|
|
@@ -867,7 +1231,17 @@ function createInertBBArcade() {
|
|
|
867
1231
|
rewardedBreak: () => Promise.resolve(false),
|
|
868
1232
|
save: () => Promise.reject(sdkError2("unsupported")),
|
|
869
1233
|
load: () => Promise.reject(sdkError2("unsupported")),
|
|
1234
|
+
// No window to shim and nothing to persist to: report the honest mode
|
|
1235
|
+
// rather than pretending an install succeeded.
|
|
1236
|
+
storage: {
|
|
1237
|
+
install: () => "memory",
|
|
1238
|
+
ready: () => Promise.resolve("memory"),
|
|
1239
|
+
flush: () => Promise.resolve(),
|
|
1240
|
+
mode: "memory"
|
|
1241
|
+
},
|
|
870
1242
|
getPlayer: () => Promise.resolve(null),
|
|
1243
|
+
onPlayerChange: () => () => {
|
|
1244
|
+
},
|
|
871
1245
|
getVariant: (key, variants) => {
|
|
872
1246
|
const sorted = Array.isArray(variants) ? variants.slice().sort() : [];
|
|
873
1247
|
return Promise.resolve(sorted.length > 0 ? sorted[0] : null);
|
|
@@ -885,4 +1259,4 @@ export {
|
|
|
885
1259
|
BBArcade,
|
|
886
1260
|
src_default
|
|
887
1261
|
};
|
|
888
|
-
//# sourceMappingURL=chunk-
|
|
1262
|
+
//# sourceMappingURL=chunk-PYW5F45R.js.map
|