fix: 优化跳一跳运行态与地块资源

This commit is contained in:
2026-06-09 01:28:30 +08:00
parent c9c66f046b
commit a0473771f1
30 changed files with 3180 additions and 1010 deletions

View File

@@ -473,9 +473,9 @@ fn validate_jump_hop_runtime_ready(
}
validate_jump_hop_default_character_ready(work)?;
validate_jump_hop_tile_atlas_asset_ready(&work.tile_atlas_asset, "tile_atlas_asset")?;
if work.tile_assets.len() < 25 {
if work.tile_assets.len() < 18 {
return Err(SpacetimeClientError::validation_failed(
"jump-hop runtime 需要 25 个地块资产",
"jump-hop runtime 需要 18 个地块资产",
));
}
for (index, asset) in work.tile_assets.iter().enumerate() {
@@ -761,12 +761,12 @@ fn build_compile_input(
draft.default_character = Some(default_jump_hop_default_character());
let tile_atlas_asset = draft.tile_atlas_asset.clone().ok_or_else(|| {
SpacetimeClientError::validation_failed(
"jump-hop compile-draft 缺少真实地图集资产,请先由 api-server 生成并持久化 asset_object",
"jump-hop compile-draft 缺少真实地板贴图图集资产,请先由 api-server 生成并持久化 asset_object",
)
})?;
let tile_assets = if draft.tile_assets.len() < 25 {
let tile_assets = if draft.tile_assets.len() < 18 {
return Err(SpacetimeClientError::validation_failed(
"jump-hop compile-draft 需要 25 个真实地块资产,请先由 api-server 生成并持久化 asset_object",
"jump-hop compile-draft 需要 18 个真实地块资产,请先由 api-server 生成并持久化 asset_object",
));
} else {
draft.tile_assets.clone()
@@ -878,7 +878,7 @@ fn default_draft() -> JumpHopDraftResponse {
style_preset: JumpHopStylePreset::MinimalBlocks,
default_character: Some(default_jump_hop_default_character()),
character_prompt: "内置默认 3D 角色".to_string(),
tile_prompt: "跳一跳主题的正面30度视角主题物体图集物体本身作为跳跃落点".to_string(),
tile_prompt: "跳一跳主题的3D立方体主题身份方块包装图集".to_string(),
end_mood_prompt: None,
character_asset: None,
tile_atlas_asset: None,
@@ -994,7 +994,7 @@ mod tests {
const NOW_MICROS: i64 = 1_763_456_789_000_000;
#[test]
fn jump_hop_action_compile_draft_builds_compile_input_with_25_tile_assets_and_builtin_character()
fn jump_hop_action_compile_draft_builds_compile_input_with_18_tile_assets_and_builtin_character()
{
let session = session_with_draft(draft_without_character_asset());
let payload = action(JumpHopActionType::CompileDraft);
@@ -1028,9 +1028,9 @@ mod tests {
.tile_assets_json
.as_deref()
.unwrap_or("")
.contains("old-tile-25-object")
.contains("old-tile-18-object")
);
assert_eq!(draft.tile_assets.len(), 25);
assert_eq!(draft.tile_assets.len(), 18);
assert_eq!(draft.generation_status, JumpHopGenerationStatus::Ready);
}
@@ -1040,7 +1040,7 @@ mod tests {
let mut payload = action(JumpHopActionType::RegenerateTiles);
payload.tile_prompt = Some("新的地块提示词".to_string());
payload.tile_atlas_asset = Some(tile_atlas_asset("new-tile-atlas", NOW_MICROS));
payload.tile_assets = Some(tile_assets("new", 25));
payload.tile_assets = Some(tile_assets("new", 18));
let (plan, _draft) =
build_jump_hop_action_plan(&session, OWNER_USER_ID, &payload, NOW_MICROS)
@@ -1082,7 +1082,7 @@ mod tests {
.tile_assets_json
.as_deref()
.unwrap_or("")
.contains("new-tile-25-object")
.contains("new-tile-18-object")
);
}
@@ -1196,7 +1196,7 @@ mod tests {
JumpHopDraftResponse {
profile_id: None,
tile_atlas_asset: Some(tile_atlas_asset("old-tile-atlas", 0)),
tile_assets: tile_assets("old", 25),
tile_assets: tile_assets("old", 18),
..base_draft()
}
}
@@ -1206,7 +1206,7 @@ mod tests {
profile_id: Some(PROFILE_ID.to_string()),
character_asset: Some(build_jump_hop_default_character_asset(PROFILE_ID, "旧主题")),
tile_atlas_asset: Some(tile_atlas_asset("old-tile-atlas", 0)),
tile_assets: tile_assets("old", 25),
tile_assets: tile_assets("old", 18),
path: Some(sample_jump_hop_path()),
cover_composite: Some("/generated-jump-hop-assets/old-cover.png".to_string()),
generation_status: JumpHopGenerationStatus::Ready,
@@ -1243,13 +1243,14 @@ mod tests {
index + 1
),
asset_object_id: format!("{prefix}-tile-{:02}-object", index + 1),
source_atlas_cell: format!("row-{}-col-{}", index / 5 + 1, index % 5 + 1),
atlas_row: Some(index as u32 / 5 + 1),
atlas_col: Some(index as u32 % 5 + 1),
source_atlas_cell: format!("row-{}-col-{}", index / 3 + 1, index % 3 + 1),
atlas_row: Some(index as u32 / 3 + 1),
atlas_col: Some(index as u32 % 3 + 1),
visual_width: 256,
visual_height: 192,
top_surface_radius: 42.0,
landing_radius: 34.0,
face_assets: None,
})
.collect()
}

View File

@@ -8,9 +8,9 @@ pub use shared_contracts::jump_hop::{
JumpHopRestartRunRequest, JumpHopRunResponse, JumpHopRunStatus,
JumpHopRuntimeRunSnapshotResponse, JumpHopScoring, JumpHopSessionResponse,
JumpHopSessionSnapshotResponse, JumpHopStartRunRequest, JumpHopStylePreset, JumpHopTileAsset,
JumpHopTileType, JumpHopWorkDetailResponse, JumpHopWorkMutationResponse,
JumpHopWorkProfileResponse, JumpHopWorkSummaryResponse, JumpHopWorksResponse,
JumpHopWorkspaceCreateRequest,
JumpHopTileFaceAsset, JumpHopTileFaceAssets, JumpHopTileFaceKey, JumpHopTileType,
JumpHopWorkDetailResponse, JumpHopWorkMutationResponse, JumpHopWorkProfileResponse,
JumpHopWorkSummaryResponse, JumpHopWorksResponse, JumpHopWorkspaceCreateRequest,
};
pub(crate) fn map_jump_hop_agent_session_procedure_result(
@@ -267,6 +267,33 @@ fn map_tile_asset(snapshot: JumpHopTileAssetSnapshot) -> JumpHopTileAsset {
visual_height: snapshot.visual_height,
top_surface_radius: snapshot.top_surface_radius,
landing_radius: snapshot.landing_radius,
face_assets: snapshot.face_assets.map(map_tile_face_assets),
}
}
fn map_tile_face_assets(snapshot: JumpHopTileFaceAssetsSnapshot) -> JumpHopTileFaceAssets {
JumpHopTileFaceAssets {
top: map_tile_face_asset(snapshot.top),
front: map_tile_face_asset(snapshot.front),
right: map_tile_face_asset(snapshot.right),
back: map_tile_face_asset(snapshot.back),
left: map_tile_face_asset(snapshot.left),
bottom: map_tile_face_asset(snapshot.bottom),
}
}
fn map_tile_face_asset(snapshot: JumpHopTileFaceAssetSnapshot) -> JumpHopTileFaceAsset {
JumpHopTileFaceAsset {
face: parse_tile_face_key(&snapshot.face),
asset_id: snapshot.asset_id,
image_src: snapshot.image_src,
image_object_key: snapshot.image_object_key,
asset_object_id: snapshot.asset_object_id,
generation_provider: snapshot.generation_provider,
prompt: snapshot.prompt,
width: snapshot.width,
height: snapshot.height,
source_atlas_cell: snapshot.source_atlas_cell,
}
}
@@ -405,6 +432,17 @@ fn parse_tile_type(value: &str) -> JumpHopTileType {
}
}
fn parse_tile_face_key(value: &str) -> JumpHopTileFaceKey {
match value {
"front" => JumpHopTileFaceKey::Front,
"right" => JumpHopTileFaceKey::Right,
"back" => JumpHopTileFaceKey::Back,
"left" => JumpHopTileFaceKey::Left,
"bottom" => JumpHopTileFaceKey::Bottom,
_ => JumpHopTileFaceKey::Top,
}
}
fn parse_domain_tile_type(value: crate::module_bindings::JumpHopTileType) -> JumpHopTileType {
match value {
crate::module_bindings::JumpHopTileType::Start => JumpHopTileType::Start,

View File

@@ -463,6 +463,8 @@ pub mod jump_hop_runtime_run_row_type;
pub mod jump_hop_runtime_run_table;
pub mod jump_hop_scoring_type;
pub mod jump_hop_tile_asset_snapshot_type;
pub mod jump_hop_tile_face_asset_snapshot_type;
pub mod jump_hop_tile_face_assets_snapshot_type;
pub mod jump_hop_tile_type_type;
pub mod jump_hop_work_delete_input_type;
pub mod jump_hop_work_get_input_type;
@@ -1567,6 +1569,8 @@ pub use jump_hop_runtime_run_row_type::JumpHopRuntimeRunRow;
pub use jump_hop_runtime_run_table::*;
pub use jump_hop_scoring_type::JumpHopScoring;
pub use jump_hop_tile_asset_snapshot_type::JumpHopTileAssetSnapshot;
pub use jump_hop_tile_face_asset_snapshot_type::JumpHopTileFaceAssetSnapshot;
pub use jump_hop_tile_face_assets_snapshot_type::JumpHopTileFaceAssetsSnapshot;
pub use jump_hop_tile_type_type::JumpHopTileType;
pub use jump_hop_work_delete_input_type::JumpHopWorkDeleteInput;
pub use jump_hop_work_get_input_type::JumpHopWorkGetInput;

View File

@@ -4,6 +4,8 @@
#![allow(unused, clippy::all)]
use spacetimedb_sdk::__codegen::{self as __sdk, __lib, __sats, __ws};
use super::jump_hop_tile_face_assets_snapshot_type::JumpHopTileFaceAssetsSnapshot;
#[derive(__lib::ser::Serialize, __lib::de::Deserialize, Clone, PartialEq, Debug)]
#[sats(crate = __lib)]
pub struct JumpHopTileAssetSnapshot {
@@ -19,6 +21,7 @@ pub struct JumpHopTileAssetSnapshot {
pub visual_height: u32,
pub top_surface_radius: f32,
pub landing_radius: f32,
pub face_assets: Option<JumpHopTileFaceAssetsSnapshot>,
}
impl __sdk::InModule for JumpHopTileAssetSnapshot {

View File

@@ -0,0 +1,24 @@
// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE
// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD.
#![allow(unused, clippy::all)]
use spacetimedb_sdk::__codegen::{self as __sdk, __lib, __sats, __ws};
#[derive(__lib::ser::Serialize, __lib::de::Deserialize, Clone, PartialEq, Debug)]
#[sats(crate = __lib)]
pub struct JumpHopTileFaceAssetSnapshot {
pub face: String,
pub asset_id: String,
pub image_src: String,
pub image_object_key: String,
pub asset_object_id: String,
pub generation_provider: String,
pub prompt: String,
pub width: u32,
pub height: u32,
pub source_atlas_cell: String,
}
impl __sdk::InModule for JumpHopTileFaceAssetSnapshot {
type Module = super::RemoteModule;
}

View File

@@ -0,0 +1,22 @@
// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE
// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD.
#![allow(unused, clippy::all)]
use spacetimedb_sdk::__codegen::{self as __sdk, __lib, __sats, __ws};
use super::jump_hop_tile_face_asset_snapshot_type::JumpHopTileFaceAssetSnapshot;
#[derive(__lib::ser::Serialize, __lib::de::Deserialize, Clone, PartialEq, Debug)]
#[sats(crate = __lib)]
pub struct JumpHopTileFaceAssetsSnapshot {
pub top: JumpHopTileFaceAssetSnapshot,
pub front: JumpHopTileFaceAssetSnapshot,
pub right: JumpHopTileFaceAssetSnapshot,
pub back: JumpHopTileFaceAssetSnapshot,
pub left: JumpHopTileFaceAssetSnapshot,
pub bottom: JumpHopTileFaceAssetSnapshot,
}
impl __sdk::InModule for JumpHopTileFaceAssetsSnapshot {
type Module = super::RemoteModule;
}