382 lines
9.1 KiB
TypeScript
382 lines
9.1 KiB
TypeScript
import type { JsonObject } from './common';
|
|
|
|
export const SAVE_SNAPSHOT_VERSION = 2;
|
|
export const DEFAULT_MUSIC_VOLUME = 0.42;
|
|
export const DEFAULT_PLATFORM_THEME = 'light';
|
|
export const PLATFORM_THEMES = ['light', 'dark'] as const;
|
|
export type PlatformTheme = (typeof PLATFORM_THEMES)[number];
|
|
|
|
export type SavedGameSnapshot<
|
|
TGameState = unknown,
|
|
TBottomTab extends string = string,
|
|
TCurrentStory = unknown,
|
|
> = {
|
|
version: number;
|
|
savedAt: string;
|
|
gameState: TGameState;
|
|
bottomTab: TBottomTab;
|
|
currentStory: TCurrentStory | null;
|
|
};
|
|
|
|
export type SavedGameSnapshotInput<
|
|
TGameState = unknown,
|
|
TBottomTab extends string = string,
|
|
TCurrentStory = unknown,
|
|
> = Omit<
|
|
SavedGameSnapshot<TGameState, TBottomTab, TCurrentStory>,
|
|
'savedAt' | 'version'
|
|
> & {
|
|
savedAt?: string;
|
|
};
|
|
|
|
export type RuntimeSettings = {
|
|
musicVolume: number;
|
|
platformTheme: PlatformTheme;
|
|
};
|
|
|
|
export type BasicOkResult = {
|
|
ok: true;
|
|
};
|
|
|
|
export type ProfileDashboardCardKey = 'wallet' | 'playTime' | 'playedWorks';
|
|
|
|
export type ProfileDashboardSummary = {
|
|
walletBalance: number;
|
|
totalPlayTimeMs: number;
|
|
playedWorldCount: number;
|
|
updatedAt: string | null;
|
|
};
|
|
|
|
export type ProfileWalletLedgerEntry = {
|
|
id: string;
|
|
amountDelta: number;
|
|
balanceAfter: number;
|
|
sourceType:
|
|
| 'snapshot_sync'
|
|
| 'invite_inviter_reward'
|
|
| 'invite_invitee_reward'
|
|
| 'points_recharge'
|
|
| 'asset_generation_consume'
|
|
| 'asset_generation_refund'
|
|
| 'redeem_code_reward';
|
|
createdAt: string;
|
|
};
|
|
|
|
export type ProfileWalletLedgerResponse = {
|
|
entries: ProfileWalletLedgerEntry[];
|
|
};
|
|
|
|
export type ProfileRechargeProductKind = 'points' | 'membership';
|
|
export type ProfileMembershipStatus = 'normal' | 'active';
|
|
export type ProfileMembershipTier = 'normal' | 'month' | 'season' | 'year';
|
|
export type ProfileRechargeOrderStatus = 'paid';
|
|
|
|
export type ProfileRechargeProduct = {
|
|
productId: string;
|
|
title: string;
|
|
priceCents: number;
|
|
kind: ProfileRechargeProductKind;
|
|
pointsAmount: number;
|
|
bonusPoints: number;
|
|
durationDays: number;
|
|
badgeLabel: string;
|
|
description: string;
|
|
tier: ProfileMembershipTier;
|
|
};
|
|
|
|
export type ProfileMembershipBenefit = {
|
|
benefitName: string;
|
|
normalValue: string;
|
|
monthValue: string;
|
|
seasonValue: string;
|
|
yearValue: string;
|
|
};
|
|
|
|
export type ProfileMembership = {
|
|
status: ProfileMembershipStatus;
|
|
tier: ProfileMembershipTier;
|
|
startedAt: string | null;
|
|
expiresAt: string | null;
|
|
updatedAt: string | null;
|
|
};
|
|
|
|
export type ProfileRechargeOrder = {
|
|
orderId: string;
|
|
productId: string;
|
|
productTitle: string;
|
|
kind: ProfileRechargeProductKind;
|
|
amountCents: number;
|
|
status: ProfileRechargeOrderStatus;
|
|
paymentChannel: string;
|
|
paidAt: string;
|
|
createdAt: string;
|
|
pointsDelta: number;
|
|
membershipExpiresAt: string | null;
|
|
};
|
|
|
|
export type ProfileRechargeCenterResponse = {
|
|
walletBalance: number;
|
|
membership: ProfileMembership;
|
|
pointProducts: ProfileRechargeProduct[];
|
|
membershipProducts: ProfileRechargeProduct[];
|
|
benefits: ProfileMembershipBenefit[];
|
|
latestOrder: ProfileRechargeOrder | null;
|
|
hasPointsRecharged: boolean;
|
|
};
|
|
|
|
export type CreateProfileRechargeOrderRequest = {
|
|
productId: string;
|
|
paymentChannel?: string;
|
|
};
|
|
|
|
export type CreateProfileRechargeOrderResponse = {
|
|
order: ProfileRechargeOrder;
|
|
center: ProfileRechargeCenterResponse;
|
|
};
|
|
|
|
export type ProfileReferralInviteCenterResponse = {
|
|
inviteCode: string;
|
|
inviteLinkPath: string;
|
|
invitedCount: number;
|
|
rewardedInviteCount: number;
|
|
todayInviterRewardCount: number;
|
|
todayInviterRewardRemaining: number;
|
|
rewardPoints: number;
|
|
hasRedeemedCode: boolean;
|
|
boundInviterUserId: string | null;
|
|
boundAt: string | null;
|
|
updatedAt: string;
|
|
};
|
|
|
|
export type RedeemProfileReferralInviteCodeRequest = {
|
|
inviteCode: string;
|
|
};
|
|
|
|
export type RedeemProfileReferralInviteCodeResponse = {
|
|
center: ProfileReferralInviteCenterResponse;
|
|
inviteeRewardGranted: boolean;
|
|
inviterRewardGranted: boolean;
|
|
inviteeBalanceAfter: number;
|
|
inviterBalanceAfter: number;
|
|
};
|
|
|
|
export type RedeemProfileRewardCodeRequest = {
|
|
code: string;
|
|
};
|
|
|
|
export type RedeemProfileRewardCodeResponse = {
|
|
walletBalance: number;
|
|
amountGranted: number;
|
|
ledgerEntry: ProfileWalletLedgerEntry;
|
|
};
|
|
|
|
export type ProfilePlayedWorkSummary = {
|
|
worldKey: string;
|
|
ownerUserId: string | null;
|
|
profileId: string | null;
|
|
worldType: string | null;
|
|
worldTitle: string;
|
|
worldSubtitle: string;
|
|
firstPlayedAt: string;
|
|
lastPlayedAt: string;
|
|
lastObservedPlayTimeMs: number;
|
|
};
|
|
|
|
export type ProfilePlayStatsResponse = {
|
|
totalPlayTimeMs: number;
|
|
playedWorks: ProfilePlayedWorkSummary[];
|
|
updatedAt: string | null;
|
|
};
|
|
|
|
export type ProfileSaveArchiveSummary = {
|
|
worldKey: string;
|
|
ownerUserId: string | null;
|
|
profileId: string | null;
|
|
worldType: string | null;
|
|
worldName: string;
|
|
subtitle: string;
|
|
summaryText: string;
|
|
coverImageSrc: string | null;
|
|
lastPlayedAt: string;
|
|
};
|
|
|
|
export type ProfileSaveArchiveListResponse = {
|
|
entries: ProfileSaveArchiveSummary[];
|
|
};
|
|
|
|
export type ProfileSaveArchiveResumeResponse<
|
|
TGameState = unknown,
|
|
TBottomTab extends string = string,
|
|
TCurrentStory = unknown,
|
|
> = {
|
|
entry: ProfileSaveArchiveSummary;
|
|
snapshot: SavedGameSnapshot<TGameState, TBottomTab, TCurrentStory>;
|
|
};
|
|
|
|
export type CustomWorldPublicationStatus = 'draft' | 'published';
|
|
export type CustomWorldThemeMode =
|
|
| 'martial'
|
|
| 'arcane'
|
|
| 'machina'
|
|
| 'tide'
|
|
| 'rift'
|
|
| 'mythic';
|
|
|
|
export type CustomWorldProfileRecord = JsonObject & {
|
|
id?: string;
|
|
};
|
|
|
|
export type CustomWorldLibraryEntry<TProfile = CustomWorldProfileRecord> = {
|
|
ownerUserId: string;
|
|
profileId: string;
|
|
publicWorkCode: string | null;
|
|
authorPublicUserCode: string | null;
|
|
profile: TProfile;
|
|
visibility: CustomWorldPublicationStatus;
|
|
publishedAt: string | null;
|
|
updatedAt: string;
|
|
authorDisplayName: string;
|
|
worldName: string;
|
|
subtitle: string;
|
|
summaryText: string;
|
|
coverImageSrc: string | null;
|
|
themeMode: CustomWorldThemeMode;
|
|
playableNpcCount: number;
|
|
landmarkCount: number;
|
|
};
|
|
|
|
export type CustomWorldGalleryCard = Omit<
|
|
CustomWorldLibraryEntry<never>,
|
|
'profile'
|
|
>;
|
|
|
|
export type CustomWorldLibraryResponse<TProfile = CustomWorldProfileRecord> = {
|
|
entries: CustomWorldLibraryEntry<TProfile>[];
|
|
};
|
|
|
|
export type CustomWorldLibraryMutationResponse<
|
|
TProfile = CustomWorldProfileRecord,
|
|
> = {
|
|
entry: CustomWorldLibraryEntry<TProfile>;
|
|
entries: CustomWorldLibraryEntry<TProfile>[];
|
|
};
|
|
|
|
export type CustomWorldGalleryResponse = {
|
|
entries: CustomWorldGalleryCard[];
|
|
};
|
|
|
|
export type CustomWorldGalleryDetailResponse<
|
|
TProfile = CustomWorldProfileRecord,
|
|
> = {
|
|
entry: CustomWorldLibraryEntry<TProfile>;
|
|
};
|
|
|
|
export type PlatformBrowseHistoryEntry = {
|
|
ownerUserId: string;
|
|
profileId: string;
|
|
worldName: string;
|
|
subtitle: string;
|
|
summaryText: string;
|
|
coverImageSrc: string | null;
|
|
themeMode: CustomWorldThemeMode;
|
|
authorDisplayName: string;
|
|
visitedAt: string;
|
|
};
|
|
|
|
export type PlatformBrowseHistoryWriteEntry = Omit<
|
|
PlatformBrowseHistoryEntry,
|
|
'visitedAt'
|
|
> & {
|
|
visitedAt?: string;
|
|
};
|
|
|
|
export type PlatformBrowseHistoryResponse = {
|
|
entries: PlatformBrowseHistoryEntry[];
|
|
};
|
|
|
|
export type PlatformBrowseHistoryBatchSyncRequest = {
|
|
entries: PlatformBrowseHistoryWriteEntry[];
|
|
};
|
|
|
|
export const CUSTOM_WORLD_GENERATION_MODES = ['fast', 'full'] as const;
|
|
export type CustomWorldGenerationMode =
|
|
(typeof CUSTOM_WORLD_GENERATION_MODES)[number];
|
|
|
|
export const CUSTOM_WORLD_SESSION_STATUSES = [
|
|
'clarifying',
|
|
'ready_to_generate',
|
|
'generating',
|
|
'completed',
|
|
'generation_error',
|
|
] as const;
|
|
export type CustomWorldSessionStatus =
|
|
(typeof CUSTOM_WORLD_SESSION_STATUSES)[number];
|
|
|
|
export type CustomWorldQuestion = {
|
|
id: string;
|
|
label: string;
|
|
question: string;
|
|
answer?: string;
|
|
};
|
|
|
|
export type CustomWorldGenerationStep = {
|
|
id: string;
|
|
label: string;
|
|
detail: string;
|
|
completed: number;
|
|
total: number;
|
|
status: 'pending' | 'active' | 'completed';
|
|
};
|
|
|
|
export type CustomWorldGenerationProgress = {
|
|
phaseId: string;
|
|
phaseLabel: string;
|
|
phaseDetail: string;
|
|
batchLabel?: string;
|
|
overallProgress: number;
|
|
completedWeight: number;
|
|
totalWeight: number;
|
|
elapsedMs: number;
|
|
estimatedRemainingMs: number | null;
|
|
activeStepIndex: number;
|
|
steps: CustomWorldGenerationStep[];
|
|
};
|
|
|
|
export type GenerateCustomWorldProfileOptions = {
|
|
onProgress?: (progress: CustomWorldGenerationProgress) => void;
|
|
signal?: AbortSignal;
|
|
};
|
|
|
|
export type GenerateCustomWorldProfileInput = {
|
|
settingText: string;
|
|
creatorIntent?: JsonObject | null;
|
|
generationMode?: CustomWorldGenerationMode;
|
|
};
|
|
|
|
export type CreateCustomWorldSessionRequest = {
|
|
settingText: string;
|
|
creatorIntent?: JsonObject | null;
|
|
generationMode: CustomWorldGenerationMode;
|
|
};
|
|
|
|
export type AnswerCustomWorldSessionQuestionRequest = {
|
|
questionId: string;
|
|
answer: string;
|
|
};
|
|
|
|
export type CustomWorldSessionSummary = {
|
|
sessionId: string;
|
|
status: CustomWorldSessionStatus;
|
|
questions: CustomWorldQuestion[];
|
|
createdAt: string;
|
|
updatedAt: string;
|
|
};
|
|
|
|
export type CustomWorldSessionRecord = CustomWorldSessionSummary & {
|
|
settingText: string;
|
|
creatorIntent?: JsonObject | null;
|
|
generationMode: CustomWorldGenerationMode;
|
|
result?: JsonObject;
|
|
lastError?: string;
|
|
};
|