This commit is contained in:
897
server-rs/crates/shared-contracts/src/runtime.rs
Normal file
897
server-rs/crates/shared-contracts/src/runtime.rs
Normal file
@@ -0,0 +1,897 @@
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
pub const RUNTIME_PLATFORM_THEME_LIGHT: &str = "light";
|
||||
pub const RUNTIME_PLATFORM_THEME_DARK: &str = "dark";
|
||||
pub const SAVE_SNAPSHOT_VERSION: u32 = 2;
|
||||
pub const PROFILE_WALLET_LEDGER_SOURCE_TYPE_SNAPSHOT_SYNC: &str = "snapshot_sync";
|
||||
pub const PROFILE_WALLET_LEDGER_SOURCE_TYPE_POINTS_RECHARGE: &str = "points_recharge";
|
||||
pub const PROFILE_WALLET_LEDGER_SOURCE_TYPE_INVITE_INVITER_REWARD: &str = "invite_inviter_reward";
|
||||
pub const PROFILE_WALLET_LEDGER_SOURCE_TYPE_INVITE_INVITEE_REWARD: &str = "invite_invitee_reward";
|
||||
pub const BROWSE_HISTORY_THEME_MODE_MARTIAL: &str = "martial";
|
||||
pub const BROWSE_HISTORY_THEME_MODE_ARCANE: &str = "arcane";
|
||||
pub const BROWSE_HISTORY_THEME_MODE_MACHINA: &str = "machina";
|
||||
pub const BROWSE_HISTORY_THEME_MODE_TIDE: &str = "tide";
|
||||
pub const BROWSE_HISTORY_THEME_MODE_RIFT: &str = "rift";
|
||||
pub const BROWSE_HISTORY_THEME_MODE_MYTHIC: &str = "mythic";
|
||||
pub const CUSTOM_WORLD_VISIBILITY_DRAFT: &str = "draft";
|
||||
pub const CUSTOM_WORLD_VISIBILITY_PUBLISHED: &str = "published";
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct RuntimeSettingsResponse {
|
||||
pub music_volume: f32,
|
||||
pub platform_theme: String,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct PutRuntimeSettingsRequest {
|
||||
pub music_volume: f32,
|
||||
pub platform_theme: String,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct SavedGameSnapshotResponse {
|
||||
pub version: u32,
|
||||
pub saved_at: String,
|
||||
pub game_state: serde_json::Value,
|
||||
pub bottom_tab: String,
|
||||
pub current_story: Option<serde_json::Value>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct PutSavedGameSnapshotRequest {
|
||||
pub game_state: serde_json::Value,
|
||||
pub bottom_tab: String,
|
||||
#[serde(default)]
|
||||
pub current_story: Option<serde_json::Value>,
|
||||
#[serde(default)]
|
||||
pub saved_at: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct BasicOkResponse {
|
||||
pub ok: bool,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct PlatformBrowseHistoryEntryResponse {
|
||||
pub owner_user_id: String,
|
||||
pub profile_id: String,
|
||||
pub world_name: String,
|
||||
pub subtitle: String,
|
||||
pub summary_text: String,
|
||||
pub cover_image_src: Option<String>,
|
||||
pub theme_mode: String,
|
||||
pub author_display_name: String,
|
||||
pub visited_at: String,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct PlatformBrowseHistoryWriteEntryRequest {
|
||||
pub owner_user_id: String,
|
||||
pub profile_id: String,
|
||||
pub world_name: String,
|
||||
#[serde(default)]
|
||||
pub subtitle: Option<String>,
|
||||
#[serde(default)]
|
||||
pub summary_text: Option<String>,
|
||||
#[serde(default)]
|
||||
pub cover_image_src: Option<String>,
|
||||
#[serde(default)]
|
||||
pub theme_mode: Option<String>,
|
||||
#[serde(default)]
|
||||
pub author_display_name: Option<String>,
|
||||
#[serde(default)]
|
||||
pub visited_at: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct PlatformBrowseHistoryBatchSyncRequest {
|
||||
pub entries: Vec<PlatformBrowseHistoryWriteEntryRequest>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
||||
#[serde(untagged)]
|
||||
pub enum PlatformBrowseHistoryUpsertRequest {
|
||||
Single(PlatformBrowseHistoryWriteEntryRequest),
|
||||
Batch(PlatformBrowseHistoryBatchSyncRequest),
|
||||
}
|
||||
|
||||
impl PlatformBrowseHistoryUpsertRequest {
|
||||
pub fn into_entries(self) -> Vec<PlatformBrowseHistoryWriteEntryRequest> {
|
||||
match self {
|
||||
Self::Single(entry) => vec![entry],
|
||||
Self::Batch(batch) => batch.entries,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct PlatformBrowseHistoryResponse {
|
||||
pub entries: Vec<PlatformBrowseHistoryEntryResponse>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct ProfileDashboardSummaryResponse {
|
||||
pub wallet_balance: u64,
|
||||
pub total_play_time_ms: u64,
|
||||
pub played_world_count: u32,
|
||||
pub updated_at: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct ProfileWalletLedgerEntryResponse {
|
||||
pub id: String,
|
||||
pub amount_delta: i64,
|
||||
pub balance_after: u64,
|
||||
pub source_type: String,
|
||||
pub created_at: String,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct ProfileWalletLedgerResponse {
|
||||
pub entries: Vec<ProfileWalletLedgerEntryResponse>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct ProfileRechargeProductResponse {
|
||||
pub product_id: String,
|
||||
pub title: String,
|
||||
pub price_cents: u64,
|
||||
pub kind: String,
|
||||
pub points_amount: u64,
|
||||
pub bonus_points: u64,
|
||||
pub duration_days: u32,
|
||||
pub badge_label: String,
|
||||
pub description: String,
|
||||
pub tier: String,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct ProfileMembershipBenefitResponse {
|
||||
pub benefit_name: String,
|
||||
pub normal_value: String,
|
||||
pub month_value: String,
|
||||
pub season_value: String,
|
||||
pub year_value: String,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct ProfileMembershipResponse {
|
||||
pub status: String,
|
||||
pub tier: String,
|
||||
pub started_at: Option<String>,
|
||||
pub expires_at: Option<String>,
|
||||
pub updated_at: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct ProfileRechargeOrderResponse {
|
||||
pub order_id: String,
|
||||
pub product_id: String,
|
||||
pub product_title: String,
|
||||
pub kind: String,
|
||||
pub amount_cents: u64,
|
||||
pub status: String,
|
||||
pub payment_channel: String,
|
||||
pub paid_at: String,
|
||||
pub created_at: String,
|
||||
pub points_delta: i64,
|
||||
pub membership_expires_at: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct ProfileRechargeCenterResponse {
|
||||
pub wallet_balance: u64,
|
||||
pub membership: ProfileMembershipResponse,
|
||||
pub point_products: Vec<ProfileRechargeProductResponse>,
|
||||
pub membership_products: Vec<ProfileRechargeProductResponse>,
|
||||
pub benefits: Vec<ProfileMembershipBenefitResponse>,
|
||||
pub latest_order: Option<ProfileRechargeOrderResponse>,
|
||||
pub has_points_recharged: bool,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct CreateProfileRechargeOrderRequest {
|
||||
pub product_id: String,
|
||||
#[serde(default)]
|
||||
pub payment_channel: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct CreateProfileRechargeOrderResponse {
|
||||
pub order: ProfileRechargeOrderResponse,
|
||||
pub center: ProfileRechargeCenterResponse,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct ProfileReferralInviteCenterResponse {
|
||||
pub invite_code: String,
|
||||
pub invite_link_path: String,
|
||||
pub invited_count: u32,
|
||||
pub rewarded_invite_count: u32,
|
||||
pub today_inviter_reward_count: u32,
|
||||
pub today_inviter_reward_remaining: u32,
|
||||
pub reward_points: u64,
|
||||
pub has_redeemed_code: bool,
|
||||
pub bound_inviter_user_id: Option<String>,
|
||||
pub bound_at: Option<String>,
|
||||
pub updated_at: String,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct RedeemProfileReferralInviteCodeRequest {
|
||||
pub invite_code: String,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct RedeemProfileReferralInviteCodeResponse {
|
||||
pub center: ProfileReferralInviteCenterResponse,
|
||||
pub invitee_reward_granted: bool,
|
||||
pub inviter_reward_granted: bool,
|
||||
pub invitee_balance_after: u64,
|
||||
pub inviter_balance_after: u64,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct ProfilePlayedWorkSummaryResponse {
|
||||
pub world_key: String,
|
||||
pub owner_user_id: Option<String>,
|
||||
pub profile_id: Option<String>,
|
||||
pub world_type: Option<String>,
|
||||
pub world_title: String,
|
||||
pub world_subtitle: String,
|
||||
pub first_played_at: String,
|
||||
pub last_played_at: String,
|
||||
pub last_observed_play_time_ms: u64,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct ProfilePlayStatsResponse {
|
||||
pub total_play_time_ms: u64,
|
||||
pub played_works: Vec<ProfilePlayedWorkSummaryResponse>,
|
||||
pub updated_at: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct ProfileSaveArchiveSummaryResponse {
|
||||
pub world_key: String,
|
||||
pub owner_user_id: Option<String>,
|
||||
pub profile_id: Option<String>,
|
||||
pub world_type: Option<String>,
|
||||
pub world_name: String,
|
||||
pub subtitle: String,
|
||||
pub summary_text: String,
|
||||
pub cover_image_src: Option<String>,
|
||||
pub last_played_at: String,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct ProfileSaveArchiveListResponse {
|
||||
pub entries: Vec<ProfileSaveArchiveSummaryResponse>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct ProfileSaveArchiveResumeResponse {
|
||||
pub entry: ProfileSaveArchiveSummaryResponse,
|
||||
pub snapshot: SavedGameSnapshotResponse,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct RuntimeInventorySlotResponse {
|
||||
pub slot_id: String,
|
||||
pub container_kind: String,
|
||||
pub slot_key: String,
|
||||
pub item_id: String,
|
||||
pub category: String,
|
||||
pub name: String,
|
||||
pub description: Option<String>,
|
||||
pub quantity: u32,
|
||||
pub rarity: String,
|
||||
pub tags: Vec<String>,
|
||||
pub stackable: bool,
|
||||
pub stack_key: String,
|
||||
pub equipment_slot_id: Option<String>,
|
||||
pub source_kind: String,
|
||||
pub source_reference_id: Option<String>,
|
||||
pub created_at: String,
|
||||
pub updated_at: String,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct RuntimeInventoryStateResponse {
|
||||
pub runtime_session_id: String,
|
||||
pub actor_user_id: String,
|
||||
pub backpack_items: Vec<RuntimeInventorySlotResponse>,
|
||||
pub equipment_items: Vec<RuntimeInventorySlotResponse>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct CustomWorldProfileUpsertRequest {
|
||||
pub profile: serde_json::Value,
|
||||
pub source_agent_session_id: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct CustomWorldLibraryEntryResponse {
|
||||
pub owner_user_id: String,
|
||||
pub profile_id: String,
|
||||
pub public_work_code: Option<String>,
|
||||
pub author_public_user_code: Option<String>,
|
||||
pub profile: serde_json::Value,
|
||||
pub visibility: String,
|
||||
pub published_at: Option<String>,
|
||||
pub updated_at: String,
|
||||
pub author_display_name: String,
|
||||
pub world_name: String,
|
||||
pub subtitle: String,
|
||||
pub summary_text: String,
|
||||
pub cover_image_src: Option<String>,
|
||||
pub theme_mode: String,
|
||||
pub playable_npc_count: u32,
|
||||
pub landmark_count: u32,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct CustomWorldGalleryCardResponse {
|
||||
pub owner_user_id: String,
|
||||
pub profile_id: String,
|
||||
pub public_work_code: String,
|
||||
pub author_public_user_code: String,
|
||||
pub visibility: String,
|
||||
pub published_at: Option<String>,
|
||||
pub updated_at: String,
|
||||
pub author_display_name: String,
|
||||
pub world_name: String,
|
||||
pub subtitle: String,
|
||||
pub summary_text: String,
|
||||
pub cover_image_src: Option<String>,
|
||||
pub theme_mode: String,
|
||||
pub playable_npc_count: u32,
|
||||
pub landmark_count: u32,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct CustomWorldLibraryResponse {
|
||||
pub entries: Vec<CustomWorldLibraryEntryResponse>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct CustomWorldLibraryMutationResponse {
|
||||
pub entry: CustomWorldLibraryEntryResponse,
|
||||
pub entries: Vec<CustomWorldLibraryEntryResponse>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct CustomWorldGalleryResponse {
|
||||
pub entries: Vec<CustomWorldGalleryCardResponse>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct CustomWorldGalleryDetailResponse {
|
||||
pub entry: CustomWorldLibraryEntryResponse,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct CustomWorldWorkSummaryResponse {
|
||||
pub work_id: String,
|
||||
pub source_type: String,
|
||||
pub status: String,
|
||||
pub title: String,
|
||||
pub subtitle: String,
|
||||
pub summary: String,
|
||||
pub cover_image_src: Option<String>,
|
||||
#[serde(default)]
|
||||
pub cover_render_mode: Option<String>,
|
||||
#[serde(default)]
|
||||
pub cover_character_image_srcs: Vec<String>,
|
||||
pub updated_at: String,
|
||||
pub published_at: Option<String>,
|
||||
pub stage: Option<String>,
|
||||
pub stage_label: Option<String>,
|
||||
pub playable_npc_count: u32,
|
||||
pub landmark_count: u32,
|
||||
pub role_visual_ready_count: Option<u32>,
|
||||
pub role_animation_ready_count: Option<u32>,
|
||||
pub role_asset_summary_label: Option<String>,
|
||||
pub session_id: Option<String>,
|
||||
pub profile_id: Option<String>,
|
||||
pub can_resume: bool,
|
||||
pub can_enter_world: bool,
|
||||
pub blocker_count: u32,
|
||||
pub publish_ready: bool,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct CustomWorldWorksResponse {
|
||||
pub items: Vec<CustomWorldWorkSummaryResponse>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct CreateCustomWorldAgentSessionRequest {
|
||||
#[serde(default)]
|
||||
pub seed_text: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct SendCustomWorldAgentMessageRequest {
|
||||
pub client_message_id: String,
|
||||
pub text: String,
|
||||
#[serde(default)]
|
||||
pub quick_fill_requested: Option<bool>,
|
||||
#[serde(default)]
|
||||
pub focus_card_id: Option<String>,
|
||||
#[serde(default)]
|
||||
pub selected_card_ids: Option<Vec<String>>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct CustomWorldAgentMessageResponse {
|
||||
pub id: String,
|
||||
pub role: String,
|
||||
pub kind: String,
|
||||
pub text: String,
|
||||
pub created_at: String,
|
||||
pub related_operation_id: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct CustomWorldAgentOperationResponse {
|
||||
pub operation_id: String,
|
||||
#[serde(rename = "type")]
|
||||
pub operation_type: String,
|
||||
pub status: String,
|
||||
pub phase_label: String,
|
||||
pub phase_detail: String,
|
||||
pub progress: u32,
|
||||
pub error: Option<String>,
|
||||
pub started_at: Option<String>,
|
||||
pub updated_at: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct CustomWorldDraftCardSummaryResponse {
|
||||
pub id: String,
|
||||
pub kind: String,
|
||||
pub title: String,
|
||||
pub subtitle: String,
|
||||
pub summary: String,
|
||||
pub status: String,
|
||||
pub linked_ids: Vec<String>,
|
||||
pub warning_count: u32,
|
||||
pub asset_status: Option<String>,
|
||||
pub asset_status_label: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct CustomWorldDraftCardDetailSectionResponse {
|
||||
pub id: String,
|
||||
pub label: String,
|
||||
pub value: String,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct CustomWorldDraftCardDetailResponse {
|
||||
pub id: String,
|
||||
pub kind: String,
|
||||
pub title: String,
|
||||
pub sections: Vec<CustomWorldDraftCardDetailSectionResponse>,
|
||||
pub linked_ids: Vec<String>,
|
||||
pub locked: bool,
|
||||
pub editable: bool,
|
||||
pub editable_section_ids: Vec<String>,
|
||||
pub warning_messages: Vec<String>,
|
||||
pub asset_status: Option<String>,
|
||||
pub asset_status_label: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct CustomWorldAgentCardDetailResponse {
|
||||
pub card: CustomWorldDraftCardDetailResponse,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct CustomWorldAgentCheckpointResponse {
|
||||
pub checkpoint_id: String,
|
||||
pub created_at: String,
|
||||
pub label: String,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct CustomWorldSupportedActionResponse {
|
||||
pub action: String,
|
||||
pub enabled: bool,
|
||||
pub reason: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct CustomWorldResultPreviewBlockerResponse {
|
||||
pub id: String,
|
||||
pub code: String,
|
||||
pub message: String,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct CustomWorldPublishGateResponse {
|
||||
pub profile_id: String,
|
||||
pub blockers: Vec<CustomWorldResultPreviewBlockerResponse>,
|
||||
pub blocker_count: u32,
|
||||
pub publish_ready: bool,
|
||||
pub can_enter_world: bool,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct CustomWorldAgentSessionSnapshotResponse {
|
||||
pub session_id: String,
|
||||
pub current_turn: u32,
|
||||
pub anchor_content: serde_json::Value,
|
||||
pub progress_percent: u32,
|
||||
pub last_assistant_reply: Option<String>,
|
||||
pub stage: String,
|
||||
pub focus_card_id: Option<String>,
|
||||
pub creator_intent: serde_json::Value,
|
||||
pub creator_intent_readiness: serde_json::Value,
|
||||
pub anchor_pack: serde_json::Value,
|
||||
pub lock_state: serde_json::Value,
|
||||
pub draft_profile: serde_json::Value,
|
||||
pub messages: Vec<CustomWorldAgentMessageResponse>,
|
||||
pub draft_cards: Vec<CustomWorldDraftCardSummaryResponse>,
|
||||
pub pending_clarifications: Vec<serde_json::Value>,
|
||||
pub suggested_actions: Vec<serde_json::Value>,
|
||||
pub recommended_replies: Vec<String>,
|
||||
pub quality_findings: Vec<serde_json::Value>,
|
||||
pub asset_coverage: serde_json::Value,
|
||||
pub checkpoints: Vec<CustomWorldAgentCheckpointResponse>,
|
||||
pub supported_actions: Vec<CustomWorldSupportedActionResponse>,
|
||||
pub publish_gate: Option<CustomWorldPublishGateResponse>,
|
||||
pub result_preview: Option<serde_json::Value>,
|
||||
pub updated_at: String,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct CustomWorldAgentSessionResponse {
|
||||
pub session: CustomWorldAgentSessionSnapshotResponse,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct ExecuteCustomWorldAgentActionRequest {
|
||||
pub action: String,
|
||||
#[serde(default)]
|
||||
pub profile_id: Option<String>,
|
||||
#[serde(default)]
|
||||
pub draft_profile: Option<serde_json::Value>,
|
||||
#[serde(default)]
|
||||
pub legacy_result_profile: Option<serde_json::Value>,
|
||||
#[serde(default)]
|
||||
pub setting_text: Option<String>,
|
||||
#[serde(default)]
|
||||
pub card_id: Option<String>,
|
||||
#[serde(default)]
|
||||
pub sections: Option<Vec<ExecuteCustomWorldAgentDraftCardSectionPatch>>,
|
||||
#[serde(default)]
|
||||
pub profile: Option<serde_json::Value>,
|
||||
#[serde(default)]
|
||||
pub count: Option<u32>,
|
||||
#[serde(default)]
|
||||
pub role_type: Option<String>,
|
||||
#[serde(default)]
|
||||
pub prompt_text: Option<String>,
|
||||
#[serde(default)]
|
||||
pub anchor_card_ids: Option<Vec<String>>,
|
||||
#[serde(default)]
|
||||
pub role_ids: Option<Vec<String>>,
|
||||
#[serde(default)]
|
||||
pub role_id: Option<String>,
|
||||
#[serde(default)]
|
||||
pub portrait_path: Option<String>,
|
||||
#[serde(default)]
|
||||
pub generated_visual_asset_id: Option<String>,
|
||||
#[serde(default)]
|
||||
pub generated_animation_set_id: Option<String>,
|
||||
#[serde(default)]
|
||||
pub animation_map: Option<serde_json::Value>,
|
||||
#[serde(default)]
|
||||
pub scene_ids: Option<Vec<String>>,
|
||||
#[serde(default)]
|
||||
pub scene_id: Option<String>,
|
||||
#[serde(default)]
|
||||
pub scene_kind: Option<String>,
|
||||
#[serde(default)]
|
||||
pub image_src: Option<String>,
|
||||
#[serde(default)]
|
||||
pub generated_scene_asset_id: Option<String>,
|
||||
#[serde(default)]
|
||||
pub generated_scene_prompt: Option<String>,
|
||||
#[serde(default)]
|
||||
pub generated_scene_model: Option<String>,
|
||||
#[serde(default)]
|
||||
pub checkpoint_id: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct ExecuteCustomWorldAgentDraftCardSectionPatch {
|
||||
pub section_id: String,
|
||||
pub value: String,
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use serde_json::json;
|
||||
|
||||
#[test]
|
||||
fn runtime_settings_request_uses_camel_case_fields() {
|
||||
let payload = serde_json::to_value(PutRuntimeSettingsRequest {
|
||||
music_volume: 0.42,
|
||||
platform_theme: RUNTIME_PLATFORM_THEME_LIGHT.to_string(),
|
||||
})
|
||||
.expect("payload should serialize");
|
||||
|
||||
assert_eq!(payload["platformTheme"], json!("light"));
|
||||
let music_volume = payload["musicVolume"]
|
||||
.as_f64()
|
||||
.expect("musicVolume should serialize as number");
|
||||
assert!((music_volume - 0.42).abs() < 0.0001);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn browse_history_response_uses_camel_case_fields() {
|
||||
let payload = serde_json::to_value(PlatformBrowseHistoryResponse {
|
||||
entries: vec![PlatformBrowseHistoryEntryResponse {
|
||||
owner_user_id: "owner-1".to_string(),
|
||||
profile_id: "profile-1".to_string(),
|
||||
world_name: "世界".to_string(),
|
||||
subtitle: "".to_string(),
|
||||
summary_text: "".to_string(),
|
||||
cover_image_src: None,
|
||||
theme_mode: BROWSE_HISTORY_THEME_MODE_MYTHIC.to_string(),
|
||||
author_display_name: "玩家".to_string(),
|
||||
visited_at: "2026-04-21T00:00:00Z".to_string(),
|
||||
}],
|
||||
})
|
||||
.expect("payload should serialize");
|
||||
|
||||
assert_eq!(payload["entries"][0]["ownerUserId"], json!("owner-1"));
|
||||
assert_eq!(payload["entries"][0]["themeMode"], json!("mythic"));
|
||||
assert_eq!(
|
||||
payload["entries"][0]["visitedAt"],
|
||||
json!("2026-04-21T00:00:00Z")
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn browse_history_upsert_request_accepts_single_or_batch_shape() {
|
||||
let single: PlatformBrowseHistoryUpsertRequest = serde_json::from_value(json!({
|
||||
"ownerUserId": "owner-1",
|
||||
"profileId": "profile-1",
|
||||
"worldName": "世界"
|
||||
}))
|
||||
.expect("single shape should deserialize");
|
||||
let batch: PlatformBrowseHistoryUpsertRequest = serde_json::from_value(json!({
|
||||
"entries": [{
|
||||
"ownerUserId": "owner-1",
|
||||
"profileId": "profile-1",
|
||||
"worldName": "世界"
|
||||
}]
|
||||
}))
|
||||
.expect("batch shape should deserialize");
|
||||
|
||||
assert_eq!(single.into_entries().len(), 1);
|
||||
assert_eq!(batch.into_entries().len(), 1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn profile_dashboard_response_uses_camel_case_fields() {
|
||||
let payload = serde_json::to_value(ProfileDashboardSummaryResponse {
|
||||
wallet_balance: 8,
|
||||
total_play_time_ms: 16,
|
||||
played_world_count: 3,
|
||||
updated_at: Some("2026-04-22T10:00:00Z".to_string()),
|
||||
})
|
||||
.expect("payload should serialize");
|
||||
|
||||
assert_eq!(payload["walletBalance"], json!(8));
|
||||
assert_eq!(payload["totalPlayTimeMs"], json!(16));
|
||||
assert_eq!(payload["playedWorldCount"], json!(3));
|
||||
assert_eq!(payload["updatedAt"], json!("2026-04-22T10:00:00Z"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn profile_wallet_ledger_response_uses_camel_case_fields() {
|
||||
let payload = serde_json::to_value(ProfileWalletLedgerResponse {
|
||||
entries: vec![ProfileWalletLedgerEntryResponse {
|
||||
id: "ledger-1".to_string(),
|
||||
amount_delta: 12,
|
||||
balance_after: 80,
|
||||
source_type: PROFILE_WALLET_LEDGER_SOURCE_TYPE_SNAPSHOT_SYNC.to_string(),
|
||||
created_at: "2026-04-22T10:00:00Z".to_string(),
|
||||
}],
|
||||
})
|
||||
.expect("payload should serialize");
|
||||
|
||||
assert_eq!(payload["entries"][0]["amountDelta"], json!(12));
|
||||
assert_eq!(payload["entries"][0]["balanceAfter"], json!(80));
|
||||
assert_eq!(payload["entries"][0]["sourceType"], json!("snapshot_sync"));
|
||||
assert_eq!(
|
||||
payload["entries"][0]["createdAt"],
|
||||
json!("2026-04-22T10:00:00Z")
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn profile_recharge_center_response_uses_camel_case_fields() {
|
||||
let payload = serde_json::to_value(ProfileRechargeCenterResponse {
|
||||
wallet_balance: 29,
|
||||
membership: ProfileMembershipResponse {
|
||||
status: "active".to_string(),
|
||||
tier: "month".to_string(),
|
||||
started_at: Some("2026-04-25T10:00:00Z".to_string()),
|
||||
expires_at: Some("2026-05-25T10:00:00Z".to_string()),
|
||||
updated_at: Some("2026-04-25T10:00:00Z".to_string()),
|
||||
},
|
||||
point_products: vec![ProfileRechargeProductResponse {
|
||||
product_id: "points_60".to_string(),
|
||||
title: "60叙世币".to_string(),
|
||||
price_cents: 600,
|
||||
kind: "points".to_string(),
|
||||
points_amount: 60,
|
||||
bonus_points: 60,
|
||||
duration_days: 0,
|
||||
badge_label: "首充双倍".to_string(),
|
||||
description: "首充送60叙世币".to_string(),
|
||||
tier: "normal".to_string(),
|
||||
}],
|
||||
membership_products: vec![],
|
||||
benefits: vec![],
|
||||
latest_order: None,
|
||||
has_points_recharged: false,
|
||||
})
|
||||
.expect("payload should serialize");
|
||||
|
||||
assert_eq!(payload["walletBalance"], json!(29));
|
||||
assert_eq!(
|
||||
payload["membership"]["expiresAt"],
|
||||
json!("2026-05-25T10:00:00Z")
|
||||
);
|
||||
assert_eq!(payload["pointProducts"][0]["productId"], json!("points_60"));
|
||||
assert_eq!(payload["pointProducts"][0]["title"], json!("60叙世币"));
|
||||
assert_eq!(payload["pointProducts"][0]["priceCents"], json!(600));
|
||||
assert_eq!(
|
||||
payload["pointProducts"][0]["description"],
|
||||
json!("首充送60叙世币")
|
||||
);
|
||||
assert_eq!(payload["hasPointsRecharged"], json!(false));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn create_profile_recharge_order_request_accepts_optional_channel() {
|
||||
let payload: CreateProfileRechargeOrderRequest = serde_json::from_value(json!({
|
||||
"productId": "member_month"
|
||||
}))
|
||||
.expect("request should deserialize");
|
||||
|
||||
assert_eq!(payload.product_id, "member_month");
|
||||
assert_eq!(payload.payment_channel, None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn profile_play_stats_response_uses_camel_case_fields() {
|
||||
let payload = serde_json::to_value(ProfilePlayStatsResponse {
|
||||
total_play_time_ms: 18,
|
||||
played_works: vec![ProfilePlayedWorkSummaryResponse {
|
||||
world_key: "builtin:WUXIA".to_string(),
|
||||
owner_user_id: None,
|
||||
profile_id: None,
|
||||
world_type: Some("WUXIA".to_string()),
|
||||
world_title: "武侠世界".to_string(),
|
||||
world_subtitle: "".to_string(),
|
||||
first_played_at: "2026-04-20T10:00:00Z".to_string(),
|
||||
last_played_at: "2026-04-22T10:00:00Z".to_string(),
|
||||
last_observed_play_time_ms: 1200,
|
||||
}],
|
||||
updated_at: Some("2026-04-22T10:00:00Z".to_string()),
|
||||
})
|
||||
.expect("payload should serialize");
|
||||
|
||||
assert_eq!(payload["totalPlayTimeMs"], json!(18));
|
||||
assert_eq!(
|
||||
payload["playedWorks"][0]["worldKey"],
|
||||
json!("builtin:WUXIA")
|
||||
);
|
||||
assert_eq!(
|
||||
payload["playedWorks"][0]["lastObservedPlayTimeMs"],
|
||||
json!(1200)
|
||||
);
|
||||
assert_eq!(payload["updatedAt"], json!("2026-04-22T10:00:00Z"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn runtime_inventory_state_response_uses_camel_case_fields() {
|
||||
let payload = serde_json::to_value(RuntimeInventoryStateResponse {
|
||||
runtime_session_id: "runtime_001".to_string(),
|
||||
actor_user_id: "user_001".to_string(),
|
||||
backpack_items: vec![RuntimeInventorySlotResponse {
|
||||
slot_id: "invslot_001".to_string(),
|
||||
container_kind: "backpack".to_string(),
|
||||
slot_key: "invslot_001".to_string(),
|
||||
item_id: "consumable_heal_potion".to_string(),
|
||||
category: "消耗品".to_string(),
|
||||
name: "疗伤药".to_string(),
|
||||
description: Some("用于恢复少量气血。".to_string()),
|
||||
quantity: 2,
|
||||
rarity: "common".to_string(),
|
||||
tags: vec!["healing".to_string()],
|
||||
stackable: true,
|
||||
stack_key: "heal_potion".to_string(),
|
||||
equipment_slot_id: None,
|
||||
source_kind: "treasure_reward".to_string(),
|
||||
source_reference_id: Some("treasure_001".to_string()),
|
||||
created_at: "2026-04-22T10:00:00Z".to_string(),
|
||||
updated_at: "2026-04-22T10:01:00Z".to_string(),
|
||||
}],
|
||||
equipment_items: vec![],
|
||||
})
|
||||
.expect("payload should serialize");
|
||||
|
||||
assert_eq!(payload["runtimeSessionId"], json!("runtime_001"));
|
||||
assert_eq!(payload["actorUserId"], json!("user_001"));
|
||||
assert_eq!(payload["backpackItems"][0]["slotId"], json!("invslot_001"));
|
||||
assert_eq!(
|
||||
payload["backpackItems"][0]["sourceKind"],
|
||||
json!("treasure_reward")
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user