639 lines
15 KiB
TypeScript
639 lines
15 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 RuntimeSaveCheckpointInput<TBottomTab extends string = string> = {
|
|
sessionId: string;
|
|
bottomTab: TBottomTab;
|
|
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'
|
|
| 'new_user_registration_reward'
|
|
| 'invite_inviter_reward'
|
|
| 'invite_invitee_reward'
|
|
| 'points_recharge'
|
|
| 'asset_operation_consume'
|
|
| 'asset_operation_refund'
|
|
| 'redeem_code_reward'
|
|
| 'puzzle_author_incentive_claim'
|
|
| 'daily_task_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 =
|
|
| 'pending'
|
|
| 'paid'
|
|
| 'failed'
|
|
| 'closed'
|
|
| 'refunded';
|
|
|
|
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 | null;
|
|
providerTransactionId: string | null;
|
|
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 WechatMiniProgramPayParams = {
|
|
timeStamp: string;
|
|
nonceStr: string;
|
|
package: string;
|
|
signType: 'RSA';
|
|
paySign: string;
|
|
};
|
|
|
|
export type CreateProfileRechargeOrderRequest = {
|
|
productId: string;
|
|
paymentChannel?: string;
|
|
};
|
|
|
|
export type CreateProfileRechargeOrderResponse = {
|
|
order: ProfileRechargeOrder;
|
|
center: ProfileRechargeCenterResponse;
|
|
wechatMiniProgramPayParams?: WechatMiniProgramPayParams | null;
|
|
};
|
|
|
|
export type ConfirmWechatProfileRechargeOrderResponse = {
|
|
order: ProfileRechargeOrder;
|
|
center: ProfileRechargeCenterResponse;
|
|
};
|
|
|
|
export type ProfileFeedbackStatus = 'open';
|
|
|
|
export type ProfileFeedbackEvidenceItemInput = {
|
|
fileName: string;
|
|
contentType: string;
|
|
sizeBytes: number;
|
|
dataUrl: string;
|
|
};
|
|
|
|
export type SubmitProfileFeedbackRequest = {
|
|
description: string;
|
|
contactPhone?: string | null;
|
|
evidenceItems: ProfileFeedbackEvidenceItemInput[];
|
|
};
|
|
|
|
export type ProfileFeedbackEvidenceItem = {
|
|
evidenceId: string;
|
|
fileName: string;
|
|
contentType: string;
|
|
sizeBytes: number;
|
|
};
|
|
|
|
export type ProfileFeedbackSubmission = {
|
|
feedbackId: string;
|
|
status: ProfileFeedbackStatus;
|
|
createdAt: string;
|
|
evidenceItems: ProfileFeedbackEvidenceItem[];
|
|
};
|
|
|
|
export type SubmitProfileFeedbackResponse = {
|
|
feedback: ProfileFeedbackSubmission;
|
|
};
|
|
|
|
export type ProfileReferralInviteCenterResponse = {
|
|
inviteCode: string;
|
|
inviteLinkPath: string;
|
|
invitedCount: number;
|
|
rewardedInviteCount: number;
|
|
todayInviterRewardCount: number;
|
|
todayInviterRewardRemaining: number;
|
|
rewardPoints: number;
|
|
invitedUsers: ProfileReferralInvitedUser[];
|
|
hasRedeemedCode: boolean;
|
|
boundInviterUserId: string | null;
|
|
boundAt: string | null;
|
|
updatedAt: string;
|
|
};
|
|
|
|
export type ProfileReferralInvitedUser = {
|
|
userId: string;
|
|
displayName: string;
|
|
avatarUrl: string | null;
|
|
boundAt: 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 ProfileTaskCycle = 'daily';
|
|
export type TrackingScopeKind = 'site' | 'work' | 'module' | 'user';
|
|
export type AnalyticsGranularity = 'day' | 'week' | 'month' | 'quarter' | 'year';
|
|
export type ProfileTaskStatus =
|
|
| 'incomplete'
|
|
| 'claimable'
|
|
| 'claimed'
|
|
| 'disabled';
|
|
|
|
export type ProfileTaskItem = {
|
|
taskId: string;
|
|
title: string;
|
|
description: string;
|
|
eventKey: string;
|
|
cycle: ProfileTaskCycle;
|
|
threshold: number;
|
|
progressCount: number;
|
|
rewardPoints: number;
|
|
status: ProfileTaskStatus;
|
|
dayKey: number;
|
|
claimedAt: string | null;
|
|
updatedAt: string;
|
|
};
|
|
|
|
export type ProfileTaskCenterResponse = {
|
|
dayKey: number;
|
|
walletBalance: number;
|
|
tasks: ProfileTaskItem[];
|
|
updatedAt: string;
|
|
};
|
|
|
|
export type ClaimProfileTaskRewardResponse = {
|
|
taskId: string;
|
|
dayKey: number;
|
|
rewardPoints: number;
|
|
walletBalance: number;
|
|
ledgerEntry: ProfileWalletLedgerEntry;
|
|
center: ProfileTaskCenterResponse;
|
|
};
|
|
|
|
export type ProfileTaskConfigAdminResponse = {
|
|
taskId: string;
|
|
title: string;
|
|
description: string;
|
|
eventKey: string;
|
|
cycle: ProfileTaskCycle;
|
|
scopeKind: TrackingScopeKind;
|
|
threshold: number;
|
|
rewardPoints: number;
|
|
enabled: boolean;
|
|
sortOrder: number;
|
|
createdBy: string;
|
|
createdAt: string;
|
|
updatedBy: string;
|
|
updatedAt: string;
|
|
};
|
|
|
|
export type ProfileTaskConfigAdminListResponse = {
|
|
entries: ProfileTaskConfigAdminResponse[];
|
|
};
|
|
|
|
export type AnalyticsMetricQueryRequest = {
|
|
eventKey: string;
|
|
scopeKind: TrackingScopeKind;
|
|
scopeId: string;
|
|
granularity: AnalyticsGranularity;
|
|
};
|
|
|
|
export type AnalyticsBucketMetric = {
|
|
bucketKey: string;
|
|
bucketStartDateKey: number;
|
|
bucketEndDateKey: number;
|
|
value: number;
|
|
};
|
|
|
|
export type AnalyticsMetricQueryResponse = {
|
|
buckets: AnalyticsBucketMetric[];
|
|
};
|
|
|
|
export type AdminUpsertProfileTaskConfigRequest = {
|
|
taskId: string;
|
|
title: string;
|
|
description?: string | null;
|
|
eventKey: string;
|
|
cycle: ProfileTaskCycle;
|
|
scopeKind: TrackingScopeKind;
|
|
threshold: number;
|
|
rewardPoints: number;
|
|
enabled?: boolean;
|
|
sortOrder?: number;
|
|
};
|
|
|
|
export type AdminDisableProfileTaskConfigRequest = {
|
|
taskId: string;
|
|
};
|
|
|
|
export type ProfileRedeemCodeMode = 'public' | 'unique' | 'private';
|
|
|
|
export type ProfileRedeemCodeAdminResponse = {
|
|
code: string;
|
|
mode: ProfileRedeemCodeMode;
|
|
rewardPoints: number;
|
|
maxUses: number;
|
|
globalUsedCount: number;
|
|
enabled: boolean;
|
|
allowedUserIds: string[];
|
|
createdBy: string;
|
|
createdAt: string;
|
|
updatedAt: string;
|
|
};
|
|
|
|
export type ProfileRedeemCodeAdminListResponse = {
|
|
entries: ProfileRedeemCodeAdminResponse[];
|
|
};
|
|
|
|
export type AdminUpsertProfileRedeemCodeRequest = {
|
|
code: string;
|
|
mode: ProfileRedeemCodeMode;
|
|
rewardPoints: number;
|
|
maxUses: number;
|
|
enabled?: boolean;
|
|
allowedUserIds?: string[];
|
|
allowedPublicUserCodes?: string[];
|
|
};
|
|
|
|
export type AdminDisableProfileRedeemCodeRequest = {
|
|
code: string;
|
|
};
|
|
|
|
export type AdminUpsertProfileInviteCodeRequest = {
|
|
inviteCode: string;
|
|
metadata?: Record<string, unknown> | null;
|
|
startsAt?: string | null;
|
|
expiresAt?: string | null;
|
|
};
|
|
|
|
export type ProfileInviteCodeAdminResponse = {
|
|
userId: string;
|
|
inviteCode: string;
|
|
metadata: Record<string, unknown>;
|
|
startsAt?: string | null;
|
|
expiresAt?: string | null;
|
|
status: 'pending' | 'active' | 'expired';
|
|
createdAt: string;
|
|
updatedAt: string;
|
|
};
|
|
|
|
export type ProfileInviteCodeAdminListResponse = {
|
|
entries: ProfileInviteCodeAdminResponse[];
|
|
};
|
|
|
|
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;
|
|
openingCg?: CustomWorldOpeningCgProfile | null;
|
|
};
|
|
|
|
export type CustomWorldOpeningCgStatus =
|
|
| 'not_started'
|
|
| 'storyboard_generating'
|
|
| 'video_generating'
|
|
| 'ready'
|
|
| 'failed';
|
|
|
|
export type CustomWorldOpeningCgProfile = {
|
|
id: string;
|
|
status: CustomWorldOpeningCgStatus;
|
|
storyboardImageSrc?: string | null;
|
|
storyboardAssetId?: string | null;
|
|
videoSrc?: string | null;
|
|
videoAssetId?: string | null;
|
|
posterImageSrc?: string | null;
|
|
posterAssetId?: string | null;
|
|
storyboardPrompt?: string | null;
|
|
videoPrompt?: string | null;
|
|
imageModel: 'gpt-image-2';
|
|
videoModel: string;
|
|
aspectRatio: '16:9';
|
|
imageSize: '2k';
|
|
videoResolution: '480p';
|
|
durationSeconds: 15;
|
|
pointCost: 80;
|
|
estimatedWaitMinutes: 10;
|
|
generatedAt?: string | null;
|
|
updatedAt: string;
|
|
errorMessage?: string | null;
|
|
};
|
|
|
|
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;
|
|
playCount?: number;
|
|
remixCount?: number;
|
|
likeCount?: number;
|
|
recentPlayCount7d?: 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;
|
|
};
|