Files
Genarrative/server-rs/crates/spacetime-client/src/mapper.rs

8651 lines
299 KiB
Rust

use super::*;
impl From<module_assets::AssetEntityBindingInput> for AssetEntityBindingInput {
fn from(input: module_assets::AssetEntityBindingInput) -> Self {
Self {
binding_id: input.binding_id,
asset_object_id: input.asset_object_id,
entity_kind: input.entity_kind,
entity_id: input.entity_id,
slot: input.slot,
asset_kind: input.asset_kind,
owner_user_id: input.owner_user_id,
profile_id: input.profile_id,
updated_at_micros: input.updated_at_micros,
}
}
}
impl From<module_assets::AssetObjectUpsertInput> for AssetObjectUpsertInput {
fn from(input: module_assets::AssetObjectUpsertInput) -> Self {
Self {
asset_object_id: input.asset_object_id,
bucket: input.bucket,
object_key: input.object_key,
access_policy: map_access_policy(input.access_policy),
content_type: input.content_type,
content_length: input.content_length,
content_hash: input.content_hash,
version: input.version,
source_job_id: input.source_job_id,
owner_user_id: input.owner_user_id,
profile_id: input.profile_id,
entity_id: input.entity_id,
asset_kind: input.asset_kind,
updated_at_micros: input.updated_at_micros,
}
}
}
impl From<module_assets::AssetHistoryListInput> for AssetHistoryListInput {
fn from(input: module_assets::AssetHistoryListInput) -> Self {
Self {
asset_kind: input.asset_kind,
limit: input.limit,
}
}
}
impl From<module_runtime::CreationEntryTypeAdminUpsertInput> for CreationEntryTypeAdminUpsertInput {
fn from(input: module_runtime::CreationEntryTypeAdminUpsertInput) -> Self {
Self {
id: input.id,
title: input.title,
subtitle: input.subtitle,
badge: input.badge,
image_src: input.image_src,
visible: input.visible,
open: input.open,
sort_order: input.sort_order,
}
}
}
impl From<module_runtime::RuntimeSettingGetInput> for RuntimeSettingGetInput {
fn from(input: module_runtime::RuntimeSettingGetInput) -> Self {
Self {
user_id: input.user_id,
}
}
}
impl From<module_runtime::RuntimeSettingUpsertInput> for RuntimeSettingUpsertInput {
fn from(input: module_runtime::RuntimeSettingUpsertInput) -> Self {
Self {
user_id: input.user_id,
music_volume: input.music_volume,
platform_theme: map_runtime_platform_theme(input.platform_theme),
updated_at_micros: input.updated_at_micros,
}
}
}
impl From<module_runtime::RuntimeBrowseHistoryListInput> for RuntimeBrowseHistoryListInput {
fn from(input: module_runtime::RuntimeBrowseHistoryListInput) -> Self {
Self {
user_id: input.user_id,
}
}
}
impl From<module_runtime::RuntimeBrowseHistoryClearInput> for RuntimeBrowseHistoryClearInput {
fn from(input: module_runtime::RuntimeBrowseHistoryClearInput) -> Self {
Self {
user_id: input.user_id,
}
}
}
impl From<module_runtime::RuntimeBrowseHistorySyncInput> for RuntimeBrowseHistorySyncInput {
fn from(input: module_runtime::RuntimeBrowseHistorySyncInput) -> Self {
Self {
user_id: input.user_id,
entries: input.entries.into_iter().map(Into::into).collect(),
updated_at_micros: input.updated_at_micros,
}
}
}
impl From<module_runtime::RuntimeBrowseHistoryWriteInput> for RuntimeBrowseHistoryWriteInput {
fn from(input: module_runtime::RuntimeBrowseHistoryWriteInput) -> Self {
Self {
owner_user_id: input.owner_user_id,
profile_id: input.profile_id,
world_name: input.world_name,
subtitle: input.subtitle,
summary_text: input.summary_text,
cover_image_src: input.cover_image_src,
theme_mode: input.theme_mode,
author_display_name: input.author_display_name,
visited_at: input.visited_at,
}
}
}
impl From<module_runtime::RuntimeProfileDashboardGetInput> for RuntimeProfileDashboardGetInput {
fn from(input: module_runtime::RuntimeProfileDashboardGetInput) -> Self {
Self {
user_id: input.user_id,
}
}
}
impl From<module_runtime::RuntimeProfileWalletLedgerListInput>
for RuntimeProfileWalletLedgerListInput
{
fn from(input: module_runtime::RuntimeProfileWalletLedgerListInput) -> Self {
Self {
user_id: input.user_id,
}
}
}
impl From<module_runtime::RuntimeProfileWalletAdjustmentInput>
for RuntimeProfileWalletAdjustmentInput
{
fn from(input: module_runtime::RuntimeProfileWalletAdjustmentInput) -> Self {
Self {
user_id: input.user_id,
amount: input.amount,
ledger_id: input.ledger_id,
created_at_micros: input.created_at_micros,
}
}
}
impl From<module_runtime::RuntimeProfileRechargeCenterGetInput>
for RuntimeProfileRechargeCenterGetInput
{
fn from(input: module_runtime::RuntimeProfileRechargeCenterGetInput) -> Self {
Self {
user_id: input.user_id,
}
}
}
impl From<module_runtime::RuntimeProfileRechargeOrderGetInput>
for RuntimeProfileRechargeOrderGetInput
{
fn from(input: module_runtime::RuntimeProfileRechargeOrderGetInput) -> Self {
Self {
order_id: input.order_id,
}
}
}
impl From<module_runtime::RuntimeProfileRechargeOrderCreateInput>
for RuntimeProfileRechargeOrderCreateInput
{
fn from(input: module_runtime::RuntimeProfileRechargeOrderCreateInput) -> Self {
Self {
user_id: input.user_id,
product_id: input.product_id,
payment_channel: input.payment_channel,
created_at_micros: input.created_at_micros,
}
}
}
impl From<module_runtime::RuntimeProfileRechargeOrderPaidInput>
for RuntimeProfileRechargeOrderPaidInput
{
fn from(input: module_runtime::RuntimeProfileRechargeOrderPaidInput) -> Self {
Self {
order_id: input.order_id,
paid_at_micros: input.paid_at_micros,
provider_transaction_id: input.provider_transaction_id,
}
}
}
impl From<module_runtime::RuntimeProfileFeedbackSubmissionInput>
for RuntimeProfileFeedbackSubmissionInput
{
fn from(input: module_runtime::RuntimeProfileFeedbackSubmissionInput) -> Self {
Self {
user_id: input.user_id,
description: input.description,
contact_phone: input.contact_phone,
evidence_items: input.evidence_items.into_iter().map(Into::into).collect(),
created_at_micros: input.created_at_micros,
}
}
}
impl From<module_runtime::RuntimeProfileFeedbackEvidenceSnapshot>
for RuntimeProfileFeedbackEvidenceSnapshot
{
fn from(input: module_runtime::RuntimeProfileFeedbackEvidenceSnapshot) -> Self {
Self {
evidence_id: input.evidence_id,
file_name: input.file_name,
content_type: input.content_type,
size_bytes: input.size_bytes,
data_url: input.data_url,
}
}
}
impl From<module_runtime::RuntimeProfileRewardCodeRedeemInput>
for RuntimeProfileRewardCodeRedeemInput
{
fn from(input: module_runtime::RuntimeProfileRewardCodeRedeemInput) -> Self {
Self {
user_id: input.user_id,
code: input.code,
redeemed_at_micros: input.redeemed_at_micros,
}
}
}
impl From<module_runtime::RuntimeProfileTaskCenterGetInput> for RuntimeProfileTaskCenterGetInput {
fn from(input: module_runtime::RuntimeProfileTaskCenterGetInput) -> Self {
Self {
user_id: input.user_id,
}
}
}
impl From<module_runtime::AnalyticsMetricQueryInput> for AnalyticsMetricQueryInput {
fn from(input: module_runtime::AnalyticsMetricQueryInput) -> Self {
Self {
event_key: input.event_key,
scope_kind: map_runtime_tracking_scope_kind(input.scope_kind),
scope_id: input.scope_id,
granularity: map_analytics_granularity(input.granularity),
}
}
}
impl From<module_runtime::RuntimeProfileTaskClaimInput> for RuntimeProfileTaskClaimInput {
fn from(input: module_runtime::RuntimeProfileTaskClaimInput) -> Self {
Self {
user_id: input.user_id,
task_id: input.task_id,
}
}
}
impl From<module_runtime::RuntimeProfileTaskConfigAdminListInput>
for RuntimeProfileTaskConfigAdminListInput
{
fn from(input: module_runtime::RuntimeProfileTaskConfigAdminListInput) -> Self {
Self {
admin_user_id: input.admin_user_id,
}
}
}
impl From<module_runtime::RuntimeProfileTaskConfigAdminUpsertInput>
for RuntimeProfileTaskConfigAdminUpsertInput
{
fn from(input: module_runtime::RuntimeProfileTaskConfigAdminUpsertInput) -> Self {
Self {
admin_user_id: input.admin_user_id,
task_id: input.task_id,
title: input.title,
description: input.description,
event_key: input.event_key,
cycle: map_runtime_profile_task_cycle(input.cycle),
scope_kind: map_runtime_tracking_scope_kind(input.scope_kind),
threshold: input.threshold,
reward_points: input.reward_points,
enabled: input.enabled,
sort_order: input.sort_order,
updated_at_micros: input.updated_at_micros,
}
}
}
impl From<module_runtime::RuntimeProfileTaskConfigAdminDisableInput>
for RuntimeProfileTaskConfigAdminDisableInput
{
fn from(input: module_runtime::RuntimeProfileTaskConfigAdminDisableInput) -> Self {
Self {
admin_user_id: input.admin_user_id,
task_id: input.task_id,
updated_at_micros: input.updated_at_micros,
}
}
}
impl From<module_runtime::RuntimeProfileRechargeProductAdminListInput>
for RuntimeProfileRechargeProductAdminListInput
{
fn from(input: module_runtime::RuntimeProfileRechargeProductAdminListInput) -> Self {
Self {
admin_user_id: input.admin_user_id,
}
}
}
impl From<module_runtime::RuntimeProfileRechargeProductAdminUpsertInput>
for RuntimeProfileRechargeProductAdminUpsertInput
{
fn from(input: module_runtime::RuntimeProfileRechargeProductAdminUpsertInput) -> Self {
Self {
admin_user_id: input.admin_user_id,
product_id: input.product_id,
title: input.title,
price_cents: input.price_cents,
kind: map_runtime_profile_recharge_product_kind(input.kind),
points_amount: input.points_amount,
bonus_points: input.bonus_points,
duration_days: input.duration_days,
badge_label: input.badge_label,
description: input.description,
tier: map_runtime_profile_membership_tier(input.tier),
enabled: input.enabled,
sort_order: input.sort_order,
updated_at_micros: input.updated_at_micros,
}
}
}
impl From<module_runtime::RuntimeProfileRedeemCodeAdminUpsertInput>
for RuntimeProfileRedeemCodeAdminUpsertInput
{
fn from(input: module_runtime::RuntimeProfileRedeemCodeAdminUpsertInput) -> Self {
Self {
admin_user_id: input.admin_user_id,
code: input.code,
mode: map_runtime_profile_redeem_code_mode(input.mode),
reward_points: input.reward_points,
max_uses: input.max_uses,
enabled: input.enabled,
allowed_user_ids: input.allowed_user_ids,
allowed_public_user_codes: input.allowed_public_user_codes,
updated_at_micros: input.updated_at_micros,
}
}
}
impl From<module_runtime::RuntimeProfileRedeemCodeAdminDisableInput>
for RuntimeProfileRedeemCodeAdminDisableInput
{
fn from(input: module_runtime::RuntimeProfileRedeemCodeAdminDisableInput) -> Self {
Self {
admin_user_id: input.admin_user_id,
code: input.code,
updated_at_micros: input.updated_at_micros,
}
}
}
impl From<module_runtime::RuntimeProfileRedeemCodeAdminListInput>
for RuntimeProfileRedeemCodeAdminListInput
{
fn from(input: module_runtime::RuntimeProfileRedeemCodeAdminListInput) -> Self {
Self {
admin_user_id: input.admin_user_id,
}
}
}
impl From<module_runtime::RuntimeProfileInviteCodeAdminUpsertInput>
for RuntimeProfileInviteCodeAdminUpsertInput
{
fn from(input: module_runtime::RuntimeProfileInviteCodeAdminUpsertInput) -> Self {
Self {
admin_user_id: input.admin_user_id,
invite_code: input.invite_code,
metadata_json: input.metadata_json,
starts_at_micros: input.starts_at_micros,
expires_at_micros: input.expires_at_micros,
updated_at_micros: input.updated_at_micros,
}
}
}
impl From<module_runtime::RuntimeProfileInviteCodeAdminListInput>
for RuntimeProfileInviteCodeAdminListInput
{
fn from(input: module_runtime::RuntimeProfileInviteCodeAdminListInput) -> Self {
Self {
admin_user_id: input.admin_user_id,
}
}
}
impl From<module_runtime::RuntimeReferralInviteCenterGetInput>
for RuntimeReferralInviteCenterGetInput
{
fn from(input: module_runtime::RuntimeReferralInviteCenterGetInput) -> Self {
Self {
user_id: input.user_id,
}
}
}
impl From<module_runtime::RuntimeReferralRedeemInput> for RuntimeReferralRedeemInput {
fn from(input: module_runtime::RuntimeReferralRedeemInput) -> Self {
Self {
user_id: input.user_id,
invite_code: input.invite_code,
updated_at_micros: input.updated_at_micros,
}
}
}
impl From<module_runtime::RuntimeProfilePlayStatsGetInput> for RuntimeProfilePlayStatsGetInput {
fn from(input: module_runtime::RuntimeProfilePlayStatsGetInput) -> Self {
Self {
user_id: input.user_id,
}
}
}
impl From<module_runtime::RuntimeSnapshotGetInput> for RuntimeSnapshotGetInput {
fn from(input: module_runtime::RuntimeSnapshotGetInput) -> Self {
Self {
user_id: input.user_id,
}
}
}
impl From<module_runtime::RuntimeSnapshotUpsertInput> for RuntimeSnapshotUpsertInput {
fn from(input: module_runtime::RuntimeSnapshotUpsertInput) -> Self {
Self {
user_id: input.user_id,
saved_at_micros: input.saved_at_micros,
bottom_tab: input.bottom_tab,
game_state_json: input.game_state_json,
current_story_json: input.current_story_json,
updated_at_micros: input.updated_at_micros,
}
}
}
impl From<module_runtime::RuntimeSnapshotDeleteInput> for RuntimeSnapshotDeleteInput {
fn from(input: module_runtime::RuntimeSnapshotDeleteInput) -> Self {
Self {
user_id: input.user_id,
}
}
}
impl From<module_runtime::RuntimeProfileSaveArchiveListInput>
for RuntimeProfileSaveArchiveListInput
{
fn from(input: module_runtime::RuntimeProfileSaveArchiveListInput) -> Self {
Self {
user_id: input.user_id,
}
}
}
impl From<module_runtime::RuntimeProfileSaveArchiveResumeInput>
for RuntimeProfileSaveArchiveResumeInput
{
fn from(input: module_runtime::RuntimeProfileSaveArchiveResumeInput) -> Self {
Self {
user_id: input.user_id,
world_key: input.world_key,
}
}
}
impl From<DomainAiTaskCreateInput> for AiTaskCreateInput {
fn from(input: DomainAiTaskCreateInput) -> Self {
Self {
task_id: input.task_id,
task_kind: map_ai_task_kind(input.task_kind),
owner_user_id: input.owner_user_id,
request_label: input.request_label,
source_module: input.source_module,
source_entity_id: input.source_entity_id,
request_payload_json: input.request_payload_json,
stages: input.stages.into_iter().map(Into::into).collect(),
created_at_micros: input.created_at_micros,
}
}
}
impl From<DomainAiTaskStartInput> for AiTaskStartInput {
fn from(input: DomainAiTaskStartInput) -> Self {
Self {
task_id: input.task_id,
started_at_micros: input.started_at_micros,
}
}
}
impl From<DomainAiTaskStageStartInput> for AiTaskStageStartInput {
fn from(input: DomainAiTaskStageStartInput) -> Self {
Self {
task_id: input.task_id,
stage_kind: map_ai_task_stage_kind(input.stage_kind),
started_at_micros: input.started_at_micros,
}
}
}
impl From<DomainAiTextChunkAppendInput> for AiTextChunkAppendInput {
fn from(input: DomainAiTextChunkAppendInput) -> Self {
Self {
task_id: input.task_id,
stage_kind: map_ai_task_stage_kind(input.stage_kind),
sequence: input.sequence,
delta_text: input.delta_text,
created_at_micros: input.created_at_micros,
}
}
}
impl From<DomainAiStageCompletionInput> for AiStageCompletionInput {
fn from(input: DomainAiStageCompletionInput) -> Self {
Self {
task_id: input.task_id,
stage_kind: map_ai_task_stage_kind(input.stage_kind),
text_output: input.text_output,
structured_payload_json: input.structured_payload_json,
warning_messages: input.warning_messages,
completed_at_micros: input.completed_at_micros,
}
}
}
impl From<DomainAiResultReferenceInput> for AiResultReferenceInput {
fn from(input: DomainAiResultReferenceInput) -> Self {
Self {
task_id: input.task_id,
reference_kind: map_ai_result_reference_kind(input.reference_kind),
reference_id: input.reference_id,
label: input.label,
created_at_micros: input.created_at_micros,
}
}
}
impl From<DomainAiTaskFinishInput> for AiTaskFinishInput {
fn from(input: DomainAiTaskFinishInput) -> Self {
Self {
task_id: input.task_id,
completed_at_micros: input.completed_at_micros,
}
}
}
impl From<DomainAiTaskFailureInput> for AiTaskFailureInput {
fn from(input: DomainAiTaskFailureInput) -> Self {
Self {
task_id: input.task_id,
failure_message: input.failure_message,
completed_at_micros: input.completed_at_micros,
}
}
}
impl From<DomainAiTaskCancelInput> for AiTaskCancelInput {
fn from(input: DomainAiTaskCancelInput) -> Self {
Self {
task_id: input.task_id,
completed_at_micros: input.completed_at_micros,
}
}
}
impl From<DomainAiTaskStageBlueprint> for AiTaskStageBlueprint {
fn from(blueprint: DomainAiTaskStageBlueprint) -> Self {
Self {
stage_kind: map_ai_task_stage_kind(blueprint.stage_kind),
label: blueprint.label,
detail: blueprint.detail,
order: blueprint.order,
}
}
}
impl From<CustomWorldProfileUpsertRecordInput> for CustomWorldProfileUpsertInput {
fn from(input: CustomWorldProfileUpsertRecordInput) -> Self {
Self {
profile_id: input.profile_id,
owner_user_id: input.owner_user_id,
public_work_code: input.public_work_code,
author_public_user_code: input.author_public_user_code,
source_agent_session_id: input.source_agent_session_id,
world_name: input.world_name,
subtitle: input.subtitle,
summary_text: input.summary_text,
theme_mode: map_custom_world_theme_mode(input.theme_mode),
cover_image_src: input.cover_image_src,
profile_payload_json: input.profile_payload_json,
playable_npc_count: input.playable_npc_count,
landmark_count: input.landmark_count,
author_display_name: input.author_display_name,
updated_at_micros: input.updated_at_micros,
}
}
}
impl From<CustomWorldPublishWorldRecordInput> for CustomWorldPublishWorldInput {
fn from(input: CustomWorldPublishWorldRecordInput) -> Self {
Self {
session_id: input.session_id,
profile_id: input.profile_id,
owner_user_id: input.owner_user_id,
public_work_code: input.public_work_code,
author_public_user_code: input.author_public_user_code,
draft_profile_json: input.draft_profile_json,
legacy_result_profile_json: input.legacy_result_profile_json,
setting_text: input.setting_text,
author_display_name: input.author_display_name,
published_at_micros: input.published_at_micros,
}
}
}
impl From<DomainStorySessionInput> for StorySessionInput {
fn from(input: DomainStorySessionInput) -> Self {
Self {
story_session_id: input.story_session_id,
runtime_session_id: input.runtime_session_id,
actor_user_id: input.actor_user_id,
world_profile_id: input.world_profile_id,
initial_prompt: input.initial_prompt,
opening_summary: input.opening_summary,
created_at_micros: input.created_at_micros,
}
}
}
impl From<DomainStoryContinueInput> for StoryContinueInput {
fn from(input: DomainStoryContinueInput) -> Self {
Self {
story_session_id: input.story_session_id,
event_id: input.event_id,
narrative_text: input.narrative_text,
choice_function_id: input.choice_function_id,
updated_at_micros: input.updated_at_micros,
}
}
}
impl From<DomainStorySessionStateInput> for StorySessionStateInput {
fn from(input: DomainStorySessionStateInput) -> Self {
Self {
story_session_id: input.story_session_id,
}
}
}
impl From<DomainRuntimeInventoryStateQueryInput> for RuntimeInventoryStateQueryInput {
fn from(input: DomainRuntimeInventoryStateQueryInput) -> Self {
Self {
runtime_session_id: input.runtime_session_id,
actor_user_id: input.actor_user_id,
}
}
}
impl From<DomainBattleStateQueryInput> for BattleStateQueryInput {
fn from(input: DomainBattleStateQueryInput) -> Self {
Self {
battle_state_id: input.battle_state_id,
}
}
}
impl From<DomainBattleStateInput> for BattleStateInput {
fn from(input: DomainBattleStateInput) -> Self {
Self {
battle_state_id: input.battle_state_id,
story_session_id: input.story_session_id,
runtime_session_id: input.runtime_session_id,
actor_user_id: input.actor_user_id,
chapter_id: input.chapter_id,
target_npc_id: input.target_npc_id,
target_name: input.target_name,
battle_mode: map_battle_mode(input.battle_mode),
player_hp: input.player_hp,
player_max_hp: input.player_max_hp,
player_mana: input.player_mana,
player_max_mana: input.player_max_mana,
target_hp: input.target_hp,
target_max_hp: input.target_max_hp,
experience_reward: input.experience_reward,
reward_items: input
.reward_items
.into_iter()
.map(map_runtime_item_reward_item_snapshot)
.collect(),
created_at_micros: input.created_at_micros,
}
}
}
impl From<DomainResolveCombatActionInput> for ResolveCombatActionInput {
fn from(input: DomainResolveCombatActionInput) -> Self {
Self {
battle_state_id: input.battle_state_id,
function_id: input.function_id,
action_text: input.action_text,
base_damage: input.base_damage,
mana_cost: input.mana_cost,
heal: input.heal,
mana_restore: input.mana_restore,
counter_multiplier_basis_points: input.counter_multiplier_basis_points,
updated_at_micros: input.updated_at_micros,
}
}
}
pub(crate) fn map_procedure_result(
result: AssetObjectProcedureResult,
) -> Result<AssetObjectRecord, SpacetimeClientError> {
if !result.ok {
return Err(SpacetimeClientError::procedure_failed(result.error_message));
}
let snapshot = result
.record
.ok_or_else(|| SpacetimeClientError::missing_snapshot("对象快照"))?;
Ok(build_asset_object_record(map_snapshot(snapshot)))
}
pub(crate) fn map_entity_binding_procedure_result(
result: AssetEntityBindingProcedureResult,
) -> Result<AssetEntityBindingRecord, SpacetimeClientError> {
if !result.ok {
return Err(SpacetimeClientError::procedure_failed(result.error_message));
}
let snapshot = result
.record
.ok_or_else(|| SpacetimeClientError::missing_snapshot("绑定快照"))?;
Ok(build_asset_entity_binding_record(
map_entity_binding_snapshot(snapshot),
))
}
pub(crate) fn map_asset_history_list_result(
result: AssetHistoryListResult,
) -> Result<Vec<AssetHistoryEntryRecord>, SpacetimeClientError> {
if !result.ok {
return Err(SpacetimeClientError::procedure_failed(result.error_message));
}
Ok(result
.entries
.into_iter()
.map(map_asset_history_entry_snapshot)
.map(build_asset_history_entry_record)
.collect())
}
pub type BarkBattleDraftConfigRecord = serde_json::Value;
pub type BarkBattleRuntimeConfigRecord = serde_json::Value;
pub type BarkBattleRunRecord = serde_json::Value;
pub(crate) fn map_bark_battle_draft_config_procedure_result(
result: BarkBattleProcedureResult,
) -> Result<BarkBattleDraftConfigRecord, SpacetimeClientError> {
parse_bark_battle_row_json(result, "Bark Battle draft config")
}
pub(crate) fn map_bark_battle_runtime_config_procedure_result(
result: BarkBattleProcedureResult,
) -> Result<BarkBattleRuntimeConfigRecord, SpacetimeClientError> {
parse_bark_battle_row_json(result, "Bark Battle runtime config")
}
pub(crate) fn map_bark_battle_run_procedure_result(
result: BarkBattleProcedureResult,
) -> Result<BarkBattleRunRecord, SpacetimeClientError> {
parse_bark_battle_row_json(result, "Bark Battle run")
}
fn parse_bark_battle_row_json<T: serde::de::DeserializeOwned>(
result: BarkBattleProcedureResult,
label: &'static str,
) -> Result<T, SpacetimeClientError> {
if !result.ok {
return Err(SpacetimeClientError::procedure_failed(result.error_message));
}
let row_json = result
.row_json
.ok_or_else(|| SpacetimeClientError::missing_snapshot(label))?;
serde_json::from_str(&row_json)
.map_err(|error| SpacetimeClientError::Runtime(format!("{label} JSON 解析失败: {error}")))
}
pub type CreationEntryConfigRecord =
shared_contracts::creation_entry_config::CreationEntryConfigResponse;
pub(crate) fn map_creation_entry_config_procedure_result(
result: CreationEntryConfigProcedureResult,
) -> Result<CreationEntryConfigRecord, SpacetimeClientError> {
if !result.ok {
return Err(SpacetimeClientError::procedure_failed(result.error_message));
}
let snapshot = result
.record
.ok_or_else(|| SpacetimeClientError::missing_snapshot("创作入口配置快照"))?;
Ok(module_runtime::build_creation_entry_config_response(
map_creation_entry_config_snapshot(snapshot),
))
}
fn map_creation_entry_config_snapshot(
snapshot: CreationEntryConfigSnapshot,
) -> module_runtime::CreationEntryConfigSnapshot {
module_runtime::CreationEntryConfigSnapshot {
config_id: snapshot.config_id,
start_card: module_runtime::CreationEntryStartCardSnapshot {
title: snapshot.start_card.title,
description: snapshot.start_card.description,
idle_badge: snapshot.start_card.idle_badge,
busy_badge: snapshot.start_card.busy_badge,
},
type_modal: module_runtime::CreationEntryTypeModalSnapshot {
title: snapshot.type_modal.title,
description: snapshot.type_modal.description,
},
creation_types: snapshot
.creation_types
.into_iter()
.map(|item| module_runtime::CreationEntryTypeSnapshot {
id: item.id,
title: item.title,
subtitle: item.subtitle,
badge: item.badge,
image_src: item.image_src,
visible: item.visible,
open: item.open,
sort_order: item.sort_order,
updated_at_micros: item.updated_at_micros,
})
.collect(),
updated_at_micros: snapshot.updated_at_micros,
}
}
pub(crate) fn map_runtime_setting_procedure_result(
result: RuntimeSettingProcedureResult,
) -> Result<RuntimeSettingsRecord, SpacetimeClientError> {
if !result.ok {
return Err(SpacetimeClientError::procedure_failed(result.error_message));
}
let snapshot = result
.record
.ok_or_else(|| SpacetimeClientError::missing_snapshot("runtime settings 快照"))?;
Ok(build_runtime_setting_record(map_runtime_setting_snapshot(
snapshot,
)))
}
pub(crate) fn map_auth_store_snapshot_procedure_result(
result: AuthStoreSnapshotProcedureResult,
) -> Result<AuthStoreSnapshotRecord, SpacetimeClientError> {
if !result.ok {
return Err(SpacetimeClientError::procedure_failed(result.error_message));
}
let record = result
.record
.ok_or_else(|| SpacetimeClientError::missing_snapshot("认证快照"))?;
Ok(map_auth_store_snapshot_record(record))
}
pub(crate) fn map_auth_store_snapshot_record(
record: crate::module_bindings::AuthStoreSnapshotRecord,
) -> crate::AuthStoreSnapshotRecord {
crate::AuthStoreSnapshotRecord {
snapshot_json: record.snapshot_json,
updated_at_micros: record.updated_at_micros,
}
}
pub(crate) fn map_auth_store_snapshot_import_procedure_result(
result: AuthStoreSnapshotImportProcedureResult,
) -> Result<AuthStoreSnapshotImportRecord, SpacetimeClientError> {
if !result.ok {
return Err(SpacetimeClientError::procedure_failed(result.error_message));
}
let record = result
.record
.ok_or_else(|| SpacetimeClientError::missing_snapshot("认证快照导入结果"))?;
Ok(AuthStoreSnapshotImportRecord {
imported_user_count: record.imported_user_count,
imported_identity_count: record.imported_identity_count,
imported_refresh_session_count: record.imported_refresh_session_count,
})
}
pub(crate) fn map_runtime_browse_history_procedure_result(
result: RuntimeBrowseHistoryProcedureResult,
) -> Result<Vec<RuntimeBrowseHistoryRecord>, SpacetimeClientError> {
if !result.ok {
return Err(SpacetimeClientError::procedure_failed(result.error_message));
}
Ok(result
.entries
.into_iter()
.map(|snapshot| {
build_runtime_browse_history_record(map_runtime_browse_history_snapshot(snapshot))
})
.collect())
}
pub(crate) fn map_runtime_profile_dashboard_procedure_result(
result: RuntimeProfileDashboardProcedureResult,
) -> Result<RuntimeProfileDashboardRecord, SpacetimeClientError> {
if !result.ok {
return Err(SpacetimeClientError::procedure_failed(result.error_message));
}
let snapshot = result
.record
.ok_or_else(|| SpacetimeClientError::missing_snapshot("profile dashboard 快照"))?;
Ok(build_runtime_profile_dashboard_record(
map_runtime_profile_dashboard_snapshot(snapshot),
))
}
pub(crate) fn map_runtime_profile_wallet_ledger_procedure_result(
result: RuntimeProfileWalletLedgerProcedureResult,
) -> Result<Vec<RuntimeProfileWalletLedgerEntryRecord>, SpacetimeClientError> {
if !result.ok {
return Err(SpacetimeClientError::procedure_failed(result.error_message));
}
Ok(result
.entries
.into_iter()
.map(|snapshot| {
build_runtime_profile_wallet_ledger_entry_record(
map_runtime_profile_wallet_ledger_entry_snapshot(snapshot),
)
})
.collect())
}
pub(crate) fn map_runtime_profile_wallet_adjustment_procedure_result(
result: RuntimeProfileWalletAdjustmentProcedureResult,
) -> Result<RuntimeProfileDashboardRecord, SpacetimeClientError> {
if !result.ok {
return Err(SpacetimeClientError::procedure_failed(result.error_message));
}
let snapshot = result
.record
.ok_or_else(|| SpacetimeClientError::missing_snapshot("profile dashboard 快照"))?;
Ok(build_runtime_profile_dashboard_record(
map_runtime_profile_dashboard_snapshot(snapshot),
))
}
pub(crate) fn map_runtime_profile_recharge_center_procedure_result(
result: RuntimeProfileRechargeCenterProcedureResult,
) -> Result<RuntimeProfileRechargeCenterRecord, SpacetimeClientError> {
if !result.ok {
return Err(SpacetimeClientError::procedure_failed(result.error_message));
}
let snapshot = result
.record
.ok_or_else(|| SpacetimeClientError::missing_snapshot("profile recharge center 快照"))?;
Ok(build_runtime_profile_recharge_center_record(
map_runtime_profile_recharge_center_snapshot(snapshot),
))
}
pub(crate) fn map_runtime_profile_recharge_order_procedure_result(
result: RuntimeProfileRechargeCenterProcedureResult,
) -> Result<
(
RuntimeProfileRechargeCenterRecord,
RuntimeProfileRechargeOrderRecord,
),
SpacetimeClientError,
> {
if !result.ok {
return Err(SpacetimeClientError::procedure_failed(result.error_message));
}
let center = result
.record
.ok_or_else(|| SpacetimeClientError::missing_snapshot("profile recharge center 快照"))?;
let order = result
.order
.ok_or_else(|| SpacetimeClientError::missing_snapshot("profile recharge order 快照"))?;
Ok((
build_runtime_profile_recharge_center_record(map_runtime_profile_recharge_center_snapshot(
center,
)),
module_runtime::build_runtime_profile_recharge_order_record(
map_runtime_profile_recharge_order_snapshot(order),
),
))
}
pub(crate) fn map_runtime_profile_feedback_submission_procedure_result(
result: RuntimeProfileFeedbackSubmissionProcedureResult,
) -> Result<RuntimeProfileFeedbackSubmissionRecord, SpacetimeClientError> {
if !result.ok {
return Err(SpacetimeClientError::procedure_failed(result.error_message));
}
let snapshot = result
.record
.ok_or_else(|| SpacetimeClientError::missing_snapshot("profile feedback 快照"))?;
build_runtime_profile_feedback_submission_record(
map_runtime_profile_feedback_submission_snapshot(snapshot),
)
.map_err(SpacetimeClientError::validation_failed)
}
pub(crate) fn map_runtime_referral_invite_center_procedure_result(
result: RuntimeReferralInviteCenterProcedureResult,
) -> Result<RuntimeReferralInviteCenterRecord, SpacetimeClientError> {
if !result.ok {
return Err(SpacetimeClientError::procedure_failed(result.error_message));
}
let snapshot = result
.record
.ok_or_else(|| SpacetimeClientError::missing_snapshot("referral invite center 快照"))?;
Ok(build_runtime_referral_invite_center_record(
map_runtime_referral_invite_center_snapshot(snapshot),
))
}
pub(crate) fn map_runtime_referral_redeem_procedure_result(
result: RuntimeReferralRedeemProcedureResult,
) -> Result<RuntimeReferralRedeemRecord, SpacetimeClientError> {
if !result.ok {
return Err(SpacetimeClientError::procedure_failed(result.error_message));
}
let snapshot = result
.record
.ok_or_else(|| SpacetimeClientError::missing_snapshot("referral redeem 快照"))?;
Ok(build_runtime_referral_redeem_record(
map_runtime_referral_redeem_snapshot(snapshot),
))
}
pub(crate) fn map_runtime_profile_reward_code_redeem_procedure_result(
result: RuntimeProfileRewardCodeRedeemProcedureResult,
) -> Result<RuntimeProfileRewardCodeRedeemRecord, SpacetimeClientError> {
if !result.ok {
return Err(SpacetimeClientError::procedure_failed(result.error_message));
}
let snapshot = result
.record
.ok_or_else(|| SpacetimeClientError::missing_snapshot("reward redeem 快照"))?;
Ok(build_runtime_profile_reward_code_redeem_record(
map_runtime_profile_reward_code_redeem_snapshot(snapshot),
))
}
pub(crate) fn map_runtime_tracking_event_procedure_result(
result: RuntimeTrackingEventProcedureResult,
) -> Result<(), SpacetimeClientError> {
if !result.ok {
return Err(SpacetimeClientError::procedure_failed(result.error_message));
}
Ok(())
}
pub(crate) fn map_runtime_profile_task_center_procedure_result(
result: RuntimeProfileTaskCenterProcedureResult,
) -> Result<RuntimeProfileTaskCenterRecord, SpacetimeClientError> {
if !result.ok {
return Err(SpacetimeClientError::procedure_failed(result.error_message));
}
let snapshot = result
.record
.ok_or_else(|| SpacetimeClientError::missing_snapshot("profile task center 快照"))?;
Ok(build_runtime_profile_task_center_record(
map_runtime_profile_task_center_snapshot(snapshot),
))
}
pub(crate) fn map_analytics_metric_query_procedure_result(
result: AnalyticsMetricQueryProcedureResult,
) -> Result<DomainAnalyticsMetricQueryResponse, SpacetimeClientError> {
if !result.ok {
return Err(SpacetimeClientError::procedure_failed(result.error_message));
}
Ok(DomainAnalyticsMetricQueryResponse {
buckets: result
.buckets
.into_iter()
.map(map_analytics_bucket_metric)
.collect(),
})
}
pub(crate) fn map_runtime_profile_task_claim_procedure_result(
result: RuntimeProfileTaskClaimProcedureResult,
) -> Result<RuntimeProfileTaskClaimRecord, SpacetimeClientError> {
if !result.ok {
return Err(SpacetimeClientError::procedure_failed(result.error_message));
}
let snapshot = result
.record
.ok_or_else(|| SpacetimeClientError::missing_snapshot("profile task claim 快照"))?;
Ok(build_runtime_profile_task_claim_record(
map_runtime_profile_task_claim_snapshot(snapshot),
))
}
pub(crate) fn map_runtime_profile_task_config_admin_list_procedure_result(
result: RuntimeProfileTaskConfigAdminListProcedureResult,
) -> Result<Vec<RuntimeProfileTaskConfigRecord>, SpacetimeClientError> {
if !result.ok {
return Err(SpacetimeClientError::procedure_failed(result.error_message));
}
Ok(result
.entries
.into_iter()
.map(|snapshot| {
build_runtime_profile_task_config_record(map_runtime_profile_task_config_snapshot(
snapshot,
))
})
.collect())
}
pub(crate) fn map_runtime_profile_task_config_admin_procedure_result(
result: RuntimeProfileTaskConfigAdminProcedureResult,
) -> Result<RuntimeProfileTaskConfigRecord, SpacetimeClientError> {
if !result.ok {
return Err(SpacetimeClientError::procedure_failed(result.error_message));
}
let snapshot = result
.record
.ok_or_else(|| SpacetimeClientError::missing_snapshot("profile task config 快照"))?;
Ok(build_runtime_profile_task_config_record(
map_runtime_profile_task_config_snapshot(snapshot),
))
}
pub(crate) fn map_runtime_profile_recharge_product_admin_list_procedure_result(
result: RuntimeProfileRechargeProductAdminListProcedureResult,
) -> Result<Vec<RuntimeProfileRechargeProductConfigRecord>, SpacetimeClientError> {
if !result.ok {
return Err(SpacetimeClientError::procedure_failed(result.error_message));
}
Ok(result
.entries
.into_iter()
.map(|snapshot| {
build_runtime_profile_recharge_product_config_record(
map_runtime_profile_recharge_product_config_snapshot(snapshot),
)
})
.collect())
}
pub(crate) fn map_runtime_profile_recharge_product_admin_procedure_result(
result: RuntimeProfileRechargeProductAdminProcedureResult,
) -> Result<RuntimeProfileRechargeProductConfigRecord, SpacetimeClientError> {
if !result.ok {
return Err(SpacetimeClientError::procedure_failed(result.error_message));
}
let snapshot = result
.record
.ok_or_else(|| SpacetimeClientError::missing_snapshot("recharge product config 快照"))?;
Ok(build_runtime_profile_recharge_product_config_record(
map_runtime_profile_recharge_product_config_snapshot(snapshot),
))
}
pub(crate) fn map_runtime_profile_redeem_code_admin_procedure_result(
result: RuntimeProfileRedeemCodeAdminProcedureResult,
) -> Result<RuntimeProfileRedeemCodeRecord, SpacetimeClientError> {
if !result.ok {
return Err(SpacetimeClientError::procedure_failed(result.error_message));
}
let snapshot = result
.record
.ok_or_else(|| SpacetimeClientError::missing_snapshot("redeem code 快照"))?;
Ok(build_runtime_profile_redeem_code_record(
map_runtime_profile_redeem_code_snapshot(snapshot),
))
}
pub(crate) fn map_runtime_profile_redeem_code_admin_list_procedure_result(
result: RuntimeProfileRedeemCodeAdminListProcedureResult,
) -> Result<Vec<RuntimeProfileRedeemCodeRecord>, SpacetimeClientError> {
if !result.ok {
return Err(SpacetimeClientError::procedure_failed(result.error_message));
}
Ok(result
.entries
.into_iter()
.map(|snapshot| {
build_runtime_profile_redeem_code_record(map_runtime_profile_redeem_code_snapshot(
snapshot,
))
})
.collect())
}
pub(crate) fn map_runtime_profile_invite_code_admin_procedure_result(
result: RuntimeProfileInviteCodeAdminProcedureResult,
) -> Result<RuntimeProfileInviteCodeRecord, SpacetimeClientError> {
if !result.ok {
return Err(SpacetimeClientError::Procedure(
result
.error_message
.unwrap_or_else(|| "SpacetimeDB procedure 返回未知错误".to_string()),
));
}
let snapshot = result.record.ok_or_else(|| {
SpacetimeClientError::Procedure("SpacetimeDB procedure 未返回 invite code 快照".to_string())
})?;
Ok(build_runtime_profile_invite_code_record(
map_runtime_profile_invite_code_snapshot(snapshot),
))
}
pub(crate) fn map_runtime_profile_invite_code_admin_list_procedure_result(
result: RuntimeProfileInviteCodeAdminListProcedureResult,
) -> Result<Vec<RuntimeProfileInviteCodeRecord>, SpacetimeClientError> {
if !result.ok {
return Err(SpacetimeClientError::procedure_failed(result.error_message));
}
Ok(result
.entries
.into_iter()
.map(|snapshot| {
build_runtime_profile_invite_code_record(map_runtime_profile_invite_code_snapshot(
snapshot,
))
})
.collect())
}
pub(crate) fn map_runtime_profile_play_stats_procedure_result(
result: RuntimeProfilePlayStatsProcedureResult,
) -> Result<RuntimeProfilePlayStatsRecord, SpacetimeClientError> {
if !result.ok {
return Err(SpacetimeClientError::procedure_failed(result.error_message));
}
let snapshot = result
.record
.ok_or_else(|| SpacetimeClientError::missing_snapshot("profile play stats 快照"))?;
Ok(build_runtime_profile_play_stats_record(
map_runtime_profile_play_stats_snapshot(snapshot),
))
}
pub(crate) fn map_runtime_snapshot_procedure_result(
result: RuntimeSnapshotProcedureResult,
) -> Result<Option<RuntimeSnapshotRecord>, SpacetimeClientError> {
if !result.ok {
return Err(SpacetimeClientError::procedure_failed(result.error_message));
}
result
.record
.map(|snapshot| {
build_runtime_snapshot_record(map_runtime_snapshot_snapshot(snapshot))
.map_err(|error| SpacetimeClientError::Runtime(error.to_string()))
})
.transpose()
}
pub(crate) fn map_runtime_snapshot_required_procedure_result(
result: RuntimeSnapshotProcedureResult,
) -> Result<RuntimeSnapshotRecord, SpacetimeClientError> {
map_runtime_snapshot_procedure_result(result)?
.ok_or_else(|| SpacetimeClientError::missing_snapshot("runtime snapshot 快照"))
}
pub(crate) fn map_runtime_snapshot_delete_procedure_result(
result: RuntimeSnapshotProcedureResult,
) -> Result<bool, SpacetimeClientError> {
map_runtime_snapshot_procedure_result(result).map(|record| record.is_some())
}
pub(crate) fn map_runtime_profile_save_archive_list_procedure_result(
result: RuntimeProfileSaveArchiveProcedureResult,
) -> Result<Vec<RuntimeProfileSaveArchiveRecord>, SpacetimeClientError> {
if !result.ok {
return Err(SpacetimeClientError::procedure_failed(result.error_message));
}
result
.entries
.into_iter()
.map(|snapshot| {
build_runtime_profile_save_archive_record(map_runtime_profile_save_archive_snapshot(
snapshot,
))
.map_err(|error| SpacetimeClientError::Runtime(error.to_string()))
})
.collect()
}
pub(crate) fn map_runtime_profile_save_archive_resume_procedure_result(
result: RuntimeProfileSaveArchiveProcedureResult,
) -> Result<(RuntimeProfileSaveArchiveRecord, RuntimeSnapshotRecord), SpacetimeClientError> {
if !result.ok {
return Err(SpacetimeClientError::procedure_failed(result.error_message));
}
let archive = result
.record
.ok_or_else(|| SpacetimeClientError::missing_snapshot("save archive 快照"))?;
let snapshot = result
.current_snapshot
.ok_or_else(|| SpacetimeClientError::missing_snapshot("恢复后的 runtime snapshot"))?;
Ok((
build_runtime_profile_save_archive_record(map_runtime_profile_save_archive_snapshot(
archive,
))
.map_err(|error| SpacetimeClientError::Runtime(error.to_string()))?,
build_runtime_snapshot_record(map_runtime_snapshot_snapshot(snapshot))
.map_err(|error| SpacetimeClientError::Runtime(error.to_string()))?,
))
}
pub(crate) fn map_ai_task_procedure_result(
result: AiTaskProcedureResult,
) -> Result<AiTaskMutationRecord, SpacetimeClientError> {
if !result.ok {
return Err(SpacetimeClientError::procedure_failed(result.error_message));
}
let task = result
.task
.ok_or_else(|| SpacetimeClientError::missing_snapshot("ai_task 快照"))?;
Ok(AiTaskMutationRecord {
task: map_ai_task_snapshot(task),
text_chunk: result.text_chunk.map(map_ai_text_chunk_snapshot),
})
}
pub(crate) fn map_custom_world_profile_list_result(
result: CustomWorldProfileListResult,
) -> Result<Vec<CustomWorldLibraryEntryRecord>, SpacetimeClientError> {
if !result.ok {
return Err(SpacetimeClientError::procedure_failed(result.error_message));
}
result
.entries
.into_iter()
.map(map_custom_world_library_entry_from_profile_snapshot)
.collect()
}
pub(crate) fn map_custom_world_library_detail_result(
result: CustomWorldLibraryMutationResult,
) -> Result<CustomWorldLibraryMutationRecord, SpacetimeClientError> {
if !result.ok {
return Err(SpacetimeClientError::procedure_failed(result.error_message));
}
let entry = result
.entry
.ok_or_else(|| SpacetimeClientError::Procedure("custom_world_profile 不存在".to_string()))
.and_then(map_custom_world_library_entry_from_profile_snapshot)?;
let gallery_entry = result
.gallery_entry
.map(map_custom_world_gallery_entry_snapshot)
.transpose()?;
Ok(CustomWorldLibraryMutationRecord {
entry,
gallery_entry,
})
}
pub(crate) fn map_custom_world_gallery_list_result(
result: CustomWorldGalleryListResult,
) -> Result<Vec<CustomWorldGalleryEntryRecord>, SpacetimeClientError> {
if !result.ok {
return Err(SpacetimeClientError::procedure_failed(result.error_message));
}
Ok(result
.entries
.into_iter()
.map(map_custom_world_gallery_entry_snapshot)
.collect::<Result<Vec<_>, _>>()?)
}
pub(crate) fn map_custom_world_library_mutation_result(
result: CustomWorldLibraryMutationResult,
) -> Result<CustomWorldLibraryMutationRecord, SpacetimeClientError> {
if !result.ok {
return Err(SpacetimeClientError::procedure_failed(result.error_message));
}
let entry = result
.entry
.ok_or_else(|| SpacetimeClientError::missing_snapshot("custom world entry"))
.and_then(map_custom_world_library_entry_from_profile_snapshot)?;
let gallery_entry = result
.gallery_entry
.map(map_custom_world_gallery_entry_snapshot)
.transpose()?;
Ok(CustomWorldLibraryMutationRecord {
entry,
gallery_entry,
})
}
pub(crate) fn map_custom_world_publish_world_result(
result: CustomWorldPublishWorldResult,
) -> Result<CustomWorldPublishWorldRecord, SpacetimeClientError> {
if !result.ok {
return Err(SpacetimeClientError::procedure_failed(result.error_message));
}
let compiled_record = result
.compiled_record
.ok_or_else(|| SpacetimeClientError::missing_snapshot("published profile compile 快照"))
.and_then(map_custom_world_published_profile_compile_snapshot)?;
let entry = result
.entry
.ok_or_else(|| SpacetimeClientError::missing_snapshot("custom world entry"))
.and_then(map_custom_world_library_entry_from_profile_snapshot)?;
let gallery_entry = result
.gallery_entry
.map(map_custom_world_gallery_entry_snapshot)
.transpose()?;
let session_stage = result
.session_stage
.ok_or_else(|| SpacetimeClientError::missing_snapshot("session stage"))
.map(map_rpg_agent_stage)?;
Ok(CustomWorldPublishWorldRecord {
compiled_record,
entry,
gallery_entry,
session_stage,
})
}
pub(crate) fn map_custom_world_agent_session_procedure_result(
result: CustomWorldAgentSessionProcedureResult,
) -> Result<CustomWorldAgentSessionRecord, SpacetimeClientError> {
if !result.ok {
return Err(SpacetimeClientError::procedure_failed(result.error_message));
}
let session = result
.session
.ok_or_else(|| SpacetimeClientError::missing_snapshot("custom world agent session 快照"))?;
map_custom_world_agent_session_snapshot(session)
}
pub(crate) fn map_custom_world_agent_operation_procedure_result(
result: CustomWorldAgentOperationProcedureResult,
) -> Result<CustomWorldAgentOperationRecord, SpacetimeClientError> {
if !result.ok {
return Err(SpacetimeClientError::procedure_failed(result.error_message));
}
let operation = result.operation.ok_or_else(|| {
SpacetimeClientError::missing_snapshot("custom world agent operation 快照")
})?;
Ok(map_custom_world_agent_operation_snapshot(operation))
}
pub(crate) fn map_custom_world_works_list_result(
result: CustomWorldWorksListResult,
) -> Result<Vec<CustomWorldWorkSummaryRecord>, SpacetimeClientError> {
if !result.ok {
return Err(SpacetimeClientError::procedure_failed(result.error_message));
}
result
.items
.into_iter()
.map(map_custom_world_work_summary_snapshot)
.collect()
}
pub(crate) fn map_custom_world_draft_card_detail_result(
result: CustomWorldDraftCardDetailResult,
) -> Result<CustomWorldDraftCardDetailRecord, SpacetimeClientError> {
if !result.ok {
return Err(SpacetimeClientError::procedure_failed(result.error_message));
}
let card = result
.card
.ok_or_else(|| SpacetimeClientError::missing_snapshot("custom world card detail 快照"))?;
map_custom_world_draft_card_detail_snapshot(card)
}
pub(crate) fn map_custom_world_agent_action_execute_result(
result: CustomWorldAgentActionExecuteResult,
) -> Result<CustomWorldAgentActionExecuteRecord, SpacetimeClientError> {
if !result.ok {
return Err(SpacetimeClientError::procedure_failed(result.error_message));
}
let operation = result.operation.ok_or_else(|| {
SpacetimeClientError::missing_snapshot("custom world action operation 快照")
})?;
Ok(CustomWorldAgentActionExecuteRecord {
operation: map_custom_world_agent_operation_snapshot(operation),
})
}
pub(crate) fn map_puzzle_agent_session_procedure_result(
result: PuzzleAgentSessionProcedureResult,
) -> Result<PuzzleAgentSessionRecord, SpacetimeClientError> {
if !result.ok {
return Err(SpacetimeClientError::procedure_failed(result.error_message));
}
let session_json = result
.session_json
.ok_or_else(|| SpacetimeClientError::missing_snapshot("puzzle agent session 快照"))?;
let session: DomainPuzzleAgentSessionSnapshot =
serde_json::from_str(&session_json).map_err(|error| {
SpacetimeClientError::Runtime(format!("puzzle agent session_json 非法: {error}"))
})?;
Ok(map_puzzle_agent_session_snapshot(session))
}
pub(crate) fn map_puzzle_work_procedure_result(
result: PuzzleWorkProcedureResult,
) -> Result<PuzzleWorkProfileRecord, SpacetimeClientError> {
if !result.ok {
return Err(SpacetimeClientError::procedure_failed(result.error_message));
}
let item_json = result
.item_json
.ok_or_else(|| SpacetimeClientError::missing_snapshot("puzzle work 快照"))?;
let item: DomainPuzzleWorkProfile = serde_json::from_str(&item_json).map_err(|error| {
SpacetimeClientError::Runtime(format!("puzzle work item_json 非法: {error}"))
})?;
Ok(map_puzzle_work_profile(item))
}
pub(crate) fn map_puzzle_works_procedure_result(
result: PuzzleWorksProcedureResult,
) -> Result<Vec<PuzzleWorkProfileRecord>, SpacetimeClientError> {
if !result.ok {
return Err(SpacetimeClientError::procedure_failed(result.error_message));
}
let items_json = result
.items_json
.ok_or_else(|| SpacetimeClientError::missing_snapshot("puzzle works 快照"))?;
let items: Vec<DomainPuzzleWorkProfile> =
serde_json::from_str(&items_json).map_err(|error| {
SpacetimeClientError::Runtime(format!("puzzle works items_json 非法: {error}"))
})?;
Ok(items.into_iter().map(map_puzzle_work_profile).collect())
}
pub(crate) fn map_puzzle_run_procedure_result(
result: PuzzleRunProcedureResult,
) -> Result<PuzzleRunRecord, SpacetimeClientError> {
if !result.ok {
return Err(SpacetimeClientError::procedure_failed(result.error_message));
}
let run_json = result
.run_json
.ok_or_else(|| SpacetimeClientError::missing_snapshot("puzzle run 快照"))?;
let run: DomainPuzzleRunSnapshot = serde_json::from_str(&run_json).map_err(|error| {
SpacetimeClientError::Runtime(format!("puzzle run run_json 非法: {error}"))
})?;
Ok(map_puzzle_run_snapshot(run))
}
pub(crate) fn map_big_fish_session_procedure_result(
result: BigFishSessionProcedureResult,
) -> Result<BigFishSessionRecord, SpacetimeClientError> {
if !result.ok {
return Err(SpacetimeClientError::procedure_failed(result.error_message));
}
let session = result
.session
.ok_or_else(|| SpacetimeClientError::missing_snapshot("big fish session 快照"))?;
Ok(map_big_fish_session_snapshot(session))
}
pub(crate) fn map_big_fish_works_procedure_result(
result: BigFishWorksProcedureResult,
fallback_owner_user_id: Option<&str>,
) -> Result<Vec<BigFishWorkSummaryRecord>, SpacetimeClientError> {
if !result.ok {
return Err(SpacetimeClientError::procedure_failed(result.error_message));
}
let items_json = result
.items_json
.ok_or_else(|| SpacetimeClientError::missing_snapshot("big fish works 快照"))?;
serde_json::from_str::<Vec<CompatibleBigFishWorkSummaryRecord>>(&items_json)
.map(|items| {
items
.into_iter()
.map(|item| item.into_record(fallback_owner_user_id))
.collect()
})
.map_err(|error| {
SpacetimeClientError::Runtime(format!("big fish works items_json 非法: {error}"))
})
}
pub(crate) fn map_big_fish_run_procedure_result(
result: BigFishRunProcedureResult,
) -> Result<BigFishRuntimeRunRecord, SpacetimeClientError> {
if !result.ok {
return Err(SpacetimeClientError::procedure_failed(result.error_message));
}
let run_json = result
.run_json
.ok_or_else(|| SpacetimeClientError::missing_snapshot("big fish run 快照"))?;
let run: module_big_fish::BigFishRuntimeSnapshot =
serde_json::from_str(&run_json).map_err(|error| {
SpacetimeClientError::Runtime(format!("big fish run run_json 非法: {error}"))
})?;
Ok(map_big_fish_runtime_snapshot(run))
}
pub(crate) fn map_match3d_agent_session_procedure_result(
result: Match3DAgentSessionProcedureResult,
) -> Result<Match3DAgentSessionRecord, SpacetimeClientError> {
if !result.ok {
return Err(SpacetimeClientError::Procedure(
result
.error_message
.unwrap_or_else(|| "SpacetimeDB procedure 返回未知错误".to_string()),
));
}
let session_json = result.session_json.ok_or_else(|| {
SpacetimeClientError::Procedure(
"SpacetimeDB procedure 未返回 match3d agent session 快照".to_string(),
)
})?;
let session =
serde_json::from_str::<Match3DAgentSessionJsonRecord>(&session_json).map_err(|error| {
SpacetimeClientError::Runtime(format!("match3d session_json 非法: {error}"))
})?;
Ok(map_match3d_agent_session_snapshot(session))
}
pub(crate) fn map_match3d_work_procedure_result(
result: Match3DWorkProcedureResult,
) -> Result<Match3DWorkProfileRecord, SpacetimeClientError> {
if !result.ok {
return Err(SpacetimeClientError::Procedure(
result
.error_message
.unwrap_or_else(|| "SpacetimeDB procedure 返回未知错误".to_string()),
));
}
let work_json = result.work_json.ok_or_else(|| {
SpacetimeClientError::Procedure(
"SpacetimeDB procedure 未返回 match3d work 快照".to_string(),
)
})?;
let work = serde_json::from_str::<Match3DWorkJsonRecord>(&work_json).map_err(|error| {
SpacetimeClientError::Runtime(format!("match3d work_json 非法: {error}"))
})?;
Ok(map_match3d_work_snapshot(work))
}
pub(crate) fn map_match3d_works_procedure_result(
result: Match3DWorksProcedureResult,
) -> Result<Vec<Match3DWorkProfileRecord>, SpacetimeClientError> {
if !result.ok {
return Err(SpacetimeClientError::Procedure(
result
.error_message
.unwrap_or_else(|| "SpacetimeDB procedure 返回未知错误".to_string()),
));
}
let items_json = result.items_json.ok_or_else(|| {
SpacetimeClientError::Procedure(
"SpacetimeDB procedure 未返回 match3d works 快照".to_string(),
)
})?;
let items =
serde_json::from_str::<Vec<Match3DWorkJsonRecord>>(&items_json).map_err(|error| {
SpacetimeClientError::Runtime(format!("match3d works items_json 非法: {error}"))
})?;
Ok(items.into_iter().map(map_match3d_work_snapshot).collect())
}
pub(crate) fn map_match3d_run_procedure_result(
result: Match3DRunProcedureResult,
) -> Result<Match3DRunRecord, SpacetimeClientError> {
if !result.ok {
return Err(SpacetimeClientError::Procedure(
result
.error_message
.unwrap_or_else(|| "SpacetimeDB procedure 返回未知错误".to_string()),
));
}
let run_json = result.run_json.ok_or_else(|| {
SpacetimeClientError::Procedure("SpacetimeDB procedure 未返回 match3d run 快照".to_string())
})?;
map_match3d_run_json(run_json)
}
pub(crate) fn map_match3d_click_item_procedure_result(
result: Match3DClickItemProcedureResult,
) -> Result<Match3DClickConfirmationRecord, SpacetimeClientError> {
if !result.ok {
return Err(SpacetimeClientError::Procedure(
result
.error_message
.unwrap_or_else(|| "SpacetimeDB procedure 返回未知错误".to_string()),
));
}
let run_json = result.run_json.ok_or_else(|| {
SpacetimeClientError::Procedure(
"SpacetimeDB procedure 未返回 match3d click run 快照".to_string(),
)
})?;
let run = map_match3d_run_json(run_json)?;
let accepted = result.status == "Accepted";
let accepted_item_instance_id = result.accepted_item_instance_id.clone();
let entered_slot_index = accepted_item_instance_id.as_deref().and_then(|item_id| {
run.items
.iter()
.find(|item| item.item_instance_id == item_id)
.and_then(|item| item.tray_slot_index)
});
Ok(Match3DClickConfirmationRecord {
status: result.status.clone(),
accepted,
reject_reason: if accepted { None } else { Some(result.status) },
accepted_item_instance_id,
entered_slot_index,
cleared_item_instance_ids: result.cleared_item_instance_ids,
failure_reason: result.failure_reason,
run,
})
}
pub(crate) fn map_square_hole_agent_session_procedure_result(
result: SquareHoleAgentSessionProcedureResult,
) -> Result<SquareHoleAgentSessionRecord, SpacetimeClientError> {
if !result.ok {
return Err(SpacetimeClientError::procedure_failed(result.error_message));
}
let session_json = result
.session_json
.ok_or_else(|| SpacetimeClientError::missing_snapshot("square hole agent session 快照"))?;
let session = serde_json::from_str::<SquareHoleAgentSessionJsonRecord>(&session_json).map_err(
|error| SpacetimeClientError::Runtime(format!("square hole session_json 非法: {error}")),
)?;
Ok(map_square_hole_agent_session_snapshot(session))
}
pub(crate) fn map_square_hole_work_procedure_result(
result: SquareHoleWorkProcedureResult,
) -> Result<SquareHoleWorkProfileRecord, SpacetimeClientError> {
if !result.ok {
return Err(SpacetimeClientError::procedure_failed(result.error_message));
}
let work_json = result
.work_json
.ok_or_else(|| SpacetimeClientError::missing_snapshot("square hole work 快照"))?;
let work = serde_json::from_str::<SquareHoleWorkJsonRecord>(&work_json).map_err(|error| {
SpacetimeClientError::Runtime(format!("square hole work_json 非法: {error}"))
})?;
Ok(map_square_hole_work_snapshot(work))
}
pub(crate) fn map_square_hole_works_procedure_result(
result: SquareHoleWorksProcedureResult,
) -> Result<Vec<SquareHoleWorkProfileRecord>, SpacetimeClientError> {
if !result.ok {
return Err(SpacetimeClientError::procedure_failed(result.error_message));
}
let items_json = result
.items_json
.ok_or_else(|| SpacetimeClientError::missing_snapshot("square hole works 快照"))?;
let items =
serde_json::from_str::<Vec<SquareHoleWorkJsonRecord>>(&items_json).map_err(|error| {
SpacetimeClientError::Runtime(format!("square hole works items_json 非法: {error}"))
})?;
Ok(items
.into_iter()
.map(map_square_hole_work_snapshot)
.collect())
}
pub(crate) fn map_square_hole_run_procedure_result(
result: SquareHoleRunProcedureResult,
) -> Result<SquareHoleRunRecord, SpacetimeClientError> {
if !result.ok {
return Err(SpacetimeClientError::procedure_failed(result.error_message));
}
let run_json = result
.run_json
.ok_or_else(|| SpacetimeClientError::missing_snapshot("square hole run 快照"))?;
map_square_hole_run_json(run_json)
}
pub(crate) fn map_square_hole_drop_shape_procedure_result(
result: SquareHoleDropShapeProcedureResult,
) -> Result<SquareHoleDropConfirmationRecord, SpacetimeClientError> {
if !result.ok {
return Err(SpacetimeClientError::procedure_failed(result.error_message));
}
let run_json = result
.run_json
.ok_or_else(|| SpacetimeClientError::missing_snapshot("square hole drop run 快照"))?;
let feedback_json = result
.feedback_json
.ok_or_else(|| SpacetimeClientError::missing_snapshot("square hole drop feedback 快照"))?;
let run = map_square_hole_run_json(run_json)?;
let feedback = serde_json::from_str::<SquareHoleDropFeedbackJsonRecord>(&feedback_json)
.map_err(|error| {
SpacetimeClientError::Runtime(format!("square hole feedback_json 非法: {error}"))
})?;
Ok(SquareHoleDropConfirmationRecord {
status: result.status,
accepted: feedback.accepted,
reject_reason: feedback.reject_reason.clone(),
failure_reason: result.failure_reason,
feedback: map_square_hole_feedback_snapshot(feedback),
run,
})
}
pub(crate) fn map_visual_novel_agent_session_procedure_result(
result: VisualNovelAgentSessionProcedureResult,
) -> Result<VisualNovelAgentSessionRecord, SpacetimeClientError> {
if !result.ok {
return Err(SpacetimeClientError::procedure_failed(result.error_message));
}
let session_json = result
.session_json
.ok_or_else(|| SpacetimeClientError::missing_snapshot("visual novel agent session 快照"))?;
let session = serde_json::from_str::<VisualNovelAgentSessionJsonRecord>(&session_json)
.map_err(|error| {
SpacetimeClientError::Runtime(format!("visual novel session_json 非法: {error}"))
})?;
Ok(map_visual_novel_agent_session_snapshot(session))
}
pub(crate) fn map_visual_novel_work_procedure_result(
result: VisualNovelWorkProcedureResult,
) -> Result<VisualNovelWorkProfileRecord, SpacetimeClientError> {
if !result.ok {
return Err(SpacetimeClientError::procedure_failed(result.error_message));
}
let work_json = result
.work_json
.ok_or_else(|| SpacetimeClientError::missing_snapshot("visual novel work 快照"))?;
let work = serde_json::from_str::<VisualNovelWorkJsonRecord>(&work_json).map_err(|error| {
SpacetimeClientError::Runtime(format!("visual novel work_json 非法: {error}"))
})?;
Ok(map_visual_novel_work_snapshot(work))
}
pub(crate) fn map_visual_novel_works_procedure_result(
result: VisualNovelWorksProcedureResult,
) -> Result<Vec<VisualNovelWorkProfileRecord>, SpacetimeClientError> {
if !result.ok {
return Err(SpacetimeClientError::procedure_failed(result.error_message));
}
let items_json = result
.items_json
.ok_or_else(|| SpacetimeClientError::missing_snapshot("visual novel works 快照"))?;
let items =
serde_json::from_str::<Vec<VisualNovelWorkJsonRecord>>(&items_json).map_err(|error| {
SpacetimeClientError::Runtime(format!("visual novel works items_json 非法: {error}"))
})?;
Ok(items
.into_iter()
.map(map_visual_novel_work_snapshot)
.collect())
}
pub(crate) fn map_visual_novel_run_procedure_result(
result: VisualNovelRunProcedureResult,
) -> Result<VisualNovelRunRecord, SpacetimeClientError> {
if !result.ok {
return Err(SpacetimeClientError::procedure_failed(result.error_message));
}
let run_json = result
.run_json
.ok_or_else(|| SpacetimeClientError::missing_snapshot("visual novel run 快照"))?;
let run = serde_json::from_str::<VisualNovelRunJsonRecord>(&run_json).map_err(|error| {
SpacetimeClientError::Runtime(format!("visual novel run_json 非法: {error}"))
})?;
Ok(map_visual_novel_run_snapshot(run))
}
pub(crate) fn map_visual_novel_history_procedure_result(
result: VisualNovelHistoryProcedureResult,
) -> Result<Vec<VisualNovelHistoryEntryRecord>, SpacetimeClientError> {
if !result.ok {
return Err(SpacetimeClientError::procedure_failed(result.error_message));
}
let items_json = result
.items_json
.ok_or_else(|| SpacetimeClientError::missing_snapshot("visual novel history 快照"))?;
let items = serde_json::from_str::<Vec<VisualNovelHistoryEntryJsonRecord>>(&items_json)
.map_err(|error| {
SpacetimeClientError::Runtime(format!("visual novel history items_json 非法: {error}"))
})?;
Ok(items
.into_iter()
.map(map_visual_novel_history_entry)
.collect())
}
pub(crate) fn map_visual_novel_runtime_event_procedure_result(
result: VisualNovelRuntimeEventProcedureResult,
) -> Result<VisualNovelRuntimeEventRecord, SpacetimeClientError> {
if !result.ok {
return Err(SpacetimeClientError::procedure_failed(result.error_message));
}
let event_json = result
.event_json
.ok_or_else(|| SpacetimeClientError::missing_snapshot("visual novel runtime event 快照"))?;
let event = serde_json::from_str::<VisualNovelRuntimeEventJsonRecord>(&event_json).map_err(
|error| SpacetimeClientError::Runtime(format!("visual novel event_json 非法: {error}")),
)?;
Ok(map_visual_novel_runtime_event(event))
}
pub(crate) fn map_story_session_procedure_result(
result: StorySessionProcedureResult,
) -> Result<StorySessionResultRecord, SpacetimeClientError> {
if !result.ok {
return Err(SpacetimeClientError::procedure_failed(result.error_message));
}
let session = result
.session
.ok_or_else(|| SpacetimeClientError::missing_snapshot("story session 快照"))?;
let event = result
.event
.ok_or_else(|| SpacetimeClientError::missing_snapshot("story event 快照"))?;
Ok(StorySessionResultRecord {
session: map_story_session_snapshot(session),
event: map_story_event_snapshot(event),
})
}
pub(crate) fn map_story_session_state_procedure_result(
result: StorySessionStateProcedureResult,
) -> Result<StorySessionStateRecord, SpacetimeClientError> {
if !result.ok {
return Err(SpacetimeClientError::procedure_failed(result.error_message));
}
let session = result
.session
.ok_or_else(|| SpacetimeClientError::missing_snapshot("story session state 快照"))?;
Ok(StorySessionStateRecord {
session: map_story_session_snapshot(session),
events: result
.events
.into_iter()
.map(map_story_event_snapshot)
.collect(),
})
}
pub(crate) fn map_runtime_inventory_state_procedure_result(
result: RuntimeInventoryStateProcedureResult,
) -> Result<RuntimeInventoryStateRecord, SpacetimeClientError> {
if !result.ok {
return Err(SpacetimeClientError::procedure_failed(result.error_message));
}
let snapshot = result
.snapshot
.ok_or_else(|| SpacetimeClientError::missing_snapshot("runtime inventory state 快照"))?;
Ok(build_runtime_inventory_state_record(
map_runtime_inventory_state_snapshot(snapshot),
))
}
pub(crate) fn map_battle_state_procedure_result(
result: BattleStateProcedureResult,
) -> Result<BattleStateRecord, SpacetimeClientError> {
if !result.ok {
return Err(SpacetimeClientError::procedure_failed(result.error_message));
}
let snapshot = result
.snapshot
.ok_or_else(|| SpacetimeClientError::missing_snapshot("battle_state 快照"))?;
Ok(build_battle_state_record(map_battle_state_snapshot(
snapshot,
)))
}
pub(crate) fn map_resolve_combat_action_procedure_result(
result: ResolveCombatActionProcedureResult,
) -> Result<ResolveCombatActionRecord, SpacetimeClientError> {
if !result.ok {
return Err(SpacetimeClientError::procedure_failed(result.error_message));
}
let action_result = result
.result
.ok_or_else(|| SpacetimeClientError::missing_snapshot("战斗结算结果"))?;
Ok(build_resolve_combat_action_record(
map_resolve_combat_action_result(action_result),
))
}
pub(crate) fn map_npc_battle_interaction_procedure_result(
result: NpcBattleInteractionProcedureResult,
) -> Result<NpcBattleInteractionRecord, SpacetimeClientError> {
if !result.ok {
return Err(SpacetimeClientError::procedure_failed(result.error_message));
}
let interaction_result = result
.result
.ok_or_else(|| SpacetimeClientError::missing_snapshot("NPC 开战结果"))?;
Ok(build_npc_battle_interaction_record(
map_npc_battle_interaction_result(interaction_result),
))
}
pub(crate) fn map_entity_binding_snapshot(
snapshot: AssetEntityBindingSnapshot,
) -> module_assets::AssetEntityBindingSnapshot {
module_assets::AssetEntityBindingSnapshot {
binding_id: snapshot.binding_id,
asset_object_id: snapshot.asset_object_id,
entity_kind: snapshot.entity_kind,
entity_id: snapshot.entity_id,
slot: snapshot.slot,
asset_kind: snapshot.asset_kind,
owner_user_id: snapshot.owner_user_id,
profile_id: snapshot.profile_id,
created_at_micros: snapshot.created_at_micros,
updated_at_micros: snapshot.updated_at_micros,
}
}
pub(crate) fn map_snapshot(
snapshot: AssetObjectUpsertSnapshot,
) -> module_assets::AssetObjectUpsertSnapshot {
module_assets::AssetObjectUpsertSnapshot {
asset_object_id: snapshot.asset_object_id,
bucket: snapshot.bucket,
object_key: snapshot.object_key,
access_policy: map_access_policy_back(snapshot.access_policy),
content_type: snapshot.content_type,
content_length: snapshot.content_length,
content_hash: snapshot.content_hash,
version: snapshot.version,
source_job_id: snapshot.source_job_id,
owner_user_id: snapshot.owner_user_id,
profile_id: snapshot.profile_id,
entity_id: snapshot.entity_id,
asset_kind: snapshot.asset_kind,
created_at_micros: snapshot.created_at_micros,
updated_at_micros: snapshot.updated_at_micros,
}
}
pub(crate) fn map_asset_history_entry_snapshot(
snapshot: AssetHistoryEntrySnapshot,
) -> module_assets::AssetHistoryEntrySnapshot {
module_assets::AssetHistoryEntrySnapshot {
asset_object_id: snapshot.asset_object_id,
asset_kind: snapshot.asset_kind,
image_src: snapshot.image_src,
owner_user_id: snapshot.owner_user_id,
profile_id: snapshot.profile_id,
entity_id: snapshot.entity_id,
created_at_micros: snapshot.created_at_micros,
updated_at_micros: snapshot.updated_at_micros,
}
}
pub(crate) fn map_runtime_setting_snapshot(
snapshot: RuntimeSettingSnapshot,
) -> module_runtime::RuntimeSettingSnapshot {
module_runtime::RuntimeSettingSnapshot {
user_id: snapshot.user_id,
music_volume: snapshot.music_volume,
platform_theme: map_runtime_platform_theme_back(snapshot.platform_theme),
created_at_micros: snapshot.created_at_micros,
updated_at_micros: snapshot.updated_at_micros,
}
}
pub(crate) fn map_runtime_browse_history_snapshot(
snapshot: RuntimeBrowseHistorySnapshot,
) -> module_runtime::RuntimeBrowseHistorySnapshot {
module_runtime::RuntimeBrowseHistorySnapshot {
browse_history_id: snapshot.browse_history_id,
user_id: snapshot.user_id,
owner_user_id: snapshot.owner_user_id,
profile_id: snapshot.profile_id,
world_name: snapshot.world_name,
subtitle: snapshot.subtitle,
summary_text: snapshot.summary_text,
cover_image_src: snapshot.cover_image_src,
theme_mode: map_runtime_browse_history_theme_mode_back(snapshot.theme_mode),
author_display_name: snapshot.author_display_name,
visited_at_micros: snapshot.visited_at_micros,
created_at_micros: snapshot.created_at_micros,
updated_at_micros: snapshot.updated_at_micros,
}
}
pub(crate) fn map_runtime_profile_dashboard_snapshot(
snapshot: RuntimeProfileDashboardSnapshot,
) -> module_runtime::RuntimeProfileDashboardSnapshot {
module_runtime::RuntimeProfileDashboardSnapshot {
user_id: snapshot.user_id,
wallet_balance: snapshot.wallet_balance,
total_play_time_ms: snapshot.total_play_time_ms,
played_world_count: snapshot.played_world_count,
updated_at_micros: snapshot.updated_at_micros,
}
}
pub(crate) fn map_analytics_bucket_metric(
bucket: AnalyticsBucketMetric,
) -> module_runtime::AnalyticsBucketMetric {
module_runtime::AnalyticsBucketMetric {
bucket_key: bucket.bucket_key,
bucket_start_date_key: bucket.bucket_start_date_key,
bucket_end_date_key: bucket.bucket_end_date_key,
value: bucket.value,
}
}
pub(crate) fn map_runtime_profile_wallet_ledger_entry_snapshot(
snapshot: RuntimeProfileWalletLedgerEntrySnapshot,
) -> module_runtime::RuntimeProfileWalletLedgerEntrySnapshot {
module_runtime::RuntimeProfileWalletLedgerEntrySnapshot {
wallet_ledger_id: snapshot.wallet_ledger_id,
user_id: snapshot.user_id,
amount_delta: snapshot.amount_delta,
balance_after: snapshot.balance_after,
source_type: map_runtime_profile_wallet_ledger_source_type_back(snapshot.source_type),
created_at_micros: snapshot.created_at_micros,
}
}
pub(crate) fn map_runtime_profile_recharge_center_snapshot(
snapshot: RuntimeProfileRechargeCenterSnapshot,
) -> module_runtime::RuntimeProfileRechargeCenterSnapshot {
module_runtime::RuntimeProfileRechargeCenterSnapshot {
user_id: snapshot.user_id,
wallet_balance: snapshot.wallet_balance,
membership: map_runtime_profile_membership_snapshot(snapshot.membership),
point_products: snapshot
.point_products
.into_iter()
.map(map_runtime_profile_recharge_product_snapshot)
.collect(),
membership_products: snapshot
.membership_products
.into_iter()
.map(map_runtime_profile_recharge_product_snapshot)
.collect(),
benefits: snapshot
.benefits
.into_iter()
.map(map_runtime_profile_membership_benefit_snapshot)
.collect(),
latest_order: snapshot
.latest_order
.map(map_runtime_profile_recharge_order_snapshot),
has_points_recharged: snapshot.has_points_recharged,
}
}
pub(crate) fn map_runtime_profile_recharge_product_snapshot(
snapshot: RuntimeProfileRechargeProductSnapshot,
) -> module_runtime::RuntimeProfileRechargeProductSnapshot {
module_runtime::RuntimeProfileRechargeProductSnapshot {
product_id: snapshot.product_id,
title: snapshot.title,
price_cents: snapshot.price_cents,
kind: map_runtime_profile_recharge_product_kind_back(snapshot.kind),
points_amount: snapshot.points_amount,
bonus_points: snapshot.bonus_points,
duration_days: snapshot.duration_days,
badge_label: snapshot.badge_label,
description: snapshot.description,
tier: map_runtime_profile_membership_tier_back(snapshot.tier),
}
}
pub(crate) fn map_runtime_profile_recharge_product_config_snapshot(
snapshot: RuntimeProfileRechargeProductConfigSnapshot,
) -> module_runtime::RuntimeProfileRechargeProductConfigSnapshot {
module_runtime::RuntimeProfileRechargeProductConfigSnapshot {
product_id: snapshot.product_id,
title: snapshot.title,
price_cents: snapshot.price_cents,
kind: map_runtime_profile_recharge_product_kind_back(snapshot.kind),
points_amount: snapshot.points_amount,
bonus_points: snapshot.bonus_points,
duration_days: snapshot.duration_days,
badge_label: snapshot.badge_label,
description: snapshot.description,
tier: map_runtime_profile_membership_tier_back(snapshot.tier),
enabled: snapshot.enabled,
sort_order: snapshot.sort_order,
created_by: snapshot.created_by,
created_at_micros: snapshot.created_at_micros,
updated_by: snapshot.updated_by,
updated_at_micros: snapshot.updated_at_micros,
}
}
pub(crate) fn map_runtime_profile_membership_benefit_snapshot(
snapshot: RuntimeProfileMembershipBenefitSnapshot,
) -> module_runtime::RuntimeProfileMembershipBenefitSnapshot {
module_runtime::RuntimeProfileMembershipBenefitSnapshot {
benefit_name: snapshot.benefit_name,
normal_value: snapshot.normal_value,
month_value: snapshot.month_value,
season_value: snapshot.season_value,
year_value: snapshot.year_value,
}
}
pub(crate) fn map_runtime_profile_membership_snapshot(
snapshot: RuntimeProfileMembershipSnapshot,
) -> module_runtime::RuntimeProfileMembershipSnapshot {
module_runtime::RuntimeProfileMembershipSnapshot {
user_id: snapshot.user_id,
status: map_runtime_profile_membership_status_back(snapshot.status),
tier: map_runtime_profile_membership_tier_back(snapshot.tier),
started_at_micros: snapshot.started_at_micros,
expires_at_micros: snapshot.expires_at_micros,
updated_at_micros: snapshot.updated_at_micros,
}
}
pub(crate) fn map_runtime_profile_recharge_order_snapshot(
snapshot: RuntimeProfileRechargeOrderSnapshot,
) -> module_runtime::RuntimeProfileRechargeOrderSnapshot {
module_runtime::RuntimeProfileRechargeOrderSnapshot {
order_id: snapshot.order_id,
user_id: snapshot.user_id,
product_id: snapshot.product_id,
product_title: snapshot.product_title,
kind: map_runtime_profile_recharge_product_kind_back(snapshot.kind),
amount_cents: snapshot.amount_cents,
status: map_runtime_profile_recharge_order_status_back(snapshot.status),
payment_channel: snapshot.payment_channel,
paid_at_micros: snapshot.paid_at_micros,
provider_transaction_id: snapshot.provider_transaction_id,
created_at_micros: snapshot.created_at_micros,
points_delta: snapshot.points_delta,
membership_expires_at_micros: snapshot.membership_expires_at_micros,
}
}
pub(crate) fn map_runtime_profile_feedback_submission_snapshot(
snapshot: RuntimeProfileFeedbackSubmissionSnapshot,
) -> module_runtime::RuntimeProfileFeedbackSubmissionSnapshot {
module_runtime::RuntimeProfileFeedbackSubmissionSnapshot {
feedback_id: snapshot.feedback_id,
user_id: snapshot.user_id,
description: snapshot.description,
contact_phone: snapshot.contact_phone,
evidence_json: snapshot.evidence_json,
status: map_runtime_profile_feedback_status_back(snapshot.status),
created_at_micros: snapshot.created_at_micros,
updated_at_micros: snapshot.updated_at_micros,
}
}
pub(crate) fn map_runtime_referral_invite_center_snapshot(
snapshot: RuntimeReferralInviteCenterSnapshot,
) -> module_runtime::RuntimeReferralInviteCenterSnapshot {
module_runtime::RuntimeReferralInviteCenterSnapshot {
user_id: snapshot.user_id,
invite_code: snapshot.invite_code,
invite_link_path: snapshot.invite_link_path,
invited_count: snapshot.invited_count,
rewarded_invite_count: snapshot.rewarded_invite_count,
today_inviter_reward_count: snapshot.today_inviter_reward_count,
today_inviter_reward_remaining: snapshot.today_inviter_reward_remaining,
reward_points: snapshot.reward_points,
invited_users: snapshot
.invited_users
.into_iter()
.map(|user| module_runtime::RuntimeReferralInvitedUserSnapshot {
user_id: user.user_id,
display_name: user.display_name,
avatar_url: user.avatar_url,
bound_at_micros: user.bound_at_micros,
})
.collect(),
has_redeemed_code: snapshot.has_redeemed_code,
bound_inviter_user_id: snapshot.bound_inviter_user_id,
bound_at_micros: snapshot.bound_at_micros,
updated_at_micros: snapshot.updated_at_micros,
}
}
pub(crate) fn map_runtime_referral_redeem_snapshot(
snapshot: RuntimeReferralRedeemSnapshot,
) -> module_runtime::RuntimeReferralRedeemSnapshot {
module_runtime::RuntimeReferralRedeemSnapshot {
center: map_runtime_referral_invite_center_snapshot(snapshot.center),
invitee_reward_granted: snapshot.invitee_reward_granted,
inviter_reward_granted: snapshot.inviter_reward_granted,
invitee_balance_after: snapshot.invitee_balance_after,
inviter_balance_after: snapshot.inviter_balance_after,
}
}
pub(crate) fn map_runtime_profile_reward_code_redeem_snapshot(
snapshot: RuntimeProfileRewardCodeRedeemSnapshot,
) -> module_runtime::RuntimeProfileRewardCodeRedeemSnapshot {
module_runtime::RuntimeProfileRewardCodeRedeemSnapshot {
wallet_balance: snapshot.wallet_balance,
amount_granted: snapshot.amount_granted,
ledger_entry: map_runtime_profile_wallet_ledger_entry_snapshot(snapshot.ledger_entry),
}
}
pub(crate) fn map_runtime_profile_task_config_snapshot(
snapshot: RuntimeProfileTaskConfigSnapshot,
) -> module_runtime::RuntimeProfileTaskConfigSnapshot {
module_runtime::RuntimeProfileTaskConfigSnapshot {
task_id: snapshot.task_id,
title: snapshot.title,
description: snapshot.description,
event_key: snapshot.event_key,
cycle: map_runtime_profile_task_cycle_back(snapshot.cycle),
scope_kind: map_runtime_tracking_scope_kind_back(snapshot.scope_kind),
threshold: snapshot.threshold,
reward_points: snapshot.reward_points,
enabled: snapshot.enabled,
sort_order: snapshot.sort_order,
created_by: snapshot.created_by,
created_at_micros: snapshot.created_at_micros,
updated_by: snapshot.updated_by,
updated_at_micros: snapshot.updated_at_micros,
}
}
pub(crate) fn map_runtime_profile_task_item_snapshot(
snapshot: RuntimeProfileTaskItemSnapshot,
) -> module_runtime::RuntimeProfileTaskItemSnapshot {
module_runtime::RuntimeProfileTaskItemSnapshot {
task_id: snapshot.task_id,
title: snapshot.title,
description: snapshot.description,
event_key: snapshot.event_key,
cycle: map_runtime_profile_task_cycle_back(snapshot.cycle),
threshold: snapshot.threshold,
progress_count: snapshot.progress_count,
reward_points: snapshot.reward_points,
status: map_runtime_profile_task_status_back(snapshot.status),
day_key: snapshot.day_key,
claimed_at_micros: snapshot.claimed_at_micros,
updated_at_micros: snapshot.updated_at_micros,
}
}
pub(crate) fn map_runtime_profile_task_center_snapshot(
snapshot: RuntimeProfileTaskCenterSnapshot,
) -> module_runtime::RuntimeProfileTaskCenterSnapshot {
module_runtime::RuntimeProfileTaskCenterSnapshot {
user_id: snapshot.user_id,
day_key: snapshot.day_key,
wallet_balance: snapshot.wallet_balance,
tasks: snapshot
.tasks
.into_iter()
.map(map_runtime_profile_task_item_snapshot)
.collect(),
updated_at_micros: snapshot.updated_at_micros,
}
}
pub(crate) fn map_runtime_profile_task_claim_snapshot(
snapshot: RuntimeProfileTaskClaimSnapshot,
) -> module_runtime::RuntimeProfileTaskClaimSnapshot {
module_runtime::RuntimeProfileTaskClaimSnapshot {
user_id: snapshot.user_id,
task_id: snapshot.task_id,
day_key: snapshot.day_key,
reward_points: snapshot.reward_points,
wallet_balance: snapshot.wallet_balance,
ledger_entry: map_runtime_profile_wallet_ledger_entry_snapshot(snapshot.ledger_entry),
center: map_runtime_profile_task_center_snapshot(snapshot.center),
}
}
pub(crate) fn map_runtime_profile_redeem_code_snapshot(
snapshot: RuntimeProfileRedeemCodeSnapshot,
) -> module_runtime::RuntimeProfileRedeemCodeSnapshot {
module_runtime::RuntimeProfileRedeemCodeSnapshot {
code: snapshot.code,
mode: map_runtime_profile_redeem_code_mode_back(snapshot.mode),
reward_points: snapshot.reward_points,
max_uses: snapshot.max_uses,
global_used_count: snapshot.global_used_count,
enabled: snapshot.enabled,
allowed_user_ids: snapshot.allowed_user_ids,
created_by: snapshot.created_by,
created_at_micros: snapshot.created_at_micros,
updated_at_micros: snapshot.updated_at_micros,
}
}
pub(crate) fn map_runtime_profile_invite_code_snapshot(
snapshot: RuntimeProfileInviteCodeSnapshot,
) -> module_runtime::RuntimeProfileInviteCodeSnapshot {
module_runtime::RuntimeProfileInviteCodeSnapshot {
user_id: snapshot.user_id,
invite_code: snapshot.invite_code,
metadata_json: snapshot.metadata_json,
starts_at_micros: snapshot.starts_at_micros,
expires_at_micros: snapshot.expires_at_micros,
created_at_micros: snapshot.created_at_micros,
updated_at_micros: snapshot.updated_at_micros,
}
}
pub(crate) fn map_runtime_profile_played_world_snapshot(
snapshot: RuntimeProfilePlayedWorldSnapshot,
) -> module_runtime::RuntimeProfilePlayedWorldSnapshot {
module_runtime::RuntimeProfilePlayedWorldSnapshot {
played_world_id: snapshot.played_world_id,
user_id: snapshot.user_id,
world_key: snapshot.world_key,
owner_user_id: snapshot.owner_user_id,
profile_id: snapshot.profile_id,
world_type: snapshot.world_type,
world_title: snapshot.world_title,
world_subtitle: snapshot.world_subtitle,
first_played_at_micros: snapshot.first_played_at_micros,
last_played_at_micros: snapshot.last_played_at_micros,
last_observed_play_time_ms: snapshot.last_observed_play_time_ms,
}
}
pub(crate) fn map_runtime_profile_play_stats_snapshot(
snapshot: RuntimeProfilePlayStatsSnapshot,
) -> module_runtime::RuntimeProfilePlayStatsSnapshot {
module_runtime::RuntimeProfilePlayStatsSnapshot {
user_id: snapshot.user_id,
total_play_time_ms: snapshot.total_play_time_ms,
played_works: snapshot
.played_works
.into_iter()
.map(map_runtime_profile_played_world_snapshot)
.collect(),
updated_at_micros: snapshot.updated_at_micros,
}
}
pub(crate) fn map_runtime_snapshot_snapshot(
snapshot: RuntimeSnapshot,
) -> module_runtime::RuntimeSnapshot {
module_runtime::RuntimeSnapshot {
user_id: snapshot.user_id,
version: snapshot.version,
saved_at_micros: snapshot.saved_at_micros,
bottom_tab: snapshot.bottom_tab,
game_state_json: snapshot.game_state_json,
current_story_json: snapshot.current_story_json,
created_at_micros: snapshot.created_at_micros,
updated_at_micros: snapshot.updated_at_micros,
}
}
pub(crate) fn map_runtime_profile_save_archive_snapshot(
snapshot: RuntimeProfileSaveArchiveSnapshot,
) -> module_runtime::RuntimeProfileSaveArchiveSnapshot {
module_runtime::RuntimeProfileSaveArchiveSnapshot {
archive_id: snapshot.archive_id,
user_id: snapshot.user_id,
world_key: snapshot.world_key,
owner_user_id: snapshot.owner_user_id,
profile_id: snapshot.profile_id,
world_type: snapshot.world_type,
world_name: snapshot.world_name,
subtitle: snapshot.subtitle,
summary_text: snapshot.summary_text,
cover_image_src: snapshot.cover_image_src,
saved_at_micros: snapshot.saved_at_micros,
bottom_tab: snapshot.bottom_tab,
game_state_json: snapshot.game_state_json,
current_story_json: snapshot.current_story_json,
created_at_micros: snapshot.created_at_micros,
updated_at_micros: snapshot.updated_at_micros,
}
}
pub(crate) fn map_custom_world_library_entry_from_profile_snapshot(
snapshot: CustomWorldProfileSnapshot,
) -> Result<CustomWorldLibraryEntryRecord, SpacetimeClientError> {
let profile = serde_json::from_str::<serde_json::Value>(&snapshot.profile_payload_json)
.map_err(|error| {
SpacetimeClientError::Runtime(format!(
"custom world profile payload JSON 非法: {error}"
))
})?;
Ok(CustomWorldLibraryEntryRecord {
owner_user_id: snapshot.owner_user_id,
profile_id: snapshot.profile_id,
public_work_code: snapshot.public_work_code,
author_public_user_code: snapshot.author_public_user_code,
profile,
visibility: map_custom_world_publication_status(snapshot.publication_status).to_string(),
published_at: snapshot.published_at_micros.map(format_timestamp_micros),
updated_at: format_timestamp_micros(snapshot.updated_at_micros),
author_display_name: snapshot.author_display_name,
world_name: snapshot.world_name,
subtitle: snapshot.subtitle,
summary_text: snapshot.summary_text,
cover_image_src: snapshot.cover_image_src,
theme_mode: format_custom_world_theme_mode(map_custom_world_theme_mode_back(
snapshot.theme_mode,
))
.to_string(),
playable_npc_count: snapshot.playable_npc_count,
landmark_count: snapshot.landmark_count,
play_count: snapshot.play_count,
remix_count: snapshot.remix_count,
like_count: snapshot.like_count,
recent_play_count_7d: 0,
})
}
pub(crate) fn map_custom_world_gallery_entry_snapshot(
snapshot: CustomWorldGalleryEntrySnapshot,
) -> Result<CustomWorldGalleryEntryRecord, SpacetimeClientError> {
Ok(CustomWorldGalleryEntryRecord {
owner_user_id: snapshot.owner_user_id,
profile_id: snapshot.profile_id,
public_work_code: snapshot.public_work_code,
author_public_user_code: snapshot.author_public_user_code,
visibility: "published".to_string(),
published_at: Some(format_timestamp_micros(snapshot.published_at_micros)),
updated_at: format_timestamp_micros(snapshot.updated_at_micros),
author_display_name: snapshot.author_display_name,
world_name: snapshot.world_name,
subtitle: snapshot.subtitle,
summary_text: snapshot.summary_text,
cover_image_src: snapshot.cover_image_src,
theme_mode: format_custom_world_theme_mode(map_custom_world_theme_mode_back(
snapshot.theme_mode,
))
.to_string(),
playable_npc_count: snapshot.playable_npc_count,
landmark_count: snapshot.landmark_count,
play_count: snapshot.play_count,
remix_count: snapshot.remix_count,
like_count: snapshot.like_count,
recent_play_count_7d: snapshot.recent_play_count_7_d,
})
}
pub(crate) fn map_custom_world_published_profile_compile_snapshot(
snapshot: CustomWorldPublishedProfileCompileSnapshot,
) -> Result<CustomWorldPublishedProfileCompileRecord, SpacetimeClientError> {
let compiled_profile =
serde_json::from_str::<serde_json::Value>(&snapshot.compiled_profile_payload_json)
.map_err(|error| {
SpacetimeClientError::Runtime(format!(
"published profile compile JSON 非法: {error}"
))
})?;
Ok(CustomWorldPublishedProfileCompileRecord {
profile_id: snapshot.profile_id,
owner_user_id: snapshot.owner_user_id,
world_name: snapshot.world_name,
subtitle: snapshot.subtitle,
summary_text: snapshot.summary_text,
theme_mode: format_custom_world_theme_mode(map_custom_world_theme_mode_back(
snapshot.theme_mode,
))
.to_string(),
cover_image_src: snapshot.cover_image_src,
playable_npc_count: snapshot.playable_npc_count,
landmark_count: snapshot.landmark_count,
author_display_name: snapshot.author_display_name,
compiled_profile: compiled_profile,
updated_at: format_timestamp_micros(snapshot.updated_at_micros),
})
}
pub(crate) fn map_custom_world_work_summary_snapshot(
snapshot: CustomWorldWorkSummarySnapshot,
) -> Result<CustomWorldWorkSummaryRecord, SpacetimeClientError> {
Ok(CustomWorldWorkSummaryRecord {
work_id: snapshot.work_id,
source_type: snapshot.source_type,
status: snapshot.status,
title: snapshot.title,
subtitle: snapshot.subtitle,
summary: snapshot.summary,
cover_image_src: snapshot.cover_image_src,
cover_render_mode: snapshot.cover_render_mode,
cover_character_image_srcs: parse_json_string_array(
&snapshot.cover_character_image_srcs_json,
"custom world work cover_character_image_srcs_json",
)?,
updated_at: format_timestamp_micros(snapshot.updated_at_micros),
published_at: snapshot.published_at_micros.map(format_timestamp_micros),
stage: snapshot.stage.map(map_rpg_agent_stage),
stage_label: snapshot.stage_label,
playable_npc_count: snapshot.playable_npc_count,
landmark_count: snapshot.landmark_count,
role_visual_ready_count: snapshot.role_visual_ready_count,
role_animation_ready_count: snapshot.role_animation_ready_count,
role_asset_summary_label: snapshot.role_asset_summary_label,
session_id: snapshot.session_id,
profile_id: snapshot.profile_id,
can_resume: snapshot.can_resume,
can_enter_world: snapshot.can_enter_world,
blocker_count: snapshot.blocker_count,
publish_ready: snapshot.publish_ready,
})
}
pub(crate) fn map_custom_world_agent_session_snapshot(
snapshot: CustomWorldAgentSessionSnapshot,
) -> Result<CustomWorldAgentSessionRecord, SpacetimeClientError> {
let anchor_content = parse_json_value(
&snapshot.anchor_content_json,
"custom world agent anchor_content_json",
)?;
let creator_intent = parse_optional_json_value(
snapshot.creator_intent_json.as_deref(),
serde_json::json!({}),
"custom world agent creator_intent_json",
)?;
let creator_intent_readiness = parse_json_value(
&snapshot.creator_intent_readiness_json,
"custom world agent creator_intent_readiness_json",
)?;
let anchor_pack = parse_optional_json_value(
snapshot.anchor_pack_json.as_deref(),
serde_json::json!({}),
"custom world agent anchor_pack_json",
)?;
let lock_state = parse_optional_json_value(
snapshot.lock_state_json.as_deref(),
serde_json::json!({}),
"custom world agent lock_state_json",
)?;
let draft_profile = parse_optional_json_value(
snapshot.draft_profile_json.as_deref(),
serde_json::json!({}),
"custom world agent draft_profile_json",
)?;
let pending_clarifications = parse_json_array(
&snapshot.pending_clarifications_json,
"custom world agent pending_clarifications_json",
)?;
let suggested_actions = parse_json_array(
&snapshot.suggested_actions_json,
"custom world agent suggested_actions_json",
)?;
let recommended_replies = parse_json_string_array(
&snapshot.recommended_replies_json,
"custom world agent recommended_replies_json",
)?;
let quality_findings = parse_json_array(
&snapshot.quality_findings_json,
"custom world agent quality_findings_json",
)?;
let asset_coverage = parse_json_value(
&snapshot.asset_coverage_json,
"custom world agent asset_coverage_json",
)?;
let checkpoints_json = parse_json_array(
&snapshot.checkpoints_json,
"custom world agent checkpoints_json",
)?;
let checkpoints = checkpoints_json
.into_iter()
.map(map_custom_world_checkpoint_record)
.collect::<Result<Vec<_>, _>>()?;
let supported_actions = parse_supported_actions_json(&snapshot.supported_actions_json)?;
let publish_gate = snapshot
.publish_gate_json
.as_deref()
.map(parse_custom_world_publish_gate_record)
.transpose()?;
Ok(CustomWorldAgentSessionRecord {
session_id: snapshot.session_id,
seed_text: snapshot.seed_text,
current_turn: snapshot.current_turn,
anchor_content,
progress_percent: snapshot.progress_percent,
last_assistant_reply: snapshot.last_assistant_reply,
stage: map_rpg_agent_stage(snapshot.stage),
focus_card_id: snapshot.focus_card_id,
creator_intent,
creator_intent_readiness,
anchor_pack,
lock_state,
draft_profile,
messages: snapshot
.messages
.into_iter()
.map(map_custom_world_agent_message_snapshot)
.collect(),
draft_cards: snapshot
.draft_cards
.into_iter()
.map(map_custom_world_draft_card_snapshot)
.collect::<Result<Vec<_>, _>>()?,
pending_clarifications,
suggested_actions,
recommended_replies,
quality_findings,
asset_coverage,
checkpoints,
supported_actions,
publish_gate,
result_preview: snapshot
.result_preview_json
.as_deref()
.map(|value| parse_json_value(value, "custom world agent result_preview_json"))
.transpose()?,
updated_at: format_timestamp_micros(snapshot.updated_at_micros),
})
}
pub(crate) fn map_custom_world_agent_message_snapshot(
snapshot: CustomWorldAgentMessageSnapshot,
) -> CustomWorldAgentMessageRecord {
CustomWorldAgentMessageRecord {
message_id: snapshot.message_id,
role: format_rpg_agent_message_role(snapshot.role).to_string(),
kind: format_rpg_agent_message_kind(snapshot.kind).to_string(),
text: snapshot.text,
created_at: format_timestamp_micros(snapshot.created_at_micros),
related_operation_id: snapshot.related_operation_id,
}
}
pub(crate) fn map_custom_world_agent_operation_snapshot(
snapshot: CustomWorldAgentOperationSnapshot,
) -> CustomWorldAgentOperationRecord {
CustomWorldAgentOperationRecord {
operation_id: snapshot.operation_id,
operation_type: format_rpg_agent_operation_type(snapshot.operation_type).to_string(),
status: format_rpg_agent_operation_status(snapshot.status).to_string(),
phase_label: snapshot.phase_label,
phase_detail: snapshot.phase_detail,
progress: snapshot.progress,
error_message: snapshot.error_message,
started_at_micros: snapshot.created_at_micros,
updated_at_micros: snapshot.updated_at_micros,
}
}
pub(crate) fn map_custom_world_draft_card_snapshot(
snapshot: CustomWorldDraftCardSnapshot,
) -> Result<CustomWorldDraftCardRecord, SpacetimeClientError> {
Ok(CustomWorldDraftCardRecord {
card_id: snapshot.card_id,
kind: format_rpg_agent_draft_card_kind(snapshot.kind).to_string(),
title: snapshot.title,
subtitle: snapshot.subtitle,
summary: snapshot.summary,
status: format_rpg_agent_draft_card_status(snapshot.status).to_string(),
linked_ids: parse_json_string_array(
&snapshot.linked_ids_json,
"custom world draft_card linked_ids_json",
)?,
warning_count: snapshot.warning_count,
asset_status: snapshot
.asset_status
.map(format_custom_world_role_asset_status_back),
asset_status_label: snapshot.asset_status_label,
detail_payload: snapshot
.detail_payload_json
.as_deref()
.map(|value| parse_json_value(value, "custom world draft_card detail_payload_json"))
.transpose()?,
})
}
pub(crate) fn map_custom_world_draft_card_detail_snapshot(
snapshot: CustomWorldDraftCardDetailSnapshot,
) -> Result<CustomWorldDraftCardDetailRecord, SpacetimeClientError> {
Ok(CustomWorldDraftCardDetailRecord {
card_id: snapshot.card_id,
kind: format_rpg_agent_draft_card_kind(snapshot.kind).to_string(),
title: snapshot.title,
sections: snapshot
.sections
.into_iter()
.map(map_custom_world_draft_card_detail_section_snapshot)
.collect(),
linked_ids: parse_json_string_array(
&snapshot.linked_ids_json,
"custom world card detail linked_ids_json",
)?,
locked: snapshot.locked,
editable: snapshot.editable,
editable_section_ids: parse_json_string_array(
&snapshot.editable_section_ids_json,
"custom world card detail editable_section_ids_json",
)?,
warning_messages: parse_json_string_array(
&snapshot.warning_messages_json,
"custom world card detail warning_messages_json",
)?,
asset_status: snapshot
.asset_status
.map(format_custom_world_role_asset_status_back),
asset_status_label: snapshot.asset_status_label,
})
}
pub(crate) fn map_custom_world_draft_card_detail_section_snapshot(
snapshot: CustomWorldDraftCardDetailSectionSnapshot,
) -> CustomWorldDraftCardDetailSectionRecord {
CustomWorldDraftCardDetailSectionRecord {
section_id: snapshot.section_id,
label: snapshot.label,
value: snapshot.value,
}
}
pub(crate) fn map_big_fish_session_snapshot(
snapshot: BigFishSessionSnapshot,
) -> BigFishSessionRecord {
BigFishSessionRecord {
session_id: snapshot.session_id,
current_turn: snapshot.current_turn,
progress_percent: snapshot.progress_percent,
stage: format_big_fish_creation_stage(snapshot.stage).to_string(),
anchor_pack: map_big_fish_anchor_pack(snapshot.anchor_pack),
draft: snapshot.draft.map(map_big_fish_game_draft),
asset_slots: snapshot
.asset_slots
.into_iter()
.map(map_big_fish_asset_slot_snapshot)
.collect(),
asset_coverage: map_big_fish_asset_coverage(snapshot.asset_coverage),
messages: snapshot
.messages
.into_iter()
.map(map_big_fish_agent_message_snapshot)
.collect(),
last_assistant_reply: snapshot.last_assistant_reply,
publish_ready: snapshot.publish_ready,
updated_at: format_timestamp_micros(snapshot.updated_at_micros),
}
}
pub(crate) fn map_puzzle_agent_session_snapshot(
snapshot: DomainPuzzleAgentSessionSnapshot,
) -> PuzzleAgentSessionRecord {
PuzzleAgentSessionRecord {
session_id: snapshot.session_id,
seed_text: snapshot.seed_text,
current_turn: snapshot.current_turn,
progress_percent: snapshot.progress_percent,
stage: snapshot.stage.as_str().to_string(),
anchor_pack: map_puzzle_anchor_pack(snapshot.anchor_pack),
draft: snapshot.draft.map(map_puzzle_result_draft),
messages: snapshot
.messages
.into_iter()
.map(map_puzzle_agent_message_snapshot)
.collect(),
last_assistant_reply: snapshot.last_assistant_reply,
published_profile_id: snapshot.published_profile_id,
suggested_actions: snapshot
.suggested_actions
.into_iter()
.map(map_puzzle_suggested_action)
.collect(),
result_preview: snapshot.result_preview.map(map_puzzle_result_preview),
updated_at: format_timestamp_micros(snapshot.updated_at_micros),
}
}
pub(crate) fn map_puzzle_anchor_pack(snapshot: DomainPuzzleAnchorPack) -> PuzzleAnchorPackRecord {
PuzzleAnchorPackRecord {
theme_promise: map_puzzle_anchor_item(snapshot.theme_promise),
visual_subject: map_puzzle_anchor_item(snapshot.visual_subject),
visual_mood: map_puzzle_anchor_item(snapshot.visual_mood),
composition_hooks: map_puzzle_anchor_item(snapshot.composition_hooks),
tags_and_forbidden: map_puzzle_anchor_item(snapshot.tags_and_forbidden),
}
}
pub(crate) fn map_puzzle_anchor_item(snapshot: DomainPuzzleAnchorItem) -> PuzzleAnchorItemRecord {
PuzzleAnchorItemRecord {
key: snapshot.key,
label: snapshot.label,
value: snapshot.value,
status: snapshot.status.as_str().to_string(),
}
}
pub(crate) fn map_puzzle_result_draft(
snapshot: DomainPuzzleResultDraft,
) -> PuzzleResultDraftRecord {
PuzzleResultDraftRecord {
work_title: snapshot.work_title,
work_description: snapshot.work_description,
level_name: snapshot.level_name,
summary: snapshot.summary,
theme_tags: snapshot.theme_tags,
forbidden_directives: snapshot.forbidden_directives,
creator_intent: snapshot.creator_intent.map(map_puzzle_creator_intent),
anchor_pack: map_puzzle_anchor_pack(snapshot.anchor_pack),
candidates: snapshot
.candidates
.into_iter()
.map(map_puzzle_generated_image_candidate)
.collect(),
selected_candidate_id: snapshot.selected_candidate_id,
cover_image_src: snapshot.cover_image_src,
cover_asset_id: snapshot.cover_asset_id,
generation_status: snapshot.generation_status,
levels: snapshot
.levels
.into_iter()
.map(map_puzzle_draft_level)
.collect(),
form_draft: snapshot.form_draft.map(map_puzzle_form_draft),
}
}
pub(crate) fn map_puzzle_form_draft(
snapshot: module_puzzle::PuzzleFormDraft,
) -> PuzzleFormDraftRecord {
PuzzleFormDraftRecord {
work_title: snapshot.work_title,
work_description: snapshot.work_description,
picture_description: snapshot.picture_description,
}
}
pub(crate) fn map_puzzle_draft_level(snapshot: DomainPuzzleDraftLevel) -> PuzzleDraftLevelRecord {
PuzzleDraftLevelRecord {
level_id: snapshot.level_id,
level_name: snapshot.level_name,
picture_description: snapshot.picture_description,
picture_reference: snapshot.picture_reference,
ui_background_prompt: snapshot.ui_background_prompt,
ui_background_image_src: snapshot.ui_background_image_src,
ui_background_image_object_key: snapshot.ui_background_image_object_key,
background_music: snapshot.background_music.map(map_puzzle_audio_asset),
candidates: snapshot
.candidates
.into_iter()
.map(map_puzzle_generated_image_candidate)
.collect(),
selected_candidate_id: snapshot.selected_candidate_id,
cover_image_src: snapshot.cover_image_src,
cover_asset_id: snapshot.cover_asset_id,
generation_status: snapshot.generation_status,
}
}
pub(crate) fn map_puzzle_audio_asset(
asset: module_puzzle::PuzzleAudioAsset,
) -> PuzzleAudioAssetRecord {
PuzzleAudioAssetRecord {
task_id: asset.task_id,
provider: asset.provider,
asset_object_id: asset.asset_object_id,
asset_kind: asset.asset_kind,
audio_src: asset.audio_src,
prompt: asset.prompt,
title: asset.title,
updated_at: asset.updated_at,
}
}
pub(crate) fn map_puzzle_creator_intent(
snapshot: DomainPuzzleCreatorIntent,
) -> PuzzleCreatorIntentRecord {
PuzzleCreatorIntentRecord {
source_mode: snapshot.source_mode,
raw_messages_summary: snapshot.raw_messages_summary,
theme_promise: snapshot.theme_promise,
visual_subject: snapshot.visual_subject,
visual_mood: snapshot.visual_mood,
composition_hooks: snapshot.composition_hooks,
theme_tags: snapshot.theme_tags,
forbidden_directives: snapshot.forbidden_directives,
}
}
pub(crate) fn map_puzzle_generated_image_candidate(
snapshot: DomainPuzzleGeneratedImageCandidate,
) -> PuzzleGeneratedImageCandidateRecord {
PuzzleGeneratedImageCandidateRecord {
candidate_id: snapshot.candidate_id,
image_src: snapshot.image_src,
asset_id: snapshot.asset_id,
prompt: snapshot.prompt,
actual_prompt: snapshot.actual_prompt,
source_type: snapshot.source_type,
selected: snapshot.selected,
}
}
pub(crate) fn map_puzzle_agent_message_snapshot(
snapshot: DomainPuzzleAgentMessageSnapshot,
) -> PuzzleAgentMessageRecord {
PuzzleAgentMessageRecord {
message_id: snapshot.message_id,
role: snapshot.role.as_str().to_string(),
kind: snapshot.kind.as_str().to_string(),
text: snapshot.text,
created_at: format_timestamp_micros(snapshot.created_at_micros),
}
}
fn map_match3d_agent_session_snapshot(
snapshot: Match3DAgentSessionJsonRecord,
) -> Match3DAgentSessionRecord {
let config = map_match3d_creator_config(snapshot.config);
Match3DAgentSessionRecord {
session_id: snapshot.session_id,
current_turn: snapshot.current_turn,
progress_percent: snapshot.progress_percent,
stage: normalize_match3d_stage(&snapshot.stage).to_string(),
anchor_pack: build_match3d_anchor_pack(&config),
draft: snapshot
.draft
.map(|draft| map_match3d_result_draft(draft, config.reference_image_src.clone())),
config: Some(config),
messages: snapshot
.messages
.into_iter()
.map(map_match3d_agent_message_snapshot)
.collect(),
last_assistant_reply: empty_string_to_none(snapshot.last_assistant_reply),
published_profile_id: snapshot.published_profile_id,
updated_at: format_timestamp_micros(snapshot.updated_at_micros),
}
}
fn map_match3d_creator_config(
snapshot: Match3DCreatorConfigJsonRecord,
) -> Match3DCreatorConfigRecord {
Match3DCreatorConfigRecord {
theme_text: snapshot.theme_text,
reference_image_src: snapshot.reference_image_src,
clear_count: snapshot.clear_count,
difficulty: snapshot.difficulty,
asset_style_id: snapshot.asset_style_id,
asset_style_label: snapshot.asset_style_label,
asset_style_prompt: snapshot.asset_style_prompt,
generate_click_sound: snapshot.generate_click_sound,
}
}
fn map_match3d_result_draft(
snapshot: Match3DDraftJsonRecord,
reference_image_src: Option<String>,
) -> Match3DResultDraftRecord {
Match3DResultDraftRecord {
profile_id: snapshot.profile_id,
game_name: snapshot.game_name,
theme_text: snapshot.theme_text,
summary_text: snapshot.summary_text,
tags: snapshot.tags,
cover_image_src: None,
reference_image_src,
clear_count: snapshot.clear_count,
difficulty: snapshot.difficulty,
total_item_count: snapshot.clear_count.saturating_mul(3),
publish_ready: false,
blockers: Vec::new(),
}
}
fn map_match3d_agent_message_snapshot(
snapshot: Match3DAgentMessageJsonRecord,
) -> Match3DAgentMessageRecord {
Match3DAgentMessageRecord {
message_id: snapshot.message_id,
role: snapshot.role,
kind: normalize_match3d_message_kind(&snapshot.kind).to_string(),
text: snapshot.text,
created_at: format_timestamp_micros(snapshot.created_at_micros),
}
}
fn map_match3d_work_snapshot(snapshot: Match3DWorkJsonRecord) -> Match3DWorkProfileRecord {
let config = map_match3d_creator_config(snapshot.config);
Match3DWorkProfileRecord {
work_id: snapshot.profile_id.clone(),
profile_id: snapshot.profile_id,
owner_user_id: snapshot.owner_user_id,
source_session_id: empty_string_to_none(snapshot.source_session_id),
author_display_name: snapshot.author_display_name,
game_name: snapshot.game_name,
theme_text: snapshot.theme_text,
summary: snapshot.summary_text,
tags: snapshot.tags,
cover_image_src: empty_string_to_none(snapshot.cover_image_src),
cover_asset_id: empty_string_to_none(snapshot.cover_asset_id),
reference_image_src: config.reference_image_src,
clear_count: snapshot.clear_count,
difficulty: snapshot.difficulty,
publication_status: normalize_match3d_publication_status(&snapshot.publication_status)
.to_string(),
play_count: snapshot.play_count,
updated_at: format_timestamp_micros(snapshot.updated_at_micros),
published_at: snapshot.published_at_micros.map(format_timestamp_micros),
publish_ready: snapshot.publish_ready,
generated_item_assets_json: snapshot.generated_item_assets_json,
}
}
fn map_match3d_run_json(run_json: String) -> Result<Match3DRunRecord, SpacetimeClientError> {
let run = serde_json::from_str::<Match3DRunJsonRecord>(&run_json).map_err(|error| {
SpacetimeClientError::Runtime(format!("match3d run_json 非法: {error}"))
})?;
Ok(map_match3d_run_snapshot(run))
}
fn map_match3d_run_snapshot(snapshot: Match3DRunJsonRecord) -> Match3DRunRecord {
let tray_slots = snapshot
.tray_slots
.into_iter()
.map(map_match3d_tray_slot_snapshot)
.collect::<Vec<_>>();
let items = snapshot
.items
.into_iter()
.map(|item| {
let tray_slot_index = tray_slots
.iter()
.find(|slot| {
slot.item_instance_id.as_deref() == Some(item.item_instance_id.as_str())
})
.map(|slot| slot.slot_index);
map_match3d_item_snapshot(item, tray_slot_index)
})
.collect();
Match3DRunRecord {
run_id: snapshot.run_id,
profile_id: snapshot.profile_id,
owner_user_id: String::new(),
status: snapshot.status,
snapshot_version: u64::from(snapshot.snapshot_version),
started_at_ms: i64_to_u64_ms(snapshot.started_at_ms),
duration_limit_ms: i64_to_u64_ms(snapshot.duration_limit_ms),
server_now_ms: Some(i64_to_u64_ms(snapshot.server_now_ms)),
remaining_ms: i64_to_u64_ms(snapshot.remaining_ms),
clear_count: snapshot.clear_count,
total_item_count: snapshot.total_item_count,
cleared_item_count: snapshot.cleared_item_count,
items,
tray_slots,
failure_reason: snapshot.failure_reason,
last_confirmed_action_id: None,
}
}
fn map_match3d_item_snapshot(
snapshot: Match3DItemJsonRecord,
tray_slot_index: Option<u32>,
) -> Match3DItemSnapshotRecord {
Match3DItemSnapshotRecord {
item_instance_id: snapshot.item_instance_id,
item_type_id: snapshot.item_type_id,
visual_key: snapshot.visual_key,
x: snapshot.x,
y: snapshot.y,
radius: snapshot.radius,
layer: snapshot.layer,
state: snapshot.state,
clickable: snapshot.clickable,
tray_slot_index,
}
}
fn map_match3d_tray_slot_snapshot(snapshot: Match3DTraySlotJsonRecord) -> Match3DTraySlotRecord {
Match3DTraySlotRecord {
slot_index: snapshot.slot_index,
item_instance_id: snapshot.item_instance_id,
item_type_id: snapshot.item_type_id,
visual_key: snapshot.visual_key,
}
}
fn build_match3d_anchor_pack(config: &Match3DCreatorConfigRecord) -> Match3DAnchorPackRecord {
let clear_count = config.clear_count.to_string();
let difficulty = config.difficulty.to_string();
Match3DAnchorPackRecord {
theme: build_match3d_anchor_item("theme", "题材主题", config.theme_text.as_str()),
clear_count: build_match3d_anchor_item("clearCount", "需要消除次数", clear_count.as_str()),
difficulty: build_match3d_anchor_item("difficulty", "难度", difficulty.as_str()),
}
}
fn build_match3d_anchor_item(key: &str, label: &str, value: &str) -> Match3DAnchorItemRecord {
Match3DAnchorItemRecord {
key: key.to_string(),
label: label.to_string(),
value: value.to_string(),
status: if value.trim().is_empty() {
"missing"
} else {
"confirmed"
}
.to_string(),
}
}
fn map_square_hole_agent_session_snapshot(
snapshot: SquareHoleAgentSessionJsonRecord,
) -> SquareHoleAgentSessionRecord {
let config = map_square_hole_creator_config(snapshot.config);
SquareHoleAgentSessionRecord {
session_id: snapshot.session_id,
current_turn: snapshot.current_turn,
progress_percent: snapshot.progress_percent,
stage: normalize_square_hole_stage(&snapshot.stage).to_string(),
anchor_pack: build_square_hole_anchor_pack(&config),
config,
draft: snapshot.draft.map(map_square_hole_result_draft),
messages: snapshot
.messages
.into_iter()
.map(map_square_hole_agent_message_snapshot)
.collect(),
last_assistant_reply: empty_string_to_none(snapshot.last_assistant_reply),
published_profile_id: snapshot.published_profile_id,
updated_at: format_timestamp_micros(snapshot.updated_at_micros),
}
}
fn map_square_hole_creator_config(
snapshot: SquareHoleCreatorConfigJsonRecord,
) -> SquareHoleCreatorConfigRecord {
SquareHoleCreatorConfigRecord {
theme_text: snapshot.theme_text,
twist_rule: snapshot.twist_rule,
shape_count: snapshot.shape_count,
difficulty: snapshot.difficulty,
shape_options: snapshot
.shape_options
.into_iter()
.map(map_square_hole_shape_option)
.collect(),
hole_options: snapshot
.hole_options
.into_iter()
.map(map_square_hole_hole_option)
.collect(),
background_prompt: snapshot.background_prompt,
cover_image_src: empty_string_to_none(snapshot.cover_image_src),
background_image_src: empty_string_to_none(snapshot.background_image_src),
}
}
fn map_square_hole_result_draft(
snapshot: SquareHoleDraftJsonRecord,
) -> SquareHoleResultDraftRecord {
SquareHoleResultDraftRecord {
profile_id: snapshot.profile_id,
game_name: snapshot.game_name,
theme_text: snapshot.theme_text,
twist_rule: snapshot.twist_rule,
summary: snapshot.summary_text,
tags: snapshot.tags,
cover_image_src: empty_string_to_none(snapshot.cover_image_src),
background_prompt: snapshot.background_prompt,
background_image_src: empty_string_to_none(snapshot.background_image_src),
shape_options: snapshot
.shape_options
.into_iter()
.map(map_square_hole_shape_option)
.collect(),
hole_options: snapshot
.hole_options
.into_iter()
.map(map_square_hole_hole_option)
.collect(),
shape_count: snapshot.shape_count,
difficulty: snapshot.difficulty,
publish_ready: false,
blockers: Vec::new(),
}
}
fn map_square_hole_agent_message_snapshot(
snapshot: SquareHoleAgentMessageJsonRecord,
) -> SquareHoleAgentMessageRecord {
SquareHoleAgentMessageRecord {
id: snapshot.message_id,
role: snapshot.role,
kind: normalize_square_hole_message_kind(&snapshot.kind).to_string(),
text: snapshot.text,
created_at: format_timestamp_micros(snapshot.created_at_micros),
}
}
fn map_square_hole_work_snapshot(
snapshot: SquareHoleWorkJsonRecord,
) -> SquareHoleWorkProfileRecord {
SquareHoleWorkProfileRecord {
work_id: snapshot.work_id,
profile_id: snapshot.profile_id,
owner_user_id: snapshot.owner_user_id,
source_session_id: empty_string_to_none(snapshot.source_session_id),
author_display_name: snapshot.author_display_name,
game_name: snapshot.game_name,
theme_text: snapshot.theme_text,
twist_rule: snapshot.twist_rule,
summary: snapshot.summary_text,
tags: snapshot.tags,
cover_image_src: empty_string_to_none(snapshot.cover_image_src),
background_prompt: snapshot.background_prompt,
background_image_src: empty_string_to_none(snapshot.background_image_src),
shape_options: snapshot
.shape_options
.into_iter()
.map(map_square_hole_shape_option)
.collect(),
hole_options: snapshot
.hole_options
.into_iter()
.map(map_square_hole_hole_option)
.collect(),
shape_count: snapshot.shape_count,
difficulty: snapshot.difficulty,
publication_status: normalize_square_hole_publication_status(&snapshot.publication_status)
.to_string(),
play_count: snapshot.play_count,
updated_at: format_timestamp_micros(snapshot.updated_at_micros),
published_at: snapshot.published_at_micros.map(format_timestamp_micros),
publish_ready: snapshot.publish_ready,
}
}
fn map_square_hole_run_json(run_json: String) -> Result<SquareHoleRunRecord, SpacetimeClientError> {
let run = serde_json::from_str::<SquareHoleRunJsonRecord>(&run_json).map_err(|error| {
SpacetimeClientError::Runtime(format!("square hole run_json 非法: {error}"))
})?;
Ok(map_square_hole_run_snapshot(run))
}
fn map_square_hole_run_snapshot(snapshot: SquareHoleRunJsonRecord) -> SquareHoleRunRecord {
SquareHoleRunRecord {
run_id: snapshot.run_id,
profile_id: snapshot.profile_id,
owner_user_id: snapshot.owner_user_id,
status: normalize_square_hole_run_status(&snapshot.status).to_string(),
snapshot_version: snapshot.snapshot_version,
started_at_ms: i64_to_u64_ms(snapshot.started_at_ms),
duration_limit_ms: i64_to_u64_ms(snapshot.duration_limit_ms),
server_now_ms: Some(i64_to_u64_ms(snapshot.server_now_ms)),
remaining_ms: i64_to_u64_ms(snapshot.remaining_ms),
total_shape_count: snapshot.total_shape_count,
completed_shape_count: snapshot.completed_shape_count,
combo: snapshot.combo,
best_combo: snapshot.best_combo,
score: snapshot.score,
rule_label: snapshot.rule_label,
background_image_src: empty_string_to_none(snapshot.background_image_src),
current_shape: snapshot.current_shape.map(map_square_hole_shape_snapshot),
holes: snapshot
.holes
.into_iter()
.map(map_square_hole_hole_snapshot)
.collect(),
last_feedback: snapshot
.last_feedback
.map(map_square_hole_feedback_snapshot),
last_confirmed_action_id: None,
}
}
fn map_square_hole_shape_snapshot(
snapshot: SquareHoleShapeJsonRecord,
) -> SquareHoleShapeSnapshotRecord {
SquareHoleShapeSnapshotRecord {
shape_id: snapshot.shape_id,
shape_kind: snapshot.shape_kind,
label: snapshot.label,
target_hole_id: snapshot.target_hole_id,
color: snapshot.color,
image_src: empty_string_to_none(snapshot.image_src),
}
}
fn map_square_hole_hole_snapshot(
snapshot: SquareHoleHoleJsonRecord,
) -> SquareHoleHoleSnapshotRecord {
SquareHoleHoleSnapshotRecord {
hole_id: snapshot.hole_id,
hole_kind: snapshot.hole_kind,
label: snapshot.label,
x: snapshot.x,
y: snapshot.y,
image_src: empty_string_to_none(snapshot.image_src),
}
}
fn map_square_hole_shape_option(
snapshot: SquareHoleShapeOptionJsonRecord,
) -> SquareHoleShapeOptionRecord {
SquareHoleShapeOptionRecord {
option_id: snapshot.option_id,
shape_kind: snapshot.shape_kind,
label: snapshot.label,
target_hole_id: snapshot.target_hole_id,
image_prompt: snapshot.image_prompt,
image_src: empty_string_to_none(snapshot.image_src),
}
}
fn map_square_hole_hole_option(
snapshot: SquareHoleHoleOptionJsonRecord,
) -> SquareHoleHoleOptionRecord {
SquareHoleHoleOptionRecord {
hole_id: snapshot.hole_id,
hole_kind: snapshot.hole_kind,
label: snapshot.label,
image_prompt: snapshot.image_prompt,
image_src: empty_string_to_none(snapshot.image_src),
}
}
fn map_square_hole_feedback_snapshot(
snapshot: SquareHoleDropFeedbackJsonRecord,
) -> SquareHoleDropFeedbackRecord {
SquareHoleDropFeedbackRecord {
accepted: snapshot.accepted,
reject_reason: snapshot
.reject_reason
.map(|value| normalize_square_hole_reject_reason(&value).to_string()),
message: snapshot.message,
}
}
fn build_square_hole_anchor_pack(
config: &SquareHoleCreatorConfigRecord,
) -> SquareHoleAnchorPackRecord {
let shape_count = config.shape_count.to_string();
let difficulty = config.difficulty.to_string();
SquareHoleAnchorPackRecord {
theme: build_square_hole_anchor_item("theme", "题材主题", config.theme_text.as_str()),
twist_rule: build_square_hole_anchor_item(
"twistRule",
"反差规则",
config.twist_rule.as_str(),
),
shape_count: build_square_hole_anchor_item("shapeCount", "形状数量", shape_count.as_str()),
difficulty: build_square_hole_anchor_item("difficulty", "难度", difficulty.as_str()),
}
}
fn build_square_hole_anchor_item(
key: &str,
label: &str,
value: &str,
) -> SquareHoleAnchorItemRecord {
SquareHoleAnchorItemRecord {
key: key.to_string(),
label: label.to_string(),
value: value.to_string(),
status: if value.trim().is_empty() {
"missing"
} else {
"confirmed"
}
.to_string(),
}
}
fn map_visual_novel_agent_session_snapshot(
snapshot: VisualNovelAgentSessionJsonRecord,
) -> VisualNovelAgentSessionRecord {
VisualNovelAgentSessionRecord {
session_id: snapshot.session_id,
owner_user_id: snapshot.owner_user_id,
source_mode: snapshot.source_mode,
status: snapshot.status,
seed_text: snapshot.seed_text,
source_asset_ids: snapshot.source_asset_ids,
current_turn: snapshot.current_turn,
progress_percent: snapshot.progress_percent,
messages: snapshot
.messages
.into_iter()
.map(map_visual_novel_agent_message)
.collect(),
draft: snapshot.draft,
pending_action: snapshot.pending_action,
last_assistant_reply: snapshot.last_assistant_reply,
published_profile_id: snapshot.published_profile_id,
created_at: format_timestamp_micros(snapshot.created_at_micros),
updated_at: format_timestamp_micros(snapshot.updated_at_micros),
}
}
fn map_visual_novel_agent_message(
snapshot: VisualNovelAgentMessageJsonRecord,
) -> VisualNovelAgentMessageRecord {
VisualNovelAgentMessageRecord {
message_id: snapshot.message_id,
session_id: snapshot.session_id,
role: snapshot.role,
kind: snapshot.kind,
text: snapshot.text,
created_at: format_timestamp_micros(snapshot.created_at_micros),
}
}
fn map_visual_novel_work_snapshot(
snapshot: VisualNovelWorkJsonRecord,
) -> VisualNovelWorkProfileRecord {
VisualNovelWorkProfileRecord {
work_id: snapshot.work_id,
profile_id: snapshot.profile_id,
owner_user_id: snapshot.owner_user_id,
source_session_id: snapshot.source_session_id,
author_display_name: snapshot.author_display_name,
work_title: snapshot.work_title,
work_description: snapshot.work_description,
tags: snapshot.tags,
cover_image_src: snapshot.cover_image_src,
source_asset_ids: snapshot.source_asset_ids,
draft: snapshot.draft,
publication_status: snapshot.publication_status,
publish_ready: snapshot.publish_ready,
play_count: snapshot.play_count,
created_at: format_timestamp_micros(snapshot.created_at_micros),
updated_at: format_timestamp_micros(snapshot.updated_at_micros),
published_at: snapshot.published_at_micros.map(format_timestamp_micros),
}
}
fn map_visual_novel_run_snapshot(snapshot: VisualNovelRunJsonRecord) -> VisualNovelRunRecord {
VisualNovelRunRecord {
run_id: snapshot.run_id,
owner_user_id: snapshot.owner_user_id,
profile_id: snapshot.profile_id,
mode: snapshot.mode,
status: snapshot.status,
current_scene_id: snapshot.current_scene_id,
current_phase_id: snapshot.current_phase_id,
visible_character_ids: snapshot.visible_character_ids,
flags: snapshot.flags,
metrics: snapshot.metrics,
history: snapshot
.history
.into_iter()
.map(map_visual_novel_history_entry)
.collect(),
available_choices: snapshot.available_choices,
text_mode_enabled: snapshot.text_mode_enabled,
created_at: format_timestamp_micros(snapshot.created_at_micros),
updated_at: format_timestamp_micros(snapshot.updated_at_micros),
}
}
fn map_visual_novel_history_entry(
snapshot: VisualNovelHistoryEntryJsonRecord,
) -> VisualNovelHistoryEntryRecord {
VisualNovelHistoryEntryRecord {
entry_id: snapshot.entry_id,
run_id: snapshot.run_id,
owner_user_id: snapshot.owner_user_id,
profile_id: snapshot.profile_id,
turn_index: snapshot.turn_index,
source: snapshot.source,
action_text: snapshot.action_text,
steps: snapshot.steps,
snapshot_before_hash: snapshot.snapshot_before_hash,
snapshot_after_hash: snapshot.snapshot_after_hash,
created_at: format_timestamp_micros(snapshot.created_at_micros),
}
}
fn map_visual_novel_runtime_event(
snapshot: VisualNovelRuntimeEventJsonRecord,
) -> VisualNovelRuntimeEventRecord {
VisualNovelRuntimeEventRecord {
event_id: snapshot.event_id,
run_id: snapshot.run_id,
owner_user_id: snapshot.owner_user_id,
profile_id: snapshot.profile_id,
event_kind: snapshot.event_kind,
client_event_id: snapshot.client_event_id,
history_entry_id: snapshot.history_entry_id,
payload: snapshot.payload,
occurred_at: format_timestamp_micros(snapshot.occurred_at_micros),
}
}
fn normalize_match3d_stage(value: &str) -> &str {
match value {
"Collecting" | "collecting" | "collecting_config" => "collecting_config",
"ReadyToCompile" | "ready_to_compile" => "ready_to_compile",
"DraftCompiled" | "draft_compiled" | "draft_ready" => "draft_ready",
"Published" | "published" => "published",
_ => value,
}
}
fn normalize_match3d_publication_status(value: &str) -> &str {
match value {
"Draft" | "draft" => "draft",
"Published" | "published" => "published",
_ => value,
}
}
fn normalize_match3d_message_kind(value: &str) -> &str {
match value {
"text" => "chat",
_ => value,
}
}
fn normalize_square_hole_stage(value: &str) -> &str {
match value {
"Collecting" | "CollectingConfig" | "collecting" | "collecting_config" => {
"collecting_config"
}
"ReadyToCompile" | "ready_to_compile" => "ready_to_compile",
"DraftCompiled" | "DraftReady" | "draft_compiled" | "draft_ready" => "draft_ready",
"Published" | "published" => "published",
_ => value,
}
}
fn normalize_square_hole_publication_status(value: &str) -> &str {
match value {
"Draft" | "draft" => "draft",
"Published" | "published" => "published",
_ => value,
}
}
fn normalize_square_hole_run_status(value: &str) -> &str {
match value {
"Running" | "running" => "running",
"Won" | "won" => "won",
"Failed" | "failed" => "failed",
"Stopped" | "stopped" => "stopped",
_ => value,
}
}
fn normalize_square_hole_message_kind(value: &str) -> &str {
match value {
"text" => "chat",
_ => value,
}
}
fn normalize_square_hole_reject_reason(value: &str) -> &str {
match value {
"RunNotActive" | "run_not_active" => "run_not_active",
"SnapshotVersionMismatch" | "snapshot_version_mismatch" => "snapshot_version_mismatch",
"HoleNotFound" | "hole_not_found" => "hole_not_found",
"Incompatible" | "incompatible" => "incompatible",
"TimeUp" | "time_up" => "time_up",
_ => value,
}
}
fn empty_string_to_none(value: String) -> Option<String> {
let trimmed = value.trim();
if trimmed.is_empty() {
None
} else {
Some(trimmed.to_string())
}
}
fn i64_to_u64_ms(value: i64) -> u64 {
value.max(0) as u64
}
pub(crate) fn map_puzzle_suggested_action(
snapshot: DomainPuzzleAgentSuggestedAction,
) -> PuzzleAgentSuggestedActionRecord {
PuzzleAgentSuggestedActionRecord {
action_id: snapshot.id,
action_type: snapshot.action_type,
label: snapshot.label,
}
}
pub(crate) fn map_puzzle_result_preview(
snapshot: DomainPuzzleResultPreviewEnvelope,
) -> PuzzleResultPreviewRecord {
PuzzleResultPreviewRecord {
draft: map_puzzle_result_draft(snapshot.draft),
blockers: snapshot
.blockers
.into_iter()
.map(map_puzzle_result_preview_blocker)
.collect(),
quality_findings: snapshot
.quality_findings
.into_iter()
.map(map_puzzle_result_preview_finding)
.collect(),
publish_ready: snapshot.publish_ready,
}
}
pub(crate) fn map_puzzle_result_preview_blocker(
snapshot: DomainPuzzleResultPreviewBlocker,
) -> PuzzleResultPreviewBlockerRecord {
PuzzleResultPreviewBlockerRecord {
blocker_id: snapshot.id,
code: snapshot.code,
message: snapshot.message,
}
}
pub(crate) fn map_puzzle_result_preview_finding(
snapshot: DomainPuzzleResultPreviewFinding,
) -> PuzzleResultPreviewFindingRecord {
PuzzleResultPreviewFindingRecord {
finding_id: snapshot.id,
severity: snapshot.severity,
code: snapshot.code,
message: snapshot.message,
}
}
pub(crate) fn map_puzzle_work_profile(
snapshot: DomainPuzzleWorkProfile,
) -> PuzzleWorkProfileRecord {
PuzzleWorkProfileRecord {
work_id: snapshot.work_id,
profile_id: snapshot.profile_id,
owner_user_id: snapshot.owner_user_id,
source_session_id: snapshot.source_session_id,
author_display_name: snapshot.author_display_name,
work_title: snapshot.work_title,
work_description: snapshot.work_description,
level_name: snapshot.level_name,
summary: snapshot.summary,
theme_tags: snapshot.theme_tags,
cover_image_src: snapshot.cover_image_src,
cover_asset_id: snapshot.cover_asset_id,
publication_status: snapshot.publication_status.as_str().to_string(),
updated_at: format_timestamp_micros(snapshot.updated_at_micros),
published_at: snapshot.published_at_micros.map(format_timestamp_micros),
play_count: snapshot.play_count,
remix_count: snapshot.remix_count,
like_count: snapshot.like_count,
recent_play_count_7d: snapshot.recent_play_count_7d,
point_incentive_total_half_points: snapshot.point_incentive_total_half_points,
point_incentive_claimed_points: snapshot.point_incentive_claimed_points,
publish_ready: snapshot.publish_ready,
anchor_pack: map_puzzle_anchor_pack(snapshot.anchor_pack),
levels: snapshot
.levels
.into_iter()
.map(map_puzzle_draft_level)
.collect(),
}
}
pub(crate) fn map_puzzle_run_snapshot(snapshot: DomainPuzzleRunSnapshot) -> PuzzleRunRecord {
PuzzleRunRecord {
run_id: snapshot.run_id,
entry_profile_id: snapshot.entry_profile_id,
cleared_level_count: snapshot.cleared_level_count,
current_level_index: snapshot.current_level_index,
current_grid_size: snapshot.current_grid_size,
played_profile_ids: snapshot.played_profile_ids,
previous_level_tags: snapshot.previous_level_tags,
current_level: snapshot
.current_level
.map(map_puzzle_runtime_level_snapshot),
recommended_next_profile_id: snapshot.recommended_next_profile_id,
next_level_mode: snapshot.next_level_mode,
next_level_profile_id: snapshot.next_level_profile_id,
next_level_id: snapshot.next_level_id,
recommended_next_works: snapshot
.recommended_next_works
.into_iter()
.map(map_puzzle_recommended_next_work)
.collect(),
leaderboard_entries: snapshot
.leaderboard_entries
.into_iter()
.map(map_puzzle_leaderboard_entry)
.collect(),
}
}
fn map_puzzle_recommended_next_work(
snapshot: module_puzzle::PuzzleRecommendedNextWork,
) -> PuzzleRecommendedNextWorkRecord {
PuzzleRecommendedNextWorkRecord {
profile_id: snapshot.profile_id,
level_name: snapshot.level_name,
author_display_name: snapshot.author_display_name,
theme_tags: snapshot.theme_tags,
cover_image_src: snapshot.cover_image_src,
similarity_score: snapshot.similarity_score,
}
}
pub(crate) fn map_puzzle_runtime_level_snapshot(
snapshot: DomainPuzzleRuntimeLevelSnapshot,
) -> PuzzleRuntimeLevelRecord {
let started_at_ms = if snapshot.started_at_ms == 0 {
// 中文注释:旧 run_json 没有计时字段时只补一个可用开始时间,其余限时字段保持旧默认值。
current_unix_millis_for_legacy_puzzle_snapshot()
} else {
snapshot.started_at_ms
};
PuzzleRuntimeLevelRecord {
run_id: snapshot.run_id,
level_index: snapshot.level_index,
level_id: snapshot.level_id,
grid_size: snapshot.grid_size,
profile_id: snapshot.profile_id,
level_name: snapshot.level_name,
author_display_name: snapshot.author_display_name,
theme_tags: snapshot.theme_tags,
cover_image_src: snapshot.cover_image_src,
ui_background_image_src: snapshot.ui_background_image_src,
ui_background_image_object_key: snapshot.ui_background_image_object_key,
background_music: snapshot.background_music.map(map_puzzle_audio_asset),
board: map_puzzle_board_snapshot(snapshot.board),
status: snapshot.status.as_str().to_string(),
started_at_ms,
cleared_at_ms: snapshot.cleared_at_ms,
elapsed_ms: snapshot.elapsed_ms,
time_limit_ms: snapshot.time_limit_ms,
remaining_ms: snapshot.remaining_ms,
paused_accumulated_ms: snapshot.paused_accumulated_ms,
pause_started_at_ms: snapshot.pause_started_at_ms,
freeze_accumulated_ms: snapshot.freeze_accumulated_ms,
freeze_started_at_ms: snapshot.freeze_started_at_ms,
freeze_until_ms: snapshot.freeze_until_ms,
leaderboard_entries: snapshot
.leaderboard_entries
.into_iter()
.map(map_puzzle_leaderboard_entry)
.collect(),
}
}
fn current_unix_millis_for_legacy_puzzle_snapshot() -> u64 {
std::time::SystemTime::now()
.duration_since(std::time::UNIX_EPOCH)
.map(|duration| duration.as_millis().min(u128::from(u64::MAX)) as u64)
.unwrap_or(1)
}
pub(crate) fn map_puzzle_leaderboard_entry(
snapshot: module_puzzle::PuzzleLeaderboardEntry,
) -> PuzzleLeaderboardEntryRecord {
PuzzleLeaderboardEntryRecord {
rank: snapshot.rank,
nickname: snapshot.nickname,
elapsed_ms: snapshot.elapsed_ms,
visible_tags: snapshot.visible_tags,
is_current_player: snapshot.is_current_player,
}
}
pub(crate) fn map_puzzle_board_snapshot(snapshot: DomainPuzzleBoardSnapshot) -> PuzzleBoardRecord {
PuzzleBoardRecord {
rows: snapshot.rows,
cols: snapshot.cols,
pieces: snapshot
.pieces
.into_iter()
.map(map_puzzle_piece_state)
.collect(),
merged_groups: snapshot
.merged_groups
.into_iter()
.map(map_puzzle_merged_group_state)
.collect(),
selected_piece_id: snapshot.selected_piece_id,
all_tiles_resolved: snapshot.all_tiles_resolved,
}
}
pub(crate) fn map_puzzle_piece_state(snapshot: DomainPuzzlePieceState) -> PuzzlePieceStateRecord {
PuzzlePieceStateRecord {
piece_id: snapshot.piece_id,
correct_row: snapshot.correct_row,
correct_col: snapshot.correct_col,
current_row: snapshot.current_row,
current_col: snapshot.current_col,
merged_group_id: snapshot.merged_group_id,
}
}
pub(crate) fn map_puzzle_merged_group_state(
snapshot: DomainPuzzleMergedGroupState,
) -> PuzzleMergedGroupRecord {
PuzzleMergedGroupRecord {
group_id: snapshot.group_id,
piece_ids: snapshot.piece_ids,
occupied_cells: snapshot
.occupied_cells
.into_iter()
.map(map_puzzle_cell_position)
.collect(),
}
}
pub(crate) fn map_puzzle_cell_position(
snapshot: DomainPuzzleCellPosition,
) -> PuzzleCellPositionRecord {
PuzzleCellPositionRecord {
row: snapshot.row,
col: snapshot.col,
}
}
pub(crate) fn map_big_fish_anchor_pack(snapshot: BigFishAnchorPack) -> BigFishAnchorPackRecord {
BigFishAnchorPackRecord {
gameplay_promise: map_big_fish_anchor_item(snapshot.gameplay_promise),
ecology_visual_theme: map_big_fish_anchor_item(snapshot.ecology_visual_theme),
growth_ladder: map_big_fish_anchor_item(snapshot.growth_ladder),
risk_tempo: map_big_fish_anchor_item(snapshot.risk_tempo),
}
}
pub(crate) fn map_big_fish_anchor_item(snapshot: BigFishAnchorItem) -> BigFishAnchorItemRecord {
BigFishAnchorItemRecord {
key: snapshot.key,
label: snapshot.label,
value: snapshot.value,
status: format_big_fish_anchor_status(snapshot.status).to_string(),
}
}
pub(crate) fn map_big_fish_game_draft(snapshot: BigFishGameDraft) -> BigFishGameDraftRecord {
BigFishGameDraftRecord {
title: snapshot.title,
subtitle: snapshot.subtitle,
core_fun: snapshot.core_fun,
ecology_theme: snapshot.ecology_theme,
levels: snapshot
.levels
.into_iter()
.map(map_big_fish_level_blueprint)
.collect(),
background: map_big_fish_background_blueprint(snapshot.background),
runtime_params: map_big_fish_runtime_params(snapshot.runtime_params),
}
}
pub(crate) fn map_big_fish_level_blueprint(
snapshot: BigFishLevelBlueprint,
) -> BigFishLevelBlueprintRecord {
BigFishLevelBlueprintRecord {
level: snapshot.level,
name: snapshot.name,
one_line_fantasy: snapshot.one_line_fantasy,
text_description: snapshot.text_description,
silhouette_direction: snapshot.silhouette_direction,
size_ratio: snapshot.size_ratio,
visual_description: snapshot.visual_description,
visual_prompt_seed: snapshot.visual_prompt_seed,
idle_motion_description: snapshot.idle_motion_description,
move_motion_description: snapshot.move_motion_description,
motion_prompt_seed: snapshot.motion_prompt_seed,
merge_source_level: snapshot.merge_source_level,
prey_window: snapshot.prey_window,
threat_window: snapshot.threat_window,
is_final_level: snapshot.is_final_level,
}
}
pub(crate) fn map_big_fish_background_blueprint(
snapshot: BigFishBackgroundBlueprint,
) -> BigFishBackgroundBlueprintRecord {
BigFishBackgroundBlueprintRecord {
theme: snapshot.theme,
color_mood: snapshot.color_mood,
foreground_hints: snapshot.foreground_hints,
midground_composition: snapshot.midground_composition,
background_depth: snapshot.background_depth,
safe_play_area_hint: snapshot.safe_play_area_hint,
spawn_edge_hint: snapshot.spawn_edge_hint,
background_prompt_seed: snapshot.background_prompt_seed,
}
}
pub(crate) fn map_big_fish_runtime_params(
snapshot: BigFishRuntimeParams,
) -> BigFishRuntimeParamsRecord {
BigFishRuntimeParamsRecord {
level_count: snapshot.level_count,
merge_count_per_upgrade: snapshot.merge_count_per_upgrade,
spawn_target_count: snapshot.spawn_target_count,
leader_move_speed: snapshot.leader_move_speed,
follower_catch_up_speed: snapshot.follower_catch_up_speed,
offscreen_cull_seconds: snapshot.offscreen_cull_seconds,
prey_spawn_delta_levels: snapshot.prey_spawn_delta_levels,
threat_spawn_delta_levels: snapshot.threat_spawn_delta_levels,
win_level: snapshot.win_level,
}
}
pub(crate) fn map_big_fish_asset_slot_snapshot(
snapshot: BigFishAssetSlotSnapshot,
) -> BigFishAssetSlotRecord {
BigFishAssetSlotRecord {
slot_id: snapshot.slot_id,
asset_kind: format_big_fish_asset_kind(snapshot.asset_kind).to_string(),
level: snapshot.level,
motion_key: snapshot.motion_key,
status: format_big_fish_asset_status(snapshot.status).to_string(),
asset_url: snapshot.asset_url,
prompt_snapshot: snapshot.prompt_snapshot,
updated_at: format_timestamp_micros(snapshot.updated_at_micros),
}
}
pub(crate) fn map_big_fish_asset_coverage(
snapshot: BigFishAssetCoverage,
) -> BigFishAssetCoverageRecord {
BigFishAssetCoverageRecord {
level_main_image_ready_count: snapshot.level_main_image_ready_count,
level_motion_ready_count: snapshot.level_motion_ready_count,
background_ready: snapshot.background_ready,
required_level_count: snapshot.required_level_count,
publish_ready: snapshot.publish_ready,
blockers: snapshot.blockers,
}
}
pub(crate) fn map_big_fish_agent_message_snapshot(
snapshot: BigFishAgentMessageSnapshot,
) -> BigFishAgentMessageRecord {
BigFishAgentMessageRecord {
message_id: snapshot.message_id,
role: format_big_fish_agent_message_role(snapshot.role).to_string(),
kind: format_big_fish_agent_message_kind(snapshot.kind).to_string(),
text: snapshot.text,
created_at: format_timestamp_micros(snapshot.created_at_micros),
}
}
pub(crate) fn map_big_fish_runtime_snapshot(
snapshot: module_big_fish::BigFishRuntimeSnapshot,
) -> BigFishRuntimeRunRecord {
BigFishRuntimeRunRecord {
run_id: snapshot.run_id,
session_id: snapshot.session_id,
status: snapshot.status.as_str().to_string(),
tick: snapshot.tick,
player_level: snapshot.player_level,
win_level: snapshot.win_level,
leader_entity_id: snapshot.leader_entity_id,
owned_entities: snapshot
.owned_entities
.into_iter()
.map(map_big_fish_runtime_entity_snapshot)
.collect(),
wild_entities: snapshot
.wild_entities
.into_iter()
.map(map_big_fish_runtime_entity_snapshot)
.collect(),
camera_center: map_big_fish_vector2(snapshot.camera_center),
last_input: map_big_fish_vector2(snapshot.last_input),
event_log: snapshot.event_log,
updated_at: format_timestamp_micros(snapshot.updated_at_micros),
}
}
fn map_big_fish_runtime_entity_snapshot(
snapshot: module_big_fish::BigFishRuntimeEntitySnapshot,
) -> BigFishRuntimeEntityRecord {
BigFishRuntimeEntityRecord {
entity_id: snapshot.entity_id,
level: snapshot.level,
position: map_big_fish_vector2(snapshot.position),
radius: snapshot.radius,
offscreen_seconds: snapshot.offscreen_seconds,
}
}
fn map_big_fish_vector2(snapshot: module_big_fish::BigFishVector2) -> BigFishVector2Record {
BigFishVector2Record {
x: snapshot.x,
y: snapshot.y,
}
}
pub(crate) fn map_story_session_snapshot(snapshot: StorySessionSnapshot) -> StorySessionRecord {
StorySessionRecord {
story_session_id: snapshot.story_session_id,
runtime_session_id: snapshot.runtime_session_id,
actor_user_id: snapshot.actor_user_id,
world_profile_id: snapshot.world_profile_id,
initial_prompt: snapshot.initial_prompt,
opening_summary: snapshot.opening_summary,
latest_narrative_text: snapshot.latest_narrative_text,
latest_choice_function_id: snapshot.latest_choice_function_id,
status: map_story_session_status(snapshot.status)
.as_str()
.to_string(),
version: snapshot.version,
created_at: format_timestamp_micros(snapshot.created_at_micros),
updated_at: format_timestamp_micros(snapshot.updated_at_micros),
}
}
pub(crate) fn map_ai_task_snapshot(snapshot: AiTaskSnapshot) -> AiTaskRecord {
AiTaskRecord {
task_id: snapshot.task_id,
task_kind: format_ai_task_kind(snapshot.task_kind).to_string(),
owner_user_id: snapshot.owner_user_id,
request_label: snapshot.request_label,
source_module: snapshot.source_module,
source_entity_id: snapshot.source_entity_id,
request_payload_json: snapshot.request_payload_json,
status: format_ai_task_status(snapshot.status).to_string(),
failure_message: snapshot.failure_message,
stages: snapshot
.stages
.into_iter()
.map(map_ai_task_stage_snapshot)
.collect(),
result_references: snapshot
.result_references
.into_iter()
.map(map_ai_result_reference_snapshot)
.collect(),
latest_text_output: snapshot.latest_text_output,
latest_structured_payload_json: snapshot.latest_structured_payload_json,
version: snapshot.version,
created_at: format_timestamp_micros(snapshot.created_at_micros),
started_at: snapshot.started_at_micros.map(format_timestamp_micros),
completed_at: snapshot.completed_at_micros.map(format_timestamp_micros),
updated_at: format_timestamp_micros(snapshot.updated_at_micros),
}
}
pub(crate) fn map_ai_task_stage_snapshot(snapshot: AiTaskStageSnapshot) -> AiTaskStageRecord {
AiTaskStageRecord {
stage_kind: format_ai_task_stage_kind(snapshot.stage_kind).to_string(),
label: snapshot.label,
detail: snapshot.detail,
order: snapshot.order,
status: format_ai_task_stage_status(snapshot.status).to_string(),
text_output: snapshot.text_output,
structured_payload_json: snapshot.structured_payload_json,
warning_messages: snapshot.warning_messages,
started_at: snapshot.started_at_micros.map(format_timestamp_micros),
completed_at: snapshot.completed_at_micros.map(format_timestamp_micros),
}
}
pub(crate) fn map_ai_text_chunk_snapshot(snapshot: AiTextChunkSnapshot) -> AiTextChunkRecord {
AiTextChunkRecord {
chunk_id: snapshot.chunk_id,
task_id: snapshot.task_id,
stage_kind: format_ai_task_stage_kind(snapshot.stage_kind).to_string(),
sequence: snapshot.sequence,
delta_text: snapshot.delta_text,
created_at: format_timestamp_micros(snapshot.created_at_micros),
}
}
pub(crate) fn map_ai_result_reference_snapshot(
snapshot: AiResultReferenceSnapshot,
) -> AiResultReferenceRecord {
AiResultReferenceRecord {
result_ref_id: snapshot.result_ref_id,
task_id: snapshot.task_id,
reference_kind: format_ai_result_reference_kind(snapshot.reference_kind).to_string(),
reference_id: snapshot.reference_id,
label: snapshot.label,
created_at: format_timestamp_micros(snapshot.created_at_micros),
}
}
pub(crate) fn map_story_event_snapshot(snapshot: StoryEventSnapshot) -> StoryEventRecord {
StoryEventRecord {
event_id: snapshot.event_id,
story_session_id: snapshot.story_session_id,
event_kind: map_story_event_kind(snapshot.event_kind)
.as_str()
.to_string(),
narrative_text: snapshot.narrative_text,
choice_function_id: snapshot.choice_function_id,
created_at: format_timestamp_micros(snapshot.created_at_micros),
}
}
pub(crate) fn map_battle_state_snapshot(
snapshot: BattleStateSnapshot,
) -> DomainBattleStateSnapshot {
DomainBattleStateSnapshot {
battle_state_id: snapshot.battle_state_id,
story_session_id: snapshot.story_session_id,
runtime_session_id: snapshot.runtime_session_id,
actor_user_id: snapshot.actor_user_id,
chapter_id: snapshot.chapter_id,
target_npc_id: snapshot.target_npc_id,
target_name: snapshot.target_name,
battle_mode: map_battle_mode_back(snapshot.battle_mode),
status: map_battle_status(snapshot.status),
player_hp: snapshot.player_hp,
player_max_hp: snapshot.player_max_hp,
player_mana: snapshot.player_mana,
player_max_mana: snapshot.player_max_mana,
target_hp: snapshot.target_hp,
target_max_hp: snapshot.target_max_hp,
experience_reward: snapshot.experience_reward,
reward_items: snapshot
.reward_items
.into_iter()
.map(map_runtime_item_reward_item_snapshot_back)
.collect(),
turn_index: snapshot.turn_index,
last_action_function_id: snapshot.last_action_function_id,
last_action_text: snapshot.last_action_text,
last_result_text: snapshot.last_result_text,
last_damage_dealt: snapshot.last_damage_dealt,
last_damage_taken: snapshot.last_damage_taken,
last_outcome: map_combat_outcome(snapshot.last_outcome),
version: snapshot.version,
created_at_micros: snapshot.created_at_micros,
updated_at_micros: snapshot.updated_at_micros,
}
}
pub(crate) fn map_runtime_inventory_state_snapshot(
snapshot: RuntimeInventoryStateSnapshot,
) -> DomainRuntimeInventoryStateSnapshot {
DomainRuntimeInventoryStateSnapshot {
runtime_session_id: snapshot.runtime_session_id,
actor_user_id: snapshot.actor_user_id,
backpack_items: snapshot
.backpack_items
.into_iter()
.map(map_inventory_slot_snapshot)
.collect(),
equipment_items: snapshot
.equipment_items
.into_iter()
.map(map_inventory_slot_snapshot)
.collect(),
}
}
pub(crate) fn map_resolve_combat_action_result(
result: ResolveCombatActionResult,
) -> DomainResolveCombatActionResult {
DomainResolveCombatActionResult {
snapshot: map_battle_state_snapshot(result.snapshot),
damage_dealt: result.damage_dealt,
damage_taken: result.damage_taken,
outcome: map_combat_outcome(result.outcome),
}
}
pub(crate) fn map_npc_battle_interaction_result(
result: NpcBattleInteractionResult,
) -> NpcBattleInteractionSnapshot {
NpcBattleInteractionSnapshot {
interaction: map_npc_interaction_result(result.interaction),
battle_state: map_battle_state_snapshot(result.battle_state),
}
}
pub(crate) fn map_inventory_slot_snapshot(
snapshot: InventorySlotSnapshot,
) -> module_inventory::InventorySlotSnapshot {
module_inventory::InventorySlotSnapshot {
slot_id: snapshot.slot_id,
runtime_session_id: snapshot.runtime_session_id,
story_session_id: snapshot.story_session_id,
actor_user_id: snapshot.actor_user_id,
container_kind: map_inventory_container_kind(snapshot.container_kind),
slot_key: snapshot.slot_key,
item_id: snapshot.item_id,
category: snapshot.category,
name: snapshot.name,
description: snapshot.description,
quantity: snapshot.quantity,
rarity: map_inventory_item_rarity(snapshot.rarity),
tags: snapshot.tags,
stackable: snapshot.stackable,
stack_key: snapshot.stack_key,
equipment_slot_id: snapshot.equipment_slot_id.map(map_inventory_equipment_slot),
source_kind: map_inventory_item_source_kind(snapshot.source_kind),
source_reference_id: snapshot.source_reference_id,
created_at_micros: snapshot.created_at_micros,
updated_at_micros: snapshot.updated_at_micros,
}
}
pub(crate) fn map_npc_interaction_result(
result: NpcInteractionResult,
) -> DomainNpcInteractionResult {
DomainNpcInteractionResult {
npc_state: map_npc_state_snapshot(result.npc_state),
interaction_status: map_npc_interaction_status(result.interaction_status),
action_text: result.action_text,
result_text: result.result_text,
story_text: result.story_text,
battle_mode: result.battle_mode.map(map_npc_interaction_battle_mode),
encounter_closed: result.encounter_closed,
affinity_changed: result.affinity_changed,
previous_affinity: result.previous_affinity,
next_affinity: result.next_affinity,
}
}
pub(crate) fn map_npc_state_snapshot(snapshot: NpcStateSnapshot) -> DomainNpcStateSnapshot {
DomainNpcStateSnapshot {
npc_state_id: snapshot.npc_state_id,
runtime_session_id: snapshot.runtime_session_id,
npc_id: snapshot.npc_id,
npc_name: snapshot.npc_name,
affinity: snapshot.affinity,
relation_state: map_npc_relation_state(snapshot.relation_state),
help_used: snapshot.help_used,
chatted_count: snapshot.chatted_count,
gifts_given: snapshot.gifts_given,
recruited: snapshot.recruited,
trade_stock_signature: snapshot.trade_stock_signature,
revealed_facts: snapshot.revealed_facts,
known_attribute_rumors: snapshot.known_attribute_rumors,
first_meaningful_contact_resolved: snapshot.first_meaningful_contact_resolved,
seen_backstory_chapter_ids: snapshot.seen_backstory_chapter_ids,
stance_profile: map_npc_stance_profile(snapshot.stance_profile),
created_at_micros: snapshot.created_at_micros,
updated_at_micros: snapshot.updated_at_micros,
}
}
pub(crate) fn map_npc_relation_state(value: NpcRelationState) -> DomainNpcRelationState {
DomainNpcRelationState {
affinity: value.affinity,
stance: map_npc_relation_stance(value.stance),
}
}
pub(crate) fn map_npc_stance_profile(value: NpcStanceProfile) -> DomainNpcStanceProfile {
DomainNpcStanceProfile {
trust: value.trust,
warmth: value.warmth,
ideological_fit: value.ideological_fit,
fear_or_guard: value.fear_or_guard,
loyalty: value.loyalty,
current_conflict_tag: value.current_conflict_tag,
recent_approvals: value.recent_approvals,
recent_disapprovals: value.recent_disapprovals,
}
}
pub(crate) fn map_npc_interaction_status(
value: NpcInteractionStatus,
) -> DomainNpcInteractionStatus {
match value {
NpcInteractionStatus::Previewed => DomainNpcInteractionStatus::Previewed,
NpcInteractionStatus::Dialogue => DomainNpcInteractionStatus::Dialogue,
NpcInteractionStatus::Resolved => DomainNpcInteractionStatus::Resolved,
NpcInteractionStatus::Recruited => DomainNpcInteractionStatus::Recruited,
NpcInteractionStatus::BattlePending => DomainNpcInteractionStatus::BattlePending,
NpcInteractionStatus::Left => DomainNpcInteractionStatus::Left,
}
}
pub(crate) fn map_npc_interaction_battle_mode(
value: NpcInteractionBattleMode,
) -> DomainNpcInteractionBattleMode {
match value {
NpcInteractionBattleMode::Fight => DomainNpcInteractionBattleMode::Fight,
NpcInteractionBattleMode::Spar => DomainNpcInteractionBattleMode::Spar,
}
}
pub(crate) fn map_npc_relation_stance(value: NpcRelationStance) -> DomainNpcRelationStance {
match value {
NpcRelationStance::Hostile => DomainNpcRelationStance::Hostile,
NpcRelationStance::Guarded => DomainNpcRelationStance::Guarded,
NpcRelationStance::Neutral => DomainNpcRelationStance::Neutral,
NpcRelationStance::Cooperative => DomainNpcRelationStance::Cooperative,
NpcRelationStance::Bonded => DomainNpcRelationStance::Bonded,
}
}
pub(crate) fn map_access_policy(
value: AssetObjectAccessPolicy,
) -> crate::module_bindings::AssetObjectAccessPolicy {
match value {
AssetObjectAccessPolicy::Private => {
crate::module_bindings::AssetObjectAccessPolicy::Private
}
AssetObjectAccessPolicy::PublicRead => {
crate::module_bindings::AssetObjectAccessPolicy::PublicRead
}
}
}
pub(crate) fn map_access_policy_back(
value: crate::module_bindings::AssetObjectAccessPolicy,
) -> AssetObjectAccessPolicy {
match value {
crate::module_bindings::AssetObjectAccessPolicy::Private => {
AssetObjectAccessPolicy::Private
}
crate::module_bindings::AssetObjectAccessPolicy::PublicRead => {
AssetObjectAccessPolicy::PublicRead
}
}
}
pub(crate) fn map_runtime_platform_theme(
value: DomainRuntimePlatformTheme,
) -> crate::module_bindings::RuntimePlatformTheme {
match value {
DomainRuntimePlatformTheme::Light => crate::module_bindings::RuntimePlatformTheme::Light,
DomainRuntimePlatformTheme::Dark => crate::module_bindings::RuntimePlatformTheme::Dark,
}
}
pub(crate) fn map_runtime_item_reward_item_rarity(
value: DomainRuntimeItemRewardItemRarity,
) -> RuntimeItemRewardItemRarity {
match value {
DomainRuntimeItemRewardItemRarity::Common => RuntimeItemRewardItemRarity::Common,
DomainRuntimeItemRewardItemRarity::Uncommon => RuntimeItemRewardItemRarity::Uncommon,
DomainRuntimeItemRewardItemRarity::Rare => RuntimeItemRewardItemRarity::Rare,
DomainRuntimeItemRewardItemRarity::Epic => RuntimeItemRewardItemRarity::Epic,
DomainRuntimeItemRewardItemRarity::Legendary => RuntimeItemRewardItemRarity::Legendary,
}
}
pub(crate) fn map_runtime_item_equipment_slot(
value: DomainRuntimeItemEquipmentSlot,
) -> RuntimeItemEquipmentSlot {
match value {
DomainRuntimeItemEquipmentSlot::Weapon => RuntimeItemEquipmentSlot::Weapon,
DomainRuntimeItemEquipmentSlot::Armor => RuntimeItemEquipmentSlot::Armor,
DomainRuntimeItemEquipmentSlot::Relic => RuntimeItemEquipmentSlot::Relic,
}
}
pub(crate) fn map_custom_world_theme_mode(
value: DomainCustomWorldThemeMode,
) -> CustomWorldThemeMode {
match value {
DomainCustomWorldThemeMode::Martial => CustomWorldThemeMode::Martial,
DomainCustomWorldThemeMode::Arcane => CustomWorldThemeMode::Arcane,
DomainCustomWorldThemeMode::Machina => CustomWorldThemeMode::Machina,
DomainCustomWorldThemeMode::Tide => CustomWorldThemeMode::Tide,
DomainCustomWorldThemeMode::Rift => CustomWorldThemeMode::Rift,
DomainCustomWorldThemeMode::Mythic => CustomWorldThemeMode::Mythic,
}
}
pub(crate) fn map_battle_mode(value: DomainBattleMode) -> BattleMode {
match value {
DomainBattleMode::Fight => BattleMode::Fight,
DomainBattleMode::Spar => BattleMode::Spar,
}
}
pub(crate) fn map_runtime_platform_theme_back(
value: crate::module_bindings::RuntimePlatformTheme,
) -> DomainRuntimePlatformTheme {
match value {
crate::module_bindings::RuntimePlatformTheme::Light => DomainRuntimePlatformTheme::Light,
crate::module_bindings::RuntimePlatformTheme::Dark => DomainRuntimePlatformTheme::Dark,
}
}
pub(crate) fn map_runtime_item_reward_item_rarity_back(
value: RuntimeItemRewardItemRarity,
) -> DomainRuntimeItemRewardItemRarity {
match value {
RuntimeItemRewardItemRarity::Common => DomainRuntimeItemRewardItemRarity::Common,
RuntimeItemRewardItemRarity::Uncommon => DomainRuntimeItemRewardItemRarity::Uncommon,
RuntimeItemRewardItemRarity::Rare => DomainRuntimeItemRewardItemRarity::Rare,
RuntimeItemRewardItemRarity::Epic => DomainRuntimeItemRewardItemRarity::Epic,
RuntimeItemRewardItemRarity::Legendary => DomainRuntimeItemRewardItemRarity::Legendary,
}
}
pub(crate) fn map_runtime_item_equipment_slot_back(
value: RuntimeItemEquipmentSlot,
) -> DomainRuntimeItemEquipmentSlot {
match value {
RuntimeItemEquipmentSlot::Weapon => DomainRuntimeItemEquipmentSlot::Weapon,
RuntimeItemEquipmentSlot::Armor => DomainRuntimeItemEquipmentSlot::Armor,
RuntimeItemEquipmentSlot::Relic => DomainRuntimeItemEquipmentSlot::Relic,
}
}
pub(crate) fn map_custom_world_theme_mode_back(
value: CustomWorldThemeMode,
) -> DomainCustomWorldThemeMode {
match value {
CustomWorldThemeMode::Martial => DomainCustomWorldThemeMode::Martial,
CustomWorldThemeMode::Arcane => DomainCustomWorldThemeMode::Arcane,
CustomWorldThemeMode::Machina => DomainCustomWorldThemeMode::Machina,
CustomWorldThemeMode::Tide => DomainCustomWorldThemeMode::Tide,
CustomWorldThemeMode::Rift => DomainCustomWorldThemeMode::Rift,
CustomWorldThemeMode::Mythic => DomainCustomWorldThemeMode::Mythic,
}
}
pub(crate) fn map_custom_world_publication_status(
value: CustomWorldPublicationStatus,
) -> &'static str {
match value {
CustomWorldPublicationStatus::Draft => "draft",
CustomWorldPublicationStatus::Published => "published",
}
}
pub(crate) fn map_rpg_agent_stage(value: crate::module_bindings::RpgAgentStage) -> String {
match value {
crate::module_bindings::RpgAgentStage::CollectingIntent => "collecting_intent",
crate::module_bindings::RpgAgentStage::Clarifying => "clarifying",
crate::module_bindings::RpgAgentStage::FoundationReview => "foundation_review",
crate::module_bindings::RpgAgentStage::ObjectRefining => "object_refining",
crate::module_bindings::RpgAgentStage::VisualRefining => "visual_refining",
crate::module_bindings::RpgAgentStage::LongTailReview => "long_tail_review",
crate::module_bindings::RpgAgentStage::ReadyToPublish => "ready_to_publish",
crate::module_bindings::RpgAgentStage::Published => "published",
crate::module_bindings::RpgAgentStage::Error => "error",
}
.to_string()
}
pub(crate) fn parse_puzzle_agent_stage_record(
value: &str,
) -> Result<crate::module_bindings::PuzzleAgentStage, SpacetimeClientError> {
match value.trim() {
"collecting_anchors" => Ok(crate::module_bindings::PuzzleAgentStage::CollectingAnchors),
"draft_ready" => Ok(crate::module_bindings::PuzzleAgentStage::DraftReady),
"image_refining" => Ok(crate::module_bindings::PuzzleAgentStage::ImageRefining),
"ready_to_publish" => Ok(crate::module_bindings::PuzzleAgentStage::ReadyToPublish),
"published" => Ok(crate::module_bindings::PuzzleAgentStage::Published),
other => Err(SpacetimeClientError::Runtime(format!(
"未知 puzzle agent stage: {other}"
))),
}
}
pub(crate) fn parse_rpg_agent_stage_record(
value: &str,
) -> Result<crate::module_bindings::RpgAgentStage, SpacetimeClientError> {
match value.trim() {
"collecting_intent" => Ok(crate::module_bindings::RpgAgentStage::CollectingIntent),
"clarifying" => Ok(crate::module_bindings::RpgAgentStage::Clarifying),
"foundation_review" => Ok(crate::module_bindings::RpgAgentStage::FoundationReview),
"object_refining" => Ok(crate::module_bindings::RpgAgentStage::ObjectRefining),
"visual_refining" => Ok(crate::module_bindings::RpgAgentStage::VisualRefining),
"long_tail_review" => Ok(crate::module_bindings::RpgAgentStage::LongTailReview),
"ready_to_publish" => Ok(crate::module_bindings::RpgAgentStage::ReadyToPublish),
"published" => Ok(crate::module_bindings::RpgAgentStage::Published),
"error" => Ok(crate::module_bindings::RpgAgentStage::Error),
other => Err(SpacetimeClientError::Runtime(format!(
"未知 rpg agent stage: {other}"
))),
}
}
pub(crate) fn format_rpg_agent_message_role(
value: crate::module_bindings::RpgAgentMessageRole,
) -> &'static str {
match value {
crate::module_bindings::RpgAgentMessageRole::User => "user",
crate::module_bindings::RpgAgentMessageRole::Assistant => "assistant",
crate::module_bindings::RpgAgentMessageRole::System => "system",
}
}
pub(crate) fn format_rpg_agent_message_kind(
value: crate::module_bindings::RpgAgentMessageKind,
) -> &'static str {
match value {
crate::module_bindings::RpgAgentMessageKind::Chat => "chat",
crate::module_bindings::RpgAgentMessageKind::Clarification => "clarification",
crate::module_bindings::RpgAgentMessageKind::Summary => "summary",
crate::module_bindings::RpgAgentMessageKind::Checkpoint => "checkpoint",
crate::module_bindings::RpgAgentMessageKind::Warning => "warning",
crate::module_bindings::RpgAgentMessageKind::ActionResult => "action_result",
}
}
pub(crate) fn format_rpg_agent_operation_type(
value: crate::module_bindings::RpgAgentOperationType,
) -> &'static str {
match value {
crate::module_bindings::RpgAgentOperationType::ProcessMessage => "process_message",
crate::module_bindings::RpgAgentOperationType::DraftFoundation => "draft_foundation",
crate::module_bindings::RpgAgentOperationType::UpdateDraftCard => "update_draft_card",
crate::module_bindings::RpgAgentOperationType::SyncResultProfile => "sync_result_profile",
crate::module_bindings::RpgAgentOperationType::GenerateCharacters => "generate_characters",
crate::module_bindings::RpgAgentOperationType::GenerateLandmarks => "generate_landmarks",
crate::module_bindings::RpgAgentOperationType::GenerateRoleAssets => "generate_role_assets",
crate::module_bindings::RpgAgentOperationType::SyncRoleAssets => "sync_role_assets",
crate::module_bindings::RpgAgentOperationType::GenerateSceneAssets => {
"generate_scene_assets"
}
crate::module_bindings::RpgAgentOperationType::SyncSceneAssets => "sync_scene_assets",
crate::module_bindings::RpgAgentOperationType::ExpandLongTail => "expand_long_tail",
crate::module_bindings::RpgAgentOperationType::PublishWorld => "publish_world",
crate::module_bindings::RpgAgentOperationType::RevertCheckpoint => "revert_checkpoint",
crate::module_bindings::RpgAgentOperationType::DeleteCharacters => "delete_characters",
crate::module_bindings::RpgAgentOperationType::DeleteLandmarks => "delete_landmarks",
}
}
pub(crate) fn parse_rpg_agent_operation_type_record(
value: &str,
) -> Result<crate::module_bindings::RpgAgentOperationType, SpacetimeClientError> {
match value.trim() {
"process_message" => Ok(crate::module_bindings::RpgAgentOperationType::ProcessMessage),
"draft_foundation" => Ok(crate::module_bindings::RpgAgentOperationType::DraftFoundation),
"update_draft_card" => Ok(crate::module_bindings::RpgAgentOperationType::UpdateDraftCard),
"sync_result_profile" => {
Ok(crate::module_bindings::RpgAgentOperationType::SyncResultProfile)
}
"generate_characters" => {
Ok(crate::module_bindings::RpgAgentOperationType::GenerateCharacters)
}
"generate_landmarks" => {
Ok(crate::module_bindings::RpgAgentOperationType::GenerateLandmarks)
}
"generate_role_assets" => {
Ok(crate::module_bindings::RpgAgentOperationType::GenerateRoleAssets)
}
"sync_role_assets" => Ok(crate::module_bindings::RpgAgentOperationType::SyncRoleAssets),
"generate_scene_assets" => {
Ok(crate::module_bindings::RpgAgentOperationType::GenerateSceneAssets)
}
"sync_scene_assets" => Ok(crate::module_bindings::RpgAgentOperationType::SyncSceneAssets),
"expand_long_tail" => Ok(crate::module_bindings::RpgAgentOperationType::ExpandLongTail),
"publish_world" => Ok(crate::module_bindings::RpgAgentOperationType::PublishWorld),
"revert_checkpoint" => Ok(crate::module_bindings::RpgAgentOperationType::RevertCheckpoint),
"delete_characters" => Ok(crate::module_bindings::RpgAgentOperationType::DeleteCharacters),
"delete_landmarks" => Ok(crate::module_bindings::RpgAgentOperationType::DeleteLandmarks),
other => Err(SpacetimeClientError::Runtime(format!(
"未知 rpg agent operation type: {other}"
))),
}
}
pub(crate) fn format_rpg_agent_operation_status(
value: crate::module_bindings::RpgAgentOperationStatus,
) -> &'static str {
match value {
crate::module_bindings::RpgAgentOperationStatus::Queued => "queued",
crate::module_bindings::RpgAgentOperationStatus::Running => "running",
crate::module_bindings::RpgAgentOperationStatus::Completed => "completed",
crate::module_bindings::RpgAgentOperationStatus::Failed => "failed",
}
}
pub(crate) fn parse_rpg_agent_operation_status_record(
value: &str,
) -> Result<crate::module_bindings::RpgAgentOperationStatus, SpacetimeClientError> {
match value.trim() {
"queued" => Ok(crate::module_bindings::RpgAgentOperationStatus::Queued),
"running" => Ok(crate::module_bindings::RpgAgentOperationStatus::Running),
"completed" => Ok(crate::module_bindings::RpgAgentOperationStatus::Completed),
"failed" => Ok(crate::module_bindings::RpgAgentOperationStatus::Failed),
other => Err(SpacetimeClientError::Runtime(format!(
"未知 rpg agent operation status: {other}"
))),
}
}
pub(crate) fn format_rpg_agent_draft_card_kind(
value: crate::module_bindings::RpgAgentDraftCardKind,
) -> &'static str {
match value {
crate::module_bindings::RpgAgentDraftCardKind::World => "world",
crate::module_bindings::RpgAgentDraftCardKind::Camp => "camp",
crate::module_bindings::RpgAgentDraftCardKind::Faction => "faction",
crate::module_bindings::RpgAgentDraftCardKind::Character => "character",
crate::module_bindings::RpgAgentDraftCardKind::Landmark => "landmark",
crate::module_bindings::RpgAgentDraftCardKind::Thread => "thread",
crate::module_bindings::RpgAgentDraftCardKind::Chapter => "chapter",
crate::module_bindings::RpgAgentDraftCardKind::SceneChapter => "scene_chapter",
crate::module_bindings::RpgAgentDraftCardKind::Carrier => "carrier",
crate::module_bindings::RpgAgentDraftCardKind::SidequestSeed => "sidequest_seed",
}
}
pub(crate) fn format_rpg_agent_draft_card_status(
value: crate::module_bindings::RpgAgentDraftCardStatus,
) -> &'static str {
match value {
crate::module_bindings::RpgAgentDraftCardStatus::Suggested => "suggested",
crate::module_bindings::RpgAgentDraftCardStatus::Confirmed => "confirmed",
crate::module_bindings::RpgAgentDraftCardStatus::Locked => "locked",
crate::module_bindings::RpgAgentDraftCardStatus::Warning => "warning",
}
}
pub(crate) fn format_custom_world_role_asset_status_back(
value: crate::module_bindings::CustomWorldRoleAssetStatus,
) -> String {
match value {
crate::module_bindings::CustomWorldRoleAssetStatus::Missing => "missing",
crate::module_bindings::CustomWorldRoleAssetStatus::VisualReady => "visual_ready",
crate::module_bindings::CustomWorldRoleAssetStatus::AnimationsReady => "animations_ready",
crate::module_bindings::CustomWorldRoleAssetStatus::Complete => "complete",
}
.to_string()
}
impl TryFrom<&str> for BigFishAssetKind {
type Error = SpacetimeClientError;
fn try_from(value: &str) -> Result<Self, Self::Error> {
match value.trim() {
"level_main_image" => Ok(Self::LevelMainImage),
"level_motion" => Ok(Self::LevelMotion),
"stage_background" => Ok(Self::StageBackground),
other => Err(SpacetimeClientError::Runtime(format!(
"big fish asset kind `{other}` 当前尚未支持"
))),
}
}
}
pub(crate) fn parse_big_fish_creation_stage(
value: &str,
) -> Result<BigFishCreationStage, SpacetimeClientError> {
match value.trim() {
"collecting_anchors" => Ok(BigFishCreationStage::CollectingAnchors),
"draft_ready" => Ok(BigFishCreationStage::DraftReady),
"asset_refining" => Ok(BigFishCreationStage::AssetRefining),
"ready_to_publish" => Ok(BigFishCreationStage::ReadyToPublish),
"published" => Ok(BigFishCreationStage::Published),
other => Err(SpacetimeClientError::Runtime(format!(
"big fish creation stage `{other}` 当前尚未支持"
))),
}
}
pub(crate) fn format_big_fish_creation_stage(value: BigFishCreationStage) -> &'static str {
match value {
BigFishCreationStage::CollectingAnchors => "collecting_anchors",
BigFishCreationStage::DraftReady => "draft_ready",
BigFishCreationStage::AssetRefining => "asset_refining",
BigFishCreationStage::ReadyToPublish => "ready_to_publish",
BigFishCreationStage::Published => "published",
}
}
pub(crate) fn format_big_fish_anchor_status(value: BigFishAnchorStatus) -> &'static str {
match value {
BigFishAnchorStatus::Confirmed => "confirmed",
BigFishAnchorStatus::Inferred => "inferred",
BigFishAnchorStatus::Missing => "missing",
BigFishAnchorStatus::Locked => "locked",
}
}
pub(crate) fn format_big_fish_agent_message_role(value: BigFishAgentMessageRole) -> &'static str {
match value {
BigFishAgentMessageRole::User => "user",
BigFishAgentMessageRole::Assistant => "assistant",
BigFishAgentMessageRole::System => "system",
}
}
pub(crate) fn format_big_fish_agent_message_kind(value: BigFishAgentMessageKind) -> &'static str {
match value {
BigFishAgentMessageKind::Chat => "chat",
BigFishAgentMessageKind::Summary => "summary",
BigFishAgentMessageKind::ActionResult => "action_result",
BigFishAgentMessageKind::Warning => "warning",
}
}
pub(crate) fn format_big_fish_asset_kind(value: BigFishAssetKind) -> &'static str {
match value {
BigFishAssetKind::LevelMainImage => "level_main_image",
BigFishAssetKind::LevelMotion => "level_motion",
BigFishAssetKind::StageBackground => "stage_background",
}
}
pub(crate) fn format_big_fish_asset_status(value: BigFishAssetStatus) -> &'static str {
match value {
BigFishAssetStatus::Missing => "missing",
BigFishAssetStatus::Ready => "ready",
}
}
pub(crate) fn format_custom_world_theme_mode(value: DomainCustomWorldThemeMode) -> &'static str {
match value {
DomainCustomWorldThemeMode::Martial => "martial",
DomainCustomWorldThemeMode::Arcane => "arcane",
DomainCustomWorldThemeMode::Machina => "machina",
DomainCustomWorldThemeMode::Tide => "tide",
DomainCustomWorldThemeMode::Rift => "rift",
DomainCustomWorldThemeMode::Mythic => "mythic",
}
}
pub(crate) fn map_battle_mode_back(value: BattleMode) -> DomainBattleMode {
match value {
BattleMode::Fight => DomainBattleMode::Fight,
BattleMode::Spar => DomainBattleMode::Spar,
}
}
pub(crate) fn map_runtime_browse_history_theme_mode_back(
value: crate::module_bindings::RuntimeBrowseHistoryThemeMode,
) -> module_runtime::RuntimeBrowseHistoryThemeMode {
match value {
crate::module_bindings::RuntimeBrowseHistoryThemeMode::Martial => {
module_runtime::RuntimeBrowseHistoryThemeMode::Martial
}
crate::module_bindings::RuntimeBrowseHistoryThemeMode::Arcane => {
module_runtime::RuntimeBrowseHistoryThemeMode::Arcane
}
crate::module_bindings::RuntimeBrowseHistoryThemeMode::Machina => {
module_runtime::RuntimeBrowseHistoryThemeMode::Machina
}
crate::module_bindings::RuntimeBrowseHistoryThemeMode::Tide => {
module_runtime::RuntimeBrowseHistoryThemeMode::Tide
}
crate::module_bindings::RuntimeBrowseHistoryThemeMode::Rift => {
module_runtime::RuntimeBrowseHistoryThemeMode::Rift
}
crate::module_bindings::RuntimeBrowseHistoryThemeMode::Mythic => {
module_runtime::RuntimeBrowseHistoryThemeMode::Mythic
}
}
}
pub(crate) fn map_runtime_profile_wallet_ledger_source_type_back(
value: crate::module_bindings::RuntimeProfileWalletLedgerSourceType,
) -> module_runtime::RuntimeProfileWalletLedgerSourceType {
match value {
crate::module_bindings::RuntimeProfileWalletLedgerSourceType::SnapshotSync => {
module_runtime::RuntimeProfileWalletLedgerSourceType::SnapshotSync
}
crate::module_bindings::RuntimeProfileWalletLedgerSourceType::NewUserRegistrationReward => {
module_runtime::RuntimeProfileWalletLedgerSourceType::NewUserRegistrationReward
}
crate::module_bindings::RuntimeProfileWalletLedgerSourceType::InviteInviterReward => {
module_runtime::RuntimeProfileWalletLedgerSourceType::InviteInviterReward
}
crate::module_bindings::RuntimeProfileWalletLedgerSourceType::InviteInviteeReward => {
module_runtime::RuntimeProfileWalletLedgerSourceType::InviteInviteeReward
}
crate::module_bindings::RuntimeProfileWalletLedgerSourceType::PointsRecharge => {
module_runtime::RuntimeProfileWalletLedgerSourceType::PointsRecharge
}
crate::module_bindings::RuntimeProfileWalletLedgerSourceType::AssetOperationConsume => {
module_runtime::RuntimeProfileWalletLedgerSourceType::AssetOperationConsume
}
crate::module_bindings::RuntimeProfileWalletLedgerSourceType::AssetOperationRefund => {
module_runtime::RuntimeProfileWalletLedgerSourceType::AssetOperationRefund
}
crate::module_bindings::RuntimeProfileWalletLedgerSourceType::RedeemCodeReward => {
module_runtime::RuntimeProfileWalletLedgerSourceType::RedeemCodeReward
}
crate::module_bindings::RuntimeProfileWalletLedgerSourceType::PuzzleAuthorIncentiveClaim => {
module_runtime::RuntimeProfileWalletLedgerSourceType::PuzzleAuthorIncentiveClaim
}
crate::module_bindings::RuntimeProfileWalletLedgerSourceType::DailyTaskReward => {
module_runtime::RuntimeProfileWalletLedgerSourceType::DailyTaskReward
}
}
}
pub(crate) fn map_analytics_granularity(
granularity: module_runtime::AnalyticsGranularity,
) -> AnalyticsGranularity {
match granularity {
module_runtime::AnalyticsGranularity::Day => AnalyticsGranularity::Day,
module_runtime::AnalyticsGranularity::Week => AnalyticsGranularity::Week,
module_runtime::AnalyticsGranularity::Month => AnalyticsGranularity::Month,
module_runtime::AnalyticsGranularity::Quarter => AnalyticsGranularity::Quarter,
module_runtime::AnalyticsGranularity::Year => AnalyticsGranularity::Year,
}
}
pub(crate) fn map_runtime_tracking_scope_kind(
value: DomainRuntimeTrackingScopeKind,
) -> crate::module_bindings::RuntimeTrackingScopeKind {
match value {
DomainRuntimeTrackingScopeKind::Site => {
crate::module_bindings::RuntimeTrackingScopeKind::Site
}
DomainRuntimeTrackingScopeKind::Work => {
crate::module_bindings::RuntimeTrackingScopeKind::Work
}
DomainRuntimeTrackingScopeKind::Module => {
crate::module_bindings::RuntimeTrackingScopeKind::Module
}
DomainRuntimeTrackingScopeKind::User => {
crate::module_bindings::RuntimeTrackingScopeKind::User
}
}
}
pub(crate) fn map_runtime_tracking_scope_kind_back(
value: crate::module_bindings::RuntimeTrackingScopeKind,
) -> DomainRuntimeTrackingScopeKind {
match value {
crate::module_bindings::RuntimeTrackingScopeKind::Site => {
DomainRuntimeTrackingScopeKind::Site
}
crate::module_bindings::RuntimeTrackingScopeKind::Work => {
DomainRuntimeTrackingScopeKind::Work
}
crate::module_bindings::RuntimeTrackingScopeKind::Module => {
DomainRuntimeTrackingScopeKind::Module
}
crate::module_bindings::RuntimeTrackingScopeKind::User => {
DomainRuntimeTrackingScopeKind::User
}
}
}
pub(crate) fn map_runtime_profile_task_cycle(
value: DomainRuntimeProfileTaskCycle,
) -> crate::module_bindings::RuntimeProfileTaskCycle {
match value {
DomainRuntimeProfileTaskCycle::Daily => {
crate::module_bindings::RuntimeProfileTaskCycle::Daily
}
}
}
pub(crate) fn map_runtime_profile_task_cycle_back(
value: crate::module_bindings::RuntimeProfileTaskCycle,
) -> DomainRuntimeProfileTaskCycle {
match value {
crate::module_bindings::RuntimeProfileTaskCycle::Daily => {
DomainRuntimeProfileTaskCycle::Daily
}
}
}
pub(crate) fn map_runtime_profile_task_status_back(
value: crate::module_bindings::RuntimeProfileTaskStatus,
) -> DomainRuntimeProfileTaskStatus {
match value {
crate::module_bindings::RuntimeProfileTaskStatus::Incomplete => {
DomainRuntimeProfileTaskStatus::Incomplete
}
crate::module_bindings::RuntimeProfileTaskStatus::Claimable => {
DomainRuntimeProfileTaskStatus::Claimable
}
crate::module_bindings::RuntimeProfileTaskStatus::Claimed => {
DomainRuntimeProfileTaskStatus::Claimed
}
crate::module_bindings::RuntimeProfileTaskStatus::Disabled => {
DomainRuntimeProfileTaskStatus::Disabled
}
}
}
pub(crate) fn map_runtime_profile_redeem_code_mode(
value: module_runtime::RuntimeProfileRedeemCodeMode,
) -> crate::module_bindings::RuntimeProfileRedeemCodeMode {
match value {
module_runtime::RuntimeProfileRedeemCodeMode::Public => {
crate::module_bindings::RuntimeProfileRedeemCodeMode::Public
}
module_runtime::RuntimeProfileRedeemCodeMode::Unique => {
crate::module_bindings::RuntimeProfileRedeemCodeMode::Unique
}
module_runtime::RuntimeProfileRedeemCodeMode::Private => {
crate::module_bindings::RuntimeProfileRedeemCodeMode::Private
}
}
}
pub(crate) fn map_runtime_profile_redeem_code_mode_back(
value: crate::module_bindings::RuntimeProfileRedeemCodeMode,
) -> module_runtime::RuntimeProfileRedeemCodeMode {
match value {
crate::module_bindings::RuntimeProfileRedeemCodeMode::Public => {
module_runtime::RuntimeProfileRedeemCodeMode::Public
}
crate::module_bindings::RuntimeProfileRedeemCodeMode::Unique => {
module_runtime::RuntimeProfileRedeemCodeMode::Unique
}
crate::module_bindings::RuntimeProfileRedeemCodeMode::Private => {
module_runtime::RuntimeProfileRedeemCodeMode::Private
}
}
}
pub(crate) fn map_runtime_profile_recharge_product_kind(
value: module_runtime::RuntimeProfileRechargeProductKind,
) -> crate::module_bindings::RuntimeProfileRechargeProductKind {
match value {
module_runtime::RuntimeProfileRechargeProductKind::Points => {
crate::module_bindings::RuntimeProfileRechargeProductKind::Points
}
module_runtime::RuntimeProfileRechargeProductKind::Membership => {
crate::module_bindings::RuntimeProfileRechargeProductKind::Membership
}
}
}
pub(crate) fn map_runtime_profile_recharge_product_kind_back(
value: crate::module_bindings::RuntimeProfileRechargeProductKind,
) -> module_runtime::RuntimeProfileRechargeProductKind {
match value {
crate::module_bindings::RuntimeProfileRechargeProductKind::Points => {
module_runtime::RuntimeProfileRechargeProductKind::Points
}
crate::module_bindings::RuntimeProfileRechargeProductKind::Membership => {
module_runtime::RuntimeProfileRechargeProductKind::Membership
}
}
}
pub(crate) fn map_runtime_profile_membership_tier(
value: module_runtime::RuntimeProfileMembershipTier,
) -> crate::module_bindings::RuntimeProfileMembershipTier {
match value {
module_runtime::RuntimeProfileMembershipTier::Normal => {
crate::module_bindings::RuntimeProfileMembershipTier::Normal
}
module_runtime::RuntimeProfileMembershipTier::Month => {
crate::module_bindings::RuntimeProfileMembershipTier::Month
}
module_runtime::RuntimeProfileMembershipTier::Season => {
crate::module_bindings::RuntimeProfileMembershipTier::Season
}
module_runtime::RuntimeProfileMembershipTier::Year => {
crate::module_bindings::RuntimeProfileMembershipTier::Year
}
}
}
pub(crate) fn map_runtime_profile_membership_status_back(
value: crate::module_bindings::RuntimeProfileMembershipStatus,
) -> module_runtime::RuntimeProfileMembershipStatus {
match value {
crate::module_bindings::RuntimeProfileMembershipStatus::Normal => {
module_runtime::RuntimeProfileMembershipStatus::Normal
}
crate::module_bindings::RuntimeProfileMembershipStatus::Active => {
module_runtime::RuntimeProfileMembershipStatus::Active
}
}
}
pub(crate) fn map_runtime_profile_membership_tier_back(
value: crate::module_bindings::RuntimeProfileMembershipTier,
) -> module_runtime::RuntimeProfileMembershipTier {
match value {
crate::module_bindings::RuntimeProfileMembershipTier::Normal => {
module_runtime::RuntimeProfileMembershipTier::Normal
}
crate::module_bindings::RuntimeProfileMembershipTier::Month => {
module_runtime::RuntimeProfileMembershipTier::Month
}
crate::module_bindings::RuntimeProfileMembershipTier::Season => {
module_runtime::RuntimeProfileMembershipTier::Season
}
crate::module_bindings::RuntimeProfileMembershipTier::Year => {
module_runtime::RuntimeProfileMembershipTier::Year
}
}
}
pub(crate) fn map_runtime_profile_recharge_order_status_back(
value: crate::module_bindings::RuntimeProfileRechargeOrderStatus,
) -> module_runtime::RuntimeProfileRechargeOrderStatus {
match value {
crate::module_bindings::RuntimeProfileRechargeOrderStatus::Pending => {
module_runtime::RuntimeProfileRechargeOrderStatus::Pending
}
crate::module_bindings::RuntimeProfileRechargeOrderStatus::Paid => {
module_runtime::RuntimeProfileRechargeOrderStatus::Paid
}
crate::module_bindings::RuntimeProfileRechargeOrderStatus::Failed => {
module_runtime::RuntimeProfileRechargeOrderStatus::Failed
}
crate::module_bindings::RuntimeProfileRechargeOrderStatus::Closed => {
module_runtime::RuntimeProfileRechargeOrderStatus::Closed
}
crate::module_bindings::RuntimeProfileRechargeOrderStatus::Refunded => {
module_runtime::RuntimeProfileRechargeOrderStatus::Refunded
}
}
}
pub(crate) fn map_runtime_profile_feedback_status_back(
value: crate::module_bindings::RuntimeProfileFeedbackStatus,
) -> module_runtime::RuntimeProfileFeedbackStatus {
match value {
crate::module_bindings::RuntimeProfileFeedbackStatus::Open => {
module_runtime::RuntimeProfileFeedbackStatus::Open
}
}
}
pub(crate) fn map_story_session_status(value: StorySessionStatus) -> DomainStorySessionStatus {
match value {
StorySessionStatus::Active => DomainStorySessionStatus::Active,
StorySessionStatus::Completed => DomainStorySessionStatus::Completed,
StorySessionStatus::Archived => DomainStorySessionStatus::Archived,
}
}
pub(crate) fn map_battle_status(value: BattleStatus) -> DomainBattleStatus {
match value {
BattleStatus::Ongoing => DomainBattleStatus::Ongoing,
BattleStatus::Resolved => DomainBattleStatus::Resolved,
BattleStatus::Aborted => DomainBattleStatus::Aborted,
}
}
pub(crate) fn map_story_event_kind(value: StoryEventKind) -> DomainStoryEventKind {
match value {
StoryEventKind::SessionStarted => DomainStoryEventKind::SessionStarted,
StoryEventKind::StoryContinued => DomainStoryEventKind::StoryContinued,
}
}
pub(crate) fn map_ai_task_kind(value: DomainAiTaskKind) -> AiTaskKind {
match value {
DomainAiTaskKind::StoryGeneration => AiTaskKind::StoryGeneration,
DomainAiTaskKind::CharacterChat => AiTaskKind::CharacterChat,
DomainAiTaskKind::NpcChat => AiTaskKind::NpcChat,
DomainAiTaskKind::CustomWorldGeneration => AiTaskKind::CustomWorldGeneration,
DomainAiTaskKind::QuestIntent => AiTaskKind::QuestIntent,
DomainAiTaskKind::RuntimeItemIntent => AiTaskKind::RuntimeItemIntent,
}
}
pub(crate) fn map_ai_task_stage_kind(value: DomainAiTaskStageKind) -> AiTaskStageKind {
match value {
DomainAiTaskStageKind::PreparePrompt => AiTaskStageKind::PreparePrompt,
DomainAiTaskStageKind::RequestModel => AiTaskStageKind::RequestModel,
DomainAiTaskStageKind::RepairResponse => AiTaskStageKind::RepairResponse,
DomainAiTaskStageKind::NormalizeResult => AiTaskStageKind::NormalizeResult,
DomainAiTaskStageKind::PersistResult => AiTaskStageKind::PersistResult,
}
}
pub(crate) fn map_ai_result_reference_kind(
value: DomainAiResultReferenceKind,
) -> AiResultReferenceKind {
match value {
DomainAiResultReferenceKind::StorySession => AiResultReferenceKind::StorySession,
DomainAiResultReferenceKind::StoryEvent => AiResultReferenceKind::StoryEvent,
DomainAiResultReferenceKind::CustomWorldProfile => {
AiResultReferenceKind::CustomWorldProfile
}
DomainAiResultReferenceKind::QuestRecord => AiResultReferenceKind::QuestRecord,
DomainAiResultReferenceKind::RuntimeItemRecord => AiResultReferenceKind::RuntimeItemRecord,
DomainAiResultReferenceKind::AssetObject => AiResultReferenceKind::AssetObject,
}
}
pub(crate) fn format_ai_task_kind(value: AiTaskKind) -> &'static str {
match value {
AiTaskKind::StoryGeneration => "story_generation",
AiTaskKind::CharacterChat => "character_chat",
AiTaskKind::NpcChat => "npc_chat",
AiTaskKind::CustomWorldGeneration => "custom_world_generation",
AiTaskKind::QuestIntent => "quest_intent",
AiTaskKind::RuntimeItemIntent => "runtime_item_intent",
}
}
pub(crate) fn format_ai_task_status(value: AiTaskStatus) -> &'static str {
match value {
AiTaskStatus::Pending => "pending",
AiTaskStatus::Running => "running",
AiTaskStatus::Completed => "completed",
AiTaskStatus::Failed => "failed",
AiTaskStatus::Cancelled => "cancelled",
}
}
pub(crate) fn format_ai_task_stage_kind(value: AiTaskStageKind) -> &'static str {
match value {
AiTaskStageKind::PreparePrompt => "prepare_prompt",
AiTaskStageKind::RequestModel => "request_model",
AiTaskStageKind::RepairResponse => "repair_response",
AiTaskStageKind::NormalizeResult => "normalize_result",
AiTaskStageKind::PersistResult => "persist_result",
}
}
pub(crate) fn format_ai_task_stage_status(value: AiTaskStageStatus) -> &'static str {
match value {
AiTaskStageStatus::Pending => "pending",
AiTaskStageStatus::Running => "running",
AiTaskStageStatus::Completed => "completed",
AiTaskStageStatus::Skipped => "skipped",
}
}
pub(crate) fn format_ai_result_reference_kind(value: AiResultReferenceKind) -> &'static str {
match value {
AiResultReferenceKind::StorySession => "story_session",
AiResultReferenceKind::StoryEvent => "story_event",
AiResultReferenceKind::CustomWorldProfile => "custom_world_profile",
AiResultReferenceKind::QuestRecord => "quest_record",
AiResultReferenceKind::RuntimeItemRecord => "runtime_item_record",
AiResultReferenceKind::AssetObject => "asset_object",
}
}
pub(crate) fn map_combat_outcome(value: CombatOutcome) -> DomainCombatOutcome {
match value {
CombatOutcome::Ongoing => DomainCombatOutcome::Ongoing,
CombatOutcome::Victory => DomainCombatOutcome::Victory,
CombatOutcome::SparComplete => DomainCombatOutcome::SparComplete,
CombatOutcome::Escaped => DomainCombatOutcome::Escaped,
}
}
pub(crate) fn map_runtime_item_reward_item_snapshot(
snapshot: DomainRuntimeItemRewardItemSnapshot,
) -> RuntimeItemRewardItemSnapshot {
RuntimeItemRewardItemSnapshot {
item_id: snapshot.item_id,
category: snapshot.category,
item_name: snapshot.item_name,
description: snapshot.description,
quantity: snapshot.quantity,
rarity: map_runtime_item_reward_item_rarity(snapshot.rarity),
tags: snapshot.tags,
stackable: snapshot.stackable,
stack_key: snapshot.stack_key,
equipment_slot_id: snapshot
.equipment_slot_id
.map(map_runtime_item_equipment_slot),
}
}
pub(crate) fn map_runtime_item_reward_item_snapshot_back(
snapshot: RuntimeItemRewardItemSnapshot,
) -> DomainRuntimeItemRewardItemSnapshot {
DomainRuntimeItemRewardItemSnapshot {
item_id: snapshot.item_id,
category: snapshot.category,
item_name: snapshot.item_name,
description: snapshot.description,
quantity: snapshot.quantity,
rarity: map_runtime_item_reward_item_rarity_back(snapshot.rarity),
tags: snapshot.tags,
stackable: snapshot.stackable,
stack_key: snapshot.stack_key,
equipment_slot_id: snapshot
.equipment_slot_id
.map(map_runtime_item_equipment_slot_back),
}
}
pub(crate) fn parse_json_value(
value: &str,
label: &str,
) -> Result<serde_json::Value, SpacetimeClientError> {
serde_json::from_str::<serde_json::Value>(value)
.map_err(|error| SpacetimeClientError::Runtime(format!("{label} 非法: {error}")))
}
pub(crate) fn parse_optional_json_value(
value: Option<&str>,
fallback: serde_json::Value,
label: &str,
) -> Result<serde_json::Value, SpacetimeClientError> {
match value.map(str::trim).filter(|value| !value.is_empty()) {
Some(value) => parse_json_value(value, label),
None => Ok(fallback),
}
}
pub(crate) fn parse_json_array(
value: &str,
label: &str,
) -> Result<Vec<serde_json::Value>, SpacetimeClientError> {
match parse_json_value(value, label)? {
serde_json::Value::Array(entries) => Ok(entries),
_ => Err(SpacetimeClientError::Runtime(format!(
"{label} 必须是 JSON array"
))),
}
}
pub(crate) fn parse_json_string_array(
value: &str,
label: &str,
) -> Result<Vec<String>, SpacetimeClientError> {
parse_json_array(value, label)?
.into_iter()
.map(|entry| match entry {
serde_json::Value::String(value) => Ok(value),
_ => Err(SpacetimeClientError::Runtime(format!(
"{label} 必须是 string array"
))),
})
.collect()
}
pub(crate) fn map_custom_world_checkpoint_record(
value: serde_json::Value,
) -> Result<CustomWorldCheckpointRecord, SpacetimeClientError> {
let object = value.as_object().ok_or_else(|| {
SpacetimeClientError::Runtime("custom world checkpoint 必须是 JSON object".to_string())
})?;
let checkpoint_id = object
.get("checkpointId")
.and_then(serde_json::Value::as_str)
.map(str::trim)
.filter(|value| !value.is_empty())
.ok_or_else(|| {
SpacetimeClientError::Runtime("custom world checkpoint.checkpointId 缺失".to_string())
})?;
let created_at = object
.get("createdAt")
.and_then(serde_json::Value::as_str)
.map(str::trim)
.filter(|value| !value.is_empty())
.ok_or_else(|| {
SpacetimeClientError::Runtime("custom world checkpoint.createdAt 缺失".to_string())
})?;
let label = object
.get("label")
.and_then(serde_json::Value::as_str)
.map(str::trim)
.filter(|value| !value.is_empty())
.ok_or_else(|| {
SpacetimeClientError::Runtime("custom world checkpoint.label 缺失".to_string())
})?;
Ok(CustomWorldCheckpointRecord {
checkpoint_id: checkpoint_id.to_string(),
created_at: created_at.to_string(),
label: label.to_string(),
})
}
pub(crate) fn parse_supported_actions_json(
value: &str,
) -> Result<Vec<CustomWorldSupportedActionRecord>, SpacetimeClientError> {
parse_json_array(value, "custom world agent supported_actions_json")?
.into_iter()
.map(|entry| {
let object = entry.as_object().ok_or_else(|| {
SpacetimeClientError::Runtime(
"custom world supported action 必须是 JSON object".to_string(),
)
})?;
let action = object
.get("action")
.and_then(serde_json::Value::as_str)
.map(str::trim)
.filter(|value| !value.is_empty())
.ok_or_else(|| {
SpacetimeClientError::Runtime(
"custom world supported action.action 缺失".to_string(),
)
})?;
let enabled = object
.get("enabled")
.and_then(serde_json::Value::as_bool)
.ok_or_else(|| {
SpacetimeClientError::Runtime(
"custom world supported action.enabled 缺失".to_string(),
)
})?;
Ok(CustomWorldSupportedActionRecord {
action: action.to_string(),
enabled,
reason: object
.get("reason")
.and_then(serde_json::Value::as_str)
.map(str::trim)
.filter(|value| !value.is_empty())
.map(ToOwned::to_owned),
})
})
.collect()
}
pub(crate) fn parse_custom_world_publish_gate_record(
value: &str,
) -> Result<CustomWorldPublishGateRecord, SpacetimeClientError> {
let object = parse_json_value(value, "custom world publish_gate_json")?
.as_object()
.cloned()
.ok_or_else(|| {
SpacetimeClientError::Runtime(
"custom world publish_gate_json 必须是 JSON object".to_string(),
)
})?;
let profile_id = object
.get("profileId")
.and_then(serde_json::Value::as_str)
.map(str::trim)
.filter(|value| !value.is_empty())
.ok_or_else(|| {
SpacetimeClientError::Runtime("custom world publish_gate.profileId 缺失".to_string())
})?;
let blockers = object
.get("blockers")
.and_then(serde_json::Value::as_array)
.ok_or_else(|| {
SpacetimeClientError::Runtime("custom world publish_gate.blockers 缺失".to_string())
})?
.iter()
.cloned()
.map(|entry| {
let object = entry.as_object().ok_or_else(|| {
SpacetimeClientError::Runtime(
"custom world publish gate blocker 必须是 JSON object".to_string(),
)
})?;
let id = object
.get("id")
.and_then(serde_json::Value::as_str)
.map(str::trim)
.filter(|value| !value.is_empty())
.ok_or_else(|| {
SpacetimeClientError::Runtime(
"custom world publish gate blocker.id 缺失".to_string(),
)
})?;
let code = object
.get("code")
.and_then(serde_json::Value::as_str)
.map(str::trim)
.filter(|value| !value.is_empty())
.ok_or_else(|| {
SpacetimeClientError::Runtime(
"custom world publish gate blocker.code 缺失".to_string(),
)
})?;
let message = object
.get("message")
.and_then(serde_json::Value::as_str)
.map(str::trim)
.filter(|value| !value.is_empty())
.ok_or_else(|| {
SpacetimeClientError::Runtime(
"custom world publish gate blocker.message 缺失".to_string(),
)
})?;
Ok(CustomWorldResultPreviewBlockerRecord {
id: id.to_string(),
code: code.to_string(),
message: message.to_string(),
})
})
.collect::<Result<Vec<_>, _>>()?;
let blocker_count = object
.get("blockerCount")
.and_then(serde_json::Value::as_u64)
.and_then(|value| u32::try_from(value).ok())
.ok_or_else(|| {
SpacetimeClientError::Runtime("custom world publish_gate.blockerCount 缺失".to_string())
})?;
let publish_ready = object
.get("publishReady")
.and_then(serde_json::Value::as_bool)
.ok_or_else(|| {
SpacetimeClientError::Runtime("custom world publish_gate.publishReady 缺失".to_string())
})?;
let can_enter_world = object
.get("canEnterWorld")
.and_then(serde_json::Value::as_bool)
.ok_or_else(|| {
SpacetimeClientError::Runtime(
"custom world publish_gate.canEnterWorld 缺失".to_string(),
)
})?;
Ok(CustomWorldPublishGateRecord {
profile_id: profile_id.to_string(),
blockers,
blocker_count,
publish_ready,
can_enter_world,
})
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct BattleStateRecord {
pub battle_state_id: String,
pub story_session_id: String,
pub runtime_session_id: String,
pub actor_user_id: String,
pub chapter_id: Option<String>,
pub target_npc_id: String,
pub target_name: String,
pub battle_mode: String,
pub status: String,
pub player_hp: i32,
pub player_max_hp: i32,
pub player_mana: i32,
pub player_max_mana: i32,
pub target_hp: i32,
pub target_max_hp: i32,
pub experience_reward: u32,
pub reward_items: Vec<DomainRuntimeItemRewardItemSnapshot>,
pub turn_index: u32,
pub last_action_function_id: Option<String>,
pub last_action_text: Option<String>,
pub last_result_text: Option<String>,
pub last_damage_dealt: i32,
pub last_damage_taken: i32,
pub last_outcome: String,
pub version: u32,
pub created_at: String,
pub updated_at: String,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct ResolveCombatActionRecord {
pub battle_state: BattleStateRecord,
pub damage_dealt: i32,
pub damage_taken: i32,
pub outcome: String,
}
#[derive(Clone, Debug, PartialEq)]
pub struct CustomWorldLibraryEntryRecord {
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,
pub play_count: u32,
pub remix_count: u32,
pub like_count: u32,
pub recent_play_count_7d: u32,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct CustomWorldGalleryEntryRecord {
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,
pub play_count: u32,
pub remix_count: u32,
pub like_count: u32,
pub recent_play_count_7d: u32,
}
#[derive(Clone, Debug, PartialEq)]
pub struct CustomWorldLibraryMutationRecord {
pub entry: CustomWorldLibraryEntryRecord,
pub gallery_entry: Option<CustomWorldGalleryEntryRecord>,
}
#[derive(Clone, Debug, PartialEq)]
pub struct CustomWorldPublishedProfileCompileRecord {
pub profile_id: String,
pub owner_user_id: String,
pub world_name: String,
pub subtitle: String,
pub summary_text: String,
pub theme_mode: String,
pub cover_image_src: Option<String>,
pub playable_npc_count: u32,
pub landmark_count: u32,
pub author_display_name: String,
pub compiled_profile: serde_json::Value,
pub updated_at: String,
}
#[derive(Clone, Debug, PartialEq)]
pub struct CustomWorldPublishWorldRecord {
pub compiled_record: CustomWorldPublishedProfileCompileRecord,
pub entry: CustomWorldLibraryEntryRecord,
pub gallery_entry: Option<CustomWorldGalleryEntryRecord>,
pub session_stage: String,
}
#[derive(Clone, Debug, PartialEq)]
pub struct CustomWorldAgentMessageRecord {
pub message_id: String,
pub role: String,
pub kind: String,
pub text: String,
pub created_at: String,
pub related_operation_id: Option<String>,
}
#[derive(Clone, Debug, PartialEq)]
pub struct CustomWorldAgentOperationRecord {
pub operation_id: String,
pub operation_type: String,
pub status: String,
pub phase_label: String,
pub phase_detail: String,
pub progress: u32,
pub error_message: Option<String>,
pub started_at_micros: i64,
pub updated_at_micros: i64,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct CustomWorldAgentOperationProgressRecordInput {
pub session_id: String,
pub owner_user_id: String,
pub operation_id: String,
// SpacetimeDB 模块侧使用枚举存储操作类型,这里保留字符串给 API 层做轻量传参。
pub operation_type: String,
pub operation_status: String,
pub phase_label: String,
pub phase_detail: String,
pub operation_progress: u32,
pub error_message: Option<String>,
pub updated_at_micros: i64,
}
#[derive(Clone, Debug, PartialEq)]
pub struct CustomWorldDraftCardRecord {
pub card_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>,
pub detail_payload: Option<serde_json::Value>,
}
#[derive(Clone, Debug, PartialEq)]
pub struct CustomWorldSupportedActionRecord {
pub action: String,
pub enabled: bool,
pub reason: Option<String>,
}
#[derive(Clone, Debug, PartialEq)]
pub struct CustomWorldCheckpointRecord {
pub checkpoint_id: String,
pub created_at: String,
pub label: String,
}
// 兼容并行 custom world facade 中仍在使用的旧命名,避免本轮 module-npc 收口被无关改动阻塞。
pub type CustomWorldAgentCheckpointRecord = CustomWorldCheckpointRecord;
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct CustomWorldResultPreviewBlockerRecord {
pub id: String,
pub code: String,
pub message: String,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct CustomWorldPublishGateRecord {
pub profile_id: String,
pub blockers: Vec<CustomWorldResultPreviewBlockerRecord>,
pub blocker_count: u32,
pub publish_ready: bool,
pub can_enter_world: bool,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct CustomWorldWorkSummaryRecord {
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>,
pub cover_render_mode: Option<String>,
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, PartialEq, Eq)]
pub struct CustomWorldDraftCardDetailSectionRecord {
pub section_id: String,
pub label: String,
pub value: String,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct CustomWorldDraftCardDetailRecord {
pub card_id: String,
pub kind: String,
pub title: String,
pub sections: Vec<CustomWorldDraftCardDetailSectionRecord>,
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, PartialEq)]
pub struct CustomWorldAgentSessionRecord {
pub session_id: String,
pub seed_text: 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<CustomWorldAgentMessageRecord>,
pub draft_cards: Vec<CustomWorldDraftCardRecord>,
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<CustomWorldCheckpointRecord>,
pub supported_actions: Vec<CustomWorldSupportedActionRecord>,
pub publish_gate: Option<CustomWorldPublishGateRecord>,
pub result_preview: Option<serde_json::Value>,
pub updated_at: String,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct CustomWorldProfileUpsertRecordInput {
pub profile_id: String,
pub owner_user_id: String,
pub public_work_code: Option<String>,
pub author_public_user_code: Option<String>,
pub source_agent_session_id: Option<String>,
pub world_name: String,
pub subtitle: String,
pub summary_text: String,
pub theme_mode: DomainCustomWorldThemeMode,
pub cover_image_src: Option<String>,
pub profile_payload_json: String,
pub playable_npc_count: u32,
pub landmark_count: u32,
pub author_display_name: String,
pub updated_at_micros: i64,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct CustomWorldProfileRemixRecordInput {
pub source_owner_user_id: String,
pub source_profile_id: String,
pub target_owner_user_id: String,
pub target_profile_id: String,
pub author_display_name: String,
pub remixed_at_micros: i64,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct CustomWorldProfilePlayReportRecordInput {
pub owner_user_id: String,
pub profile_id: String,
pub played_at_micros: i64,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct CustomWorldProfileLikeReportRecordInput {
pub owner_user_id: String,
pub profile_id: String,
pub user_id: String,
pub liked_at_micros: i64,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct CustomWorldPublishWorldRecordInput {
pub session_id: String,
pub profile_id: String,
pub owner_user_id: String,
pub public_work_code: Option<String>,
pub author_public_user_code: String,
pub draft_profile_json: String,
pub legacy_result_profile_json: Option<String>,
pub setting_text: String,
pub author_display_name: String,
pub published_at_micros: i64,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct CustomWorldAgentSessionCreateRecordInput {
pub session_id: String,
pub owner_user_id: String,
pub seed_text: String,
pub welcome_message_id: String,
pub welcome_message_text: String,
pub anchor_content_json: String,
pub creator_intent_json: Option<String>,
pub creator_intent_readiness_json: String,
pub anchor_pack_json: Option<String>,
pub lock_state_json: Option<String>,
pub draft_profile_json: Option<String>,
pub pending_clarifications_json: String,
pub suggested_actions_json: String,
pub recommended_replies_json: String,
pub quality_findings_json: String,
pub asset_coverage_json: String,
pub checkpoints_json: String,
pub created_at_micros: i64,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct CustomWorldAgentMessageSubmitRecordInput {
pub session_id: String,
pub owner_user_id: String,
pub user_message_id: String,
pub user_message_text: String,
pub operation_id: String,
pub submitted_at_micros: i64,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct CustomWorldAgentMessageFinalizeRecordInput {
pub session_id: String,
pub owner_user_id: String,
pub operation_id: String,
pub assistant_message_id: Option<String>,
pub assistant_reply_text: Option<String>,
pub phase_label: String,
pub phase_detail: String,
pub operation_status: String,
pub operation_progress: u32,
pub stage: String,
pub progress_percent: u32,
pub focus_card_id: Option<String>,
pub anchor_content_json: String,
pub creator_intent_json: Option<String>,
pub creator_intent_readiness_json: String,
pub anchor_pack_json: Option<String>,
pub draft_profile_json: Option<String>,
pub pending_clarifications_json: String,
pub suggested_actions_json: String,
pub recommended_replies_json: String,
pub quality_findings_json: String,
pub asset_coverage_json: String,
pub error_message: Option<String>,
pub updated_at_micros: i64,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct CustomWorldAgentActionExecuteRecordInput {
pub session_id: String,
pub owner_user_id: String,
pub operation_id: String,
pub action: String,
pub payload_json: Option<String>,
pub submitted_at_micros: i64,
}
#[derive(Clone, Debug, PartialEq)]
pub struct CustomWorldAgentActionExecuteRecord {
pub operation: CustomWorldAgentOperationRecord,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct PuzzleAgentSessionCreateRecordInput {
pub session_id: String,
pub owner_user_id: String,
pub seed_text: String,
pub welcome_message_id: String,
pub welcome_message_text: String,
pub created_at_micros: i64,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct PuzzleFormDraftSaveRecordInput {
pub session_id: String,
pub owner_user_id: String,
pub seed_text: String,
pub saved_at_micros: i64,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct PuzzleAgentMessageSubmitRecordInput {
pub session_id: String,
pub owner_user_id: String,
pub user_message_id: String,
pub user_message_text: String,
pub submitted_at_micros: i64,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct PuzzleAgentMessageFinalizeRecordInput {
pub session_id: String,
pub owner_user_id: String,
pub assistant_message_id: Option<String>,
pub assistant_reply_text: Option<String>,
pub stage: String,
pub progress_percent: u32,
pub anchor_pack_json: String,
pub error_message: Option<String>,
pub updated_at_micros: i64,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct PuzzleGeneratedImagesSaveRecordInput {
pub session_id: String,
pub owner_user_id: String,
pub level_id: Option<String>,
pub levels_json: Option<String>,
pub candidates_json: String,
pub saved_at_micros: i64,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct PuzzleUiBackgroundSaveRecordInput {
pub session_id: String,
pub owner_user_id: String,
pub level_id: Option<String>,
pub levels_json: Option<String>,
pub prompt: String,
pub image_src: String,
pub image_object_key: Option<String>,
pub saved_at_micros: i64,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct PuzzleSelectCoverImageRecordInput {
pub session_id: String,
pub owner_user_id: String,
pub level_id: Option<String>,
pub candidate_id: String,
pub selected_at_micros: i64,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct PuzzlePublishRecordInput {
pub session_id: String,
pub owner_user_id: String,
pub work_id: String,
pub profile_id: String,
pub author_display_name: String,
pub work_title: Option<String>,
pub work_description: Option<String>,
pub level_name: Option<String>,
pub summary: Option<String>,
pub theme_tags: Option<Vec<String>>,
pub levels_json: Option<String>,
pub published_at_micros: i64,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct PuzzleWorkUpsertRecordInput {
pub profile_id: String,
pub owner_user_id: String,
pub work_title: String,
pub work_description: String,
pub level_name: String,
pub summary: String,
pub theme_tags: Vec<String>,
pub cover_image_src: Option<String>,
pub cover_asset_id: Option<String>,
pub levels_json: Option<String>,
pub updated_at_micros: i64,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct PuzzleWorkRemixRecordInput {
pub source_profile_id: String,
pub target_owner_user_id: String,
pub target_session_id: String,
pub target_profile_id: String,
pub target_work_id: String,
pub author_display_name: String,
pub welcome_message_id: String,
pub remixed_at_micros: i64,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct PuzzleWorkLikeReportRecordInput {
pub profile_id: String,
pub user_id: String,
pub liked_at_micros: i64,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct PuzzleRunStartRecordInput {
pub run_id: String,
pub owner_user_id: String,
pub profile_id: String,
pub level_id: Option<String>,
pub started_at_micros: i64,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct PuzzleRunSwapRecordInput {
pub run_id: String,
pub owner_user_id: String,
pub first_piece_id: String,
pub second_piece_id: String,
pub swapped_at_micros: i64,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct PuzzleRunDragRecordInput {
pub run_id: String,
pub owner_user_id: String,
pub piece_id: String,
pub target_row: u32,
pub target_col: u32,
pub dragged_at_micros: i64,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct PuzzleRunNextLevelRecordInput {
pub run_id: String,
pub owner_user_id: String,
pub target_profile_id: Option<String>,
pub advanced_at_micros: i64,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct PuzzleRunPauseRecordInput {
pub run_id: String,
pub owner_user_id: String,
pub paused: bool,
pub updated_at_micros: i64,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct PuzzleRunPropRecordInput {
pub run_id: String,
pub owner_user_id: String,
pub prop_kind: String,
pub used_at_micros: i64,
pub spent_points: u64,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct BigFishPlayReportRecordInput {
pub session_id: String,
pub user_id: String,
pub elapsed_ms: u64,
pub reported_at_micros: i64,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct BigFishRunStartRecordInput {
pub run_id: String,
pub session_id: String,
pub owner_user_id: String,
pub started_at_micros: i64,
}
#[derive(Clone, Debug, PartialEq)]
pub struct BigFishInputSubmitRecordInput {
pub run_id: String,
pub owner_user_id: String,
pub x: f32,
pub y: f32,
pub submitted_at_micros: i64,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct BigFishLikeReportRecordInput {
pub session_id: String,
pub user_id: String,
pub liked_at_micros: i64,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct BigFishWorkRemixRecordInput {
pub source_session_id: String,
pub target_session_id: String,
pub target_owner_user_id: String,
pub welcome_message_id: String,
pub remixed_at_micros: i64,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct Match3DAgentSessionCreateRecordInput {
pub session_id: String,
pub owner_user_id: String,
pub seed_text: String,
pub welcome_message_id: String,
pub welcome_message_text: String,
pub config_json: Option<String>,
pub created_at_micros: i64,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct Match3DAgentMessageSubmitRecordInput {
pub session_id: String,
pub owner_user_id: String,
pub user_message_id: String,
pub user_message_text: String,
pub submitted_at_micros: i64,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct Match3DAgentMessageFinalizeRecordInput {
pub session_id: String,
pub owner_user_id: String,
pub assistant_message_id: Option<String>,
pub assistant_reply_text: Option<String>,
pub config_json: Option<String>,
pub progress_percent: u32,
pub stage: String,
pub updated_at_micros: i64,
pub error_message: Option<String>,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct Match3DCompileDraftRecordInput {
pub session_id: String,
pub owner_user_id: String,
pub profile_id: String,
pub author_display_name: String,
pub game_name: Option<String>,
pub summary_text: Option<String>,
pub tags_json: Option<String>,
pub cover_image_src: Option<String>,
pub cover_asset_id: Option<String>,
pub compiled_at_micros: i64,
pub generated_item_assets_json: Option<String>,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct Match3DWorkUpdateRecordInput {
pub profile_id: String,
pub owner_user_id: String,
pub game_name: String,
pub theme_text: String,
pub summary_text: String,
pub tags_json: String,
pub cover_image_src: String,
pub cover_asset_id: String,
pub clear_count: u32,
pub difficulty: u32,
pub updated_at_micros: i64,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct Match3DRunStartRecordInput {
pub run_id: String,
pub owner_user_id: String,
pub profile_id: String,
pub started_at_ms: i64,
pub item_type_count_override: u32,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct Match3DRunClickRecordInput {
pub run_id: String,
pub owner_user_id: String,
pub item_instance_id: String,
pub client_snapshot_version: u32,
pub client_event_id: String,
pub clicked_at_ms: i64,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct Match3DRunStopRecordInput {
pub run_id: String,
pub owner_user_id: String,
pub stopped_at_ms: i64,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct Match3DRunRestartRecordInput {
pub source_run_id: String,
pub next_run_id: String,
pub owner_user_id: String,
pub restarted_at_ms: i64,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct Match3DRunTimeUpRecordInput {
pub run_id: String,
pub owner_user_id: String,
pub finished_at_ms: i64,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct Match3DAnchorItemRecord {
pub key: String,
pub label: String,
pub value: String,
pub status: String,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct Match3DAnchorPackRecord {
pub theme: Match3DAnchorItemRecord,
pub clear_count: Match3DAnchorItemRecord,
pub difficulty: Match3DAnchorItemRecord,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct Match3DCreatorConfigRecord {
pub theme_text: String,
pub reference_image_src: Option<String>,
pub clear_count: u32,
pub difficulty: u32,
pub asset_style_id: Option<String>,
pub asset_style_label: Option<String>,
pub asset_style_prompt: Option<String>,
pub generate_click_sound: bool,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct Match3DResultDraftRecord {
pub profile_id: String,
pub game_name: String,
pub theme_text: String,
pub summary_text: String,
pub tags: Vec<String>,
pub cover_image_src: Option<String>,
pub reference_image_src: Option<String>,
pub clear_count: u32,
pub difficulty: u32,
pub total_item_count: u32,
pub publish_ready: bool,
pub blockers: Vec<String>,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct Match3DAgentMessageRecord {
pub message_id: String,
pub role: String,
pub kind: String,
pub text: String,
pub created_at: String,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct Match3DAgentSessionRecord {
pub session_id: String,
pub current_turn: u32,
pub progress_percent: u32,
pub stage: String,
pub anchor_pack: Match3DAnchorPackRecord,
pub config: Option<Match3DCreatorConfigRecord>,
pub draft: Option<Match3DResultDraftRecord>,
pub messages: Vec<Match3DAgentMessageRecord>,
pub last_assistant_reply: Option<String>,
pub published_profile_id: Option<String>,
pub updated_at: String,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct Match3DWorkProfileRecord {
pub work_id: String,
pub profile_id: String,
pub owner_user_id: String,
pub source_session_id: Option<String>,
pub author_display_name: String,
pub game_name: String,
pub theme_text: String,
pub summary: String,
pub tags: Vec<String>,
pub cover_image_src: Option<String>,
pub cover_asset_id: Option<String>,
pub reference_image_src: Option<String>,
pub clear_count: u32,
pub difficulty: u32,
pub publication_status: String,
pub play_count: u32,
pub updated_at: String,
pub published_at: Option<String>,
pub publish_ready: bool,
pub generated_item_assets_json: Option<String>,
}
#[derive(Clone, Debug, PartialEq)]
pub struct Match3DItemSnapshotRecord {
pub item_instance_id: String,
pub item_type_id: String,
pub visual_key: String,
pub x: f32,
pub y: f32,
pub radius: f32,
pub layer: u32,
pub state: String,
pub clickable: bool,
pub tray_slot_index: Option<u32>,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct Match3DTraySlotRecord {
pub slot_index: u32,
pub item_instance_id: Option<String>,
pub item_type_id: Option<String>,
pub visual_key: Option<String>,
}
#[derive(Clone, Debug, PartialEq)]
pub struct Match3DRunRecord {
pub run_id: String,
pub profile_id: String,
pub owner_user_id: String,
pub status: String,
pub snapshot_version: u64,
pub started_at_ms: u64,
pub duration_limit_ms: u64,
pub server_now_ms: Option<u64>,
pub remaining_ms: u64,
pub clear_count: u32,
pub total_item_count: u32,
pub cleared_item_count: u32,
pub items: Vec<Match3DItemSnapshotRecord>,
pub tray_slots: Vec<Match3DTraySlotRecord>,
pub failure_reason: Option<String>,
pub last_confirmed_action_id: Option<String>,
}
#[derive(Clone, Debug, PartialEq)]
pub struct Match3DClickConfirmationRecord {
pub status: String,
pub accepted: bool,
pub reject_reason: Option<String>,
pub accepted_item_instance_id: Option<String>,
pub entered_slot_index: Option<u32>,
pub cleared_item_instance_ids: Vec<String>,
pub failure_reason: Option<String>,
pub run: Match3DRunRecord,
}
#[derive(Clone, Debug, PartialEq, Eq, serde::Deserialize)]
#[serde(rename_all = "camelCase")]
struct Match3DCreatorConfigJsonRecord {
theme_text: String,
reference_image_src: Option<String>,
clear_count: u32,
difficulty: u32,
#[serde(default)]
asset_style_id: Option<String>,
#[serde(default)]
asset_style_label: Option<String>,
#[serde(default)]
asset_style_prompt: Option<String>,
#[serde(default)]
generate_click_sound: bool,
}
#[derive(Clone, Debug, PartialEq, Eq, serde::Deserialize)]
#[serde(rename_all = "camelCase")]
struct Match3DAgentMessageJsonRecord {
message_id: String,
#[allow(dead_code)]
session_id: String,
role: String,
kind: String,
text: String,
created_at_micros: i64,
}
#[derive(Clone, Debug, PartialEq, Eq, serde::Deserialize)]
#[serde(rename_all = "camelCase")]
struct Match3DDraftJsonRecord {
profile_id: String,
game_name: String,
theme_text: String,
summary_text: String,
tags: Vec<String>,
clear_count: u32,
difficulty: u32,
}
#[derive(Clone, Debug, PartialEq, Eq, serde::Deserialize)]
#[serde(rename_all = "camelCase")]
struct Match3DAgentSessionJsonRecord {
session_id: String,
#[allow(dead_code)]
owner_user_id: String,
#[allow(dead_code)]
seed_text: String,
current_turn: u32,
progress_percent: u32,
stage: String,
config: Match3DCreatorConfigJsonRecord,
draft: Option<Match3DDraftJsonRecord>,
messages: Vec<Match3DAgentMessageJsonRecord>,
last_assistant_reply: String,
published_profile_id: Option<String>,
#[allow(dead_code)]
created_at_micros: i64,
updated_at_micros: i64,
}
#[derive(Clone, Debug, PartialEq, Eq, serde::Deserialize)]
#[serde(rename_all = "camelCase")]
struct Match3DWorkJsonRecord {
profile_id: String,
owner_user_id: String,
source_session_id: String,
author_display_name: String,
game_name: String,
theme_text: String,
summary_text: String,
tags: Vec<String>,
cover_image_src: String,
cover_asset_id: String,
clear_count: u32,
difficulty: u32,
config: Match3DCreatorConfigJsonRecord,
publication_status: String,
publish_ready: bool,
play_count: u32,
updated_at_micros: i64,
published_at_micros: Option<i64>,
#[serde(default)]
generated_item_assets_json: Option<String>,
}
#[derive(Clone, Debug, PartialEq, serde::Deserialize)]
#[serde(rename_all = "camelCase")]
struct Match3DItemJsonRecord {
item_instance_id: String,
item_type_id: String,
visual_key: String,
x: f32,
y: f32,
radius: f32,
layer: u32,
state: String,
clickable: bool,
}
#[derive(Clone, Debug, PartialEq, Eq, serde::Deserialize)]
#[serde(rename_all = "camelCase")]
struct Match3DTraySlotJsonRecord {
slot_index: u32,
item_instance_id: Option<String>,
item_type_id: Option<String>,
visual_key: Option<String>,
}
#[derive(Clone, Debug, PartialEq, serde::Deserialize)]
#[serde(rename_all = "camelCase")]
struct Match3DRunJsonRecord {
run_id: String,
profile_id: String,
status: String,
snapshot_version: u32,
started_at_ms: i64,
duration_limit_ms: i64,
server_now_ms: i64,
remaining_ms: i64,
clear_count: u32,
total_item_count: u32,
cleared_item_count: u32,
tray_slots: Vec<Match3DTraySlotJsonRecord>,
items: Vec<Match3DItemJsonRecord>,
failure_reason: Option<String>,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct SquareHoleAgentSessionCreateRecordInput {
pub session_id: String,
pub owner_user_id: String,
pub seed_text: String,
pub welcome_message_id: String,
pub welcome_message_text: String,
pub config_json: Option<String>,
pub created_at_micros: i64,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct SquareHoleAgentMessageSubmitRecordInput {
pub session_id: String,
pub owner_user_id: String,
pub user_message_id: String,
pub user_message_text: String,
pub submitted_at_micros: i64,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct SquareHoleAgentMessageFinalizeRecordInput {
pub session_id: String,
pub owner_user_id: String,
pub assistant_message_id: Option<String>,
pub assistant_reply_text: Option<String>,
pub config_json: Option<String>,
pub progress_percent: u32,
pub stage: String,
pub updated_at_micros: i64,
pub error_message: Option<String>,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct SquareHoleCompileDraftRecordInput {
pub session_id: String,
pub owner_user_id: String,
pub profile_id: String,
pub author_display_name: String,
pub game_name: Option<String>,
pub summary_text: Option<String>,
pub tags_json: Option<String>,
pub cover_image_src: Option<String>,
pub compiled_at_micros: i64,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct SquareHoleWorkUpdateRecordInput {
pub profile_id: String,
pub owner_user_id: String,
pub game_name: String,
pub theme_text: String,
pub twist_rule: String,
pub summary_text: String,
pub tags_json: String,
pub cover_image_src: String,
pub background_prompt: String,
pub background_image_src: String,
pub shape_options_json: String,
pub hole_options_json: String,
pub shape_count: u32,
pub difficulty: u32,
pub updated_at_micros: i64,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct SquareHoleRunStartRecordInput {
pub run_id: String,
pub owner_user_id: String,
pub profile_id: String,
pub started_at_ms: i64,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct SquareHoleRunDropRecordInput {
pub run_id: String,
pub owner_user_id: String,
pub hole_id: String,
pub client_snapshot_version: u64,
pub client_event_id: String,
pub dropped_at_ms: i64,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct SquareHoleRunStopRecordInput {
pub run_id: String,
pub owner_user_id: String,
pub stopped_at_ms: i64,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct SquareHoleRunRestartRecordInput {
pub source_run_id: String,
pub next_run_id: String,
pub owner_user_id: String,
pub restarted_at_ms: i64,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct SquareHoleRunTimeUpRecordInput {
pub run_id: String,
pub owner_user_id: String,
pub finished_at_ms: i64,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct VisualNovelAgentSessionCreateRecordInput {
pub session_id: String,
pub owner_user_id: String,
pub source_mode: String,
pub seed_text: String,
pub source_asset_ids_json: String,
pub welcome_message_id: String,
pub welcome_message_text: String,
pub draft_json: Option<String>,
pub created_at_micros: i64,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct VisualNovelAgentMessageSubmitRecordInput {
pub session_id: String,
pub owner_user_id: String,
pub user_message_id: String,
pub user_message_text: String,
pub submitted_at_micros: i64,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct VisualNovelAgentMessageFinalizeRecordInput {
pub session_id: String,
pub owner_user_id: String,
pub assistant_message_id: Option<String>,
pub assistant_reply_text: Option<String>,
pub draft_json: Option<String>,
pub pending_action_json: Option<String>,
pub status: String,
pub progress_percent: u32,
pub updated_at_micros: i64,
pub error_message: Option<String>,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct VisualNovelWorkCompileRecordInput {
pub session_id: String,
pub owner_user_id: String,
pub profile_id: String,
pub work_id: Option<String>,
pub author_display_name: String,
pub work_title: Option<String>,
pub work_description: Option<String>,
pub tags_json: Option<String>,
pub cover_image_src: Option<String>,
pub compiled_at_micros: i64,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct VisualNovelWorkUpdateRecordInput {
pub profile_id: String,
pub owner_user_id: String,
pub work_title: String,
pub work_description: String,
pub tags_json: String,
pub cover_image_src: Option<String>,
pub source_asset_ids_json: String,
pub draft_json: String,
pub publish_ready: bool,
pub updated_at_micros: i64,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct VisualNovelRunStartRecordInput {
pub run_id: String,
pub owner_user_id: String,
pub profile_id: String,
pub mode: String,
pub snapshot_json: Option<String>,
pub started_at_micros: i64,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct VisualNovelRunSnapshotRecordInput {
pub run_id: String,
pub owner_user_id: String,
pub status: String,
pub current_scene_id: Option<String>,
pub current_phase_id: Option<String>,
pub visible_character_ids_json: String,
pub flags_json: String,
pub metrics_json: String,
pub available_choices_json: String,
pub text_mode_enabled: bool,
pub snapshot_json: Option<String>,
pub updated_at_micros: i64,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct VisualNovelHistoryEntryRecordInput {
pub entry_id: String,
pub run_id: String,
pub owner_user_id: String,
pub turn_index: u32,
pub source: String,
pub action_text: Option<String>,
pub steps_json: String,
pub snapshot_before_hash: Option<String>,
pub snapshot_after_hash: Option<String>,
pub created_at_micros: i64,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct VisualNovelRuntimeEventRecordInput {
pub event_id: String,
pub run_id: String,
pub owner_user_id: String,
pub profile_id: Option<String>,
pub event_kind: String,
pub client_event_id: Option<String>,
pub history_entry_id: Option<String>,
pub payload_json: String,
pub occurred_at_micros: i64,
}
#[derive(Clone, Debug, PartialEq)]
pub struct VisualNovelAgentMessageRecord {
pub message_id: String,
pub session_id: String,
pub role: String,
pub kind: String,
pub text: String,
pub created_at: String,
}
#[derive(Clone, Debug, PartialEq)]
pub struct VisualNovelAgentSessionRecord {
pub session_id: String,
pub owner_user_id: String,
pub source_mode: String,
pub status: String,
pub seed_text: String,
pub source_asset_ids: Vec<String>,
pub current_turn: u32,
pub progress_percent: u32,
pub messages: Vec<VisualNovelAgentMessageRecord>,
pub draft: Option<serde_json::Value>,
pub pending_action: Option<serde_json::Value>,
pub last_assistant_reply: Option<String>,
pub published_profile_id: Option<String>,
pub created_at: String,
pub updated_at: String,
}
#[derive(Clone, Debug, PartialEq)]
pub struct VisualNovelWorkProfileRecord {
pub work_id: String,
pub profile_id: String,
pub owner_user_id: String,
pub source_session_id: Option<String>,
pub author_display_name: String,
pub work_title: String,
pub work_description: String,
pub tags: Vec<String>,
pub cover_image_src: Option<String>,
pub source_asset_ids: Vec<String>,
pub draft: serde_json::Value,
pub publication_status: String,
pub publish_ready: bool,
pub play_count: u32,
pub created_at: String,
pub updated_at: String,
pub published_at: Option<String>,
}
#[derive(Clone, Debug, PartialEq)]
pub struct VisualNovelHistoryEntryRecord {
pub entry_id: String,
pub run_id: String,
pub owner_user_id: String,
pub profile_id: String,
pub turn_index: u32,
pub source: String,
pub action_text: Option<String>,
pub steps: serde_json::Value,
pub snapshot_before_hash: Option<String>,
pub snapshot_after_hash: Option<String>,
pub created_at: String,
}
#[derive(Clone, Debug, PartialEq)]
pub struct VisualNovelRunRecord {
pub run_id: String,
pub owner_user_id: String,
pub profile_id: String,
pub mode: String,
pub status: String,
pub current_scene_id: Option<String>,
pub current_phase_id: Option<String>,
pub visible_character_ids: Vec<String>,
pub flags: serde_json::Value,
pub metrics: serde_json::Value,
pub history: Vec<VisualNovelHistoryEntryRecord>,
pub available_choices: serde_json::Value,
pub text_mode_enabled: bool,
pub created_at: String,
pub updated_at: String,
}
#[derive(Clone, Debug, PartialEq)]
pub struct VisualNovelRuntimeEventRecord {
pub event_id: String,
pub run_id: Option<String>,
pub owner_user_id: String,
pub profile_id: Option<String>,
pub event_kind: String,
pub client_event_id: Option<String>,
pub history_entry_id: Option<String>,
pub payload: serde_json::Value,
pub occurred_at: String,
}
#[derive(Clone, Debug, PartialEq, serde::Deserialize)]
#[serde(rename_all = "camelCase")]
struct VisualNovelAgentMessageJsonRecord {
message_id: String,
session_id: String,
role: String,
kind: String,
text: String,
created_at_micros: i64,
}
#[derive(Clone, Debug, PartialEq, serde::Deserialize)]
#[serde(rename_all = "camelCase")]
struct VisualNovelAgentSessionJsonRecord {
session_id: String,
owner_user_id: String,
source_mode: String,
status: String,
seed_text: String,
source_asset_ids: Vec<String>,
current_turn: u32,
progress_percent: u32,
messages: Vec<VisualNovelAgentMessageJsonRecord>,
draft: Option<serde_json::Value>,
pending_action: Option<serde_json::Value>,
last_assistant_reply: Option<String>,
published_profile_id: Option<String>,
created_at_micros: i64,
updated_at_micros: i64,
}
#[derive(Clone, Debug, PartialEq, serde::Deserialize)]
#[serde(rename_all = "camelCase")]
struct VisualNovelWorkJsonRecord {
work_id: String,
profile_id: String,
owner_user_id: String,
source_session_id: Option<String>,
author_display_name: String,
work_title: String,
work_description: String,
tags: Vec<String>,
cover_image_src: Option<String>,
source_asset_ids: Vec<String>,
draft: serde_json::Value,
publication_status: String,
publish_ready: bool,
play_count: u32,
created_at_micros: i64,
updated_at_micros: i64,
published_at_micros: Option<i64>,
}
#[derive(Clone, Debug, PartialEq, serde::Deserialize)]
#[serde(rename_all = "camelCase")]
struct VisualNovelHistoryEntryJsonRecord {
entry_id: String,
run_id: String,
owner_user_id: String,
profile_id: String,
turn_index: u32,
source: String,
action_text: Option<String>,
steps: serde_json::Value,
snapshot_before_hash: Option<String>,
snapshot_after_hash: Option<String>,
created_at_micros: i64,
}
#[derive(Clone, Debug, PartialEq, serde::Deserialize)]
#[serde(rename_all = "camelCase")]
struct VisualNovelRunJsonRecord {
run_id: String,
owner_user_id: String,
profile_id: String,
mode: String,
status: String,
current_scene_id: Option<String>,
current_phase_id: Option<String>,
visible_character_ids: Vec<String>,
flags: serde_json::Value,
metrics: serde_json::Value,
history: Vec<VisualNovelHistoryEntryJsonRecord>,
available_choices: serde_json::Value,
text_mode_enabled: bool,
created_at_micros: i64,
updated_at_micros: i64,
}
#[derive(Clone, Debug, PartialEq, serde::Deserialize)]
#[serde(rename_all = "camelCase")]
struct VisualNovelRuntimeEventJsonRecord {
event_id: String,
run_id: Option<String>,
owner_user_id: String,
profile_id: Option<String>,
event_kind: String,
client_event_id: Option<String>,
history_entry_id: Option<String>,
payload: serde_json::Value,
occurred_at_micros: i64,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct SquareHoleAnchorItemRecord {
pub key: String,
pub label: String,
pub value: String,
pub status: String,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct SquareHoleAnchorPackRecord {
pub theme: SquareHoleAnchorItemRecord,
pub twist_rule: SquareHoleAnchorItemRecord,
pub shape_count: SquareHoleAnchorItemRecord,
pub difficulty: SquareHoleAnchorItemRecord,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct SquareHoleCreatorConfigRecord {
pub theme_text: String,
pub twist_rule: String,
pub shape_count: u32,
pub difficulty: u32,
pub shape_options: Vec<SquareHoleShapeOptionRecord>,
pub hole_options: Vec<SquareHoleHoleOptionRecord>,
pub background_prompt: String,
pub cover_image_src: Option<String>,
pub background_image_src: Option<String>,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct SquareHoleShapeOptionRecord {
pub option_id: String,
pub shape_kind: String,
pub label: String,
pub target_hole_id: String,
pub image_prompt: String,
pub image_src: Option<String>,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct SquareHoleHoleOptionRecord {
pub hole_id: String,
pub hole_kind: String,
pub label: String,
pub image_prompt: String,
pub image_src: Option<String>,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct SquareHoleResultDraftRecord {
pub profile_id: String,
pub game_name: String,
pub theme_text: String,
pub twist_rule: String,
pub summary: String,
pub tags: Vec<String>,
pub cover_image_src: Option<String>,
pub background_prompt: String,
pub background_image_src: Option<String>,
pub shape_options: Vec<SquareHoleShapeOptionRecord>,
pub hole_options: Vec<SquareHoleHoleOptionRecord>,
pub shape_count: u32,
pub difficulty: u32,
pub publish_ready: bool,
pub blockers: Vec<String>,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct SquareHoleAgentMessageRecord {
pub id: String,
pub role: String,
pub kind: String,
pub text: String,
pub created_at: String,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct SquareHoleAgentSessionRecord {
pub session_id: String,
pub current_turn: u32,
pub progress_percent: u32,
pub stage: String,
pub anchor_pack: SquareHoleAnchorPackRecord,
pub config: SquareHoleCreatorConfigRecord,
pub draft: Option<SquareHoleResultDraftRecord>,
pub messages: Vec<SquareHoleAgentMessageRecord>,
pub last_assistant_reply: Option<String>,
pub published_profile_id: Option<String>,
pub updated_at: String,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct SquareHoleWorkProfileRecord {
pub work_id: String,
pub profile_id: String,
pub owner_user_id: String,
pub source_session_id: Option<String>,
pub author_display_name: String,
pub game_name: String,
pub theme_text: String,
pub twist_rule: String,
pub summary: String,
pub tags: Vec<String>,
pub cover_image_src: Option<String>,
pub background_prompt: String,
pub background_image_src: Option<String>,
pub shape_options: Vec<SquareHoleShapeOptionRecord>,
pub hole_options: Vec<SquareHoleHoleOptionRecord>,
pub shape_count: u32,
pub difficulty: u32,
pub publication_status: String,
pub play_count: u32,
pub updated_at: String,
pub published_at: Option<String>,
pub publish_ready: bool,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct SquareHoleShapeSnapshotRecord {
pub shape_id: String,
pub shape_kind: String,
pub label: String,
pub target_hole_id: String,
pub color: String,
pub image_src: Option<String>,
}
#[derive(Clone, Debug, PartialEq)]
pub struct SquareHoleHoleSnapshotRecord {
pub hole_id: String,
pub hole_kind: String,
pub label: String,
pub x: f32,
pub y: f32,
pub image_src: Option<String>,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct SquareHoleDropFeedbackRecord {
pub accepted: bool,
pub reject_reason: Option<String>,
pub message: String,
}
#[derive(Clone, Debug, PartialEq)]
pub struct SquareHoleRunRecord {
pub run_id: String,
pub profile_id: String,
pub owner_user_id: String,
pub status: String,
pub snapshot_version: u64,
pub started_at_ms: u64,
pub duration_limit_ms: u64,
pub server_now_ms: Option<u64>,
pub remaining_ms: u64,
pub total_shape_count: u32,
pub completed_shape_count: u32,
pub combo: u32,
pub best_combo: u32,
pub score: u32,
pub rule_label: String,
pub background_image_src: Option<String>,
pub current_shape: Option<SquareHoleShapeSnapshotRecord>,
pub holes: Vec<SquareHoleHoleSnapshotRecord>,
pub last_feedback: Option<SquareHoleDropFeedbackRecord>,
pub last_confirmed_action_id: Option<String>,
}
#[derive(Clone, Debug, PartialEq)]
pub struct SquareHoleDropConfirmationRecord {
pub status: String,
pub accepted: bool,
pub reject_reason: Option<String>,
pub failure_reason: Option<String>,
pub feedback: SquareHoleDropFeedbackRecord,
pub run: SquareHoleRunRecord,
}
#[derive(Clone, Debug, PartialEq, Eq, serde::Deserialize)]
#[serde(rename_all = "camelCase")]
struct SquareHoleCreatorConfigJsonRecord {
theme_text: String,
twist_rule: String,
shape_count: u32,
difficulty: u32,
#[serde(default)]
shape_options: Vec<SquareHoleShapeOptionJsonRecord>,
#[serde(default)]
hole_options: Vec<SquareHoleHoleOptionJsonRecord>,
#[serde(default)]
background_prompt: String,
#[serde(default)]
cover_image_src: String,
#[serde(default)]
background_image_src: String,
}
#[derive(Clone, Debug, PartialEq, Eq, serde::Deserialize)]
#[serde(rename_all = "camelCase")]
struct SquareHoleShapeOptionJsonRecord {
option_id: String,
shape_kind: String,
label: String,
#[serde(default)]
target_hole_id: String,
image_prompt: String,
#[serde(default)]
image_src: String,
}
#[derive(Clone, Debug, PartialEq, Eq, serde::Deserialize)]
#[serde(rename_all = "camelCase")]
struct SquareHoleHoleOptionJsonRecord {
hole_id: String,
hole_kind: String,
label: String,
#[serde(default)]
image_prompt: String,
#[serde(default)]
image_src: String,
#[serde(default)]
bonus: bool,
}
#[derive(Clone, Debug, PartialEq, Eq, serde::Deserialize)]
#[serde(rename_all = "camelCase")]
struct SquareHoleAgentMessageJsonRecord {
message_id: String,
#[allow(dead_code)]
session_id: String,
role: String,
kind: String,
text: String,
created_at_micros: i64,
}
#[derive(Clone, Debug, PartialEq, Eq, serde::Deserialize)]
#[serde(rename_all = "camelCase")]
struct SquareHoleDraftJsonRecord {
profile_id: String,
game_name: String,
theme_text: String,
twist_rule: String,
summary_text: String,
tags: Vec<String>,
#[serde(default)]
cover_image_src: String,
#[serde(default)]
background_prompt: String,
#[serde(default)]
background_image_src: String,
#[serde(default)]
shape_options: Vec<SquareHoleShapeOptionJsonRecord>,
#[serde(default)]
hole_options: Vec<SquareHoleHoleOptionJsonRecord>,
shape_count: u32,
difficulty: u32,
}
#[derive(Clone, Debug, PartialEq, Eq, serde::Deserialize)]
#[serde(rename_all = "camelCase")]
struct SquareHoleAgentSessionJsonRecord {
session_id: String,
#[allow(dead_code)]
owner_user_id: String,
#[allow(dead_code)]
seed_text: String,
current_turn: u32,
progress_percent: u32,
stage: String,
config: SquareHoleCreatorConfigJsonRecord,
draft: Option<SquareHoleDraftJsonRecord>,
messages: Vec<SquareHoleAgentMessageJsonRecord>,
last_assistant_reply: String,
published_profile_id: Option<String>,
#[allow(dead_code)]
created_at_micros: i64,
updated_at_micros: i64,
}
#[derive(Clone, Debug, PartialEq, Eq, serde::Deserialize)]
#[serde(rename_all = "camelCase")]
struct SquareHoleWorkJsonRecord {
work_id: String,
profile_id: String,
owner_user_id: String,
source_session_id: String,
author_display_name: String,
game_name: String,
theme_text: String,
twist_rule: String,
summary_text: String,
tags: Vec<String>,
cover_image_src: String,
#[serde(default)]
background_prompt: String,
#[serde(default)]
background_image_src: String,
#[serde(default)]
shape_options: Vec<SquareHoleShapeOptionJsonRecord>,
#[serde(default)]
hole_options: Vec<SquareHoleHoleOptionJsonRecord>,
shape_count: u32,
difficulty: u32,
#[allow(dead_code)]
config: SquareHoleCreatorConfigJsonRecord,
publication_status: String,
publish_ready: bool,
play_count: u32,
updated_at_micros: i64,
published_at_micros: Option<i64>,
}
#[derive(Clone, Debug, PartialEq, Eq, serde::Deserialize)]
#[serde(rename_all = "camelCase")]
struct SquareHoleShapeJsonRecord {
shape_id: String,
shape_kind: String,
label: String,
#[serde(default)]
target_hole_id: String,
color: String,
#[serde(default)]
image_src: String,
}
#[derive(Clone, Debug, PartialEq, serde::Deserialize)]
#[serde(rename_all = "camelCase")]
struct SquareHoleHoleJsonRecord {
hole_id: String,
hole_kind: String,
label: String,
x: f32,
y: f32,
#[serde(default)]
image_src: String,
#[serde(default)]
bonus: bool,
}
#[derive(Clone, Debug, PartialEq, Eq, serde::Deserialize)]
#[serde(rename_all = "camelCase")]
struct SquareHoleDropFeedbackJsonRecord {
accepted: bool,
reject_reason: Option<String>,
message: String,
}
#[derive(Clone, Debug, PartialEq, serde::Deserialize)]
#[serde(rename_all = "camelCase")]
struct SquareHoleRunJsonRecord {
run_id: String,
profile_id: String,
owner_user_id: String,
status: String,
snapshot_version: u64,
started_at_ms: i64,
duration_limit_ms: i64,
server_now_ms: i64,
remaining_ms: i64,
total_shape_count: u32,
completed_shape_count: u32,
combo: u32,
best_combo: u32,
score: u32,
rule_label: String,
#[serde(default)]
background_image_src: String,
#[serde(default)]
#[allow(dead_code)]
shape_options: Vec<SquareHoleShapeOptionJsonRecord>,
current_shape: Option<SquareHoleShapeJsonRecord>,
holes: Vec<SquareHoleHoleJsonRecord>,
last_feedback: Option<SquareHoleDropFeedbackJsonRecord>,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct PuzzleAnchorItemRecord {
pub key: String,
pub label: String,
pub value: String,
pub status: String,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct PuzzleAnchorPackRecord {
pub theme_promise: PuzzleAnchorItemRecord,
pub visual_subject: PuzzleAnchorItemRecord,
pub visual_mood: PuzzleAnchorItemRecord,
pub composition_hooks: PuzzleAnchorItemRecord,
pub tags_and_forbidden: PuzzleAnchorItemRecord,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct PuzzleCreatorIntentRecord {
pub source_mode: String,
pub raw_messages_summary: String,
pub theme_promise: String,
pub visual_subject: String,
pub visual_mood: Vec<String>,
pub composition_hooks: Vec<String>,
pub theme_tags: Vec<String>,
pub forbidden_directives: Vec<String>,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct PuzzleGeneratedImageCandidateRecord {
pub candidate_id: String,
pub image_src: String,
pub asset_id: String,
pub prompt: String,
pub actual_prompt: Option<String>,
pub source_type: String,
pub selected: bool,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct PuzzleResultDraftRecord {
pub work_title: String,
pub work_description: String,
pub level_name: String,
pub summary: String,
pub theme_tags: Vec<String>,
pub forbidden_directives: Vec<String>,
pub creator_intent: Option<PuzzleCreatorIntentRecord>,
pub anchor_pack: PuzzleAnchorPackRecord,
pub candidates: Vec<PuzzleGeneratedImageCandidateRecord>,
pub selected_candidate_id: Option<String>,
pub cover_image_src: Option<String>,
pub cover_asset_id: Option<String>,
pub generation_status: String,
pub levels: Vec<PuzzleDraftLevelRecord>,
pub form_draft: Option<PuzzleFormDraftRecord>,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct PuzzleFormDraftRecord {
pub work_title: Option<String>,
pub work_description: Option<String>,
pub picture_description: Option<String>,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct PuzzleDraftLevelRecord {
pub level_id: String,
pub level_name: String,
pub picture_description: String,
pub picture_reference: Option<String>,
pub ui_background_prompt: Option<String>,
pub ui_background_image_src: Option<String>,
pub ui_background_image_object_key: Option<String>,
pub background_music: Option<PuzzleAudioAssetRecord>,
pub candidates: Vec<PuzzleGeneratedImageCandidateRecord>,
pub selected_candidate_id: Option<String>,
pub cover_image_src: Option<String>,
pub cover_asset_id: Option<String>,
pub generation_status: String,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct PuzzleAudioAssetRecord {
pub task_id: String,
pub provider: String,
pub asset_object_id: Option<String>,
pub asset_kind: Option<String>,
pub audio_src: String,
pub prompt: Option<String>,
pub title: Option<String>,
pub updated_at: Option<String>,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct PuzzleAgentMessageRecord {
pub message_id: String,
pub role: String,
pub kind: String,
pub text: String,
pub created_at: String,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct PuzzleAgentSuggestedActionRecord {
pub action_id: String,
pub action_type: String,
pub label: String,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct PuzzleResultPreviewBlockerRecord {
pub blocker_id: String,
pub code: String,
pub message: String,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct PuzzleResultPreviewFindingRecord {
pub finding_id: String,
pub severity: String,
pub code: String,
pub message: String,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct PuzzleResultPreviewRecord {
pub draft: PuzzleResultDraftRecord,
pub blockers: Vec<PuzzleResultPreviewBlockerRecord>,
pub quality_findings: Vec<PuzzleResultPreviewFindingRecord>,
pub publish_ready: bool,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct PuzzleAgentSessionRecord {
pub session_id: String,
pub seed_text: String,
pub current_turn: u32,
pub progress_percent: u32,
pub stage: String,
pub anchor_pack: PuzzleAnchorPackRecord,
pub draft: Option<PuzzleResultDraftRecord>,
pub messages: Vec<PuzzleAgentMessageRecord>,
pub last_assistant_reply: Option<String>,
pub published_profile_id: Option<String>,
pub suggested_actions: Vec<PuzzleAgentSuggestedActionRecord>,
pub result_preview: Option<PuzzleResultPreviewRecord>,
pub updated_at: String,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct PuzzleWorkProfileRecord {
pub work_id: String,
pub profile_id: String,
pub owner_user_id: String,
pub source_session_id: Option<String>,
pub author_display_name: String,
pub work_title: String,
pub work_description: String,
pub level_name: String,
pub summary: String,
pub theme_tags: Vec<String>,
pub cover_image_src: Option<String>,
pub cover_asset_id: Option<String>,
pub publication_status: String,
pub updated_at: String,
pub published_at: Option<String>,
pub play_count: u32,
pub remix_count: u32,
pub like_count: u32,
pub recent_play_count_7d: u32,
pub point_incentive_total_half_points: u64,
pub point_incentive_claimed_points: u64,
pub publish_ready: bool,
pub anchor_pack: PuzzleAnchorPackRecord,
pub levels: Vec<PuzzleDraftLevelRecord>,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct PuzzleWorkPointIncentiveClaimRecordInput {
pub profile_id: String,
pub owner_user_id: String,
pub claimed_at_micros: i64,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct PuzzleCellPositionRecord {
pub row: u32,
pub col: u32,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct PuzzlePieceStateRecord {
pub piece_id: String,
pub correct_row: u32,
pub correct_col: u32,
pub current_row: u32,
pub current_col: u32,
pub merged_group_id: Option<String>,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct PuzzleMergedGroupRecord {
pub group_id: String,
pub piece_ids: Vec<String>,
pub occupied_cells: Vec<PuzzleCellPositionRecord>,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct PuzzleLeaderboardEntryRecord {
pub rank: u32,
pub nickname: String,
pub elapsed_ms: u64,
pub visible_tags: Vec<String>,
pub is_current_player: bool,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct PuzzleBoardRecord {
pub rows: u32,
pub cols: u32,
pub pieces: Vec<PuzzlePieceStateRecord>,
pub merged_groups: Vec<PuzzleMergedGroupRecord>,
pub selected_piece_id: Option<String>,
pub all_tiles_resolved: bool,
}
#[derive(Clone, Debug, PartialEq)]
pub struct PuzzleRecommendedNextWorkRecord {
pub profile_id: String,
pub level_name: String,
pub author_display_name: String,
pub theme_tags: Vec<String>,
pub cover_image_src: Option<String>,
pub similarity_score: f32,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct PuzzleRuntimeLevelRecord {
pub run_id: String,
pub level_index: u32,
pub level_id: Option<String>,
pub grid_size: u32,
pub profile_id: String,
pub level_name: String,
pub author_display_name: String,
pub theme_tags: Vec<String>,
pub cover_image_src: Option<String>,
pub ui_background_image_src: Option<String>,
pub ui_background_image_object_key: Option<String>,
pub background_music: Option<PuzzleAudioAssetRecord>,
pub board: PuzzleBoardRecord,
pub status: String,
pub started_at_ms: u64,
pub cleared_at_ms: Option<u64>,
pub elapsed_ms: Option<u64>,
pub time_limit_ms: u64,
pub remaining_ms: u64,
pub paused_accumulated_ms: u64,
pub pause_started_at_ms: Option<u64>,
pub freeze_accumulated_ms: u64,
pub freeze_started_at_ms: Option<u64>,
pub freeze_until_ms: Option<u64>,
pub leaderboard_entries: Vec<PuzzleLeaderboardEntryRecord>,
}
#[derive(Clone, Debug, PartialEq)]
pub struct PuzzleRunRecord {
pub run_id: String,
pub entry_profile_id: String,
pub cleared_level_count: u32,
pub current_level_index: u32,
pub current_grid_size: u32,
pub played_profile_ids: Vec<String>,
pub previous_level_tags: Vec<String>,
pub current_level: Option<PuzzleRuntimeLevelRecord>,
pub recommended_next_profile_id: Option<String>,
pub next_level_mode: String,
pub next_level_profile_id: Option<String>,
pub next_level_id: Option<String>,
pub recommended_next_works: Vec<PuzzleRecommendedNextWorkRecord>,
pub leaderboard_entries: Vec<PuzzleLeaderboardEntryRecord>,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct PuzzleLeaderboardSubmitRecordInput {
pub run_id: String,
pub owner_user_id: String,
pub profile_id: String,
pub grid_size: u32,
pub elapsed_ms: u64,
pub nickname: String,
pub submitted_at_micros: i64,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct BigFishSessionCreateRecordInput {
pub session_id: String,
pub owner_user_id: String,
pub seed_text: String,
pub welcome_message_id: String,
pub welcome_message_text: String,
pub created_at_micros: i64,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct BigFishMessageSubmitRecordInput {
pub session_id: String,
pub owner_user_id: String,
pub user_message_id: String,
pub user_message_text: String,
pub assistant_message_id: String,
pub submitted_at_micros: i64,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct BigFishMessageFinalizeRecordInput {
pub session_id: String,
pub owner_user_id: String,
pub assistant_message_id: Option<String>,
pub assistant_reply_text: Option<String>,
pub stage: String,
pub progress_percent: u32,
pub anchor_pack_json: String,
pub error_message: Option<String>,
pub updated_at_micros: i64,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct BigFishDraftCompileRecordInput {
pub session_id: String,
pub owner_user_id: String,
pub draft_json: Option<String>,
pub compiled_at_micros: i64,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct BigFishAssetGenerateRecordInput {
pub session_id: String,
pub owner_user_id: String,
pub asset_kind: String,
pub level: Option<u32>,
pub motion_key: Option<String>,
pub asset_url: Option<String>,
pub generated_at_micros: i64,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct BigFishAnchorItemRecord {
pub key: String,
pub label: String,
pub value: String,
pub status: String,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct BigFishAnchorPackRecord {
pub gameplay_promise: BigFishAnchorItemRecord,
pub ecology_visual_theme: BigFishAnchorItemRecord,
pub growth_ladder: BigFishAnchorItemRecord,
pub risk_tempo: BigFishAnchorItemRecord,
}
#[derive(Clone, Debug, PartialEq)]
pub struct BigFishLevelBlueprintRecord {
pub level: u32,
pub name: String,
pub one_line_fantasy: String,
pub text_description: String,
pub silhouette_direction: String,
pub size_ratio: f32,
pub visual_description: String,
pub visual_prompt_seed: String,
pub idle_motion_description: String,
pub move_motion_description: String,
pub motion_prompt_seed: String,
pub merge_source_level: Option<u32>,
pub prey_window: Vec<u32>,
pub threat_window: Vec<u32>,
pub is_final_level: bool,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct BigFishBackgroundBlueprintRecord {
pub theme: String,
pub color_mood: String,
pub foreground_hints: String,
pub midground_composition: String,
pub background_depth: String,
pub safe_play_area_hint: String,
pub spawn_edge_hint: String,
pub background_prompt_seed: String,
}
#[derive(Clone, Debug, PartialEq)]
pub struct BigFishRuntimeParamsRecord {
pub level_count: u32,
pub merge_count_per_upgrade: u32,
pub spawn_target_count: u32,
pub leader_move_speed: f32,
pub follower_catch_up_speed: f32,
pub offscreen_cull_seconds: f32,
pub prey_spawn_delta_levels: Vec<u32>,
pub threat_spawn_delta_levels: Vec<u32>,
pub win_level: u32,
}
#[derive(Clone, Debug, PartialEq)]
pub struct BigFishGameDraftRecord {
pub title: String,
pub subtitle: String,
pub core_fun: String,
pub ecology_theme: String,
pub levels: Vec<BigFishLevelBlueprintRecord>,
pub background: BigFishBackgroundBlueprintRecord,
pub runtime_params: BigFishRuntimeParamsRecord,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct BigFishAgentMessageRecord {
pub message_id: String,
pub role: String,
pub kind: String,
pub text: String,
pub created_at: String,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct BigFishAssetSlotRecord {
pub slot_id: String,
pub asset_kind: String,
pub level: Option<u32>,
pub motion_key: Option<String>,
pub status: String,
pub asset_url: Option<String>,
pub prompt_snapshot: String,
pub updated_at: String,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct BigFishAssetCoverageRecord {
pub level_main_image_ready_count: u32,
pub level_motion_ready_count: u32,
pub background_ready: bool,
pub required_level_count: u32,
pub publish_ready: bool,
pub blockers: Vec<String>,
}
#[derive(Clone, Debug, PartialEq)]
pub struct BigFishSessionRecord {
pub session_id: String,
pub current_turn: u32,
pub progress_percent: u32,
pub stage: String,
pub anchor_pack: BigFishAnchorPackRecord,
pub draft: Option<BigFishGameDraftRecord>,
pub asset_slots: Vec<BigFishAssetSlotRecord>,
pub asset_coverage: BigFishAssetCoverageRecord,
pub messages: Vec<BigFishAgentMessageRecord>,
pub last_assistant_reply: Option<String>,
pub publish_ready: bool,
pub updated_at: String,
}
#[derive(Clone, Debug, PartialEq)]
pub struct BigFishVector2Record {
pub x: f32,
pub y: f32,
}
#[derive(Clone, Debug, PartialEq)]
pub struct BigFishRuntimeEntityRecord {
pub entity_id: String,
pub level: u32,
pub position: BigFishVector2Record,
pub radius: f32,
pub offscreen_seconds: f32,
}
#[derive(Clone, Debug, PartialEq)]
pub struct BigFishRuntimeRunRecord {
pub run_id: String,
pub session_id: String,
pub status: String,
pub tick: u64,
pub player_level: u32,
pub win_level: u32,
pub leader_entity_id: Option<String>,
pub owned_entities: Vec<BigFishRuntimeEntityRecord>,
pub wild_entities: Vec<BigFishRuntimeEntityRecord>,
pub camera_center: BigFishVector2Record,
pub last_input: BigFishVector2Record,
pub event_log: Vec<String>,
pub updated_at: String,
}
#[derive(Clone, Debug, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
pub struct BigFishWorkSummaryRecord {
pub work_id: String,
pub source_session_id: String,
pub owner_user_id: String,
pub title: String,
pub subtitle: String,
pub summary: String,
pub cover_image_src: Option<String>,
pub status: String,
pub updated_at_micros: i64,
pub published_at_micros: Option<i64>,
pub publish_ready: bool,
pub level_count: u32,
pub level_main_image_ready_count: u32,
pub level_motion_ready_count: u32,
pub background_ready: bool,
pub play_count: u32,
pub remix_count: u32,
pub like_count: u32,
pub recent_play_count_7d: u32,
}
#[derive(Clone, Debug, PartialEq, Eq, serde::Deserialize)]
struct CompatibleBigFishWorkSummaryRecord {
work_id: String,
source_session_id: String,
#[serde(default)]
owner_user_id: Option<String>,
title: String,
subtitle: String,
summary: String,
cover_image_src: Option<String>,
status: String,
updated_at_micros: i64,
#[serde(default)]
published_at_micros: Option<i64>,
publish_ready: bool,
level_count: u32,
level_main_image_ready_count: u32,
level_motion_ready_count: u32,
background_ready: bool,
#[serde(default)]
play_count: u32,
#[serde(default)]
remix_count: u32,
#[serde(default)]
like_count: u32,
#[serde(default)]
recent_play_count_7d: u32,
}
impl CompatibleBigFishWorkSummaryRecord {
fn into_record(self, fallback_owner_user_id: Option<&str>) -> BigFishWorkSummaryRecord {
BigFishWorkSummaryRecord {
work_id: self.work_id,
source_session_id: self.source_session_id,
// 中文注释:兼容旧 works JSON 没有 owner_user_id 的历史数据,避免一次字段升级把整个作品列表打崩。
owner_user_id: self.owner_user_id.unwrap_or_else(|| {
fallback_owner_user_id
.map(str::to_string)
.unwrap_or_default()
}),
title: self.title,
subtitle: self.subtitle,
summary: self.summary,
cover_image_src: self.cover_image_src,
status: self.status,
updated_at_micros: self.updated_at_micros,
published_at_micros: self.published_at_micros,
publish_ready: self.publish_ready,
level_count: self.level_count,
level_main_image_ready_count: self.level_main_image_ready_count,
level_motion_ready_count: self.level_motion_ready_count,
background_ready: self.background_ready,
play_count: self.play_count,
remix_count: self.remix_count,
like_count: self.like_count,
recent_play_count_7d: self.recent_play_count_7d,
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn puzzle_works_mapper_backfills_missing_public_stat_fields() {
let result = PuzzleWorksProcedureResult {
ok: true,
items_json: Some(
r#"[{
"work_id":"puzzle-work-1",
"profile_id":"puzzle-profile-1",
"owner_user_id":"user-1",
"source_session_id":null,
"author_display_name":"测试作者",
"level_name":"雨夜拼图",
"summary":"旧公开作品摘要",
"theme_tags":["雨夜","猫咪","神庙"],
"cover_image_src":null,
"cover_asset_id":null,
"publication_status":"Published",
"updated_at_micros":123000000,
"published_at_micros":123000000,
"publish_ready":true,
"anchor_pack":{
"theme_promise":{
"key":"themePromise",
"label":"题材承诺",
"value":"雨夜冒险",
"status":"Inferred"
},
"visual_subject":{
"key":"visualSubject",
"label":"画面主体",
"value":"猫咪神庙",
"status":"Inferred"
},
"visual_mood":{
"key":"visualMood",
"label":"视觉气质",
"value":"温暖",
"status":"Inferred"
},
"composition_hooks":{
"key":"compositionHooks",
"label":"拼图记忆点",
"value":"灯光",
"status":"Inferred"
},
"tags_and_forbidden":{
"key":"tagsAndForbidden",
"label":"标签与禁忌",
"value":"雨夜, 猫咪, 神庙",
"status":"Inferred"
}
}
}]"#
.to_string(),
),
error_message: None,
};
let items = map_puzzle_works_procedure_result(result)
.expect("旧 puzzle works JSON 缺统计字段时应按 0 兼容");
assert_eq!(items.len(), 1);
assert_eq!(items[0].play_count, 0);
assert_eq!(items[0].remix_count, 0);
assert_eq!(items[0].like_count, 0);
}
#[test]
fn puzzle_run_mapper_backfills_missing_timer_fields() {
let result = PuzzleRunProcedureResult {
ok: true,
run_json: Some(
r#"{
"run_id":"puzzle-run-1",
"entry_profile_id":"puzzle-profile-1",
"cleared_level_count":0,
"current_level_index":1,
"current_grid_size":3,
"played_profile_ids":["puzzle-profile-1"],
"previous_level_tags":["雨夜","猫咪","神庙"],
"current_level":{
"run_id":"puzzle-run-1",
"level_index":1,
"grid_size":3,
"profile_id":"puzzle-profile-1",
"level_name":"雨夜拼图",
"author_display_name":"测试作者",
"theme_tags":["雨夜","猫咪","神庙"],
"cover_image_src":null,
"board":{
"rows":3,
"cols":3,
"pieces":[{
"piece_id":"piece-1",
"correct_row":0,
"correct_col":0,
"current_row":0,
"current_col":0,
"merged_group_id":null
}],
"merged_groups":[],
"selected_piece_id":null
},
"status":"Playing"
},
"recommended_next_profile_id":null
}"#
.to_string(),
),
error_message: None,
};
let run = map_puzzle_run_procedure_result(result)
.expect("旧 puzzle run JSON 缺计时字段时应按默认值兼容");
let level = run.current_level.expect("兼容后仍应保留当前关卡");
assert_eq!(run.run_id, "puzzle-run-1");
assert!(level.started_at_ms > 0);
assert_eq!(level.time_limit_ms, 0);
assert_eq!(level.remaining_ms, 0);
assert!(level.leaderboard_entries.is_empty());
}
#[test]
fn big_fish_works_mapper_backfills_missing_owner_user_id_for_private_lists() {
let result = BigFishWorksProcedureResult {
ok: true,
items_json: Some(
r#"[{
"work_id":"big-fish-work-session-1",
"source_session_id":"session-1",
"title":"深海草稿",
"subtitle":"副标题",
"summary":"摘要",
"cover_image_src":null,
"status":"draft",
"updated_at_micros":123,
"publish_ready":false,
"level_count":8,
"level_main_image_ready_count":0,
"level_motion_ready_count":0,
"background_ready":false
}]"#
.to_string(),
),
error_message: None,
};
let items = map_big_fish_works_procedure_result(result, Some("user-1"))
.expect("旧 works JSON 应能被兼容解析");
assert_eq!(items.len(), 1);
assert_eq!(items[0].owner_user_id, "user-1");
assert_eq!(items[0].published_at_micros, None);
assert_eq!(items[0].play_count, 0);
assert_eq!(items[0].remix_count, 0);
assert_eq!(items[0].like_count, 0);
}
#[test]
fn big_fish_works_mapper_keeps_empty_owner_when_gallery_legacy_json_lacks_field() {
let result = BigFishWorksProcedureResult {
ok: true,
items_json: Some(
r#"[{
"work_id":"big-fish-work-session-2",
"source_session_id":"session-2",
"title":"公开作品",
"subtitle":"副标题",
"summary":"摘要",
"cover_image_src":null,
"status":"published",
"updated_at_micros":456,
"publish_ready":true,
"level_count":8,
"level_main_image_ready_count":8,
"level_motion_ready_count":16,
"background_ready":true
}]"#
.to_string(),
),
error_message: None,
};
let items = map_big_fish_works_procedure_result(result, None)
.expect("公开 works 旧 JSON 也不应因缺字段报错");
assert_eq!(items.len(), 1);
assert!(items[0].owner_user_id.is_empty());
assert_eq!(items[0].published_at_micros, None);
assert_eq!(items[0].play_count, 0);
assert_eq!(items[0].remix_count, 0);
assert_eq!(items[0].like_count, 0);
}
#[test]
fn match3d_work_mapper_keeps_generated_item_assets_json() {
let result = Match3DWorkProcedureResult {
ok: true,
work_json: Some(
r#"{
"profileId":"match3d-profile-1",
"ownerUserId":"user-1",
"sourceSessionId":"match3d-session-1",
"authorDisplayName":"测试作者",
"gameName":"水果抓大鹅",
"themeText":"水果",
"summaryText":"水果主题",
"tags":["水果"],
"coverImageSrc":"",
"coverAssetId":"",
"clearCount":3,
"difficulty":3,
"config":{
"themeText":"水果",
"referenceImageSrc":null,
"clearCount":3,
"difficulty":3
},
"publicationStatus":"Draft",
"publishReady":false,
"playCount":0,
"updatedAtMicros":123000000,
"publishedAtMicros":null,
"generatedItemAssetsJson":"[{\"itemId\":\"match3d-item-1\",\"itemName\":\"草莓\",\"imageSrc\":\"/generated-match3d-assets/session/profile/items/item/image.png\",\"status\":\"image_ready\"}]"
}"#
.to_string(),
),
error_message: None,
};
let item = map_match3d_work_procedure_result(result)
.expect("match3d work JSON 应保留生成素材 JSON");
assert_eq!(
item.generated_item_assets_json.as_deref(),
Some(
r#"[{"itemId":"match3d-item-1","itemName":"草莓","imageSrc":"/generated-match3d-assets/session/profile/items/item/image.png","status":"image_ready"}]"#
)
);
}
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct ResolveNpcBattleInteractionInput {
pub npc_interaction: DomainResolveNpcInteractionInput,
pub story_session_id: String,
pub actor_user_id: String,
pub battle_state_id: Option<String>,
pub player_hp: i32,
pub player_max_hp: i32,
pub player_mana: i32,
pub player_max_mana: i32,
pub target_hp: i32,
pub target_max_hp: i32,
pub experience_reward: u32,
pub reward_items: Vec<DomainRuntimeItemRewardItemSnapshot>,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct AiTaskStageRecord {
pub stage_kind: String,
pub label: String,
pub detail: String,
pub order: u32,
pub status: String,
pub text_output: Option<String>,
pub structured_payload_json: Option<String>,
pub warning_messages: Vec<String>,
pub started_at: Option<String>,
pub completed_at: Option<String>,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct AiResultReferenceRecord {
pub result_ref_id: String,
pub task_id: String,
pub reference_kind: String,
pub reference_id: String,
pub label: Option<String>,
pub created_at: String,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct AiTextChunkRecord {
pub chunk_id: String,
pub task_id: String,
pub stage_kind: String,
pub sequence: u32,
pub delta_text: String,
pub created_at: String,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct AiTaskRecord {
pub task_id: String,
pub task_kind: String,
pub owner_user_id: String,
pub request_label: String,
pub source_module: String,
pub source_entity_id: Option<String>,
pub request_payload_json: Option<String>,
pub status: String,
pub failure_message: Option<String>,
pub stages: Vec<AiTaskStageRecord>,
pub result_references: Vec<AiResultReferenceRecord>,
pub latest_text_output: Option<String>,
pub latest_structured_payload_json: Option<String>,
pub version: u32,
pub created_at: String,
pub started_at: Option<String>,
pub completed_at: Option<String>,
pub updated_at: String,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct AiTaskMutationRecord {
pub task: AiTaskRecord,
pub text_chunk: Option<AiTextChunkRecord>,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct NpcStateRecord {
pub npc_state_id: String,
pub runtime_session_id: String,
pub npc_id: String,
pub npc_name: String,
pub affinity: i32,
pub relation_stance: String,
pub help_used: bool,
pub chatted_count: u32,
pub gifts_given: u32,
pub recruited: bool,
pub trade_stock_signature: Option<String>,
pub revealed_facts: Vec<String>,
pub known_attribute_rumors: Vec<String>,
pub first_meaningful_contact_resolved: bool,
pub seen_backstory_chapter_ids: Vec<String>,
pub trust: u8,
pub warmth: u8,
pub ideological_fit: u8,
pub fear_or_guard: u8,
pub loyalty: u8,
pub current_conflict_tag: Option<String>,
pub recent_approvals: Vec<String>,
pub recent_disapprovals: Vec<String>,
pub created_at: String,
pub updated_at: String,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct NpcInteractionRecord {
pub npc_state: NpcStateRecord,
pub interaction_status: String,
pub action_text: String,
pub result_text: String,
pub story_text: Option<String>,
pub battle_mode: Option<String>,
pub encounter_closed: bool,
pub affinity_changed: bool,
pub previous_affinity: i32,
pub next_affinity: i32,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct NpcBattleInteractionRecord {
pub npc_interaction: NpcInteractionRecord,
pub battle_state: BattleStateRecord,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub(crate) struct NpcBattleInteractionSnapshot {
interaction: DomainNpcInteractionResult,
battle_state: DomainBattleStateSnapshot,
}
pub(crate) fn build_battle_state_record(snapshot: DomainBattleStateSnapshot) -> BattleStateRecord {
BattleStateRecord {
battle_state_id: snapshot.battle_state_id,
story_session_id: snapshot.story_session_id,
runtime_session_id: snapshot.runtime_session_id,
actor_user_id: snapshot.actor_user_id,
chapter_id: snapshot.chapter_id,
target_npc_id: snapshot.target_npc_id,
target_name: snapshot.target_name,
battle_mode: snapshot.battle_mode.as_str().to_string(),
status: snapshot.status.as_str().to_string(),
player_hp: snapshot.player_hp,
player_max_hp: snapshot.player_max_hp,
player_mana: snapshot.player_mana,
player_max_mana: snapshot.player_max_mana,
target_hp: snapshot.target_hp,
target_max_hp: snapshot.target_max_hp,
experience_reward: snapshot.experience_reward,
reward_items: snapshot.reward_items,
turn_index: snapshot.turn_index,
last_action_function_id: snapshot.last_action_function_id,
last_action_text: snapshot.last_action_text,
last_result_text: snapshot.last_result_text,
last_damage_dealt: snapshot.last_damage_dealt,
last_damage_taken: snapshot.last_damage_taken,
last_outcome: snapshot.last_outcome.as_str().to_string(),
version: snapshot.version,
created_at: format_timestamp_micros(snapshot.created_at_micros),
updated_at: format_timestamp_micros(snapshot.updated_at_micros),
}
}
pub(crate) fn build_resolve_combat_action_record(
result: DomainResolveCombatActionResult,
) -> ResolveCombatActionRecord {
ResolveCombatActionRecord {
battle_state: build_battle_state_record(result.snapshot),
damage_dealt: result.damage_dealt,
damage_taken: result.damage_taken,
outcome: result.outcome.as_str().to_string(),
}
}
impl From<ResolveNpcBattleInteractionInput>
for crate::module_bindings::ResolveNpcBattleInteractionInput
{
fn from(input: ResolveNpcBattleInteractionInput) -> Self {
Self {
npc_interaction: crate::module_bindings::ResolveNpcInteractionInput {
runtime_session_id: input.npc_interaction.runtime_session_id,
npc_id: input.npc_interaction.npc_id,
npc_name: input.npc_interaction.npc_name,
interaction_function_id: input.npc_interaction.interaction_function_id,
release_npc_id: input.npc_interaction.release_npc_id,
updated_at_micros: input.npc_interaction.updated_at_micros,
},
story_session_id: input.story_session_id,
actor_user_id: input.actor_user_id,
battle_state_id: input.battle_state_id,
player_hp: input.player_hp,
player_max_hp: input.player_max_hp,
player_mana: input.player_mana,
player_max_mana: input.player_max_mana,
target_hp: input.target_hp,
target_max_hp: input.target_max_hp,
experience_reward: input.experience_reward,
reward_items: input
.reward_items
.into_iter()
.map(map_runtime_item_reward_item_snapshot)
.collect(),
}
}
}
pub(crate) fn validate_npc_battle_interaction_input(
input: &ResolveNpcBattleInteractionInput,
) -> Result<(), SpacetimeClientError> {
let battle_state_input = DomainBattleStateInput {
battle_state_id: input
.battle_state_id
.clone()
.unwrap_or_else(|| "battle_preview".to_string()),
story_session_id: input.story_session_id.clone(),
runtime_session_id: input.npc_interaction.runtime_session_id.clone(),
actor_user_id: input.actor_user_id.clone(),
chapter_id: None,
target_npc_id: input.npc_interaction.npc_id.clone(),
target_name: input.npc_interaction.npc_name.clone(),
battle_mode: DomainBattleMode::Fight,
player_hp: input.player_hp,
player_max_hp: input.player_max_hp,
player_mana: input.player_mana,
player_max_mana: input.player_max_mana,
target_hp: input.target_hp,
target_max_hp: input.target_max_hp,
experience_reward: input.experience_reward,
reward_items: input.reward_items.clone(),
created_at_micros: input.npc_interaction.updated_at_micros,
};
validate_battle_state_input(&battle_state_input)
.map_err(|error| SpacetimeClientError::Runtime(error.to_string()))?;
for reward_item in input.reward_items.iter().cloned() {
normalize_reward_item_snapshot(reward_item)
.map_err(|error| SpacetimeClientError::Runtime(error.to_string()))?;
}
Ok(())
}
pub(crate) fn build_npc_state_record(snapshot: DomainNpcStateSnapshot) -> NpcStateRecord {
NpcStateRecord {
npc_state_id: snapshot.npc_state_id,
runtime_session_id: snapshot.runtime_session_id,
npc_id: snapshot.npc_id,
npc_name: snapshot.npc_name,
affinity: snapshot.affinity,
relation_stance: format_npc_relation_stance(snapshot.relation_state.stance).to_string(),
help_used: snapshot.help_used,
chatted_count: snapshot.chatted_count,
gifts_given: snapshot.gifts_given,
recruited: snapshot.recruited,
trade_stock_signature: snapshot.trade_stock_signature,
revealed_facts: snapshot.revealed_facts,
known_attribute_rumors: snapshot.known_attribute_rumors,
first_meaningful_contact_resolved: snapshot.first_meaningful_contact_resolved,
seen_backstory_chapter_ids: snapshot.seen_backstory_chapter_ids,
trust: snapshot.stance_profile.trust,
warmth: snapshot.stance_profile.warmth,
ideological_fit: snapshot.stance_profile.ideological_fit,
fear_or_guard: snapshot.stance_profile.fear_or_guard,
loyalty: snapshot.stance_profile.loyalty,
current_conflict_tag: snapshot.stance_profile.current_conflict_tag,
recent_approvals: snapshot.stance_profile.recent_approvals,
recent_disapprovals: snapshot.stance_profile.recent_disapprovals,
created_at: format_timestamp_micros(snapshot.created_at_micros),
updated_at: format_timestamp_micros(snapshot.updated_at_micros),
}
}
pub(crate) fn build_npc_interaction_record(
result: DomainNpcInteractionResult,
) -> NpcInteractionRecord {
NpcInteractionRecord {
npc_state: build_npc_state_record(result.npc_state),
interaction_status: format_npc_interaction_status(result.interaction_status).to_string(),
action_text: result.action_text,
result_text: result.result_text,
story_text: result.story_text,
battle_mode: result
.battle_mode
.map(|mode| format_npc_interaction_battle_mode(mode).to_string()),
encounter_closed: result.encounter_closed,
affinity_changed: result.affinity_changed,
previous_affinity: result.previous_affinity,
next_affinity: result.next_affinity,
}
}
pub(crate) fn build_npc_battle_interaction_record(
result: NpcBattleInteractionSnapshot,
) -> NpcBattleInteractionRecord {
NpcBattleInteractionRecord {
npc_interaction: build_npc_interaction_record(result.interaction),
battle_state: build_battle_state_record(result.battle_state),
}
}
pub(crate) fn format_npc_relation_stance(value: DomainNpcRelationStance) -> &'static str {
match value {
DomainNpcRelationStance::Hostile => "hostile",
DomainNpcRelationStance::Guarded => "guarded",
DomainNpcRelationStance::Neutral => "neutral",
DomainNpcRelationStance::Cooperative => "cooperative",
DomainNpcRelationStance::Bonded => "bonded",
}
}
pub(crate) fn format_npc_interaction_status(value: DomainNpcInteractionStatus) -> &'static str {
match value {
DomainNpcInteractionStatus::Previewed => "previewed",
DomainNpcInteractionStatus::Dialogue => "dialogue",
DomainNpcInteractionStatus::Resolved => "resolved",
DomainNpcInteractionStatus::Recruited => "recruited",
DomainNpcInteractionStatus::BattlePending => "battle_pending",
DomainNpcInteractionStatus::Left => "left",
}
}
pub(crate) fn format_npc_interaction_battle_mode(
value: DomainNpcInteractionBattleMode,
) -> &'static str {
match value {
DomainNpcInteractionBattleMode::Fight => "fight",
DomainNpcInteractionBattleMode::Spar => "spar",
}
}
pub(crate) fn map_inventory_container_kind(
value: InventoryContainerKind,
) -> module_inventory::InventoryContainerKind {
match value {
InventoryContainerKind::Backpack => module_inventory::InventoryContainerKind::Backpack,
InventoryContainerKind::Equipment => module_inventory::InventoryContainerKind::Equipment,
}
}
pub(crate) fn map_inventory_item_rarity(
value: InventoryItemRarity,
) -> module_inventory::InventoryItemRarity {
match value {
InventoryItemRarity::Common => module_inventory::InventoryItemRarity::Common,
InventoryItemRarity::Uncommon => module_inventory::InventoryItemRarity::Uncommon,
InventoryItemRarity::Rare => module_inventory::InventoryItemRarity::Rare,
InventoryItemRarity::Epic => module_inventory::InventoryItemRarity::Epic,
InventoryItemRarity::Legendary => module_inventory::InventoryItemRarity::Legendary,
}
}
pub(crate) fn map_inventory_equipment_slot(
value: InventoryEquipmentSlot,
) -> module_inventory::InventoryEquipmentSlot {
match value {
InventoryEquipmentSlot::Weapon => module_inventory::InventoryEquipmentSlot::Weapon,
InventoryEquipmentSlot::Armor => module_inventory::InventoryEquipmentSlot::Armor,
InventoryEquipmentSlot::Relic => module_inventory::InventoryEquipmentSlot::Relic,
}
}
pub(crate) fn map_inventory_item_source_kind(
value: InventoryItemSourceKind,
) -> module_inventory::InventoryItemSourceKind {
match value {
InventoryItemSourceKind::StoryReward => {
module_inventory::InventoryItemSourceKind::StoryReward
}
InventoryItemSourceKind::QuestReward => {
module_inventory::InventoryItemSourceKind::QuestReward
}
InventoryItemSourceKind::TreasureReward => {
module_inventory::InventoryItemSourceKind::TreasureReward
}
InventoryItemSourceKind::NpcGift => module_inventory::InventoryItemSourceKind::NpcGift,
InventoryItemSourceKind::NpcTrade => module_inventory::InventoryItemSourceKind::NpcTrade,
InventoryItemSourceKind::CombatDrop => {
module_inventory::InventoryItemSourceKind::CombatDrop
}
InventoryItemSourceKind::ForgeCraft => {
module_inventory::InventoryItemSourceKind::ForgeCraft
}
InventoryItemSourceKind::ForgeReforge => {
module_inventory::InventoryItemSourceKind::ForgeReforge
}
InventoryItemSourceKind::ManualPatch => {
module_inventory::InventoryItemSourceKind::ManualPatch
}
}
}