468 lines
16 KiB
Rust
468 lines
16 KiB
Rust
use super::*;
|
|
|
|
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::RuntimeSnapshotGetInput> for RuntimeSnapshotGetInput {
|
|
fn from(input: module_runtime::RuntimeSnapshotGetInput) -> Self {
|
|
Self {
|
|
user_id: input.user_id,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl From<module_runtime::RuntimeSnapshotDeleteInput> for RuntimeSnapshotDeleteInput {
|
|
fn from(input: module_runtime::RuntimeSnapshotDeleteInput) -> Self {
|
|
Self {
|
|
user_id: input.user_id,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl From<module_runtime::RuntimeTrackingEventInput> for RuntimeTrackingEventInput {
|
|
fn from(input: module_runtime::RuntimeTrackingEventInput) -> Self {
|
|
Self {
|
|
event_id: input.event_id,
|
|
event_key: input.event_key,
|
|
scope_kind: map_runtime_tracking_scope_kind(input.scope_kind),
|
|
scope_id: input.scope_id,
|
|
user_id: input.user_id,
|
|
owner_user_id: input.owner_user_id,
|
|
profile_id: input.profile_id,
|
|
module_key: input.module_key,
|
|
metadata_json: input.metadata_json,
|
|
occurred_at_micros: input.occurred_at_micros,
|
|
}
|
|
}
|
|
}
|
|
|
|
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),
|
|
))
|
|
}
|
|
|
|
pub(crate) fn build_creation_entry_config_record_from_rows(
|
|
header: CreationEntryConfig,
|
|
mut creation_types: Vec<CreationEntryTypeConfig>,
|
|
) -> CreationEntryConfigRecord {
|
|
creation_types.sort_by(|left, right| {
|
|
left.sort_order
|
|
.cmp(&right.sort_order)
|
|
.then_with(|| left.id.cmp(&right.id))
|
|
});
|
|
|
|
module_runtime::build_creation_entry_config_response(
|
|
module_runtime::CreationEntryConfigSnapshot {
|
|
config_id: header.config_id,
|
|
start_card: module_runtime::CreationEntryStartCardSnapshot {
|
|
title: header.start_title,
|
|
description: header.start_description,
|
|
idle_badge: header.start_idle_badge,
|
|
busy_badge: header.start_busy_badge,
|
|
},
|
|
type_modal: module_runtime::CreationEntryTypeModalSnapshot {
|
|
title: header.modal_title,
|
|
description: header.modal_description,
|
|
},
|
|
creation_types: 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.to_micros_since_unix_epoch(),
|
|
})
|
|
.collect(),
|
|
updated_at_micros: header.updated_at.to_micros_since_unix_epoch(),
|
|
},
|
|
)
|
|
}
|
|
|
|
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_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_tracking_event_batch_procedure_result(
|
|
result: RuntimeTrackingEventBatchProcedureResult,
|
|
) -> Result<u32, SpacetimeClientError> {
|
|
if !result.ok {
|
|
return Err(SpacetimeClientError::procedure_failed(result.error_message));
|
|
}
|
|
|
|
Ok(result.accepted_count)
|
|
}
|
|
|
|
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_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_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_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_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 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_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 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()
|
|
}
|
|
|
|
#[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)]
|
|
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,
|
|
}
|