@series-inc/rundot-game-sdk 5.24.0-beta.3 → 5.24.0-beta.5
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 +4 -4
- package/dist/{AdsApi-CscCuIMY.d.ts → AdsApi-CUkS1Vn7.d.ts} +59 -6
- package/dist/{LeaderboardApi-CrWxakrr.d.ts → LeaderboardApi-Bp1wndvJ.d.ts} +1 -1
- package/dist/{MultiplayerApi-nnrGTTcO.d.ts → MultiplayerApi-TQr01JT7.d.ts} +9 -1
- package/dist/{SyncplayRoomTransport-Bfv_KE63.d.ts → SyncplayRoomTransport-DUI16EQk.d.ts} +32 -6
- package/dist/{callRemoteFunction-NBIrdLoa.d.ts → callRemoteFunction-DeGLqhjj.d.ts} +17 -1
- package/dist/chunk-4J2RDAOR.js +12 -0
- package/dist/chunk-4J2RDAOR.js.map +1 -0
- package/dist/{chunk-WFRNUODW.js → chunk-56UNQZIB.js} +4 -30
- package/dist/chunk-56UNQZIB.js.map +1 -0
- package/dist/{chunk-KIA4VGSK.js → chunk-BXDFAXHX.js} +133 -9
- package/dist/chunk-BXDFAXHX.js.map +1 -0
- package/dist/{chunk-3GKY3LY5.js → chunk-C5APEUTZ.js} +2 -2
- package/dist/chunk-C5APEUTZ.js.map +1 -0
- package/dist/{chunk-G7JAUUTF.js → chunk-OSKQDUTI.js} +46 -128
- package/dist/chunk-OSKQDUTI.js.map +1 -0
- package/dist/{chunk-RIRXVDY4.js → chunk-PLVPZF7Z.js} +3 -3
- package/dist/{chunk-RIRXVDY4.js.map → chunk-PLVPZF7Z.js.map} +1 -1
- package/dist/{chunk-USEBN3PO.js → chunk-Q6SGGAIV.js} +35 -10
- package/dist/chunk-Q6SGGAIV.js.map +1 -0
- package/dist/{chunk-CZONPFQG.js → chunk-RPHL3EGZ.js} +175 -38
- package/dist/chunk-RPHL3EGZ.js.map +1 -0
- package/dist/{chunk-YQEDG3Z2.js → chunk-SFJILJFQ.js} +29 -3
- package/dist/chunk-SFJILJFQ.js.map +1 -0
- package/dist/chunk-SRGK6ONJ.js +10433 -0
- package/dist/chunk-SRGK6ONJ.js.map +1 -0
- package/dist/core-7QSNRRMV.js +3 -0
- package/dist/{core-6DQFSOBL.js.map → core-7QSNRRMV.js.map} +1 -1
- package/dist/host-http.d.ts +4 -20
- package/dist/host-http.js +2 -2
- package/dist/{index-Dl2PfHSb.d.ts → index-B_PIWjhp.d.ts} +2 -2
- package/dist/index.d.ts +24 -13
- package/dist/index.js +6 -6
- package/dist/mp-server/index.d.ts +1 -1
- package/dist/{multiplayer-service-BXMJaXot.d.ts → multiplayer-service-C0k76UQR.d.ts} +4 -0
- package/dist/physics3d-vehicle-1FxMRVBa.d.ts +727 -0
- package/dist/playground/index.js +8 -8
- package/dist/playground/index.js.map +1 -1
- package/dist/rundot-game-api/index.d.ts +5 -5
- package/dist/rundot-game-api/index.js +7 -7
- package/dist/rundot-game-api/index.js.map +1 -1
- package/dist/{secret-protocol-hnhTHLBs.d.ts → secret-protocol-DY332qWW.d.ts} +1 -1
- package/dist/syncplay/browser.d.ts +57 -550
- package/dist/syncplay/browser.js +668 -7045
- package/dist/syncplay/browser.js.map +1 -1
- package/dist/syncplay/creator.d.ts +5 -5
- package/dist/syncplay/creator.js +2 -2
- package/dist/syncplay/index.d.ts +3 -3
- package/dist/syncplay/index.js +2 -2
- package/dist/syncplay/node.d.ts +2 -2
- package/dist/syncplay/node.js +16 -8
- package/dist/syncplay/node.js.map +1 -1
- package/dist/syncplay/testing.d.ts +114 -5
- package/dist/syncplay/testing.js +375 -11
- package/dist/syncplay/testing.js.map +1 -1
- package/dist/{types-BV8uchSD.d.ts → types-ChJ9TO_o.d.ts} +4 -0
- package/dist/vite/{dev-server-XDCK4DL7.js → dev-server-TKX6XSJ6.js} +58 -5
- package/dist/vite/dev-server-TKX6XSJ6.js.map +1 -0
- package/dist/vite/index.d.ts +3 -3
- package/dist/vite/index.js +40 -5
- package/dist/vite/index.js.map +1 -1
- package/dist/webview/index.js +1 -1
- package/docs/README.md +3 -3
- package/docs/SUMMARY.md +1 -1
- package/docs/agents-index.txt +1 -1
- package/docs/rundot-developer-platform/api/ACCESS_GATE.md +3 -4
- package/docs/rundot-developer-platform/api/AI.md +37 -7
- package/docs/rundot-developer-platform/api/ASSETS.md +3 -3
- package/docs/rundot-developer-platform/api/AVATAR_3D.md +3 -3
- package/docs/rundot-developer-platform/api/CLIPS.md +1 -1
- package/docs/rundot-developer-platform/api/CREDITS.md +22 -0
- package/docs/rundot-developer-platform/api/EMBEDDED_LIBRARIES.md +2 -2
- package/docs/rundot-developer-platform/api/HAPTICS.md +1 -1
- package/docs/rundot-developer-platform/api/LIVEOPS.md +1 -1
- package/docs/rundot-developer-platform/api/LOGGING.md +1 -1
- package/docs/rundot-developer-platform/api/MULTIPLAYER.md +1 -1
- package/docs/rundot-developer-platform/api/PRELOADER.md +3 -3
- package/docs/rundot-developer-platform/api/RATE_LIMITS.md +1 -1
- package/docs/rundot-developer-platform/api/RELEASE_NOTES.md +1 -1
- package/docs/rundot-developer-platform/api/SERVER_AUTHORITATIVE.md +3 -3
- package/docs/rundot-developer-platform/api/STORAGE.md +12 -2
- package/docs/rundot-developer-platform/api/SYNCPLAY-MOVEMENT.md +12 -1
- package/docs/rundot-developer-platform/api/SYNCPLAY-PHYSICS.md +167 -6
- package/docs/rundot-developer-platform/api/SYNCPLAY.md +88 -4
- package/docs/rundot-developer-platform/api/UGC.md +1 -1
- package/docs/rundot-developer-platform/cli-reference.md +15 -2
- package/docs/rundot-developer-platform/deploying-your-game.md +12 -12
- package/docs/rundot-developer-platform/getting-started.md +8 -8
- package/docs/rundot-developer-platform/initializing-your-game.md +1 -1
- package/docs/rundot-developer-platform/marketing-your-game.md +17 -17
- package/docs/rundot-developer-platform/playground.md +10 -10
- package/docs/rundot-developer-platform/runtime-environment.md +3 -3
- package/docs/rundot-developer-platform/setting-your-game-thumbnail.md +1 -1
- package/docs/rundot-developer-platform/troubleshooting.md +2 -2
- package/package.json +3 -3
- package/scripts/install-hint.mjs +1 -1
- package/scripts/setup.mjs +5 -5
- package/dist/chunk-2WRAWLP3.js +0 -12
- package/dist/chunk-2WRAWLP3.js.map +0 -1
- package/dist/chunk-3GKY3LY5.js.map +0 -1
- package/dist/chunk-CZONPFQG.js.map +0 -1
- package/dist/chunk-G7JAUUTF.js.map +0 -1
- package/dist/chunk-KIA4VGSK.js.map +0 -1
- package/dist/chunk-USEBN3PO.js.map +0 -1
- package/dist/chunk-WFRNUODW.js.map +0 -1
- package/dist/chunk-XQC54EPQ.js +0 -3502
- package/dist/chunk-XQC54EPQ.js.map +0 -1
- package/dist/chunk-YQEDG3Z2.js.map +0 -1
- package/dist/core-6DQFSOBL.js +0 -3
- package/dist/session-promotion-BMoIRgKe.d.ts +0 -136
- package/dist/vite/dev-server-XDCK4DL7.js.map +0 -1
package/README.md
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
# RUN.
|
|
1
|
+
# RUN.world SDK API
|
|
2
2
|
|
|
3
|
-
Build connected HTML5 games that integrate deeply with the RUN.
|
|
3
|
+
Build connected HTML5 games that integrate deeply with the RUN.world platform. This package provides the client SDK used by hosted games as well as the local mock environment for development.
|
|
4
4
|
|
|
5
5
|
## Highlights
|
|
6
6
|
|
|
7
|
-
- Typed APIs for RUN.
|
|
7
|
+
- Typed APIs for RUN.world platform services (simulation, rooms, analytics, ads, and more)
|
|
8
8
|
- Host-aware tooling including lifecycle hooks, safe-area utilities, and asset loading helpers
|
|
9
9
|
|
|
10
10
|
## Quick Start
|
|
@@ -37,7 +37,7 @@ await RundotGameAPI.initializeAsync()
|
|
|
37
37
|
|
|
38
38
|
## Documentation
|
|
39
39
|
|
|
40
|
-
The complete RUN.
|
|
40
|
+
The complete RUN.world SDK manuals live on [RUN.world Docs](https://series-1.gitbook.io/rundot-docs). Start there for setup guides, API references, tutorials, and best practices.
|
|
41
41
|
|
|
42
42
|
## Support & Links
|
|
43
43
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { $ as ProviderErrorDetail, M as LeaderboardApi, I as ImageGenApi, A as AudioGenApi, V as VideoGenApi, q as SpriteGenApi, T as ThreeDGenApi } from './LeaderboardApi-
|
|
2
|
-
import { M as MultiplayerApi } from './MultiplayerApi-
|
|
1
|
+
import { $ as ProviderErrorDetail, M as LeaderboardApi, I as ImageGenApi, A as AudioGenApi, V as VideoGenApi, q as SpriteGenApi, T as ThreeDGenApi } from './LeaderboardApi-Bp1wndvJ.js';
|
|
2
|
+
import { M as MultiplayerApi } from './MultiplayerApi-TQr01JT7.js';
|
|
3
3
|
|
|
4
4
|
interface StorageApi {
|
|
5
5
|
key(index: number): Promise<string | null>;
|
|
@@ -793,7 +793,7 @@ interface AiMessage {
|
|
|
793
793
|
content: string | AiContentBlock[];
|
|
794
794
|
}
|
|
795
795
|
type AiChatCompletionRequest = {
|
|
796
|
-
/** Model identifier (e.g., 'gpt-
|
|
796
|
+
/** Model identifier (e.g., 'gpt-5.6-luna', 'claude-sonnet-4-6') */
|
|
797
797
|
model: string;
|
|
798
798
|
/** Array of message objects in OpenAI chat format */
|
|
799
799
|
messages: Array<AiMessage>;
|
|
@@ -831,6 +831,29 @@ type AiChatCompletionRequest = {
|
|
|
831
831
|
maxTokens?: number;
|
|
832
832
|
/** Upper bound for tokens generated, including visible output and reasoning tokens */
|
|
833
833
|
maxCompletionTokens?: number;
|
|
834
|
+
/**
|
|
835
|
+
* Requested reasoning (thinking) effort for reasoning-capable models.
|
|
836
|
+
*
|
|
837
|
+
* Per-provider support:
|
|
838
|
+
* - **OpenAI** (`gpt-5` family): all levels, passed through natively as
|
|
839
|
+
* `reasoning_effort`.
|
|
840
|
+
* - **Gemini**: all levels, translated to the model generation's thinking
|
|
841
|
+
* config (thinking level on Gemini 3.x, thinking budget on Gemini 2.5).
|
|
842
|
+
* - **Anthropic** (`claude-*`) and **DeepSeek**: not yet supported — a
|
|
843
|
+
* request carrying this field is rejected with HTTP 400.
|
|
844
|
+
*
|
|
845
|
+
* `'none'` requests minimal/disabled reasoning where the model allows it;
|
|
846
|
+
* models that cannot fully disable thinking (e.g. `gemini-2.5-pro`,
|
|
847
|
+
* Gemini 3.x) clamp to their minimum instead.
|
|
848
|
+
*
|
|
849
|
+
* Reasoning tokens are billed as OUTPUT tokens, so higher efforts increase
|
|
850
|
+
* completion-token usage and cost. When the model reasons, the response's
|
|
851
|
+
* `usage.reasoning_tokens` reports how many of the completion tokens were
|
|
852
|
+
* spent on reasoning.
|
|
853
|
+
*
|
|
854
|
+
* Older backends that predate this field silently ignore it.
|
|
855
|
+
*/
|
|
856
|
+
reasoningEffort?: 'none' | 'low' | 'medium' | 'high';
|
|
834
857
|
/** Sampling temperature (0.0 to 2.0) */
|
|
835
858
|
temperature?: number;
|
|
836
859
|
/** Nucleus sampling parameter (0.0 to 1.0) */
|
|
@@ -2195,6 +2218,35 @@ interface CreditsPurchaseResult {
|
|
|
2195
2218
|
/** Refreshed balance after the paywall closed, or `null` if it couldn't be read. */
|
|
2196
2219
|
balance: CreditBalance | null;
|
|
2197
2220
|
}
|
|
2221
|
+
type GenerationCostEstimateKind = 'image' | 'music' | 'sfx' | 'video' | 'sprite' | 'animate-sprite' | 'sprite-character-animate' | 'tts' | 'text';
|
|
2222
|
+
interface GenerationCostEstimateRequest {
|
|
2223
|
+
kind: GenerationCostEstimateKind;
|
|
2224
|
+
model?: string;
|
|
2225
|
+
provider?: string;
|
|
2226
|
+
mode?: string;
|
|
2227
|
+
durationSeconds?: number;
|
|
2228
|
+
imageSize?: string;
|
|
2229
|
+
removeBackground?: boolean;
|
|
2230
|
+
bgRemovalModel?: string;
|
|
2231
|
+
generateAudio?: boolean;
|
|
2232
|
+
resolution?: string;
|
|
2233
|
+
text?: string;
|
|
2234
|
+
messages?: AiMessage[];
|
|
2235
|
+
system?: string | AiTextContent[];
|
|
2236
|
+
maxTokens?: number;
|
|
2237
|
+
maxCompletionTokens?: number;
|
|
2238
|
+
quantity?: number;
|
|
2239
|
+
}
|
|
2240
|
+
interface GenerationCostEstimate {
|
|
2241
|
+
kind: GenerationCostEstimateKind;
|
|
2242
|
+
credits: number;
|
|
2243
|
+
lowCredits: number;
|
|
2244
|
+
highCredits: number;
|
|
2245
|
+
lowerPercent: number;
|
|
2246
|
+
upperPercent: number;
|
|
2247
|
+
exact: boolean;
|
|
2248
|
+
reason: string;
|
|
2249
|
+
}
|
|
2198
2250
|
/** Construction payload for {@link CreditsExhaustedError}. */
|
|
2199
2251
|
interface CreditsExhaustedErrorInfo {
|
|
2200
2252
|
billedTo: CreditsBilledTo;
|
|
@@ -2240,6 +2292,7 @@ interface CreditsApi {
|
|
|
2240
2292
|
getBalance(): Promise<CreditBalance>;
|
|
2241
2293
|
getSubscription(): Promise<CreditSubscription>;
|
|
2242
2294
|
getPlans(): Promise<CreditPlansCatalog>;
|
|
2295
|
+
estimateGenerationCost(request: GenerationCostEstimateRequest): Promise<GenerationCostEstimate>;
|
|
2243
2296
|
/**
|
|
2244
2297
|
* Open the host's combined paywall (plan upgrade now; top-up packs in a later
|
|
2245
2298
|
* release). Resolves once the player closes it. Reuses the same host UI the
|
|
@@ -4396,9 +4449,9 @@ declare class MockAvatarApi implements Avatar3dApi {
|
|
|
4396
4449
|
/**
|
|
4397
4450
|
* DEFINITIVE TypeScript definitions for Rundot Game API
|
|
4398
4451
|
*
|
|
4399
|
-
* This is the single source of truth for all RUN.
|
|
4452
|
+
* This is the single source of truth for all RUN.world games.
|
|
4400
4453
|
*
|
|
4401
|
-
* Usage in RUN.
|
|
4454
|
+
* Usage in RUN.world games:
|
|
4402
4455
|
* ```typescript
|
|
4403
4456
|
* import type { RundotGameAPI } from '../../rundot-game-api/types';
|
|
4404
4457
|
* declare const RundotGameAPI: RundotGameAPI;
|
|
@@ -4830,4 +4883,4 @@ interface AdsApi {
|
|
|
4830
4883
|
showInterstitialAd(options?: ShowInterstitialAdOptions): Promise<boolean>;
|
|
4831
4884
|
}
|
|
4832
4885
|
|
|
4833
|
-
export { type DeviceInfo as $, type AnalyticsApi as A, type BatchRecipeRequirementsResult as B, type NotificationsApi as C, type ScheduleLocalNotification as D, type SubmitMessageInput as E, type SubmitMessageResult as F, type ScheduleNotificationOptions as G, type Host as H, type RCSAvailabilityStatus as I, type ScheduleRCSInput as J, type ScheduleRCSResult as K, type RequestRCSOptInInput as L, type RequestRCSOptInResult as M, type NavigationApi as N, type PopupsApi as O, type Profile as P, type QuitOptions as Q, type RundotGameAPI as R, type SimulationActiveRunsUpdate as S, type ShowToastOptions as T, type LikeDialogResult as U, type CommentsPanelResult as V, type LikeStateResult as W, type ShowInterstitialAdOptions as X, type ShowRewardedAdOptions as Y, type ProfileApi as Z, type DeviceApi as _, type RecipeRequirementQuery as a, type RoomDataUpdate as a$, type EnvironmentApi as a0, type EnvironmentInfo as a1, type SystemApi as a2, type SafeArea as a3, type AddToHomeScreenResult as a4, type CdnApi as a5, type FetchFromCdnOptions as a6, type AssetUrlResult as a7, type TimeApi as a8, type ServerTimeData as a9, type QuitCallback as aA, type BackButtonCallback as aB, type IdentityChangedCallback as aC, type IdentityChangedEvent as aD, type SimulationApi as aE, type SimulationSlotValidationResult as aF, type SimulationBatchOperation as aG, type SimulationBatchOperationsResult as aH, type SimulationAvailableItem as aI, type SimulationPowerPreview as aJ, type SimulationSlotMutationResult as aK, type SimulationSlotContainer as aL, type SimulationAssignment as aM, type SimulationState as aN, type ExecuteRecipeOptions as aO, type ExecuteRecipeResponse as aP, type CollectRecipeResult as aQ, type ResetStateOptions as aR, type ResetStateResult as aS, type GetActiveRunsOptions as aT, type ExecuteScopedRecipeOptions as aU, type ExecuteScopedRecipeResult as aV, type GetAvailableRecipesOptions as aW, type GetAvailableRecipesResult as aX, type Recipe as aY, type GetBatchRecipeRequirements as aZ, type TriggerRecipeChainOptions as a_, type GetFutureTimeOptions as aa, type AiApi as ab, type AiChatCompletionRequest as ac, type AiChatCompletionData as ad, type PromptCompletionRequest as ae, type AiChatCompletionStreamOptions as af, type AiChatCompletionStreamChunk as ag, type HapticsApi as ah, HapticFeedbackStyle as ai, type GamepadSnapshot as aj, type GamepadConnectionEvent as ak, type Subscription as al, type GamepadApi as am, type GamepadLatencyStats as an, type FeaturesApi as ao, type Experiment as ap, type ExperimentAssignment as aq, type LiveOpsApi as ar, type LiveOpsConfigResult as as, type LiveOpsRawConfig as at, type LiveOpsSection as au, type LifecycleApi as av, type SleepCallback as aw, type AwakeCallback as ax, type PauseCallback as ay, type ResumeCallback as az, type RecipeRequirementResult as b, type AccessGateApi as b$, type RoomMessageEvent as b0, type ProposedMoveEvent as b1, RundotGameTransport as b2, type RoomsApi as b3, type CreateRoomOptions as b4, type JoinOrCreateRoomOptions as b5, type JoinOrCreateResult as b6, type ListRoomsOptions as b7, type UpdateRoomDataOptions as b8, type RoomMessageRequest as b9, type PreloaderApi as bA, type SocialApi as bB, type ShareMetadata as bC, type ShareLinkResult as bD, type SocialQRCodeOptions as bE, type QRCodeResult as bF, type ShareClickData as bG, type ShareFileOptions as bH, type ShareFileResult as bI, type CanShareFileResult as bJ, type ComposeSocialPostOptions as bK, type ComposeSocialPostResult as bL, type EntitlementApi as bM, type Entitlement as bN, type LedgerEntry as bO, type StatsApi as bP, type GrantInfo as bQ, type CollectiblesApi as bR, type CollectibleCard as bS, type VipClaimResult as bT, type ShopApi as bU, type StorefrontResponse as bV, type StorefrontItem as bW, type ShopPurchaseResponse as bX, type ShopOrderHistoryResponse as bY, type PromptLoginResult as bZ, type AccessTier as b_, type StartRoomGameOptions as ba, type ProposeMoveRequest as bb, type ProposeMoveResult as bc, type ValidateMoveVerdict as bd, type ValidateMoveResult as be, type RoomSubscriptionOptions as bf, type LoggingApi as bg, type IapApi as bh, type SpendCurrencyOptions as bi, type SpendCurrencyResult as bj, type SubscriptionTier as bk, type RunSubscriptionsResponse as bl, type SubscriptionInterval as bm, type PurchaseSubscriptionResponse as bn, type OpenStoreResult as bo, type LoadEmbeddedAssetsResponse as bp, type DirectPurchaseSku as bq, type SharedAssetsApi as br, type CreditsApi as bs, type CreditsBillingContext as bt, type CreditBalance as bu, type CreditSubscription as bv, type CreditPlansCatalog as bw, type OpenPaywallOptions as bx, type CreditsPurchaseResult as by, type Unsubscribe as bz, type RundotGameAvailableRecipe as c, type AdminThreeDGenBrowseParams as c$, type TextGenApi as c0, type UgcApi as c1, type VideoApi as c2, type AppApi as c3, type AdminUgcApi as c4, type AdminImageGenApi as c5, type AdminVideoGenApi as c6, type AdminSpriteGenApi as c7, type AdminAudioGenApi as c8, type AdminThreeDGenApi as c9, type RawEnvironmentInfo as cA, type SharedStorageHostApi as cB, type FilesApi as cC, type ClipsApi as cD, type AttributionApi as cE, type InitializationContext as cF, type InitializationOptions as cG, type CaptureConsent as cH, type StartClipRecordingOptions as cI, type ClipBlob as cJ, type ClipsSupport as cK, type ClipPersistOptions as cL, type ClipResult as cM, type UgcEntry as cN, type CaptureConsentStatus as cO, AccessDeniedError as cP, type AdminGenApi as cQ, type AdminImageGenBrowseParams as cR, type AdminImageGenBrowseResponse as cS, type AdminImageGenListReportsParams as cT, type AdminImageGenListReportsResponse as cU, type AdminImageGenResolveAction as cV, type AdminSpriteGenBrowseParams as cW, type AdminSpriteGenBrowseResponse as cX, type AdminSpriteGenListReportsParams as cY, type AdminSpriteGenListReportsResponse as cZ, type AdminSpriteGenResolveAction as c_, type AppRole as ca, type ResolveLaunchIntentOptions as cb, type LaunchIntent as cc, type ReleaseNote as cd, type AdminUgcBrowseParams as ce, type AdminUgcBrowseResponse as cf, type AdminUgcListReportsParams as cg, type AdminUgcListReportsResponse as ch, type AdminUgcResolveAction as ci, type AdminGenBrowseParams as cj, type AdminGenBrowseResponse as ck, type ImageGenEntry as cl, type AdminGenListReportsParams as cm, type AdminGenListReportsResponse as cn, type ImageGenReport as co, type AdminGenResolveAction as cp, type SpriteGenEntry as cq, type SpriteGenReport as cr, type ThreeDGenEntry as cs, type ThreeDGenReport as ct, type Avatar3dApi as cu, type AssetManifest as cv, type Avatar3dConfig as cw, type ShowEditorOptions as cx, type Avatar3dEdits as cy, type AdsApi as cz, type RundotGameCollectRecipeResult as d, type LoadEmbeddedAssetBeginRequest as d$, type AdminThreeDGenBrowseResponse as d0, type AdminThreeDGenListReportsParams as d1, type AdminThreeDGenListReportsResponse as d2, type AdminThreeDGenResolveAction as d3, type AdminUgcEntry as d4, type AdminVideoGenBrowseParams as d5, type AdminVideoGenBrowseResponse as d6, type AdminVideoGenListReportsParams as d7, type AdminVideoGenListReportsResponse as d8, type AdminVideoGenResolveAction as d9, type CreditPlan as dA, type CreditTopUpPack as dB, type CreditsBilledTo as dC, CreditsExhaustedError as dD, type CreditsExhaustedErrorInfo as dE, type CreditsPurchaseOutcome as dF, type DirectPurchaseGrantKind as dG, type DirectPurchaseStorePlatform as dH, type DirectPurchaseStorePrice as dI, GAMEPAD_BUTTON_NAMES as dJ, type GamepadAxes as dK, type GamepadButtonName as dL, type GamepadButtonState as dM, type GamepadSource as dN, type GetSubscriptionsForTierRequest as dO, type HudInsets as dP, type IdentityChangeReason as dQ, type InboundForKeyEntry as dR, type InboundMethodIds as dS, type InboundStorageApi as dT, type IsPlayerSubscribedRequest as dU, type JoinOrCreateRoomEnvelopeResponse as dV, type JoinRoomMatchCriteria as dW, type LaunchIntentKind as dX, type LiveOpsExperiment as dY, type LiveOpsOverride as dZ, type LiveOpsVariant as d_, type AiContentBlock as da, type AiImageContent as db, type AiImageUrlContent as dc, type AiMessage as dd, type AiResponseFormat as de, type AiTextContent as df, type AiToolResultContent as dg, type AiToolUseContent as dh, type Asset as di, type AssignedVariant as dj, type AudioGenEntry as dk, type AudioGenReport as dl, BUCKET_COUNT as dm, CLIP_CONTENT_TYPE as dn, COMPOSE_POST_MAX_TEXT_LENGTH as dp, COMPOSE_POST_MAX_TITLE_LENGTH as dq, COMPOSE_POST_SUBREDDIT_PATTERN as dr, CREDITS_EXHAUSTED_CODE as ds, type Category as dt, type ClipAudioOptions as du, type ClipCameraOptions as dv, type ClipPipLayout as dw, type ClipPipPosition as dx, type ComposeSocialPostMedia as dy, type CreditFreeDailyInfo as dz, type RundotGameExecuteRecipeOptions as e, fnv1a32 as e$, type LoadEmbeddedAssetBeginResponse as e0, type LoadEmbeddedAssetChunkRequest as e1, type LoadEmbeddedAssetChunkResponse as e2, type LoadEmbeddedAssetsRequest as e3, MockAvatarApi as e4, type NotificationTriggerInput as e5, type OnNotificationCallback as e6, type OnRequestCallback as e7, type OnResponseCallback as e8, type PlatformCapabilities as e9, type ShopOrder as eA, type SimulationBatchOperationAssign as eB, type SimulationBatchOperationRemove as eC, type SimulationBatchOperationResult as eD, type SimulationPersonalState as eE, type SimulationRoomActiveRecipe as eF, type SimulationRoomState as eG, type SocialComposePlatform as eH, type StorefrontCollection as eI, type StorefrontCollectionItem as eJ, type SubPath as eK, type SubmitMessageChannel as eL, type SubmitMessageChannelResult as eM, type SubmitMessageResultChannel as eN, TIER_SUPPORTED_INTERVALS as eO, type Tool as eP, type ToolChoice as eQ, type ToolUse as eR, type TimeIntervalTriggerInput as eS, type UgcReport as eT, type VideoGenEntry as eU, type VideoGenReport as eV, asCreditsExhaustedError as eW, assertTierSupportsInterval as eX, assignVariant as eY, assignmentBucket as eZ, createHost as e_, type ProposedMovePayload as ea, type PurchaseSubscriptionRequest as eb, type RCSAvailabilityReason as ec, type RCSOptInStatus as ed, ROOM_GAME_PHASES as ee, type RecipeInfo as ef, type ReleaseType as eg, type ResolvedLiveOps as eh, type RoomEnvelopeResponse as ei, type RoomGamePhase as ej, type RoomMessageEventType as ek, type RoomMessagePayload as el, type RoomsEnvelopeResponse as em, RpcInboundStorageApi as en, RpcSharedAssetsApi as eo, type RpcTransport as ep, type RunSubscription as eq, type RundotGameRoomCustomMetadata as er, type RundotGameRoomPayload as es, type RundotGameRoomRules as et, type RundotGameRoomRulesGameState as eu, SHARE_FILE_ALLOWED_MIME_TYPES as ev, SHARE_FILE_MAX_SIZE_BYTES as ew, SOCIAL_COMPOSE_PLATFORMS as ex, type ScheduleRCSStatus as ey, type ShareFileMimeType as ez, type RundotGameExecuteRecipeResult as f, isCreditsExhaustedError as f0, mapCreditsExhaustion as f1, resolveCollectionItemPrice as f2, resolveLiveOpsSection as f3, toPromptWireRequest as f4, type RundotGameExecuteScopedRecipeOptions as g, RundotGameRoom as h, type RundotGameSimulationConfig as i, type RundotGameSimulationEffect as j, type RundotGameSimulationRecipe as k, type RundotGameSimulationStateResponse as l, type SimulationEntityUpdate as m, type SimulationRunSummary as n, type SimulationSnapshotUpdate as o, type SimulationSubscribeOptions as p, type SimulationUpdateData as q, type SimulationUpdateType as r, type RpcRequest as s, type RpcResponse as t, type RpcNotification as u, RpcClient as v, type StorageApi as w, type NavigationStackInfo as x, type PushAppOptions as y, type NavigateToGameOptions as z };
|
|
4886
|
+
export { type DeviceInfo as $, type AnalyticsApi as A, type BatchRecipeRequirementsResult as B, type NotificationsApi as C, type ScheduleLocalNotification as D, type SubmitMessageInput as E, type SubmitMessageResult as F, type ScheduleNotificationOptions as G, type Host as H, type RCSAvailabilityStatus as I, type ScheduleRCSInput as J, type ScheduleRCSResult as K, type RequestRCSOptInInput as L, type RequestRCSOptInResult as M, type NavigationApi as N, type PopupsApi as O, type Profile as P, type QuitOptions as Q, type RundotGameAPI as R, type SimulationActiveRunsUpdate as S, type ShowToastOptions as T, type LikeDialogResult as U, type CommentsPanelResult as V, type LikeStateResult as W, type ShowInterstitialAdOptions as X, type ShowRewardedAdOptions as Y, type ProfileApi as Z, type DeviceApi as _, type RecipeRequirementQuery as a, type RoomDataUpdate as a$, type EnvironmentApi as a0, type EnvironmentInfo as a1, type SystemApi as a2, type SafeArea as a3, type AddToHomeScreenResult as a4, type CdnApi as a5, type FetchFromCdnOptions as a6, type AssetUrlResult as a7, type TimeApi as a8, type ServerTimeData as a9, type QuitCallback as aA, type BackButtonCallback as aB, type IdentityChangedCallback as aC, type IdentityChangedEvent as aD, type SimulationApi as aE, type SimulationSlotValidationResult as aF, type SimulationBatchOperation as aG, type SimulationBatchOperationsResult as aH, type SimulationAvailableItem as aI, type SimulationPowerPreview as aJ, type SimulationSlotMutationResult as aK, type SimulationSlotContainer as aL, type SimulationAssignment as aM, type SimulationState as aN, type ExecuteRecipeOptions as aO, type ExecuteRecipeResponse as aP, type CollectRecipeResult as aQ, type ResetStateOptions as aR, type ResetStateResult as aS, type GetActiveRunsOptions as aT, type ExecuteScopedRecipeOptions as aU, type ExecuteScopedRecipeResult as aV, type GetAvailableRecipesOptions as aW, type GetAvailableRecipesResult as aX, type Recipe as aY, type GetBatchRecipeRequirements as aZ, type TriggerRecipeChainOptions as a_, type GetFutureTimeOptions as aa, type AiApi as ab, type AiChatCompletionRequest as ac, type AiChatCompletionData as ad, type PromptCompletionRequest as ae, type AiChatCompletionStreamOptions as af, type AiChatCompletionStreamChunk as ag, type HapticsApi as ah, HapticFeedbackStyle as ai, type GamepadSnapshot as aj, type GamepadConnectionEvent as ak, type Subscription as al, type GamepadApi as am, type GamepadLatencyStats as an, type FeaturesApi as ao, type Experiment as ap, type ExperimentAssignment as aq, type LiveOpsApi as ar, type LiveOpsConfigResult as as, type LiveOpsRawConfig as at, type LiveOpsSection as au, type LifecycleApi as av, type SleepCallback as aw, type AwakeCallback as ax, type PauseCallback as ay, type ResumeCallback as az, type RecipeRequirementResult as b, type PromptLoginResult as b$, type RoomMessageEvent as b0, type ProposedMoveEvent as b1, RundotGameTransport as b2, type RoomsApi as b3, type CreateRoomOptions as b4, type JoinOrCreateRoomOptions as b5, type JoinOrCreateResult as b6, type ListRoomsOptions as b7, type UpdateRoomDataOptions as b8, type RoomMessageRequest as b9, type CreditsPurchaseResult as bA, type Unsubscribe as bB, type PreloaderApi as bC, type SocialApi as bD, type ShareMetadata as bE, type ShareLinkResult as bF, type SocialQRCodeOptions as bG, type QRCodeResult as bH, type ShareClickData as bI, type ShareFileOptions as bJ, type ShareFileResult as bK, type CanShareFileResult as bL, type ComposeSocialPostOptions as bM, type ComposeSocialPostResult as bN, type EntitlementApi as bO, type Entitlement as bP, type LedgerEntry as bQ, type StatsApi as bR, type GrantInfo as bS, type CollectiblesApi as bT, type CollectibleCard as bU, type VipClaimResult as bV, type ShopApi as bW, type StorefrontResponse as bX, type StorefrontItem as bY, type ShopPurchaseResponse as bZ, type ShopOrderHistoryResponse as b_, type StartRoomGameOptions as ba, type ProposeMoveRequest as bb, type ProposeMoveResult as bc, type ValidateMoveVerdict as bd, type ValidateMoveResult as be, type RoomSubscriptionOptions as bf, type LoggingApi as bg, type IapApi as bh, type SpendCurrencyOptions as bi, type SpendCurrencyResult as bj, type SubscriptionTier as bk, type RunSubscriptionsResponse as bl, type SubscriptionInterval as bm, type PurchaseSubscriptionResponse as bn, type OpenStoreResult as bo, type LoadEmbeddedAssetsResponse as bp, type DirectPurchaseSku as bq, type SharedAssetsApi as br, type CreditsApi as bs, type CreditsBillingContext as bt, type CreditBalance as bu, type CreditSubscription as bv, type CreditPlansCatalog as bw, type GenerationCostEstimateRequest as bx, type GenerationCostEstimate as by, type OpenPaywallOptions as bz, type RundotGameAvailableRecipe as c, type AdminSpriteGenListReportsResponse as c$, type AccessTier as c0, type AccessGateApi as c1, type TextGenApi as c2, type UgcApi as c3, type VideoApi as c4, type AppApi as c5, type AdminUgcApi as c6, type AdminImageGenApi as c7, type AdminVideoGenApi as c8, type AdminSpriteGenApi as c9, type Avatar3dEdits as cA, type AdsApi as cB, type RawEnvironmentInfo as cC, type SharedStorageHostApi as cD, type FilesApi as cE, type ClipsApi as cF, type AttributionApi as cG, type InitializationContext as cH, type InitializationOptions as cI, type CaptureConsent as cJ, type StartClipRecordingOptions as cK, type ClipBlob as cL, type ClipsSupport as cM, type ClipPersistOptions as cN, type ClipResult as cO, type UgcEntry as cP, type CaptureConsentStatus as cQ, AccessDeniedError as cR, type AdminGenApi as cS, type AdminImageGenBrowseParams as cT, type AdminImageGenBrowseResponse as cU, type AdminImageGenListReportsParams as cV, type AdminImageGenListReportsResponse as cW, type AdminImageGenResolveAction as cX, type AdminSpriteGenBrowseParams as cY, type AdminSpriteGenBrowseResponse as cZ, type AdminSpriteGenListReportsParams as c_, type AdminAudioGenApi as ca, type AdminThreeDGenApi as cb, type AppRole as cc, type ResolveLaunchIntentOptions as cd, type LaunchIntent as ce, type ReleaseNote as cf, type AdminUgcBrowseParams as cg, type AdminUgcBrowseResponse as ch, type AdminUgcListReportsParams as ci, type AdminUgcListReportsResponse as cj, type AdminUgcResolveAction as ck, type AdminGenBrowseParams as cl, type AdminGenBrowseResponse as cm, type ImageGenEntry as cn, type AdminGenListReportsParams as co, type AdminGenListReportsResponse as cp, type ImageGenReport as cq, type AdminGenResolveAction as cr, type SpriteGenEntry as cs, type SpriteGenReport as ct, type ThreeDGenEntry as cu, type ThreeDGenReport as cv, type Avatar3dApi as cw, type AssetManifest as cx, type Avatar3dConfig as cy, type ShowEditorOptions as cz, type RundotGameCollectRecipeResult as d, type LiveOpsExperiment as d$, type AdminSpriteGenResolveAction as d0, type AdminThreeDGenBrowseParams as d1, type AdminThreeDGenBrowseResponse as d2, type AdminThreeDGenListReportsParams as d3, type AdminThreeDGenListReportsResponse as d4, type AdminThreeDGenResolveAction as d5, type AdminUgcEntry as d6, type AdminVideoGenBrowseParams as d7, type AdminVideoGenBrowseResponse as d8, type AdminVideoGenListReportsParams as d9, type ComposeSocialPostMedia as dA, type CreditFreeDailyInfo as dB, type CreditPlan as dC, type CreditTopUpPack as dD, type CreditsBilledTo as dE, CreditsExhaustedError as dF, type CreditsExhaustedErrorInfo as dG, type CreditsPurchaseOutcome as dH, type DirectPurchaseGrantKind as dI, type DirectPurchaseStorePlatform as dJ, type DirectPurchaseStorePrice as dK, GAMEPAD_BUTTON_NAMES as dL, type GamepadAxes as dM, type GamepadButtonName as dN, type GamepadButtonState as dO, type GamepadSource as dP, type GenerationCostEstimateKind as dQ, type GetSubscriptionsForTierRequest as dR, type HudInsets as dS, type IdentityChangeReason as dT, type InboundForKeyEntry as dU, type InboundMethodIds as dV, type InboundStorageApi as dW, type IsPlayerSubscribedRequest as dX, type JoinOrCreateRoomEnvelopeResponse as dY, type JoinRoomMatchCriteria as dZ, type LaunchIntentKind as d_, type AdminVideoGenListReportsResponse as da, type AdminVideoGenResolveAction as db, type AiContentBlock as dc, type AiImageContent as dd, type AiImageUrlContent as de, type AiMessage as df, type AiResponseFormat as dg, type AiTextContent as dh, type AiToolResultContent as di, type AiToolUseContent as dj, type Asset as dk, type AssignedVariant as dl, type AudioGenEntry as dm, type AudioGenReport as dn, BUCKET_COUNT as dp, CLIP_CONTENT_TYPE as dq, COMPOSE_POST_MAX_TEXT_LENGTH as dr, COMPOSE_POST_MAX_TITLE_LENGTH as ds, COMPOSE_POST_SUBREDDIT_PATTERN as dt, CREDITS_EXHAUSTED_CODE as du, type Category as dv, type ClipAudioOptions as dw, type ClipCameraOptions as dx, type ClipPipLayout as dy, type ClipPipPosition as dz, type RundotGameExecuteRecipeOptions as e, assignVariant as e$, type LiveOpsOverride as e0, type LiveOpsVariant as e1, type LoadEmbeddedAssetBeginRequest as e2, type LoadEmbeddedAssetBeginResponse as e3, type LoadEmbeddedAssetChunkRequest as e4, type LoadEmbeddedAssetChunkResponse as e5, type LoadEmbeddedAssetsRequest as e6, MockAvatarApi as e7, type NotificationTriggerInput as e8, type OnNotificationCallback as e9, SOCIAL_COMPOSE_PLATFORMS as eA, type ScheduleRCSStatus as eB, type ShareFileMimeType as eC, type ShopOrder as eD, type SimulationBatchOperationAssign as eE, type SimulationBatchOperationRemove as eF, type SimulationBatchOperationResult as eG, type SimulationPersonalState as eH, type SimulationRoomActiveRecipe as eI, type SimulationRoomState as eJ, type SocialComposePlatform as eK, type StorefrontCollection as eL, type StorefrontCollectionItem as eM, type SubPath as eN, type SubmitMessageChannel as eO, type SubmitMessageChannelResult as eP, type SubmitMessageResultChannel as eQ, TIER_SUPPORTED_INTERVALS as eR, type Tool as eS, type ToolChoice as eT, type ToolUse as eU, type TimeIntervalTriggerInput as eV, type UgcReport as eW, type VideoGenEntry as eX, type VideoGenReport as eY, asCreditsExhaustedError as eZ, assertTierSupportsInterval as e_, type OnRequestCallback as ea, type OnResponseCallback as eb, type PlatformCapabilities as ec, type ProposedMovePayload as ed, type PurchaseSubscriptionRequest as ee, type RCSAvailabilityReason as ef, type RCSOptInStatus as eg, ROOM_GAME_PHASES as eh, type RecipeInfo as ei, type ReleaseType as ej, type ResolvedLiveOps as ek, type RoomEnvelopeResponse as el, type RoomGamePhase as em, type RoomMessageEventType as en, type RoomMessagePayload as eo, type RoomsEnvelopeResponse as ep, RpcInboundStorageApi as eq, RpcSharedAssetsApi as er, type RpcTransport as es, type RunSubscription as et, type RundotGameRoomCustomMetadata as eu, type RundotGameRoomPayload as ev, type RundotGameRoomRules as ew, type RundotGameRoomRulesGameState as ex, SHARE_FILE_ALLOWED_MIME_TYPES as ey, SHARE_FILE_MAX_SIZE_BYTES as ez, type RundotGameExecuteRecipeResult as f, assignmentBucket as f0, createHost as f1, fnv1a32 as f2, isCreditsExhaustedError as f3, mapCreditsExhaustion as f4, resolveCollectionItemPrice as f5, resolveLiveOpsSection as f6, toPromptWireRequest as f7, type RundotGameExecuteScopedRecipeOptions as g, RundotGameRoom as h, type RundotGameSimulationConfig as i, type RundotGameSimulationEffect as j, type RundotGameSimulationRecipe as k, type RundotGameSimulationStateResponse as l, type SimulationEntityUpdate as m, type SimulationRunSummary as n, type SimulationSnapshotUpdate as o, type SimulationSubscribeOptions as p, type SimulationUpdateData as q, type SimulationUpdateType as r, type RpcRequest as s, type RpcResponse as t, type RpcNotification as u, RpcClient as v, type StorageApi as w, type NavigationStackInfo as x, type PushAppOptions as y, type NavigateToGameOptions as z };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { h as ReplayFile } from './types-
|
|
1
|
+
import { h as ReplayFile } from './types-ChJ9TO_o.js';
|
|
2
2
|
|
|
3
3
|
type ImageGenModel = 'gemini-3.1-flash-image-preview' | 'gemini-3-pro-image-preview' | 'gpt-image-1' | 'gpt-image-2';
|
|
4
4
|
type BgRemovalModel = 'bria' | 'birefnet';
|
|
@@ -77,6 +77,12 @@ interface ServerRoom<P extends Protocol> {
|
|
|
77
77
|
readonly playerId: string;
|
|
78
78
|
/** Whether the room is locked */
|
|
79
79
|
readonly locked: boolean;
|
|
80
|
+
/** Authoritative current room roster. */
|
|
81
|
+
readonly players: readonly ServerPlayer[];
|
|
82
|
+
/** Effective server-enforced capacity. */
|
|
83
|
+
readonly maxPlayers: number;
|
|
84
|
+
/** Whether this player created the room. */
|
|
85
|
+
readonly isCreator: boolean;
|
|
80
86
|
/** Current latency in ms (round-trip / 2) */
|
|
81
87
|
readonly latency: number;
|
|
82
88
|
/** Connection state */
|
|
@@ -85,6 +91,8 @@ interface ServerRoom<P extends Protocol> {
|
|
|
85
91
|
on(events: RoomEvents<P>): void;
|
|
86
92
|
/** Send a typed message to the server room. */
|
|
87
93
|
send(message: P): void;
|
|
94
|
+
/** Open or close the room to new seats. Only the room creator is authorized. */
|
|
95
|
+
setSeatingOpen(open: boolean): void;
|
|
88
96
|
/**
|
|
89
97
|
* Send an opaque payload under `msgType` without the typed-message envelope
|
|
90
98
|
* transform. `data` is delivered verbatim (a raw string stays a string), so
|
|
@@ -193,4 +201,4 @@ type MatchmakeOptions = Pick<RoomOptions, 'criteria'> & {
|
|
|
193
201
|
pollIntervalMs?: number;
|
|
194
202
|
};
|
|
195
203
|
|
|
196
|
-
export type { ChatMessageData as C, JoinTicketRequest as J, ListUserRoomsOptions as L, MultiplayerApi as M, Protocol as P, RealtimeRoomSummary as R,
|
|
204
|
+
export type { ChatMessageData as C, JoinTicketRequest as J, ListUserRoomsOptions as L, MultiplayerApi as M, Protocol as P, RealtimeRoomSummary as R, ServerPlayer as S, RoomOptions as a, ServerRoom as b, MatchmakeOptions as c, ConnectionState as d, RoomEvents as e };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { C as CanonicalValue, c as DeterministicStepContext, h as ReplayFile, O as OfflineSession } from './types-
|
|
2
|
-
import { S as SyncplaySignedReceipt } from './secret-protocol-
|
|
3
|
-
import { M as MultiplayerApi } from './MultiplayerApi-
|
|
1
|
+
import { C as CanonicalValue, c as DeterministicStepContext, h as ReplayFile, O as OfflineSession } from './types-ChJ9TO_o.js';
|
|
2
|
+
import { S as SyncplaySignedReceipt } from './secret-protocol-DY332qWW.js';
|
|
3
|
+
import { S as ServerPlayer, M as MultiplayerApi } from './MultiplayerApi-TQr01JT7.js';
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* Game-agnostic input authority (server orders inputs, clients simulate — §2 Option 1).
|
|
@@ -21,6 +21,8 @@ interface ConfirmedInputFrame {
|
|
|
21
21
|
readonly inputs: readonly EncodedInput[];
|
|
22
22
|
/** Slots whose input was substituted (repeated) because it never arrived in time. */
|
|
23
23
|
readonly substitutedSlots: readonly number[];
|
|
24
|
+
/** Human-occupied slots at this authority tick. Omitted by legacy authorities. */
|
|
25
|
+
readonly occupiedSlots?: readonly number[];
|
|
24
26
|
/** Immutable authority-owned consequences applied immediately before this tick's simulation step. */
|
|
25
27
|
readonly commands?: readonly CanonicalValue[];
|
|
26
28
|
readonly checksum: string;
|
|
@@ -66,6 +68,7 @@ interface InputAuthority {
|
|
|
66
68
|
/** Lowest confirmed tick still retained, or -1 when nothing is confirmed yet. */
|
|
67
69
|
readonly earliestRetainedTick: number;
|
|
68
70
|
receiveInput(slot: number, tick: number, input: EncodedInput): InputSubmissionResult;
|
|
71
|
+
recordOccupiedSlots(tick: number, slots: readonly number[]): void;
|
|
69
72
|
queueCommand(tick: number, command: CanonicalValue): void;
|
|
70
73
|
/** Confirm every tick that can be confirmed up to and including `now`. Returns the new frames in order. */
|
|
71
74
|
advance(now: number): readonly ConfirmedInputFrame[];
|
|
@@ -307,6 +310,12 @@ interface NetworkedSyncplayClientOptions<State, Input> {
|
|
|
307
310
|
/** Decode a wire input to a game input; MUST map the neutral substitute (canonical null) to the default. */
|
|
308
311
|
readonly decodeInput: (encoded: EncodedInput) => Input;
|
|
309
312
|
readonly maxPredictionTicks?: number;
|
|
313
|
+
/**
|
|
314
|
+
* Snapshot transfer ceiling in bytes for the client collector (default
|
|
315
|
+
* DEFAULT_MAX_SNAPSHOT_BYTES). Must match the room's configured ceiling — a
|
|
316
|
+
* client ceiling below the room's snapshot size silently breaks late-join.
|
|
317
|
+
*/
|
|
318
|
+
readonly maxSnapshotBytes?: number;
|
|
310
319
|
/** Host wire envelope msgType carrying session messages. Default 'rdm'. */
|
|
311
320
|
readonly sessionMsgType?: string;
|
|
312
321
|
/**
|
|
@@ -373,6 +382,7 @@ interface NetworkedSyncplayClientNetStats {
|
|
|
373
382
|
readonly rollbacks: number;
|
|
374
383
|
readonly maxRollbackDepth: number;
|
|
375
384
|
}
|
|
385
|
+
type NetworkedSyncplaySlotPresence = 'human' | 'substituted' | 'empty' | 'unknown';
|
|
376
386
|
interface NetworkedSyncplayClient {
|
|
377
387
|
readonly slot: number;
|
|
378
388
|
/** 'player' (holds a slot) or 'spectator' (read-only follower, slot -1). From session-start. */
|
|
@@ -381,6 +391,8 @@ interface NetworkedSyncplayClient {
|
|
|
381
391
|
readonly predictedThrough: number;
|
|
382
392
|
readonly appliedThrough: number;
|
|
383
393
|
readonly rollbacks: number;
|
|
394
|
+
/** Human occupancy at the latest contiguous authority-confirmed frame. */
|
|
395
|
+
readonly confirmedPlayerPresence: readonly NetworkedSyncplaySlotPresence[];
|
|
384
396
|
/** Live local netcode telemetry (RTT, timescale, delay, rollback depth). */
|
|
385
397
|
readonly netStats: NetworkedSyncplayClientNetStats;
|
|
386
398
|
readonly secrets: SyncplaySecretsClient;
|
|
@@ -429,11 +441,23 @@ type SyncplayConnectionEvent = {
|
|
|
429
441
|
} | {
|
|
430
442
|
readonly kind: 'reconnecting';
|
|
431
443
|
};
|
|
444
|
+
interface SyncplayRoomOptions {
|
|
445
|
+
readonly maxPlayers?: number;
|
|
446
|
+
}
|
|
447
|
+
interface SyncplayOccupancySnapshot {
|
|
448
|
+
readonly players: readonly ServerPlayer[];
|
|
449
|
+
readonly occupied: number;
|
|
450
|
+
readonly maxPlayers: number;
|
|
451
|
+
readonly full: boolean;
|
|
452
|
+
readonly locked: boolean;
|
|
453
|
+
}
|
|
432
454
|
interface SyncplayRoomTransport extends NetworkedClientTransport {
|
|
433
455
|
/** The shareable room code (e.g. "HX9KWR"). */
|
|
434
456
|
readonly roomCode: string;
|
|
435
457
|
/** This client's player id, as assigned by the server on join. */
|
|
436
458
|
readonly playerId: string;
|
|
459
|
+
readonly occupancy: SyncplayOccupancySnapshot;
|
|
460
|
+
readonly isCreator: boolean;
|
|
437
461
|
/** Leave the deterministic room and close the underlying connection. */
|
|
438
462
|
close(): void;
|
|
439
463
|
/**
|
|
@@ -444,6 +468,8 @@ interface SyncplayRoomTransport extends NetworkedClientTransport {
|
|
|
444
468
|
* the match down.
|
|
445
469
|
*/
|
|
446
470
|
onConnectionEvent(handler: (event: SyncplayConnectionEvent) => void): void;
|
|
471
|
+
onOccupancyChange(handler: (snapshot: SyncplayOccupancySnapshot) => void): () => void;
|
|
472
|
+
setSeatingOpen(open: boolean): void;
|
|
447
473
|
}
|
|
448
474
|
/**
|
|
449
475
|
* Join an existing deterministic room by its 6-char code and return a transport
|
|
@@ -451,7 +477,7 @@ interface SyncplayRoomTransport extends NetworkedClientTransport {
|
|
|
451
477
|
*/
|
|
452
478
|
declare function joinSyncplayRoomByCode(api: MultiplayerApi, code: string): Promise<SyncplayRoomTransport>;
|
|
453
479
|
/** Options for {@link quickMatchSyncplayRoom}. */
|
|
454
|
-
interface QuickMatchSyncplayOptions {
|
|
480
|
+
interface QuickMatchSyncplayOptions extends SyncplayRoomOptions {
|
|
455
481
|
/**
|
|
456
482
|
* Auto-inject a coarse `region` criterion (default true). See
|
|
457
483
|
* {@link quickMatchSyncplayRoom} for the semantics and the tradeoff.
|
|
@@ -485,6 +511,6 @@ declare function quickMatchSyncplayRoom(api: MultiplayerApi, criteria?: Record<s
|
|
|
485
511
|
* (Caller-chosen codes are not supported on create — when the platform grows
|
|
486
512
|
* that path, this signature gains a typed parameter rather than a dead one.)
|
|
487
513
|
*/
|
|
488
|
-
declare function createSyncplayRoom(api: MultiplayerApi): Promise<SyncplayRoomTransport>;
|
|
514
|
+
declare function createSyncplayRoom(api: MultiplayerApi, options?: SyncplayRoomOptions): Promise<SyncplayRoomTransport>;
|
|
489
515
|
|
|
490
|
-
export {
|
|
516
|
+
export { type SyncplayRoomTransport as A, type SyncplaySecretEventReader as B, type ConfirmedInputFrame as C, type DeterministicSessionDecodeRejection as D, type EncodedInput as E, type SyncplaySecretsClient as F, createBrowserSyncplaySecretCrypto as G, createInputAuthority as H, type InputAuthority as I, createNetworkedSyncplayClient as J, createSyncplayRoom as K, createSyncplaySecretEventReader as L, createSyncplaySecretsClient as M, type NetworkedClientTransport as N, decodeDeterministicSessionMessage as O, deterministicSessionWireVersion as P, type QuickMatchSyncplayOptions as Q, encodeDeterministicSessionMessage as R, type SyncplaySecretAuthorityCrypto as S, joinSyncplayRoomByCode as T, quickMatchSyncplayRoom as U, verifySyncplaySignedReceipt as V, type DeterministicSessionDecodeResult as a, type DeterministicSessionMessage as b, type DeterministicSessionMessageKind as c, type DeterministicSessionRole as d, type InputAuthorityConfig as e, type InputAuthorityRestoreState as f, type InputAuthorityStats as g, type InputRejectionReason as h, type InputSubmissionResult as i, type NetworkedSyncplayClient as j, type NetworkedSyncplayClientInputDelayOptions as k, type NetworkedSyncplayClientNetStats as l, type NetworkedSyncplayClientOptions as m, type NetworkedSyncplayClientPacingOptions as n, type NetworkedSyncplaySlotPresence as o, type SyncplayChoiceClient as p, type SyncplayChoiceResolvedEvent as q, type SyncplayCollectionClient as r, type SyncplayCollectionRevealedEvent as s, type SyncplayOccupancySnapshot as t, type SyncplayOwnedSecret as u, type SyncplayRandomClient as v, type SyncplayRandomDrawnEvent as w, type SyncplayRoleClient as x, type SyncplayRoleRevealedEvent as y, type SyncplayRoomOptions as z };
|
|
@@ -1,3 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Backend HTTP dependencies injected into the Http*Api classes so they are
|
|
3
|
+
* decoupled from the SDK playground globals (getFirebaseClient/getCloudRunUrl).
|
|
4
|
+
* Each host (PlaygroundHost, Telegram shell, future Steam shell) supplies its own.
|
|
5
|
+
*/
|
|
6
|
+
interface BackendHttpDeps {
|
|
7
|
+
getIdToken(): Promise<string>;
|
|
8
|
+
getCloudRunUrl(): string;
|
|
9
|
+
/**
|
|
10
|
+
* Returns the host's game-session token (`x-h5-game-session`) for the current
|
|
11
|
+
* game+user, or `null` when unavailable. Optional so non-playground shells
|
|
12
|
+
* that don't mint a GST omit the header and stay fail-safe.
|
|
13
|
+
*/
|
|
14
|
+
getGameSessionToken?(): Promise<string | null>;
|
|
15
|
+
}
|
|
16
|
+
|
|
1
17
|
/**
|
|
2
18
|
* HTTP wrapper for calling Cloud Functions.
|
|
3
19
|
*
|
|
@@ -20,4 +36,4 @@
|
|
|
20
36
|
*/
|
|
21
37
|
type RemoteFunctionInvoker = <TResponse>(functionName: string, payload?: unknown) => Promise<TResponse>;
|
|
22
38
|
|
|
23
|
-
export type { RemoteFunctionInvoker as R };
|
|
39
|
+
export type { BackendHttpDeps as B, RemoteFunctionInvoker as R };
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
// raw-loader:/home/runner/work/venus/venus/packages/sdk/src/webview/webviewLibraryShim.js
|
|
2
|
+
var webviewLibraryShim_default = "/**\n * RUN.world Embedded Libraries WebView Shim\n *\n * This code is injected into H5 game WebViews BEFORE the game's main script runs.\n * It bootstraps the embedded libraries system by:\n * 1. Reading window.__rundotGameLibrariesConfig (set by the Vite plugin)\n * 2. Loading libraries via RPC (mobile) or CDN (web)\n * 3. Registering libraries in window.__rundotGameLibraryExports\n * 4. Allowing the game's virtual modules to access them\n *\n * This shim is NOT imported by H5 games - it's injected by the RUN.world host via\n * injectedJavaScriptBeforeContentLoaded in H5AppPoolRenderer.\n */\n\n;(function () {\n if (typeof window === 'undefined') {\n return\n }\n\n if (window.__rundotGameLibraryShim && window.__rundotGameLibraryShim.__initialized) {\n return\n }\n\n var RESPONSE_TYPE = 'H5_RESPONSE'\n var REQUEST_TYPE = 'H5_LOAD_EMBEDDED_ASSET'\n var REQUEST_TIMEOUT_MS = 12000\n var pendingRequests = new Map()\n\n function ensureConfig() {\n if (!window.__rundotGameLibrariesConfig) {\n window.__rundotGameLibrariesConfig = {\n enabled: false,\n required: [],\n manifest: {},\n cdnBase: '',\n }\n }\n if (!window.__rundotGameLibrariesConfig.manifest) {\n window.__rundotGameLibrariesConfig.manifest = {}\n }\n if (!Array.isArray(window.__rundotGameLibrariesConfig.required)) {\n window.__rundotGameLibrariesConfig.required = []\n }\n return window.__rundotGameLibrariesConfig\n }\n\n function ensureExportsRegistry() {\n if (!window.__rundotGameLibraryExports) {\n window.__rundotGameLibraryExports = {}\n }\n return window.__rundotGameLibraryExports\n }\n\n function hasHostBridge() {\n return !!(\n window.ReactNativeWebView &&\n typeof window.ReactNativeWebView.postMessage === 'function'\n )\n }\n\n function registerResponseListeners() {\n if (\n window.__rundotGameLibraryShim &&\n window.__rundotGameLibraryShim.__listenerRegistered\n ) {\n return\n }\n\n function handleMessage(event) {\n // Only enforce origin/source on the `window`-level listener.\n // The `document`-level listener is the RN bridge path where event.origin\n // is '' by design; the source check there is unnecessary.\n var isRnBridgeEvent =\n event && event.origin === '' && event.source == null\n if (!isRnBridgeEvent) {\n var cfg =\n (typeof window !== 'undefined' && window.__rundotConfig) || null\n var expectedParentOrigin = (cfg && cfg.parentOrigin) || ''\n if (expectedParentOrigin && event.origin !== expectedParentOrigin) {\n return\n }\n if (typeof window !== 'undefined' && event.source !== window.parent) {\n return\n }\n }\n\n var payload = parsePayload(event && event.data)\n if (!payload || payload.type !== RESPONSE_TYPE || !payload.data) {\n return\n }\n // Nonce required even for the RN bridge path (defense in depth).\n var cfg2 =\n (typeof window !== 'undefined' && window.__rundotConfig) || null\n var expectedNonce = (cfg2 && cfg2.nonce) || ''\n if (expectedNonce && payload.nonce !== expectedNonce) {\n return\n }\n var requestId = payload.data.requestId\n if (!requestId || !pendingRequests.has(requestId)) {\n return\n }\n var pending = pendingRequests.get(requestId)\n pendingRequests.delete(requestId)\n clearTimeout(pending.timeout)\n\n if (payload.data.success === false) {\n pending.reject(\n new Error(payload.data.error || 'Embedded library load failed'),\n )\n return\n }\n\n var value = payload.data.value || payload.data\n if (!value || !value.base64Data) {\n pending.reject(\n new Error('Embedded library response was missing base64Data'),\n )\n return\n }\n\n pending.resolve(value.base64Data)\n }\n\n if (\n typeof document !== 'undefined' &&\n typeof document.addEventListener === 'function'\n ) {\n document.addEventListener('message', handleMessage, false)\n }\n if (\n typeof window !== 'undefined' &&\n typeof window.addEventListener === 'function'\n ) {\n window.addEventListener('message', handleMessage, false)\n }\n\n if (!window.__rundotGameLibraryShim) {\n window.__rundotGameLibraryShim = {}\n }\n window.__rundotGameLibraryShim.__listenerRegistered = true\n }\n\n function parsePayload(raw) {\n if (!raw || typeof raw !== 'string') {\n return null\n }\n try {\n return JSON.parse(raw)\n } catch (error) {\n return null\n }\n }\n\n function createRequestId(libraryKey) {\n var sanitized = ''\n for (var i = 0; i < libraryKey.length; i++) {\n var c = libraryKey.charAt(i)\n if (\n (c >= 'a' && c <= 'z') ||\n (c >= 'A' && c <= 'Z') ||\n (c >= '0' && c <= '9') ||\n c === '-' ||\n c === '_'\n ) {\n sanitized += c\n } else {\n sanitized += '_'\n }\n }\n return (\n 'embedded-lib-' +\n sanitized +\n '-' +\n Date.now() +\n '-' +\n Math.random().toString(36).slice(2)\n )\n }\n\n function postHostRequest(assetKey, requestId) {\n if (!hasHostBridge()) {\n throw new Error('Host bridge is unavailable')\n }\n var bridge = window.ReactNativeWebView\n var cfg =\n (typeof window !== 'undefined' && window.__rundotConfig) || null\n var nonce = (cfg && cfg.nonce) || ''\n var message = {\n type: REQUEST_TYPE,\n direction: 'H5_TO_APP',\n data: {\n requestId: requestId,\n assetKey: assetKey,\n },\n instanceId:\n (window._rundotGameInitState && window._rundotGameInitState.poolId) ||\n (cfg && cfg.poolId) ||\n 'unknown',\n timestamp: Date.now(),\n }\n if (nonce) {\n message.nonce = nonce\n }\n bridge.postMessage(JSON.stringify(message))\n }\n\n function loadLibraryViaHost(assetKey, libraryKey) {\n return new Promise(function (resolve, reject) {\n var requestId = createRequestId(libraryKey)\n var timeout = setTimeout(function () {\n pendingRequests.delete(requestId)\n reject(new Error('Timed out loading embedded library: ' + libraryKey))\n }, REQUEST_TIMEOUT_MS)\n\n pendingRequests.set(requestId, {\n resolve: resolve,\n reject: reject,\n timeout: timeout,\n })\n\n try {\n postHostRequest(assetKey, requestId)\n } catch (error) {\n pendingRequests.delete(requestId)\n clearTimeout(timeout)\n reject(error)\n }\n })\n }\n\n function buildCdnUrl(config, entry) {\n var base = config.cdnBase || ''\n if (!base.endsWith('/')) {\n base += '/'\n }\n var path = entry.cdnPath\n if (path.charAt(0) === '/') {\n path = path.substring(1)\n }\n return base + path\n }\n\n async function loadLibraryViaCdn(config, entry, libraryKey) {\n if (!config.cdnBase) {\n throw new Error('CDN base URL is not configured')\n }\n var url = buildCdnUrl(config, entry)\n var response = await fetch(url, { credentials: 'omit' })\n if (!response.ok) {\n throw new Error(\n 'Failed to fetch embedded library from CDN: ' + libraryKey,\n )\n }\n return await response.text()\n }\n\n function decodeBase64ToUtf8(base64) {\n if (typeof base64 !== 'string') {\n throw new Error('Invalid base64 payload')\n }\n\n if (typeof atob === 'function') {\n var binary = atob(base64)\n if (typeof TextDecoder !== 'undefined') {\n var len = binary.length\n var bytes = new Uint8Array(len)\n for (var i = 0; i < len; i++) {\n bytes[i] = binary.charCodeAt(i)\n }\n return new TextDecoder('utf-8').decode(bytes)\n }\n return decodeURIComponent(escape(binary))\n }\n\n var bufferCtor =\n (typeof globalThis !== 'undefined' && globalThis.Buffer) ||\n (typeof window !== 'undefined' && window.Buffer)\n if (bufferCtor) {\n return bufferCtor.from(base64, 'base64').toString('utf-8')\n }\n\n throw new Error('No base64 decoder available')\n }\n\n // R13a: replaces `new Function(source).call(window)` with a Blob-URL\n // <script src=blob:...> injection. CSP `script-src 'self' blob:` accepts\n // this; SRI integrity (R32b) gates which bytes are allowed to execute,\n // so a forged blob can't satisfy the manifest hash.\n function injectLibraryScript(libraryKey, entry, source) {\n return new Promise(function (resolve, reject) {\n var registry = ensureExportsRegistry()\n if (!source) {\n reject(\n new Error('Embedded library source was empty for ' + libraryKey),\n )\n return\n }\n\n // The Blob bytes MUST match the manifest sha384 byte-for-byte \u2014\n // appending a //# sourceURL comment (or anything else) before\n // blob-ifying would invalidate the SRI hash and cause the browser\n // to block the script unconditionally. Devtools will fall back to\n // showing the blob: URL as the script name; that's acceptable.\n var blob = new Blob([source], { type: 'application/javascript' })\n var blobUrl = URL.createObjectURL(blob)\n\n var script = document.createElement('script')\n script.src = blobUrl\n if (entry.sha384) {\n script.integrity = entry.sha384\n script.crossOrigin = 'anonymous'\n }\n\n var settled = false\n function cleanup() {\n URL.revokeObjectURL(blobUrl)\n if (script.parentNode) script.parentNode.removeChild(script)\n }\n\n script.onload = function () {\n if (settled) return\n settled = true\n cleanup()\n var exported = window[entry.globalVar]\n if (!exported) {\n reject(\n new Error(\n 'Embedded library ' +\n libraryKey +\n ' did not register ' +\n entry.globalVar,\n ),\n )\n return\n }\n registry[libraryKey] = exported\n resolve(exported)\n }\n\n script.onerror = function () {\n if (settled) return\n settled = true\n cleanup()\n reject(\n new Error(\n 'Failed to inject embedded library ' +\n libraryKey +\n ' (likely SRI mismatch or syntax error)',\n ),\n )\n }\n\n document.head.appendChild(script)\n })\n }\n\n async function ensureLibraryLoaded(config, libraryKey) {\n var registry = ensureExportsRegistry()\n if (registry[libraryKey]) {\n return registry[libraryKey]\n }\n\n var entry = config.manifest && config.manifest[libraryKey]\n if (!entry) {\n throw new Error('No manifest entry for embedded library ' + libraryKey)\n }\n\n var source = null\n if (config.useHost !== false && hasHostBridge()) {\n try {\n var base64 = await loadLibraryViaHost(entry.assetKey, libraryKey)\n source = decodeBase64ToUtf8(base64)\n } catch (error) {\n // Log the RPC error loudly before fallback\n console.error(\n '[RUN:libraries] Failed to load ' +\n libraryKey +\n ' from host via RPC:',\n error,\n )\n console.warn(\n '[RUN:libraries] Falling back to CDN for ' +\n libraryKey +\n '. This may indicate an asset packaging issue.',\n )\n }\n }\n\n if (!source) {\n source = await loadLibraryViaCdn(config, entry, libraryKey)\n }\n\n return injectLibraryScript(libraryKey, entry, source)\n }\n\n async function bootstrap() {\n try {\n registerResponseListeners()\n getBootstrapPromise()\n\n var config = ensureConfig()\n\n if (!config.enabled) {\n if (bootstrapResolve) bootstrapResolve()\n return\n }\n\n if (!Array.isArray(config.required) || config.required.length === 0) {\n if (bootstrapResolve) bootstrapResolve()\n return\n }\n\n // Group libraries by load stage for parallel loading within stages\n var librariesByStage = {}\n for (var i = 0; i < config.required.length; i++) {\n var libraryKey = config.required[i]\n var entry = config.manifest[libraryKey]\n var stage = entry.loadStage || 0\n if (!librariesByStage[stage]) librariesByStage[stage] = []\n librariesByStage[stage].push(libraryKey)\n }\n\n // Load stages sequentially, libraries within each stage in parallel\n var stages = Object.keys(librariesByStage).sort(function (a, b) {\n return parseInt(a, 10) - parseInt(b, 10)\n })\n\n for (var s = 0; s < stages.length; s++) {\n var stage = stages[s]\n var libs = librariesByStage[stage]\n\n // Load all libraries in this stage in parallel\n var stagePromises = libs.map(function (libraryKey) {\n return ensureLibraryLoaded(config, libraryKey).catch(\n function (error) {\n console.error(\n '[RUN:libraries] Failed to load library ' + libraryKey,\n error,\n )\n throw error\n },\n )\n })\n\n await Promise.all(stagePromises)\n }\n\n if (bootstrapResolve) bootstrapResolve()\n } catch (error) {\n console.error('[RUN:libraries] Bootstrap error', error)\n if (bootstrapReject) bootstrapReject(error)\n throw error\n }\n }\n\n // Create a promise that resolves when bootstrap completes\n var bootstrapPromise = null\n var bootstrapResolve = null\n var bootstrapReject = null\n\n function getBootstrapPromise() {\n if (!bootstrapPromise) {\n bootstrapPromise = new Promise(function (resolve, reject) {\n bootstrapResolve = resolve\n bootstrapReject = reject\n })\n }\n return bootstrapPromise\n }\n\n window.__rundotGameLibraryShim = {\n bootstrap: bootstrap,\n ready: getBootstrapPromise,\n getExports: function (libraryKey) {\n var registry = ensureExportsRegistry()\n return registry[libraryKey]\n },\n __initialized: true,\n }\n})()\n";
|
|
3
|
+
|
|
4
|
+
// src/webview/webviewLibraryShimSource.ts
|
|
5
|
+
var WEBVIEW_LIBRARY_SHIM_SOURCE = webviewLibraryShim_default;
|
|
6
|
+
function getWebviewLibraryShimSource() {
|
|
7
|
+
return WEBVIEW_LIBRARY_SHIM_SOURCE;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export { WEBVIEW_LIBRARY_SHIM_SOURCE, getWebviewLibraryShimSource };
|
|
11
|
+
//# sourceMappingURL=chunk-4J2RDAOR.js.map
|
|
12
|
+
//# sourceMappingURL=chunk-4J2RDAOR.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["raw-loader:/home/runner/work/venus/venus/packages/sdk/src/webview/webviewLibraryShim.js","../src/webview/webviewLibraryShimSource.ts"],"names":[],"mappings":";AAAA,IAAO,0BAAA,GAAQ,kicAAA;;;ACcR,IAAM,2BAAA,GAA8B;AAEpC,SAAS,2BAAA,GAAsC;AACpD,EAAA,OAAO,2BAAA;AACT","file":"chunk-4J2RDAOR.js","sourcesContent":["export default \"/**\\n * RUN.world Embedded Libraries WebView Shim\\n *\\n * This code is injected into H5 game WebViews BEFORE the game's main script runs.\\n * It bootstraps the embedded libraries system by:\\n * 1. Reading window.__rundotGameLibrariesConfig (set by the Vite plugin)\\n * 2. Loading libraries via RPC (mobile) or CDN (web)\\n * 3. Registering libraries in window.__rundotGameLibraryExports\\n * 4. Allowing the game's virtual modules to access them\\n *\\n * This shim is NOT imported by H5 games - it's injected by the RUN.world host via\\n * injectedJavaScriptBeforeContentLoaded in H5AppPoolRenderer.\\n */\\n\\n;(function () {\\n if (typeof window === 'undefined') {\\n return\\n }\\n\\n if (window.__rundotGameLibraryShim && window.__rundotGameLibraryShim.__initialized) {\\n return\\n }\\n\\n var RESPONSE_TYPE = 'H5_RESPONSE'\\n var REQUEST_TYPE = 'H5_LOAD_EMBEDDED_ASSET'\\n var REQUEST_TIMEOUT_MS = 12000\\n var pendingRequests = new Map()\\n\\n function ensureConfig() {\\n if (!window.__rundotGameLibrariesConfig) {\\n window.__rundotGameLibrariesConfig = {\\n enabled: false,\\n required: [],\\n manifest: {},\\n cdnBase: '',\\n }\\n }\\n if (!window.__rundotGameLibrariesConfig.manifest) {\\n window.__rundotGameLibrariesConfig.manifest = {}\\n }\\n if (!Array.isArray(window.__rundotGameLibrariesConfig.required)) {\\n window.__rundotGameLibrariesConfig.required = []\\n }\\n return window.__rundotGameLibrariesConfig\\n }\\n\\n function ensureExportsRegistry() {\\n if (!window.__rundotGameLibraryExports) {\\n window.__rundotGameLibraryExports = {}\\n }\\n return window.__rundotGameLibraryExports\\n }\\n\\n function hasHostBridge() {\\n return !!(\\n window.ReactNativeWebView &&\\n typeof window.ReactNativeWebView.postMessage === 'function'\\n )\\n }\\n\\n function registerResponseListeners() {\\n if (\\n window.__rundotGameLibraryShim &&\\n window.__rundotGameLibraryShim.__listenerRegistered\\n ) {\\n return\\n }\\n\\n function handleMessage(event) {\\n // Only enforce origin/source on the `window`-level listener.\\n // The `document`-level listener is the RN bridge path where event.origin\\n // is '' by design; the source check there is unnecessary.\\n var isRnBridgeEvent =\\n event && event.origin === '' && event.source == null\\n if (!isRnBridgeEvent) {\\n var cfg =\\n (typeof window !== 'undefined' && window.__rundotConfig) || null\\n var expectedParentOrigin = (cfg && cfg.parentOrigin) || ''\\n if (expectedParentOrigin && event.origin !== expectedParentOrigin) {\\n return\\n }\\n if (typeof window !== 'undefined' && event.source !== window.parent) {\\n return\\n }\\n }\\n\\n var payload = parsePayload(event && event.data)\\n if (!payload || payload.type !== RESPONSE_TYPE || !payload.data) {\\n return\\n }\\n // Nonce required even for the RN bridge path (defense in depth).\\n var cfg2 =\\n (typeof window !== 'undefined' && window.__rundotConfig) || null\\n var expectedNonce = (cfg2 && cfg2.nonce) || ''\\n if (expectedNonce && payload.nonce !== expectedNonce) {\\n return\\n }\\n var requestId = payload.data.requestId\\n if (!requestId || !pendingRequests.has(requestId)) {\\n return\\n }\\n var pending = pendingRequests.get(requestId)\\n pendingRequests.delete(requestId)\\n clearTimeout(pending.timeout)\\n\\n if (payload.data.success === false) {\\n pending.reject(\\n new Error(payload.data.error || 'Embedded library load failed'),\\n )\\n return\\n }\\n\\n var value = payload.data.value || payload.data\\n if (!value || !value.base64Data) {\\n pending.reject(\\n new Error('Embedded library response was missing base64Data'),\\n )\\n return\\n }\\n\\n pending.resolve(value.base64Data)\\n }\\n\\n if (\\n typeof document !== 'undefined' &&\\n typeof document.addEventListener === 'function'\\n ) {\\n document.addEventListener('message', handleMessage, false)\\n }\\n if (\\n typeof window !== 'undefined' &&\\n typeof window.addEventListener === 'function'\\n ) {\\n window.addEventListener('message', handleMessage, false)\\n }\\n\\n if (!window.__rundotGameLibraryShim) {\\n window.__rundotGameLibraryShim = {}\\n }\\n window.__rundotGameLibraryShim.__listenerRegistered = true\\n }\\n\\n function parsePayload(raw) {\\n if (!raw || typeof raw !== 'string') {\\n return null\\n }\\n try {\\n return JSON.parse(raw)\\n } catch (error) {\\n return null\\n }\\n }\\n\\n function createRequestId(libraryKey) {\\n var sanitized = ''\\n for (var i = 0; i < libraryKey.length; i++) {\\n var c = libraryKey.charAt(i)\\n if (\\n (c >= 'a' && c <= 'z') ||\\n (c >= 'A' && c <= 'Z') ||\\n (c >= '0' && c <= '9') ||\\n c === '-' ||\\n c === '_'\\n ) {\\n sanitized += c\\n } else {\\n sanitized += '_'\\n }\\n }\\n return (\\n 'embedded-lib-' +\\n sanitized +\\n '-' +\\n Date.now() +\\n '-' +\\n Math.random().toString(36).slice(2)\\n )\\n }\\n\\n function postHostRequest(assetKey, requestId) {\\n if (!hasHostBridge()) {\\n throw new Error('Host bridge is unavailable')\\n }\\n var bridge = window.ReactNativeWebView\\n var cfg =\\n (typeof window !== 'undefined' && window.__rundotConfig) || null\\n var nonce = (cfg && cfg.nonce) || ''\\n var message = {\\n type: REQUEST_TYPE,\\n direction: 'H5_TO_APP',\\n data: {\\n requestId: requestId,\\n assetKey: assetKey,\\n },\\n instanceId:\\n (window._rundotGameInitState && window._rundotGameInitState.poolId) ||\\n (cfg && cfg.poolId) ||\\n 'unknown',\\n timestamp: Date.now(),\\n }\\n if (nonce) {\\n message.nonce = nonce\\n }\\n bridge.postMessage(JSON.stringify(message))\\n }\\n\\n function loadLibraryViaHost(assetKey, libraryKey) {\\n return new Promise(function (resolve, reject) {\\n var requestId = createRequestId(libraryKey)\\n var timeout = setTimeout(function () {\\n pendingRequests.delete(requestId)\\n reject(new Error('Timed out loading embedded library: ' + libraryKey))\\n }, REQUEST_TIMEOUT_MS)\\n\\n pendingRequests.set(requestId, {\\n resolve: resolve,\\n reject: reject,\\n timeout: timeout,\\n })\\n\\n try {\\n postHostRequest(assetKey, requestId)\\n } catch (error) {\\n pendingRequests.delete(requestId)\\n clearTimeout(timeout)\\n reject(error)\\n }\\n })\\n }\\n\\n function buildCdnUrl(config, entry) {\\n var base = config.cdnBase || ''\\n if (!base.endsWith('/')) {\\n base += '/'\\n }\\n var path = entry.cdnPath\\n if (path.charAt(0) === '/') {\\n path = path.substring(1)\\n }\\n return base + path\\n }\\n\\n async function loadLibraryViaCdn(config, entry, libraryKey) {\\n if (!config.cdnBase) {\\n throw new Error('CDN base URL is not configured')\\n }\\n var url = buildCdnUrl(config, entry)\\n var response = await fetch(url, { credentials: 'omit' })\\n if (!response.ok) {\\n throw new Error(\\n 'Failed to fetch embedded library from CDN: ' + libraryKey,\\n )\\n }\\n return await response.text()\\n }\\n\\n function decodeBase64ToUtf8(base64) {\\n if (typeof base64 !== 'string') {\\n throw new Error('Invalid base64 payload')\\n }\\n\\n if (typeof atob === 'function') {\\n var binary = atob(base64)\\n if (typeof TextDecoder !== 'undefined') {\\n var len = binary.length\\n var bytes = new Uint8Array(len)\\n for (var i = 0; i < len; i++) {\\n bytes[i] = binary.charCodeAt(i)\\n }\\n return new TextDecoder('utf-8').decode(bytes)\\n }\\n return decodeURIComponent(escape(binary))\\n }\\n\\n var bufferCtor =\\n (typeof globalThis !== 'undefined' && globalThis.Buffer) ||\\n (typeof window !== 'undefined' && window.Buffer)\\n if (bufferCtor) {\\n return bufferCtor.from(base64, 'base64').toString('utf-8')\\n }\\n\\n throw new Error('No base64 decoder available')\\n }\\n\\n // R13a: replaces `new Function(source).call(window)` with a Blob-URL\\n // <script src=blob:...> injection. CSP `script-src 'self' blob:` accepts\\n // this; SRI integrity (R32b) gates which bytes are allowed to execute,\\n // so a forged blob can't satisfy the manifest hash.\\n function injectLibraryScript(libraryKey, entry, source) {\\n return new Promise(function (resolve, reject) {\\n var registry = ensureExportsRegistry()\\n if (!source) {\\n reject(\\n new Error('Embedded library source was empty for ' + libraryKey),\\n )\\n return\\n }\\n\\n // The Blob bytes MUST match the manifest sha384 byte-for-byte —\\n // appending a //# sourceURL comment (or anything else) before\\n // blob-ifying would invalidate the SRI hash and cause the browser\\n // to block the script unconditionally. Devtools will fall back to\\n // showing the blob: URL as the script name; that's acceptable.\\n var blob = new Blob([source], { type: 'application/javascript' })\\n var blobUrl = URL.createObjectURL(blob)\\n\\n var script = document.createElement('script')\\n script.src = blobUrl\\n if (entry.sha384) {\\n script.integrity = entry.sha384\\n script.crossOrigin = 'anonymous'\\n }\\n\\n var settled = false\\n function cleanup() {\\n URL.revokeObjectURL(blobUrl)\\n if (script.parentNode) script.parentNode.removeChild(script)\\n }\\n\\n script.onload = function () {\\n if (settled) return\\n settled = true\\n cleanup()\\n var exported = window[entry.globalVar]\\n if (!exported) {\\n reject(\\n new Error(\\n 'Embedded library ' +\\n libraryKey +\\n ' did not register ' +\\n entry.globalVar,\\n ),\\n )\\n return\\n }\\n registry[libraryKey] = exported\\n resolve(exported)\\n }\\n\\n script.onerror = function () {\\n if (settled) return\\n settled = true\\n cleanup()\\n reject(\\n new Error(\\n 'Failed to inject embedded library ' +\\n libraryKey +\\n ' (likely SRI mismatch or syntax error)',\\n ),\\n )\\n }\\n\\n document.head.appendChild(script)\\n })\\n }\\n\\n async function ensureLibraryLoaded(config, libraryKey) {\\n var registry = ensureExportsRegistry()\\n if (registry[libraryKey]) {\\n return registry[libraryKey]\\n }\\n\\n var entry = config.manifest && config.manifest[libraryKey]\\n if (!entry) {\\n throw new Error('No manifest entry for embedded library ' + libraryKey)\\n }\\n\\n var source = null\\n if (config.useHost !== false && hasHostBridge()) {\\n try {\\n var base64 = await loadLibraryViaHost(entry.assetKey, libraryKey)\\n source = decodeBase64ToUtf8(base64)\\n } catch (error) {\\n // Log the RPC error loudly before fallback\\n console.error(\\n '[RUN:libraries] Failed to load ' +\\n libraryKey +\\n ' from host via RPC:',\\n error,\\n )\\n console.warn(\\n '[RUN:libraries] Falling back to CDN for ' +\\n libraryKey +\\n '. This may indicate an asset packaging issue.',\\n )\\n }\\n }\\n\\n if (!source) {\\n source = await loadLibraryViaCdn(config, entry, libraryKey)\\n }\\n\\n return injectLibraryScript(libraryKey, entry, source)\\n }\\n\\n async function bootstrap() {\\n try {\\n registerResponseListeners()\\n getBootstrapPromise()\\n\\n var config = ensureConfig()\\n\\n if (!config.enabled) {\\n if (bootstrapResolve) bootstrapResolve()\\n return\\n }\\n\\n if (!Array.isArray(config.required) || config.required.length === 0) {\\n if (bootstrapResolve) bootstrapResolve()\\n return\\n }\\n\\n // Group libraries by load stage for parallel loading within stages\\n var librariesByStage = {}\\n for (var i = 0; i < config.required.length; i++) {\\n var libraryKey = config.required[i]\\n var entry = config.manifest[libraryKey]\\n var stage = entry.loadStage || 0\\n if (!librariesByStage[stage]) librariesByStage[stage] = []\\n librariesByStage[stage].push(libraryKey)\\n }\\n\\n // Load stages sequentially, libraries within each stage in parallel\\n var stages = Object.keys(librariesByStage).sort(function (a, b) {\\n return parseInt(a, 10) - parseInt(b, 10)\\n })\\n\\n for (var s = 0; s < stages.length; s++) {\\n var stage = stages[s]\\n var libs = librariesByStage[stage]\\n\\n // Load all libraries in this stage in parallel\\n var stagePromises = libs.map(function (libraryKey) {\\n return ensureLibraryLoaded(config, libraryKey).catch(\\n function (error) {\\n console.error(\\n '[RUN:libraries] Failed to load library ' + libraryKey,\\n error,\\n )\\n throw error\\n },\\n )\\n })\\n\\n await Promise.all(stagePromises)\\n }\\n\\n if (bootstrapResolve) bootstrapResolve()\\n } catch (error) {\\n console.error('[RUN:libraries] Bootstrap error', error)\\n if (bootstrapReject) bootstrapReject(error)\\n throw error\\n }\\n }\\n\\n // Create a promise that resolves when bootstrap completes\\n var bootstrapPromise = null\\n var bootstrapResolve = null\\n var bootstrapReject = null\\n\\n function getBootstrapPromise() {\\n if (!bootstrapPromise) {\\n bootstrapPromise = new Promise(function (resolve, reject) {\\n bootstrapResolve = resolve\\n bootstrapReject = reject\\n })\\n }\\n return bootstrapPromise\\n }\\n\\n window.__rundotGameLibraryShim = {\\n bootstrap: bootstrap,\\n ready: getBootstrapPromise,\\n getExports: function (libraryKey) {\\n var registry = ensureExportsRegistry()\\n return registry[libraryKey]\\n },\\n __initialized: true,\\n }\\n})()\\n\"","/**\n * Webview Library Shim Source\n *\n * This module exports the shim code that is injected into H5 game WebViews.\n * The actual shim code is in webviewLibraryShim.js and imported as a raw string.\n *\n * Using Vite's ?raw import allows us to:\n * - Keep the shim as actual JavaScript (not a string literal)\n * - Get proper IDE support (syntax highlighting, linting)\n * - Avoid escaping issues\n */\n\nimport shimSource from './webviewLibraryShim.js?raw'\n\nexport const WEBVIEW_LIBRARY_SHIM_SOURCE = shimSource\n\nexport function getWebviewLibraryShimSource(): string {\n return WEBVIEW_LIBRARY_SHIM_SOURCE\n}\n"]}
|
|
@@ -1,30 +1,4 @@
|
|
|
1
|
-
import { assertValidImageGenSeed, RateLimitedError, RundotApiError, assertReplayWithinInlineCap, mapSubmitScoreFailure } from './chunk-
|
|
2
|
-
|
|
3
|
-
// src/http/backendHttpDeps.ts
|
|
4
|
-
async function resolveGameSessionToken(getGameSessionToken) {
|
|
5
|
-
if (!getGameSessionToken) return null;
|
|
6
|
-
try {
|
|
7
|
-
return await getGameSessionToken();
|
|
8
|
-
} catch {
|
|
9
|
-
return null;
|
|
10
|
-
}
|
|
11
|
-
}
|
|
12
|
-
async function authedBackendFetch(deps, method, path, body) {
|
|
13
|
-
const [idToken, gst] = await Promise.all([
|
|
14
|
-
deps.getIdToken(),
|
|
15
|
-
resolveGameSessionToken(deps.getGameSessionToken)
|
|
16
|
-
]);
|
|
17
|
-
const headers = {
|
|
18
|
-
"Content-Type": "application/json",
|
|
19
|
-
Authorization: `Bearer ${idToken}`
|
|
20
|
-
};
|
|
21
|
-
if (gst) headers["x-h5-game-session"] = gst;
|
|
22
|
-
return fetch(`${deps.getCloudRunUrl()}${path}`, {
|
|
23
|
-
method,
|
|
24
|
-
headers,
|
|
25
|
-
...body !== void 0 ? { body: JSON.stringify(body) } : {}
|
|
26
|
-
});
|
|
27
|
-
}
|
|
1
|
+
import { resolveGameSessionToken, assertValidImageGenSeed, RateLimitedError, RundotApiError, assertReplayWithinInlineCap, mapSubmitScoreFailure } from './chunk-SFJILJFQ.js';
|
|
28
2
|
|
|
29
3
|
// src/imageGen/HttpImageGenApi.ts
|
|
30
4
|
var HttpImageGenApi = class {
|
|
@@ -489,6 +463,6 @@ var HttpLeaderboardApi = class {
|
|
|
489
463
|
}
|
|
490
464
|
};
|
|
491
465
|
|
|
492
|
-
export { HttpAudioGenApi, HttpImageGenApi, HttpLeaderboardApi, HttpSpriteGenApi, HttpThreeDGenApi, HttpVideoGenApi
|
|
493
|
-
//# sourceMappingURL=chunk-
|
|
494
|
-
//# sourceMappingURL=chunk-
|
|
466
|
+
export { HttpAudioGenApi, HttpImageGenApi, HttpLeaderboardApi, HttpSpriteGenApi, HttpThreeDGenApi, HttpVideoGenApi };
|
|
467
|
+
//# sourceMappingURL=chunk-56UNQZIB.js.map
|
|
468
|
+
//# sourceMappingURL=chunk-56UNQZIB.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/imageGen/HttpImageGenApi.ts","../src/audioGen/HttpAudioGenApi.ts","../src/videoGen/HttpVideoGenApi.ts","../src/spriteGen/HttpSpriteGenApi.ts","../src/threeDGen/HttpThreeDGenApi.ts","../src/leaderboard/normalizeScores.ts","../src/leaderboard/HttpLeaderboardApi.ts"],"names":[],"mappings":"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","file":"chunk-56UNQZIB.js","sourcesContent":["// Host-facing HTTP implementation of ImageGenApi. Firebase-free: auth + base URL\n// come from the injected BackendHttpDeps, so any host (PlaygroundHost, Telegram/Steam\n// shells) can construct it. Do NOT import from barrel exports (imageGen/index.ts).\n\nimport { ImageGenApi, ImageGenParams, ImageGenResult, ImageGenJobEvent, DepthEstimationParams, DepthEstimationResult, RemoveBackgroundParams, RemoveBackgroundResult, UpscaleImageParams, UpscaleImageResult } from './ImageGenApi';\nimport { assertValidImageGenSeed } from './validateSeed';\nimport { resolveGameSessionToken } from '../http/backendHttpDeps';\nimport type { BackendHttpDeps } from '../http/backendHttpDeps';\n\nexport class HttpImageGenApi implements ImageGenApi {\n private readonly appId: string;\n private readonly deps: BackendHttpDeps;\n\n constructor(appId: string, deps: BackendHttpDeps) {\n this.appId = appId;\n this.deps = deps;\n }\n\n private async authedPost<T>(path: string, body: Record<string, unknown>): Promise<T> {\n const idToken = await this.deps.getIdToken();\n const baseUrl = this.deps.getCloudRunUrl();\n const url = `${baseUrl}/v1/imagegen/${this.appId}/${path}`;\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n 'Authorization': `Bearer ${idToken}`,\n 'x-consumer': 'sdk',\n };\n\n const gst = await resolveGameSessionToken(this.deps.getGameSessionToken);\n if (gst) headers['x-h5-game-session'] = gst;\n\n const response = await fetch(url, {\n method: 'POST',\n headers,\n body: JSON.stringify(body),\n });\n\n if (!response.ok) {\n const errorText = await response.text();\n let errorMessage = `Request failed (${response.status})`;\n try {\n const errorJson = JSON.parse(errorText);\n errorMessage = errorJson.error || errorJson.message || errorMessage;\n } catch {\n if (errorText) errorMessage = errorText;\n }\n throw new Error(errorMessage);\n }\n\n return response.json();\n }\n\n async generate(params: ImageGenParams): Promise<ImageGenResult> {\n assertValidImageGenSeed(params.seed);\n return this.authedPost<ImageGenResult>('generate', params as unknown as Record<string, unknown>);\n }\n\n async estimateDepth(params: DepthEstimationParams): Promise<DepthEstimationResult> {\n return this.authedPost<DepthEstimationResult>('estimate-depth', params as unknown as Record<string, unknown>);\n }\n\n async removeBackground(params: RemoveBackgroundParams): Promise<RemoveBackgroundResult> {\n return this.authedPost<RemoveBackgroundResult>('remove-background', params as unknown as Record<string, unknown>);\n }\n\n async upscaleImage(params: UpscaleImageParams): Promise<UpscaleImageResult> {\n return this.authedPost<UpscaleImageResult>('upscale-image', params as unknown as Record<string, unknown>);\n }\n\n async getCompletedJobs(): Promise<ImageGenJobEvent[]> {\n return [];\n }\n}\n","// Host-facing HTTP implementation of AudioGenApi. Firebase-free: auth + base URL\n// come from the injected BackendHttpDeps. Do NOT import from barrel exports\n// (audioGen/index.ts).\n\nimport {\n AudioGenApi,\n AudioGenParams,\n AudioGenResult,\n AudioGenJobEvent,\n ListVoicesResult,\n DesignVoicesParams,\n DesignVoicesResult,\n SaveDesignedVoiceParams,\n SaveDesignedVoiceResult,\n} from './AudioGenApi';\nimport { RundotApiError, RateLimitedError } from '../errors';\nimport { resolveGameSessionToken } from '../http/backendHttpDeps';\nimport type { BackendHttpDeps } from '../http/backendHttpDeps';\n\nexport class HttpAudioGenApi implements AudioGenApi {\n private readonly appId: string;\n private readonly deps: BackendHttpDeps;\n\n constructor(appId: string, deps: BackendHttpDeps) {\n this.appId = appId;\n this.deps = deps;\n }\n\n private async authedFetch(path: string, method: string, body?: unknown): Promise<Response> {\n const idToken = await this.deps.getIdToken();\n const baseUrl = this.deps.getCloudRunUrl();\n const url = `${baseUrl}/v1/audiogen/${this.appId}/${path}`;\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n 'Authorization': `Bearer ${idToken}`,\n };\n\n const gst = await resolveGameSessionToken(this.deps.getGameSessionToken);\n if (gst) headers['x-h5-game-session'] = gst;\n\n const response = await fetch(url, {\n method,\n headers,\n ...(body !== undefined ? { body: JSON.stringify(body) } : {}),\n });\n\n if (!response.ok) {\n if (response.status === 429) {\n const retryAfterSec = parseInt(response.headers.get('Retry-After') ?? '60', 10);\n throw new RateLimitedError(retryAfterSec * 1000);\n }\n const errorText = await response.text();\n let errorMessage = `Audio generation failed (${response.status})`;\n let errorCode = 'UNKNOWN';\n try {\n const errorJson = JSON.parse(errorText) as Record<string, unknown>;\n errorMessage = (errorJson.error ?? errorJson.message ?? errorMessage) as string;\n if (typeof errorJson.code === 'string') errorCode = errorJson.code;\n } catch {\n if (errorText) errorMessage = errorText;\n }\n throw new RundotApiError(errorCode, errorMessage, response.status);\n }\n\n return response;\n }\n\n async generate(params: AudioGenParams): Promise<AudioGenResult> {\n const response = await this.authedFetch('generate', 'POST', params);\n return response.json();\n }\n\n async getCompletedJobs(): Promise<AudioGenJobEvent[]> {\n return [];\n }\n\n async listVoices(): Promise<ListVoicesResult> {\n const response = await this.authedFetch('voices', 'GET');\n return response.json();\n }\n\n async designVoices(params: DesignVoicesParams): Promise<DesignVoicesResult> {\n const response = await this.authedFetch('voices/design', 'POST', params);\n return response.json();\n }\n\n async saveDesignedVoice(params: SaveDesignedVoiceParams): Promise<SaveDesignedVoiceResult> {\n const response = await this.authedFetch('voices/save', 'POST', params);\n return response.json();\n }\n}\n","// Host-facing HTTP implementation of VideoGenApi. Firebase-free: auth + base URL\n// come from the injected BackendHttpDeps. Do NOT import from barrel exports\n// (videoGen/index.ts).\n\nimport { VideoGenApi, VideoGenParams, VideoGenResult, VideoGenJobEvent, VideoGenJobStartedEvent } from './VideoGenApi'\nimport { resolveGameSessionToken } from '../http/backendHttpDeps'\nimport { RundotApiError, type ProviderErrorDetail } from '../errors'\nimport type { BackendHttpDeps } from '../http/backendHttpDeps'\n\nexport class HttpVideoGenApi implements VideoGenApi {\n private readonly appId: string\n private readonly deps: BackendHttpDeps\n\n constructor(appId: string, deps: BackendHttpDeps) {\n this.appId = appId\n this.deps = deps\n }\n\n async generate(params: VideoGenParams): Promise<VideoGenResult> {\n const idToken = await this.deps.getIdToken()\n const baseUrl = this.deps.getCloudRunUrl()\n const url = `${baseUrl}/v1/videogen/${this.appId}/sync-generate`\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n 'Authorization': `Bearer ${idToken}`,\n }\n\n const gst = await resolveGameSessionToken(this.deps.getGameSessionToken);\n if (gst) headers['x-h5-game-session'] = gst;\n\n const response = await fetch(url, {\n method: 'POST',\n headers,\n body: JSON.stringify(params),\n })\n\n if (!response.ok) {\n const errorText = await response.text()\n let errorMessage = `Video generation failed (${response.status})`\n let errorCode = 'UNKNOWN'\n let detail: string | undefined\n let errorDetail: ProviderErrorDetail | undefined\n try {\n const errorJson = JSON.parse(errorText) as Record<string, unknown>\n errorMessage = (errorJson.error ?? errorJson.message ?? errorMessage) as string\n if (typeof errorJson.code === 'string') errorCode = errorJson.code\n if (typeof errorJson.detail === 'string') detail = errorJson.detail\n if (errorJson.errorDetail && typeof errorJson.errorDetail === 'object') {\n errorDetail = errorJson.errorDetail as ProviderErrorDetail\n }\n } catch {\n if (errorText) errorMessage = errorText\n }\n throw new RundotApiError(errorCode, errorMessage, response.status, detail, errorDetail)\n }\n\n return response.json()\n }\n\n async getCompletedJobs(): Promise<VideoGenJobEvent[]> {\n return []\n }\n\n async cancel(jobId: string): Promise<void> {\n const idToken = await this.deps.getIdToken()\n const baseUrl = this.deps.getCloudRunUrl()\n const url = `${baseUrl}/v1/jobs/${this.appId}/${jobId}/cancel`\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n 'Authorization': `Bearer ${idToken}`,\n }\n\n const gst = await resolveGameSessionToken(this.deps.getGameSessionToken);\n if (gst) headers['x-h5-game-session'] = gst;\n\n const response = await fetch(url, {\n method: 'POST',\n headers,\n })\n\n if (!response.ok) {\n const errorText = await response.text()\n let errorMessage = `Job cancellation failed (${response.status})`\n try {\n const errorJson = JSON.parse(errorText)\n errorMessage = errorJson.error || errorJson.message || errorMessage\n } catch {\n if (errorText) errorMessage = errorText\n }\n throw new Error(errorMessage)\n }\n }\n\n onJobStarted(_callback: (event: VideoGenJobStartedEvent) => void): { unsubscribe: () => void } {\n return { unsubscribe: () => {} }\n }\n}\n","import {\n SpriteGenApi,\n SpriteGenParams,\n SpriteGenResult,\n AnimateSpriteParams,\n AnimateSpriteResult,\n CharacterAnimateParams,\n CharacterWorkflow,\n SpriteGenCosts,\n SpriteGenJobEvent,\n} from './SpriteGenApi';\nimport { resolveGameSessionToken } from '../http/backendHttpDeps';\nimport type { BackendHttpDeps } from '../http/backendHttpDeps';\n\nexport class HttpSpriteGenApi implements SpriteGenApi {\n private readonly appId: string;\n private readonly deps: BackendHttpDeps;\n\n constructor(appId: string, deps: BackendHttpDeps) {\n this.appId = appId;\n this.deps = deps;\n }\n\n async generate(params: SpriteGenParams): Promise<SpriteGenResult> {\n return this.post<SpriteGenResult>('generate', params);\n }\n\n async animate(params: AnimateSpriteParams): Promise<AnimateSpriteResult> {\n return this.post<AnimateSpriteResult>('animate', params);\n }\n\n async characterAnimate(params: CharacterAnimateParams): Promise<{ jobId: string }> {\n return this.post<{ jobId: string }>('character-animate', params);\n }\n\n async listCharacterWorkflows(): Promise<CharacterWorkflow[]> {\n const data = await this.get<{ workflows: CharacterWorkflow[] }>(\n `/v1/spritegen/${this.appId}/character-workflows`,\n 'List character workflows failed',\n );\n return data.workflows;\n }\n\n async listModels(): Promise<unknown> {\n const data = await this.get<{ models: unknown }>('/v1/spritegen/models', 'List sprite models failed');\n return data.models;\n }\n\n async getCosts(): Promise<SpriteGenCosts> {\n return this.get<SpriteGenCosts>('/v1/spritegen/costs', 'Get sprite costs failed');\n }\n\n async getCompletedJobs(): Promise<SpriteGenJobEvent[]> {\n const data = await this.get<{ jobs: SpriteGenJobEvent[] }>(\n `/v1/jobs/${this.appId}/spritegen/completed`,\n 'Get completed sprite jobs failed',\n );\n return data.jobs;\n }\n\n private async get<T>(path: string, errorFallback: string): Promise<T> {\n const idToken = await this.deps.getIdToken();\n const baseUrl = this.deps.getCloudRunUrl();\n const headers: Record<string, string> = { 'Authorization': `Bearer ${idToken}` };\n\n const gst = await resolveGameSessionToken(this.deps.getGameSessionToken);\n if (gst) headers['x-h5-game-session'] = gst;\n\n const response = await fetch(`${baseUrl}${path}`, {\n method: 'GET',\n headers,\n });\n\n if (!response.ok) {\n throw new Error(await this.extractError(response, errorFallback));\n }\n\n return response.json() as Promise<T>;\n }\n\n private async post<T>(endpoint: string, body: unknown): Promise<T> {\n const idToken = await this.deps.getIdToken();\n const baseUrl = this.deps.getCloudRunUrl();\n const url = `${baseUrl}/v1/spritegen/${this.appId}/${endpoint}`;\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n 'Authorization': `Bearer ${idToken}`,\n };\n\n const gst = await resolveGameSessionToken(this.deps.getGameSessionToken);\n if (gst) headers['x-h5-game-session'] = gst;\n\n const response = await fetch(url, {\n method: 'POST',\n headers,\n body: JSON.stringify(body),\n });\n\n if (!response.ok) {\n throw new Error(await this.extractError(response, `Sprite ${endpoint} failed`));\n }\n\n return response.json() as Promise<T>;\n }\n\n private async extractError(response: Response, fallback: string): Promise<string> {\n const errorText = await response.text();\n let errorMessage = `${fallback} (${response.status})`;\n try {\n const errorJson = JSON.parse(errorText);\n errorMessage = errorJson.error || errorJson.message || errorMessage;\n } catch {\n if (errorText) errorMessage = errorText;\n }\n return errorMessage;\n }\n}\n","// Host-facing HTTP implementation of ThreeDGenApi. Firebase-free: auth + base URL\n// come from the injected BackendHttpDeps. Do NOT import from barrel exports\n// (threeDGen/index.ts).\n\nimport {\n ThreeDGenApi,\n ThreeDGenParams,\n ThreeDGenResult,\n RemeshParams,\n RemeshResult,\n RigParams,\n RigResult,\n AnimateParams,\n AnimateResult,\n ThreeDGenJobEvent,\n} from './ThreeDGenApi'\nimport { RundotApiError } from '../errors'\nimport { resolveGameSessionToken } from '../http/backendHttpDeps'\nimport type { BackendHttpDeps } from '../http/backendHttpDeps'\n\nexport class HttpThreeDGenApi implements ThreeDGenApi {\n private readonly appId: string\n private readonly deps: BackendHttpDeps\n\n constructor(appId: string, deps: BackendHttpDeps) {\n this.appId = appId\n this.deps = deps\n }\n\n async generate(params: ThreeDGenParams): Promise<ThreeDGenResult> {\n return this.post<ThreeDGenResult>('sync-generate', params)\n }\n\n async remesh(params: RemeshParams): Promise<RemeshResult> {\n return this.post<RemeshResult>('sync-remesh', params)\n }\n\n async rig(params: RigParams): Promise<RigResult> {\n return this.post<RigResult>('sync-rig', params)\n }\n\n async animate(params: AnimateParams): Promise<AnimateResult> {\n return this.post<AnimateResult>('sync-animate', params)\n }\n\n async getCompletedJobs(): Promise<ThreeDGenJobEvent[]> {\n return []\n }\n\n private async post<T>(endpoint: string, body: unknown): Promise<T> {\n const idToken = await this.deps.getIdToken()\n const baseUrl = this.deps.getCloudRunUrl()\n const url = `${baseUrl}/v1/threedgen/${this.appId}/${endpoint}`\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n 'Authorization': `Bearer ${idToken}`,\n }\n\n const gst = await resolveGameSessionToken(this.deps.getGameSessionToken);\n if (gst) headers['x-h5-game-session'] = gst;\n\n const response = await fetch(url, {\n method: 'POST',\n headers,\n body: JSON.stringify(body),\n })\n\n if (!response.ok) {\n const errorText = await response.text()\n let errorMessage = `3D generation failed (${response.status})`\n let errorCode = 'UNKNOWN'\n let detail: string | undefined\n try {\n const errorJson = JSON.parse(errorText) as Record<string, unknown>\n errorMessage = (errorJson.error ?? errorJson.message ?? errorMessage) as string\n if (typeof errorJson.code === 'string') errorCode = errorJson.code\n if (typeof errorJson.detail === 'string') detail = errorJson.detail\n } catch {\n if (errorText) errorMessage = errorText\n }\n throw new RundotApiError(errorCode, errorMessage, response.status, detail)\n }\n\n return response.json()\n }\n}\n","/**\n * Idempotently convert Firestore-serialized timestamps to epoch millis on\n * leaderboard score responses. Leaderboard endpoints serialize Firestore\n * Timestamps as `{ seconds, nanoseconds }` (or `{ _seconds, _nanoseconds }`),\n * but `LeaderboardEntry` declares `submittedAt`/`expiresAt` as epoch millis.\n * Already-millis values pass through unchanged.\n */\nfunction toMillis(value: unknown): unknown {\n if (value && typeof value === 'object') {\n const v = value as Record<string, unknown>\n // Firestore Timestamp instance (defensive — survives only in-process, not\n // over HTTP/JSON, but keeps parity with the RN host's normalizer so this can\n // be the single source of truth when that migrates).\n if (typeof v.toMillis === 'function') {\n try {\n return (v.toMillis as () => number)()\n } catch {\n return value\n }\n }\n const seconds = (v.seconds ?? v._seconds) as number | undefined\n const nanos = (v.nanoseconds ?? v._nanoseconds) as number | undefined\n if (typeof seconds === 'number' && typeof nanos === 'number') {\n return seconds * 1000 + Math.floor(nanos / 1_000_000)\n }\n }\n return value\n}\n\nfunction normalizeEntry(entry: unknown): unknown {\n if (!entry || typeof entry !== 'object') return entry\n const e = entry as Record<string, unknown>\n return { ...e, submittedAt: toMillis(e.submittedAt), expiresAt: toMillis(e.expiresAt) }\n}\n\nexport function normalizeScoresResponse<T>(payload: T): T {\n if (!payload || typeof payload !== 'object') return payload\n const p = payload as Record<string, unknown>\n const result: Record<string, unknown> = { ...p }\n if (Array.isArray(p.entries)) result.entries = p.entries.map(normalizeEntry)\n if (p.context && typeof p.context === 'object') {\n const c = p.context as Record<string, unknown>\n result.context = {\n ...c,\n topEntries: Array.isArray(c.topEntries) ? c.topEntries.map(normalizeEntry) : c.topEntries,\n beforePlayer: Array.isArray(c.beforePlayer) ? c.beforePlayer.map(normalizeEntry) : c.beforePlayer,\n playerEntry: c.playerEntry ? normalizeEntry(c.playerEntry) : c.playerEntry,\n afterPlayer: Array.isArray(c.afterPlayer) ? c.afterPlayer.map(normalizeEntry) : c.afterPlayer,\n }\n }\n return result as T\n}\n","/**\n * HTTP-backed {@link LeaderboardApi} implementation usable by any host.\n *\n * Firebase-free: the caller injects `callRemote` (PlaygroundHost passes\n * `callRemoteFunction`; platform shells pass their own authenticated invoker),\n * so importing this file does NOT pull firebase into a host bundle. Do NOT\n * import from barrel exports (leaderboard/index.ts).\n */\nimport {\n LeaderboardApi,\n ScoreToken,\n SubmitScoreParams,\n SubmitScoreResult,\n GetPagedScoresOptions,\n PagedScoresResponse,\n PlayerRankOptions,\n PlayerRankResult,\n GetPodiumScoresOptions,\n PodiumScoresResponse,\n} from './LeaderboardApi'\nimport type { RemoteFunctionInvoker } from '../http/callRemoteFunction'\nimport { normalizeScoresResponse } from './normalizeScores'\nimport { assertReplayWithinInlineCap } from './replaySize'\nimport { mapSubmitScoreFailure } from './utils'\n\n/**\n * HTTP-based implementation of LeaderboardApi.\n */\nexport class HttpLeaderboardApi implements LeaderboardApi {\n private readonly appId: string\n private readonly callRemote: RemoteFunctionInvoker\n\n constructor(\n appId: string,\n options: {\n callRemote: RemoteFunctionInvoker\n },\n ) {\n this.appId = appId\n this.callRemote = options.callRemote\n }\n\n async createScoreToken(mode?: string): Promise<ScoreToken> {\n return this.callRemote<ScoreToken>('apiCreateScoreToken', {\n appId: this.appId,\n mode: mode || 'default',\n })\n }\n\n async submitScore(params: SubmitScoreParams): Promise<SubmitScoreResult> {\n if (params.replay !== undefined) {\n assertReplayWithinInlineCap(params.replay)\n }\n try {\n return await this.callRemote<SubmitScoreResult>('apiSubmitScore', {\n appId: this.appId,\n token: params.token,\n score: params.score,\n duration: params.duration,\n mode: params.mode || 'default',\n period: params.period,\n telemetry: params.telemetry,\n metadata: params.metadata,\n // Score-sealing hash auto-computed by RpcLeaderboardApi; without it sealed\n // leaderboards reject the score.\n hash: params.hash,\n // The recorded replay for a requiresReplay board; the server re-runs the\n // certified runtime over it before ranking the score.\n replay: params.replay,\n })\n } catch (error) {\n // Resolve identity-change / replay-rejection to a typed result so HTTP\n // callers (playground) complete the same pending → ranked/rejected flow as\n // the RPC path. Genuine failures still throw.\n const mapped = mapSubmitScoreFailure(error)\n if (mapped) {\n return mapped\n }\n throw error\n }\n }\n\n async getPagedScores(options?: GetPagedScoresOptions): Promise<PagedScoresResponse> {\n const res = await this.callRemote<PagedScoresResponse>('apiGetPagedScores', {\n appId: this.appId,\n mode: options?.mode || 'default',\n period: options?.period || 'alltime',\n periodDate: options?.periodDate,\n cursor: options?.cursor,\n limit: options?.limit,\n variant: options?.variant || 'standard',\n topCount: options?.topCount,\n contextAhead: options?.contextAhead,\n contextBehind: options?.contextBehind,\n })\n return normalizeScoresResponse(res)\n }\n\n async getMyRank(options?: PlayerRankOptions): Promise<PlayerRankResult> {\n const res = await this.callRemote<PlayerRankResult>('apiGetMyRank', {\n appId: this.appId,\n mode: options?.mode || 'default',\n period: options?.period || 'alltime',\n periodDate: options?.periodDate,\n })\n return normalizeScoresResponse(res)\n }\n\n async getPodiumScores(options?: GetPodiumScoresOptions): Promise<PodiumScoresResponse> {\n const res = await this.callRemote<PodiumScoresResponse>('apiGetPodiumScores', {\n appId: this.appId,\n mode: options?.mode || 'default',\n period: options?.period || 'alltime',\n periodDate: options?.periodDate,\n topCount: options?.topCount,\n contextAhead: options?.contextAhead,\n contextBehind: options?.contextBehind,\n })\n return normalizeScoresResponse(res)\n }\n}\n"]}
|