@hyve-sdk/js 2.11.2 → 2.13.0-canary.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/README.md +16 -2
- package/dist/index.d.mts +196 -8
- package/dist/index.d.ts +196 -8
- package/dist/index.js +295 -12
- package/dist/index.mjs +295 -12
- package/dist/react.d.mts +76 -4
- package/dist/react.d.ts +76 -4
- package/dist/react.js +292 -12
- package/dist/react.mjs +292 -12
- package/package.json +16 -13
package/dist/index.js
CHANGED
|
@@ -198,17 +198,26 @@ var NativeMessageType = /* @__PURE__ */ ((NativeMessageType2) => {
|
|
|
198
198
|
NativeMessageType2["REQUEST_NOTIFICATION_PERMISSION"] = "REQUEST_NOTIFICATION_PERMISSION";
|
|
199
199
|
NativeMessageType2["GET_PRODUCTS"] = "GET_PRODUCTS";
|
|
200
200
|
NativeMessageType2["PURCHASE"] = "PURCHASE";
|
|
201
|
+
NativeMessageType2["SHOW_REWARDED_AD"] = "SHOW_REWARDED_AD";
|
|
202
|
+
NativeMessageType2["SHOW_INTERSTITIAL_AD"] = "SHOW_INTERSTITIAL_AD";
|
|
201
203
|
NativeMessageType2["IAP_AVAILABILITY_RESULT"] = "IAP_AVAILABILITY_RESULT";
|
|
202
204
|
NativeMessageType2["PUSH_PERMISSION_GRANTED"] = "PUSH_PERMISSION_GRANTED";
|
|
203
205
|
NativeMessageType2["PUSH_PERMISSION_DENIED"] = "PUSH_PERMISSION_DENIED";
|
|
204
206
|
NativeMessageType2["PRODUCTS_RESULT"] = "PRODUCTS_RESULT";
|
|
205
207
|
NativeMessageType2["PURCHASE_COMPLETE"] = "PURCHASE_COMPLETE";
|
|
206
208
|
NativeMessageType2["PURCHASE_ERROR"] = "PURCHASE_ERROR";
|
|
209
|
+
NativeMessageType2["AD_RESULT"] = "AD_RESULT";
|
|
207
210
|
return NativeMessageType2;
|
|
208
211
|
})(NativeMessageType || {});
|
|
209
212
|
var NativeBridge = class {
|
|
210
213
|
static handlers = /* @__PURE__ */ new Map();
|
|
211
214
|
static isInitialized = false;
|
|
215
|
+
/**
|
|
216
|
+
* Pending `sendAdRequest()` promises, keyed by the ad type native echoes
|
|
217
|
+
* back in `AD_RESULT.type` ("rewarded" | "interstitial"). One in-flight
|
|
218
|
+
* request per type — ads are shown sequentially.
|
|
219
|
+
*/
|
|
220
|
+
static adResultResolvers = /* @__PURE__ */ new Map();
|
|
212
221
|
/**
|
|
213
222
|
* Checks if the app is running inside a React Native WebView
|
|
214
223
|
*/
|
|
@@ -261,16 +270,20 @@ var NativeBridge = class {
|
|
|
261
270
|
"PUSH_PERMISSION_DENIED" /* PUSH_PERMISSION_DENIED */,
|
|
262
271
|
"PRODUCTS_RESULT" /* PRODUCTS_RESULT */,
|
|
263
272
|
"PURCHASE_COMPLETE" /* PURCHASE_COMPLETE */,
|
|
264
|
-
"PURCHASE_ERROR" /* PURCHASE_ERROR
|
|
273
|
+
"PURCHASE_ERROR" /* PURCHASE_ERROR */,
|
|
274
|
+
"AD_RESULT" /* AD_RESULT */
|
|
265
275
|
];
|
|
266
276
|
if (!nativeResponseTypes.includes(data.type)) {
|
|
267
277
|
return;
|
|
268
278
|
}
|
|
279
|
+
if (data.type === "AD_RESULT" /* AD_RESULT */) {
|
|
280
|
+
this.resolveAdResult(data.payload);
|
|
281
|
+
}
|
|
269
282
|
const handler = this.handlers.get(data.type);
|
|
270
283
|
if (handler) {
|
|
271
284
|
logger.debug(`[NativeBridge] Handling message: ${data.type}`);
|
|
272
285
|
handler(data.payload);
|
|
273
|
-
} else {
|
|
286
|
+
} else if (data.type !== "AD_RESULT" /* AD_RESULT */) {
|
|
274
287
|
logger.warn(`[NativeBridge] No handler registered for: ${data.type}`);
|
|
275
288
|
}
|
|
276
289
|
} catch (error) {
|
|
@@ -396,6 +409,81 @@ var NativeBridge = class {
|
|
|
396
409
|
static purchase(productId, userId) {
|
|
397
410
|
this.send("PURCHASE" /* PURCHASE */, { productId, userId });
|
|
398
411
|
}
|
|
412
|
+
/**
|
|
413
|
+
* Sends a native ad request and resolves with the `AD_RESULT` native sends
|
|
414
|
+
* back. Never rejects — a missing native context, timeout, or superseded
|
|
415
|
+
* request resolves to `{ success: false }` with an error code so callers can
|
|
416
|
+
* decide whether to fall back to the web ad path.
|
|
417
|
+
*
|
|
418
|
+
* @param messageType - `SHOW_REWARDED_AD` or `SHOW_INTERSTITIAL_AD`
|
|
419
|
+
* @param payload - `{ gameId, format, placement? }`
|
|
420
|
+
* @param timeoutMs - How long to wait for `AD_RESULT` before giving up
|
|
421
|
+
*
|
|
422
|
+
* @example
|
|
423
|
+
* const result = await NativeBridge.sendAdRequest(
|
|
424
|
+
* NativeMessageType.SHOW_REWARDED_AD,
|
|
425
|
+
* { gameId: "123", format: "rewarded", placement: "level_end" },
|
|
426
|
+
* );
|
|
427
|
+
* if (result.success) grantReward();
|
|
428
|
+
*/
|
|
429
|
+
static sendAdRequest(messageType, payload, timeoutMs = 12e4) {
|
|
430
|
+
const expectedType = messageType === "SHOW_REWARDED_AD" /* SHOW_REWARDED_AD */ ? "rewarded" : "interstitial";
|
|
431
|
+
return new Promise((resolve) => {
|
|
432
|
+
if (!this.isNativeContext()) {
|
|
433
|
+
resolve({ type: expectedType, success: false, error: "no_native_context" });
|
|
434
|
+
return;
|
|
435
|
+
}
|
|
436
|
+
this.initialize();
|
|
437
|
+
const existing = this.adResultResolvers.get(expectedType);
|
|
438
|
+
if (existing) {
|
|
439
|
+
logger.warn(`[NativeBridge] Superseding in-flight ${expectedType} ad request`);
|
|
440
|
+
existing({ type: expectedType, success: false, error: "superseded" });
|
|
441
|
+
}
|
|
442
|
+
let settled = false;
|
|
443
|
+
const timer = setTimeout(() => {
|
|
444
|
+
if (settled) return;
|
|
445
|
+
settled = true;
|
|
446
|
+
this.adResultResolvers.delete(expectedType);
|
|
447
|
+
logger.warn(`[NativeBridge] Ad request timed out: ${expectedType}`);
|
|
448
|
+
resolve({ type: expectedType, success: false, error: "timeout" });
|
|
449
|
+
}, timeoutMs);
|
|
450
|
+
this.adResultResolvers.set(expectedType, (result) => {
|
|
451
|
+
if (settled) return;
|
|
452
|
+
settled = true;
|
|
453
|
+
clearTimeout(timer);
|
|
454
|
+
this.adResultResolvers.delete(expectedType);
|
|
455
|
+
resolve(result);
|
|
456
|
+
});
|
|
457
|
+
this.send(messageType, payload);
|
|
458
|
+
});
|
|
459
|
+
}
|
|
460
|
+
/**
|
|
461
|
+
* Registers a handler invoked for every `AD_RESULT` message from native,
|
|
462
|
+
* in addition to resolving any pending {@link sendAdRequest} promise.
|
|
463
|
+
* Useful for diagnostics or availability tracking.
|
|
464
|
+
*
|
|
465
|
+
* @param handler - Called with the raw `AD_RESULT` payload
|
|
466
|
+
*/
|
|
467
|
+
static onAdResult(handler) {
|
|
468
|
+
this.on("AD_RESULT" /* AD_RESULT */, handler);
|
|
469
|
+
}
|
|
470
|
+
/**
|
|
471
|
+
* Resolves the pending {@link sendAdRequest} promise that matches an
|
|
472
|
+
* incoming `AD_RESULT` payload. No-op when nothing is waiting (e.g. a late
|
|
473
|
+
* result after a timeout).
|
|
474
|
+
*/
|
|
475
|
+
static resolveAdResult(payload) {
|
|
476
|
+
if (!payload?.type) {
|
|
477
|
+
logger.warn("[NativeBridge] AD_RESULT received without a type");
|
|
478
|
+
return;
|
|
479
|
+
}
|
|
480
|
+
const resolver = this.adResultResolvers.get(payload.type);
|
|
481
|
+
if (resolver) {
|
|
482
|
+
resolver(payload);
|
|
483
|
+
} else {
|
|
484
|
+
logger.debug(`[NativeBridge] No pending ad request for: ${payload.type}`);
|
|
485
|
+
}
|
|
486
|
+
}
|
|
399
487
|
};
|
|
400
488
|
|
|
401
489
|
// src/utils/jwt.ts
|
|
@@ -752,10 +840,12 @@ function getAttributionData() {
|
|
|
752
840
|
}
|
|
753
841
|
|
|
754
842
|
// src/services/ads.ts
|
|
843
|
+
var FALLBACK_ERROR_CODES = ["not_configured", "config_fetch_failed"];
|
|
755
844
|
var AdsService = class {
|
|
756
845
|
config = {
|
|
757
846
|
sound: "on",
|
|
758
847
|
debug: false,
|
|
848
|
+
useNativeAds: false,
|
|
759
849
|
onBeforeAd: () => {
|
|
760
850
|
},
|
|
761
851
|
onAfterAd: () => {
|
|
@@ -766,6 +856,16 @@ var AdsService = class {
|
|
|
766
856
|
// Cached init promise — ensures adConfig() is only called once
|
|
767
857
|
initPromise = null;
|
|
768
858
|
ready = false;
|
|
859
|
+
// Game this SDK instance serves — sent to native so it can resolve unit IDs.
|
|
860
|
+
// The SDK never stores or resolves unit IDs itself (Decision 7).
|
|
861
|
+
gameId = null;
|
|
862
|
+
/**
|
|
863
|
+
* Set the game ID used in native ad requests. Called by the client once the
|
|
864
|
+
* game ID is known (from URL params or JWT). No-op for the web ad path.
|
|
865
|
+
*/
|
|
866
|
+
setGameId(gameId) {
|
|
867
|
+
this.gameId = gameId;
|
|
868
|
+
}
|
|
769
869
|
/**
|
|
770
870
|
* Optionally configure the ads service.
|
|
771
871
|
* Not required — ads work without calling this.
|
|
@@ -779,7 +879,10 @@ var AdsService = class {
|
|
|
779
879
|
onRewardEarned: config.onRewardEarned ?? this.config.onRewardEarned
|
|
780
880
|
};
|
|
781
881
|
if (this.config.debug) {
|
|
782
|
-
logger.debug("[AdsService] Configuration updated:", {
|
|
882
|
+
logger.debug("[AdsService] Configuration updated:", {
|
|
883
|
+
sound: this.config.sound,
|
|
884
|
+
useNativeAds: this.config.useNativeAds
|
|
885
|
+
});
|
|
783
886
|
}
|
|
784
887
|
}
|
|
785
888
|
/**
|
|
@@ -816,10 +919,93 @@ var AdsService = class {
|
|
|
816
919
|
}
|
|
817
920
|
/**
|
|
818
921
|
* Show an ad. Auto-initializes on the first call.
|
|
819
|
-
*
|
|
922
|
+
*
|
|
923
|
+
* Inside the Hyve mobile shell (`window.ReactNativeWebView` present) with
|
|
924
|
+
* `useNativeAds` enabled, the request is routed to native AdMob via the
|
|
925
|
+
* bridge. Otherwise — or when native reports the slot is `not_configured` /
|
|
926
|
+
* `config_fetch_failed` — it falls back to the Google H5 web path.
|
|
927
|
+
*
|
|
928
|
+
* Returns `success: false` if ads are disabled or unavailable.
|
|
929
|
+
*
|
|
930
|
+
* @param type - Ad type to show
|
|
931
|
+
* @param placement - Optional placement key, forwarded to native; ignored on
|
|
932
|
+
* the web path (H5 has no placement concept).
|
|
820
933
|
*/
|
|
821
|
-
async show(type) {
|
|
934
|
+
async show(type, placement) {
|
|
822
935
|
const requestedAt = Date.now();
|
|
936
|
+
if (this.isNativeAdsContext()) {
|
|
937
|
+
const nativeResult = await this.showNative(type, placement, requestedAt);
|
|
938
|
+
if (nativeResult) return nativeResult;
|
|
939
|
+
}
|
|
940
|
+
return this.showWeb(type, requestedAt, true);
|
|
941
|
+
}
|
|
942
|
+
/**
|
|
943
|
+
* True when running inside the Hyve mobile shell with native ads enabled.
|
|
944
|
+
*/
|
|
945
|
+
isNativeAdsContext() {
|
|
946
|
+
return NativeBridge.isNativeContext() && this.config.useNativeAds === true;
|
|
947
|
+
}
|
|
948
|
+
/**
|
|
949
|
+
* Route an ad request to native AdMob via the bridge (Decision 7 — native
|
|
950
|
+
* owns unit-ID resolution; the SDK only sends `{ gameId, format, placement }`).
|
|
951
|
+
*
|
|
952
|
+
* Returns the resolved `AdResult`, or `null` to indicate the caller should
|
|
953
|
+
* fall back to the web ad path for this single call.
|
|
954
|
+
*/
|
|
955
|
+
async showNative(type, placement, requestedAt) {
|
|
956
|
+
if (!this.gameId) {
|
|
957
|
+
if (this.config.debug) {
|
|
958
|
+
logger.debug("[AdsService] Native ads enabled but no gameId set \u2014 using web path");
|
|
959
|
+
}
|
|
960
|
+
return null;
|
|
961
|
+
}
|
|
962
|
+
const format = type === "rewarded" ? "rewarded" : "interstitial";
|
|
963
|
+
const messageType = type === "rewarded" ? "SHOW_REWARDED_AD" /* SHOW_REWARDED_AD */ : "SHOW_INTERSTITIAL_AD" /* SHOW_INTERSTITIAL_AD */;
|
|
964
|
+
if (this.config.debug) {
|
|
965
|
+
logger.debug(`[AdsService] Requesting native ${type} ad (format: ${format})`, {
|
|
966
|
+
gameId: this.gameId,
|
|
967
|
+
placement
|
|
968
|
+
});
|
|
969
|
+
}
|
|
970
|
+
this.config.onBeforeAd(type);
|
|
971
|
+
const result = await NativeBridge.sendAdRequest(messageType, {
|
|
972
|
+
gameId: this.gameId,
|
|
973
|
+
format,
|
|
974
|
+
placement
|
|
975
|
+
});
|
|
976
|
+
const completedAt = Date.now();
|
|
977
|
+
if (result.error && FALLBACK_ERROR_CODES.includes(result.error)) {
|
|
978
|
+
if (this.config.debug) {
|
|
979
|
+
logger.debug(`[AdsService] Native ad ${result.error} \u2014 falling back to web path`);
|
|
980
|
+
}
|
|
981
|
+
return this.showWeb(type, requestedAt, false);
|
|
982
|
+
}
|
|
983
|
+
this.config.onAfterAd(type);
|
|
984
|
+
if (type === "rewarded" && result.success) {
|
|
985
|
+
this.config.onRewardEarned();
|
|
986
|
+
}
|
|
987
|
+
if (this.config.debug) {
|
|
988
|
+
logger.debug("[AdsService] Native ad result:", {
|
|
989
|
+
type,
|
|
990
|
+
success: result.success,
|
|
991
|
+
error: result.error
|
|
992
|
+
});
|
|
993
|
+
}
|
|
994
|
+
return {
|
|
995
|
+
success: result.success,
|
|
996
|
+
type,
|
|
997
|
+
error: result.error ? new Error(result.error) : void 0,
|
|
998
|
+
requestedAt,
|
|
999
|
+
completedAt
|
|
1000
|
+
};
|
|
1001
|
+
}
|
|
1002
|
+
/**
|
|
1003
|
+
* Show an ad via the Google H5 web path. Auto-initializes on first call.
|
|
1004
|
+
*
|
|
1005
|
+
* @param fireBeforeAd - When false, `onBeforeAd` is not fired (the native
|
|
1006
|
+
* fallback path already fired it before delegating here).
|
|
1007
|
+
*/
|
|
1008
|
+
async showWeb(type, requestedAt, fireBeforeAd) {
|
|
823
1009
|
const ready = await this.initialize();
|
|
824
1010
|
if (!ready || !window.adBreak) {
|
|
825
1011
|
return {
|
|
@@ -830,12 +1016,15 @@ var AdsService = class {
|
|
|
830
1016
|
completedAt: Date.now()
|
|
831
1017
|
};
|
|
832
1018
|
}
|
|
833
|
-
return this.showAdBreak(type);
|
|
1019
|
+
return this.showAdBreak(type, fireBeforeAd);
|
|
834
1020
|
}
|
|
835
1021
|
/**
|
|
836
1022
|
* Show an ad break via the Google H5 API.
|
|
1023
|
+
*
|
|
1024
|
+
* @param fireBeforeAd - When false, skips `onBeforeAd` (already fired by the
|
|
1025
|
+
* native fallback path that delegated here).
|
|
837
1026
|
*/
|
|
838
|
-
async showAdBreak(type) {
|
|
1027
|
+
async showAdBreak(type, fireBeforeAd = true) {
|
|
839
1028
|
const requestedAt = Date.now();
|
|
840
1029
|
return new Promise((resolve) => {
|
|
841
1030
|
const googleType = type === "rewarded" ? "reward" : type === "preroll" ? "start" : "next";
|
|
@@ -843,7 +1032,9 @@ var AdsService = class {
|
|
|
843
1032
|
if (this.config.debug) {
|
|
844
1033
|
logger.debug(`[AdsService] Showing ${type} ad`);
|
|
845
1034
|
}
|
|
846
|
-
|
|
1035
|
+
if (fireBeforeAd) {
|
|
1036
|
+
this.config.onBeforeAd(type);
|
|
1037
|
+
}
|
|
847
1038
|
const adBreakConfig = {
|
|
848
1039
|
type: googleType,
|
|
849
1040
|
name: adName,
|
|
@@ -2017,6 +2208,7 @@ var HyveClient = class {
|
|
|
2017
2208
|
this.gameId = params.gameId;
|
|
2018
2209
|
logger.info("Game ID extracted from game-id parameter:", this.gameId);
|
|
2019
2210
|
}
|
|
2211
|
+
this.adsService.setGameId(this.gameId);
|
|
2020
2212
|
if (this.jwtToken) {
|
|
2021
2213
|
logger.info("Authentication successful via JWT");
|
|
2022
2214
|
} else {
|
|
@@ -2122,6 +2314,93 @@ var HyveClient = class {
|
|
|
2122
2314
|
return false;
|
|
2123
2315
|
}
|
|
2124
2316
|
}
|
|
2317
|
+
/**
|
|
2318
|
+
* Required lifecycle telemetry — Session start.
|
|
2319
|
+
* See https://docs.hyve.gg/docs/telemetry#required-lifecycle-events
|
|
2320
|
+
*/
|
|
2321
|
+
async sessionStart() {
|
|
2322
|
+
return this.sendTelemetry("game", "session", "start");
|
|
2323
|
+
}
|
|
2324
|
+
/**
|
|
2325
|
+
* Required lifecycle telemetry — Session end.
|
|
2326
|
+
*/
|
|
2327
|
+
async sessionEnd() {
|
|
2328
|
+
return this.sendTelemetry("game", "session", "end");
|
|
2329
|
+
}
|
|
2330
|
+
/**
|
|
2331
|
+
* Required lifecycle telemetry — Lobby loading start.
|
|
2332
|
+
*/
|
|
2333
|
+
async lobbyLoadingStart() {
|
|
2334
|
+
return this.sendTelemetry("game", "loading", "start");
|
|
2335
|
+
}
|
|
2336
|
+
/**
|
|
2337
|
+
* Required lifecycle telemetry — Lobby loading end.
|
|
2338
|
+
*/
|
|
2339
|
+
async lobbyLoadingEnd() {
|
|
2340
|
+
return this.sendTelemetry("game", "loading", "end");
|
|
2341
|
+
}
|
|
2342
|
+
/**
|
|
2343
|
+
* Required lifecycle telemetry — Game loading start.
|
|
2344
|
+
*/
|
|
2345
|
+
async gameLoadingStart() {
|
|
2346
|
+
return this.sendTelemetry("game", "game_loading", "start");
|
|
2347
|
+
}
|
|
2348
|
+
/**
|
|
2349
|
+
* Required lifecycle telemetry — Game loading end.
|
|
2350
|
+
*/
|
|
2351
|
+
async gameLoadingEnd() {
|
|
2352
|
+
return this.sendTelemetry("game", "game_loading", "end");
|
|
2353
|
+
}
|
|
2354
|
+
/**
|
|
2355
|
+
* Required lifecycle telemetry — Lobby initialization.
|
|
2356
|
+
*/
|
|
2357
|
+
async lobbyInit() {
|
|
2358
|
+
return this.sendTelemetry("game", "lobby", "init");
|
|
2359
|
+
}
|
|
2360
|
+
/**
|
|
2361
|
+
* Required lifecycle telemetry — Gameplay end.
|
|
2362
|
+
* Also notifies CrazyGames that gameplay has stopped.
|
|
2363
|
+
*/
|
|
2364
|
+
async gameplayEnd() {
|
|
2365
|
+
if (this.crazyGamesService) {
|
|
2366
|
+
if (this.crazyGamesInitPromise) await this.crazyGamesInitPromise;
|
|
2367
|
+
this.crazyGamesService.gameplayStop();
|
|
2368
|
+
}
|
|
2369
|
+
return this.sendTelemetry("game", "gameplay", "end");
|
|
2370
|
+
}
|
|
2371
|
+
/**
|
|
2372
|
+
* Required lifecycle telemetry — Store opened.
|
|
2373
|
+
*/
|
|
2374
|
+
async storeOpen() {
|
|
2375
|
+
return this.sendTelemetry("game", "store", "start");
|
|
2376
|
+
}
|
|
2377
|
+
/**
|
|
2378
|
+
* Required lifecycle telemetry — Purchase complete.
|
|
2379
|
+
* @param itemName Name of the purchased item (required by the platform)
|
|
2380
|
+
*/
|
|
2381
|
+
async purchaseComplete(itemName) {
|
|
2382
|
+
return this.sendTelemetry("game", "purchase", "complete", null, null, {
|
|
2383
|
+
item_name: itemName
|
|
2384
|
+
});
|
|
2385
|
+
}
|
|
2386
|
+
/**
|
|
2387
|
+
* Required lifecycle telemetry — Purchase failed.
|
|
2388
|
+
* @param itemName Name of the item the purchase was for
|
|
2389
|
+
*/
|
|
2390
|
+
async purchaseFail(itemName) {
|
|
2391
|
+
return this.sendTelemetry("game", "purchase", "fail", null, null, {
|
|
2392
|
+
item_name: itemName
|
|
2393
|
+
});
|
|
2394
|
+
}
|
|
2395
|
+
/**
|
|
2396
|
+
* Required lifecycle telemetry — Purchase cancelled.
|
|
2397
|
+
* @param itemName Name of the item the purchase was for
|
|
2398
|
+
*/
|
|
2399
|
+
async purchaseCancel(itemName) {
|
|
2400
|
+
return this.sendTelemetry("game", "purchase", "cancel", null, null, {
|
|
2401
|
+
item_name: itemName
|
|
2402
|
+
});
|
|
2403
|
+
}
|
|
2125
2404
|
/**
|
|
2126
2405
|
* Makes an authenticated API call using the JWT token
|
|
2127
2406
|
* @param endpoint API endpoint path (will be appended to base URL)
|
|
@@ -2243,6 +2522,7 @@ var HyveClient = class {
|
|
|
2243
2522
|
this.userId = null;
|
|
2244
2523
|
this.jwtToken = null;
|
|
2245
2524
|
this.gameId = null;
|
|
2525
|
+
this.adsService.setGameId(null);
|
|
2246
2526
|
logger.info("User logged out");
|
|
2247
2527
|
}
|
|
2248
2528
|
/**
|
|
@@ -2417,9 +2697,11 @@ var HyveClient = class {
|
|
|
2417
2697
|
/**
|
|
2418
2698
|
* Show an ad
|
|
2419
2699
|
* @param type Type of ad to show ('rewarded', 'interstitial', or 'preroll')
|
|
2700
|
+
* @param placement Optional placement key, forwarded to the native AdMob path
|
|
2701
|
+
* to resolve a per-placement unit ID. Ignored on the web (H5/Playgama) path.
|
|
2420
2702
|
* @returns Promise resolving to ad result
|
|
2421
2703
|
*/
|
|
2422
|
-
async showAd(type) {
|
|
2704
|
+
async showAd(type, placement) {
|
|
2423
2705
|
if (this.crazyGamesService) {
|
|
2424
2706
|
if (this.crazyGamesInitPromise) {
|
|
2425
2707
|
await this.crazyGamesInitPromise;
|
|
@@ -2458,17 +2740,18 @@ var HyveClient = class {
|
|
|
2458
2740
|
});
|
|
2459
2741
|
}
|
|
2460
2742
|
}
|
|
2461
|
-
return this.adsService.show(type);
|
|
2743
|
+
return this.adsService.show(type, placement);
|
|
2462
2744
|
}
|
|
2463
2745
|
/**
|
|
2464
|
-
*
|
|
2465
|
-
*
|
|
2746
|
+
* Required lifecycle telemetry — Gameplay start.
|
|
2747
|
+
* Also notifies CrazyGames that gameplay has started.
|
|
2466
2748
|
*/
|
|
2467
2749
|
async gameplayStart() {
|
|
2468
2750
|
if (this.crazyGamesService) {
|
|
2469
2751
|
if (this.crazyGamesInitPromise) await this.crazyGamesInitPromise;
|
|
2470
2752
|
this.crazyGamesService.gameplayStart();
|
|
2471
2753
|
}
|
|
2754
|
+
return this.sendTelemetry("game", "gameplay", "start");
|
|
2472
2755
|
}
|
|
2473
2756
|
/**
|
|
2474
2757
|
* Notifies CrazyGames that gameplay has stopped.
|