feat(jump-hop): redesign sling platform gameplay

This commit is contained in:
2026-06-03 22:21:00 +08:00
parent 40ef89aeb5
commit 7d2d67a3f5
59 changed files with 6930 additions and 1973 deletions

View File

@@ -1,10 +1,11 @@
use super::*;
pub use shared_contracts::jump_hop::{
JumpHopActionRequest, JumpHopActionResponse, JumpHopActionType, JumpHopCharacterAsset,
JumpHopDifficulty, JumpHopDraftResponse, JumpHopGalleryCardResponse,
JumpHopDefaultCharacter, JumpHopDifficulty, JumpHopDraftResponse, JumpHopGalleryCardResponse,
JumpHopGalleryDetailResponse, JumpHopGalleryResponse, JumpHopGenerationStatus,
JumpHopJumpRequest, JumpHopJumpResponse, JumpHopJumpResult, JumpHopLastJump, JumpHopPath,
JumpHopPlatform, JumpHopRestartRunRequest, JumpHopRunResponse, JumpHopRunStatus,
JumpHopJumpRequest, JumpHopJumpResponse, JumpHopJumpResult, JumpHopLastJump,
JumpHopLeaderboardEntry, JumpHopLeaderboardResponse, JumpHopPath, JumpHopPlatform,
JumpHopRestartRunRequest, JumpHopRunResponse, JumpHopRunStatus,
JumpHopRuntimeRunSnapshotResponse, JumpHopScoring, JumpHopSessionResponse,
JumpHopSessionSnapshotResponse, JumpHopStartRunRequest, JumpHopStylePreset, JumpHopTileAsset,
JumpHopTileType, JumpHopWorkDetailResponse, JumpHopWorkMutationResponse,
@@ -61,6 +62,25 @@ pub(crate) fn map_jump_hop_run_procedure_result(
Ok(map_jump_hop_run_snapshot(run))
}
pub(crate) fn map_jump_hop_leaderboard_procedure_result(
result: JumpHopLeaderboardProcedureResult,
) -> Result<JumpHopLeaderboardResponse, SpacetimeClientError> {
if !result.ok {
return Err(SpacetimeClientError::procedure_failed(result.error_message));
}
Ok(JumpHopLeaderboardResponse {
profile_id: result.profile_id,
items: result
.items
.into_iter()
.map(map_jump_hop_leaderboard_entry_snapshot)
.collect(),
viewer_best: result
.viewer_best
.map(map_jump_hop_leaderboard_entry_snapshot),
})
}
pub(crate) fn map_jump_hop_gallery_card_view_row(
row: JumpHopGalleryCardViewRow,
) -> JumpHopGalleryCardResponse {
@@ -70,6 +90,7 @@ pub(crate) fn map_jump_hop_gallery_card_view_row(
profile_id: row.profile_id,
owner_user_id: row.owner_user_id,
author_display_name: row.author_display_name,
theme_text: row.work_title.clone(),
work_title: row.work_title,
work_description: row.work_description,
cover_image_src: empty_string_to_none(row.cover_image_src),
@@ -108,11 +129,13 @@ fn map_jump_hop_work_snapshot(
template_id: "jump-hop".to_string(),
template_name: "跳一跳".to_string(),
profile_id: Some(snapshot.profile_id.clone()),
theme_text: snapshot.work_title.clone(),
work_title: snapshot.work_title.clone(),
work_description: snapshot.work_description.clone(),
theme_tags: snapshot.theme_tags.clone(),
difficulty: parse_difficulty(&snapshot.difficulty),
style_preset: parse_style_preset(&snapshot.style_preset),
default_character: Some(default_jump_hop_character()),
character_prompt: snapshot.character_prompt.clone(),
tile_prompt: snapshot.tile_prompt.clone(),
end_mood_prompt: snapshot.end_mood_prompt.clone(),
@@ -143,6 +166,7 @@ fn map_jump_hop_work_snapshot(
profile_id: snapshot.profile_id,
owner_user_id: snapshot.owner_user_id,
source_session_id: empty_string_to_none(snapshot.source_session_id),
theme_text: snapshot.work_title.clone(),
work_title: snapshot.work_title,
work_description: snapshot.work_description,
theme_tags: snapshot.theme_tags,
@@ -159,6 +183,7 @@ fn map_jump_hop_work_snapshot(
},
draft,
path: map_jump_hop_path(snapshot.path),
default_character: Some(default_jump_hop_character()),
character_asset,
tile_atlas_asset,
tile_assets: snapshot
@@ -170,15 +195,18 @@ fn map_jump_hop_work_snapshot(
}
fn map_jump_hop_draft_snapshot(snapshot: JumpHopDraftSnapshot) -> JumpHopDraftResponse {
let theme_text = snapshot.work_title.clone();
JumpHopDraftResponse {
template_id: snapshot.template_id,
template_name: snapshot.template_name,
profile_id: snapshot.profile_id,
theme_text,
work_title: snapshot.work_title,
work_description: snapshot.work_description,
theme_tags: snapshot.theme_tags,
difficulty: parse_difficulty(&snapshot.difficulty),
style_preset: parse_style_preset(&snapshot.style_preset),
default_character: Some(default_jump_hop_character()),
character_prompt: snapshot.character_prompt,
tile_prompt: snapshot.tile_prompt,
end_mood_prompt: snapshot.end_mood_prompt,
@@ -211,10 +239,13 @@ fn map_character_asset(snapshot: JumpHopCharacterAssetSnapshot) -> JumpHopCharac
fn map_tile_asset(snapshot: JumpHopTileAssetSnapshot) -> JumpHopTileAsset {
JumpHopTileAsset {
tile_type: parse_tile_type(&snapshot.tile_type),
tile_id: snapshot.tile_id,
image_src: snapshot.image_src,
image_object_key: snapshot.image_object_key,
asset_object_id: snapshot.asset_object_id,
source_atlas_cell: snapshot.source_atlas_cell,
atlas_row: snapshot.atlas_row,
atlas_col: snapshot.atlas_col,
visual_width: snapshot.visual_width,
visual_height: snapshot.visual_height,
top_surface_radius: snapshot.top_surface_radius,
@@ -263,6 +294,8 @@ fn map_jump_hop_run_snapshot(snapshot: JumpHopRunSnapshot) -> JumpHopRuntimeRunS
crate::module_bindings::JumpHopRunStatus::Playing => JumpHopRunStatus::Playing,
},
current_platform_index: snapshot.current_platform_index,
successful_jump_count: snapshot.current_platform_index,
duration_ms: jump_hop_duration_ms(snapshot.started_at_ms, snapshot.finished_at_ms),
score: snapshot.score,
combo: snapshot.combo,
path: map_jump_hop_path(snapshot.path),
@@ -286,6 +319,34 @@ fn map_jump_hop_run_snapshot(snapshot: JumpHopRunSnapshot) -> JumpHopRuntimeRunS
}
}
fn map_jump_hop_leaderboard_entry_snapshot(
snapshot: JumpHopLeaderboardEntrySnapshot,
) -> JumpHopLeaderboardEntry {
JumpHopLeaderboardEntry {
rank: snapshot.rank,
player_id: snapshot.player_id,
successful_jump_count: snapshot.successful_jump_count,
duration_ms: snapshot.duration_ms,
updated_at: format_timestamp_micros(snapshot.updated_at_micros),
}
}
fn default_jump_hop_character() -> JumpHopDefaultCharacter {
JumpHopDefaultCharacter {
character_id: "jump-hop-default-runner".to_string(),
display_name: "默认角色".to_string(),
model_kind: "builtin-three".to_string(),
body_color: "#f59e0b".to_string(),
accent_color: "#2563eb".to_string(),
}
}
fn jump_hop_duration_ms(started_at_ms: u64, finished_at_ms: Option<u64>) -> u64 {
finished_at_ms
.unwrap_or(started_at_ms)
.saturating_sub(started_at_ms)
}
fn parse_difficulty(value: &str) -> JumpHopDifficulty {
match value {
"easy" => JumpHopDifficulty::Easy,