use serde::{Deserialize, Serialize}; #[cfg(feature = "spacetime-types")] use spacetimedb::SpacetimeType; pub const MATCH3D_SESSION_ID_PREFIX: &str = "match3d-session-"; pub const MATCH3D_MESSAGE_ID_PREFIX: &str = "match3d-message-"; pub const MATCH3D_PROFILE_ID_PREFIX: &str = "match3d-profile-"; pub const MATCH3D_WORK_ID_PREFIX: &str = "match3d-work-"; pub const MATCH3D_RUN_ID_PREFIX: &str = "match3d-run-"; pub const MATCH3D_TRAY_SLOT_COUNT: u32 = 7; pub const MATCH3D_ITEMS_PER_CLEAR: u32 = 3; pub const MATCH3D_MAX_ITEM_TYPE_COUNT: u32 = 25; pub(crate) const MATCH3D_MAX_ITEM_TYPE_COUNT_USIZE: usize = 25; pub const MATCH3D_MIN_DIFFICULTY: u32 = 1; pub const MATCH3D_MAX_DIFFICULTY: u32 = 10; pub const MATCH3D_DEFAULT_DURATION_LIMIT_MS: u64 = 10 * 60 * 1000; pub const MATCH3D_BOARD_CENTER: f32 = 0.5; pub const MATCH3D_BOARD_RADIUS: f32 = 0.5; pub const MATCH3D_BOARD_SAFE_MARGIN: f32 = 0.035; // 中文注释:首版 demo 不接真实图片生成,当前先用程序化积木件作为稳定可辨认的默认素材。 // 中文注释:当前 demo 使用 25 个积木件作为默认可消除物资源池,前端据 visual_key 程序化生成 3D 模型。 pub(crate) const MATCH3D_BLOCK_VISUAL_KEYS: [&str; MATCH3D_MAX_ITEM_TYPE_COUNT_USIZE] = [ "block-red-2x4", "block-blue-1x2", "block-yellow-2x2", "block-green-1x4", "block-orange-1x6", "block-white-1x1", "block-black-1x8", "block-tan-2x3", "block-lime-1x2", "block-darkred-2x2", "block-blue-1x4", "block-pink-2x4", "block-gray-1x6", "block-lavender-tile-2x2", "block-teal-tile-1x3", "block-mint-tile-1x4", "block-magenta-tile-2x2", "block-orange-tile-2x2-stud", "block-purple-slope-1x2", "block-brown-slope-1x2", "block-sky-slope-2x2", "block-green-cylinder", "block-clear-ring", "block-mint-arch", "block-gold-cone", ]; #[cfg_attr(feature = "spacetime-types", derive(SpacetimeType))] #[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)] pub enum Match3DCreationStage { CollectingConfig, DraftReady, ReadyToPublish, Published, } #[cfg_attr(feature = "spacetime-types", derive(SpacetimeType))] #[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)] pub enum Match3DPublicationStatus { Draft, Published, } #[cfg_attr(feature = "spacetime-types", derive(SpacetimeType))] #[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)] pub enum Match3DRunStatus { Running, Won, Failed, Stopped, } #[cfg_attr(feature = "spacetime-types", derive(SpacetimeType))] #[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)] pub enum Match3DFailureReason { TimeUp, TrayFull, } #[cfg_attr(feature = "spacetime-types", derive(SpacetimeType))] #[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)] pub enum Match3DItemState { InBoard, InTray, Cleared, } #[cfg_attr(feature = "spacetime-types", derive(SpacetimeType))] #[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)] pub enum Match3DClickRejectReason { RunNotActive, SnapshotVersionMismatch, ItemNotFound, ItemNotInBoard, ItemNotClickable, TrayFull, } #[cfg_attr(feature = "spacetime-types", derive(SpacetimeType))] #[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] pub struct Match3DCreatorConfig { pub theme_text: String, pub reference_image_src: Option, pub clear_count: u32, pub difficulty: u32, } #[cfg_attr(feature = "spacetime-types", derive(SpacetimeType))] #[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] pub struct Match3DResultDraft { pub game_name: String, pub theme_text: String, pub summary: String, pub tags: Vec, pub cover_image_src: Option, pub reference_image_src: Option, pub clear_count: u32, pub difficulty: u32, pub publish_ready: bool, pub blockers: Vec, } #[cfg_attr(feature = "spacetime-types", derive(SpacetimeType))] #[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] pub struct Match3DWorkProfile { pub work_id: String, pub profile_id: String, pub owner_user_id: String, pub source_session_id: Option, pub game_name: String, pub theme_text: String, pub summary: String, pub tags: Vec, pub cover_image_src: Option, pub reference_image_src: Option, pub clear_count: u32, pub difficulty: u32, pub publication_status: Match3DPublicationStatus, pub play_count: u32, pub updated_at_micros: i64, pub published_at_micros: Option, } #[cfg_attr(feature = "spacetime-types", derive(SpacetimeType))] #[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct Match3DItemSnapshot { 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: Match3DItemState, pub clickable: bool, pub tray_slot_index: Option, } #[cfg_attr(feature = "spacetime-types", derive(SpacetimeType))] #[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] pub struct Match3DTraySlot { pub slot_index: u32, pub item_instance_id: Option, pub item_type_id: Option, pub visual_key: Option, } #[cfg_attr(feature = "spacetime-types", derive(SpacetimeType))] #[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct Match3DRunSnapshot { pub run_id: String, pub profile_id: String, pub owner_user_id: String, pub status: Match3DRunStatus, pub started_at_ms: u64, pub duration_limit_ms: u64, pub remaining_ms: u64, pub clear_count: u32, pub total_item_count: u32, pub cleared_item_count: u32, /// 领域内部权威快照版本;HTTP DTO 对外映射为 snapshotVersion。 pub board_version: u64, pub items: Vec, pub tray_slots: Vec, pub failure_reason: Option, pub last_confirmed_action_id: Option, } #[cfg_attr(feature = "spacetime-types", derive(SpacetimeType))] #[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] pub struct Match3DClickInput { pub run_id: String, pub owner_user_id: String, pub item_instance_id: String, pub client_action_id: String, pub snapshot_version: u64, pub clicked_at_ms: u64, } #[cfg_attr(feature = "spacetime-types", derive(SpacetimeType))] #[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct Match3DClickConfirmation { pub accepted: bool, pub reject_reason: Option, pub entered_slot_index: Option, pub cleared_item_instance_ids: Vec, pub run: Match3DRunSnapshot, } impl Match3DCreationStage { pub fn as_str(self) -> &'static str { match self { Self::CollectingConfig => "collecting_config", Self::DraftReady => "draft_ready", Self::ReadyToPublish => "ready_to_publish", Self::Published => "published", } } } impl Match3DPublicationStatus { pub fn as_str(self) -> &'static str { match self { Self::Draft => "draft", Self::Published => "published", } } } impl Match3DRunStatus { pub fn as_str(self) -> &'static str { match self { Self::Running => "running", Self::Won => "won", Self::Failed => "failed", Self::Stopped => "stopped", } } } impl Match3DFailureReason { pub fn as_str(self) -> &'static str { match self { Self::TimeUp => "time_up", Self::TrayFull => "tray_full", } } } impl Match3DItemState { pub fn as_str(self) -> &'static str { match self { Self::InBoard => "in_board", Self::InTray => "in_tray", Self::Cleared => "cleared", } } } impl Match3DClickRejectReason { pub fn as_str(self) -> &'static str { match self { Self::RunNotActive => "run_not_active", Self::SnapshotVersionMismatch => "snapshot_version_mismatch", Self::ItemNotFound => "item_not_found", Self::ItemNotInBoard => "item_not_in_board", Self::ItemNotClickable => "item_not_clickable", Self::TrayFull => "tray_full", } } }