Settings And Store Fulfillment
Settings and commerce share persistence infrastructure but have different responsibilities. Hs2dSettingsManager owns mutable user settings and side effects. Hs2dStoreService coordinates a platform purchase provider with idempotent fulfillment and entitlement persistence.
Settings
The standard settings are:
interface Hs2dSettingsData {
musicVolume: number;
sfxVolume: number;
fps: 30 | 60;
[key: string]: unknown;
}
Hs2dSettingsManager normalizes volume to 0..1, accepts only 30 or 60 FPS, preserves game-specific keys, saves after changes, and applies audio multipliers immediately.
const settingsManager = new Hs2dSettingsManager({
store: new Hs2dSettingsStore(),
audioManager,
onFpsChanged: (fps) => runtime.setTargetFps(fps),
onRestartRequested: () => restartActiveGame(),
});
settingsManager.adjustVolume('musicVolume', -0.1);
settingsManager.toggleFps();
settingsManager.set('unlockedCourses', ['meadow', 'coast']);
Changing FPS invokes both callbacks when the normalized value changes. The samples request a game restart because individual games may size or tune resources for the target mode.
Hs2dSettingsStore uses the hsGameSettings registry section and JSON-encodes values. Hosts with other persistence can provide initialSettings plus a save callback instead.
Store Components
| Component | Responsibility |
|---|---|
Hs2dStoreConfig | Product mapping, copy, image, purchase type, and grants. |
Hs2dStorePurchaseProvider | Platform catalog, purchase, restore, and shared-port message handling. |
Hs2dStoreFulfillment | Transaction deduplication, entitlement ledger, restore rules, and grants. |
Hs2dStoreGrantHandler | Applies currency, inventory, or game-specific grants. |
Hs2dStoreService | Busy-state coordination and public catalog/purchase/restore API. |
Hs2dPurchaseMenuScene | Optional paused store UI. |
Packages may grant an entitlement, currency, inventory, or a custom payload. Product IDs come from the platform; package IDs are stable game-facing identifiers.
Fulfillment Rules
Hs2dStoreFulfillment is the authority for exactly-once application:
- a previously processed
transactionIdis not applied again; - restored consumables are skipped;
- non-consumable entitlements are retained;
- subscription entitlements are reconciled against the platform's currently active transactions;
- transaction and entitlement ledger changes persist only after grants succeed;
- quantity scales currency, inventory, and quantity-bearing custom grants.
Use persistent ledger storage in production:
const fulfillment = new Hs2dStoreFulfillment(
new Hs2dSettingsStoreLedgerPersistence('my-game'),
grantHandler,
);
const store = new Hs2dStoreService(config, purchaseProvider, fulfillment);
Hs2dMemoryStoreLedgerPersistence exists for tests and ephemeral hosts.
Host Message Routing
The platform provider may share a message port with runtime input. Give each host message to store.handleMessage(message) before an input adapter or other consumer. If it returns true, the store provider consumed it.
Store calls return HsPromise, not native Promise. Keep the provider, fulfillment, and UI lifecycle in the host/scene layer rather than inside a per-frame simulation loop.
Security And Product Rules
- Treat platform transactions as untrusted input until the provider and fulfillment layer accept them.
- Keep product IDs and purchase types aligned with the platform dashboard.
- Never grant a consumable solely because a menu button was pressed.
- Persist the fulfillment ledger; inventory persistence alone does not prevent duplicate grants.
- Test purchase cancellation, duplicate messages, restore, unknown products, failed grant handlers, and subscription expiry.
Source References
| Source | What it proves |
|---|---|
../games/hosanna-ui/src/hosanna-game/settings/Hs2dSettingsTypes.ts | Defaults and normalization. |
../games/hosanna-ui/src/hosanna-game/settings/Hs2dSettingsManager.ts | Save behavior, audio side effects, FPS callbacks, and custom keys. |
../games/hosanna-ui/src/hosanna-game/settings/Hs2dSettingsStore.ts | Registry persistence and JSON encoding. |
../games/hosanna-ui/src/hosanna-game/store/Hs2dStoreTypes.ts | Store configuration, providers, transactions, grants, ledger, and public result types. |
../games/hosanna-ui/src/hosanna-game/store/Hs2dStoreService.ts | Catalog, purchase, restore, busy state, and message routing. |
../games/hosanna-ui/src/hosanna-game/store/Hs2dStoreFulfillment.ts | Deduplication, restore rules, grant ordering, entitlements, and ledger persistence. |
../games/hosanna-ui/src/hosanna-game/store/Hs2dChannelStorePurchaseProvider.ts | Roku channel-store provider boundary. |
../games/hosanna-ui/src/hosanna-game/store/Hs2dGameInventoryGrantHandler.ts | Applying store grants to GameInventory. |
../hosanna-ui-game-samples-public/src/hosanna-game-examples/menu/Hs2dSettingsController.ts | Runnable settings controller behavior. |