抓大鹅F3实现
Some checks failed
CI / verify (push) Has been cancelled

This commit is contained in:
2026-04-30 21:01:36 +08:00
parent 22f6e6f4e7
commit 08815d98bc
39 changed files with 5891 additions and 18 deletions

View File

@@ -31,6 +31,7 @@ mod auth;
mod big_fish;
mod domain_types;
mod entry;
mod match3d;
mod migration;
mod puzzle;
mod runtime;
@@ -41,6 +42,7 @@ pub use auth::*;
pub use big_fish::*;
pub use domain_types::*;
pub use entry::*;
pub use match3d::*;
pub use migration::*;
pub use runtime::*;
@@ -2856,7 +2858,9 @@ fn list_custom_world_profile_snapshots(
Ok(entries)
}
fn build_custom_world_profile_list_snapshot(row: &CustomWorldProfile) -> CustomWorldProfileSnapshot {
fn build_custom_world_profile_list_snapshot(
row: &CustomWorldProfile,
) -> CustomWorldProfileSnapshot {
let mut snapshot = build_custom_world_profile_snapshot(row);
snapshot.profile_payload_json = build_custom_world_profile_list_payload_json(row);
snapshot

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,86 @@
use crate::*;
#[spacetimedb::table(
accessor = match3d_agent_session,
index(accessor = by_match3d_agent_session_owner_user_id, btree(columns = [owner_user_id]))
)]
pub struct Match3DAgentSessionRow {
#[primary_key]
pub(crate) session_id: String,
pub(crate) owner_user_id: String,
pub(crate) seed_text: String,
pub(crate) current_turn: u32,
pub(crate) progress_percent: u32,
pub(crate) stage: String,
pub(crate) config_json: String,
pub(crate) draft_json: String,
pub(crate) last_assistant_reply: String,
pub(crate) published_profile_id: String,
pub(crate) created_at: Timestamp,
pub(crate) updated_at: Timestamp,
}
#[spacetimedb::table(
accessor = match3d_agent_message,
index(accessor = by_match3d_agent_message_session_id, btree(columns = [session_id]))
)]
pub struct Match3DAgentMessageRow {
#[primary_key]
pub(crate) message_id: String,
pub(crate) session_id: String,
pub(crate) role: String,
pub(crate) kind: String,
pub(crate) text: String,
pub(crate) created_at: Timestamp,
}
#[spacetimedb::table(
accessor = match3d_work_profile,
index(accessor = by_match3d_work_owner_user_id, btree(columns = [owner_user_id])),
index(accessor = by_match3d_work_publication_status, btree(columns = [publication_status]))
)]
pub struct Match3DWorkProfileRow {
#[primary_key]
pub(crate) profile_id: String,
pub(crate) owner_user_id: String,
pub(crate) source_session_id: String,
pub(crate) author_display_name: String,
pub(crate) game_name: String,
pub(crate) theme_text: String,
pub(crate) summary_text: String,
pub(crate) tags_json: String,
pub(crate) cover_image_src: String,
pub(crate) cover_asset_id: String,
pub(crate) clear_count: u32,
pub(crate) difficulty: u32,
pub(crate) config_json: String,
pub(crate) publication_status: String,
pub(crate) play_count: u32,
pub(crate) updated_at: Timestamp,
pub(crate) published_at: Option<Timestamp>,
}
#[spacetimedb::table(
accessor = match3d_runtime_run,
index(accessor = by_match3d_run_owner_user_id, btree(columns = [owner_user_id])),
index(accessor = by_match3d_run_profile_id, btree(columns = [profile_id]))
)]
pub struct Match3DRuntimeRunRow {
#[primary_key]
pub(crate) run_id: String,
pub(crate) owner_user_id: String,
pub(crate) profile_id: String,
pub(crate) status: String,
pub(crate) snapshot_version: u32,
pub(crate) started_at_ms: i64,
pub(crate) duration_limit_ms: i64,
pub(crate) finished_at_ms: i64,
pub(crate) elapsed_ms: i64,
pub(crate) clear_count: u32,
pub(crate) total_item_count: u32,
pub(crate) cleared_item_count: u32,
pub(crate) failure_reason: String,
pub(crate) snapshot_json: String,
pub(crate) created_at: Timestamp,
pub(crate) updated_at: Timestamp,
}

View File

@@ -0,0 +1,332 @@
use crate::*;
use serde::{Deserialize, Serialize};
pub const MATCH3D_DEFAULT_DURATION_LIMIT_MS: i64 = 600_000;
pub const MATCH3D_TRAY_SLOT_COUNT: u32 = 7;
pub const MATCH3D_VISUAL_VARIANT_COUNT: u32 = 10;
pub const MATCH3D_MIN_DIFFICULTY: u32 = 1;
pub const MATCH3D_MAX_DIFFICULTY: u32 = 10;
pub const MATCH3D_STAGE_COLLECTING: &str = "Collecting";
pub const MATCH3D_STAGE_READY_TO_COMPILE: &str = "ReadyToCompile";
pub const MATCH3D_STAGE_DRAFT_COMPILED: &str = "DraftCompiled";
pub const MATCH3D_STAGE_PUBLISHED: &str = "Published";
pub const MATCH3D_ROLE_USER: &str = "user";
pub const MATCH3D_ROLE_ASSISTANT: &str = "assistant";
pub const MATCH3D_KIND_TEXT: &str = "text";
pub const MATCH3D_PUBLICATION_DRAFT: &str = "Draft";
pub const MATCH3D_PUBLICATION_PUBLISHED: &str = "Published";
pub const MATCH3D_RUN_RUNNING: &str = "Running";
pub const MATCH3D_RUN_WON: &str = "Won";
pub const MATCH3D_RUN_FAILED: &str = "Failed";
pub const MATCH3D_RUN_STOPPED: &str = "Stopped";
pub const MATCH3D_FAILURE_TIME_UP: &str = "TimeUp";
pub const MATCH3D_FAILURE_TRAY_FULL: &str = "TrayFull";
pub const MATCH3D_CLICK_ACCEPTED: &str = "Accepted";
pub const MATCH3D_CLICK_REJECTED_NOT_CLICKABLE: &str = "RejectedNotClickable";
pub const MATCH3D_CLICK_REJECTED_ALREADY_MOVED: &str = "RejectedAlreadyMoved";
pub const MATCH3D_CLICK_REJECTED_TRAY_FULL: &str = "RejectedTrayFull";
pub const MATCH3D_CLICK_VERSION_CONFLICT: &str = "VersionConflict";
pub const MATCH3D_CLICK_RUN_FINISHED: &str = "RunFinished";
pub const MATCH3D_ITEM_IN_BOARD: &str = "InBoard";
pub const MATCH3D_ITEM_IN_TRAY: &str = "InTray";
pub const MATCH3D_ITEM_CLEARED: &str = "Cleared";
#[derive(Clone, Debug, PartialEq, Eq, SpacetimeType)]
pub struct Match3DAgentSessionCreateInput {
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, SpacetimeType)]
pub struct Match3DAgentSessionGetInput {
pub session_id: String,
pub owner_user_id: String,
}
#[derive(Clone, Debug, PartialEq, Eq, SpacetimeType)]
pub struct Match3DAgentMessageSubmitInput {
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, SpacetimeType)]
pub struct Match3DAgentMessageFinalizeInput {
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, SpacetimeType)]
pub struct Match3DDraftCompileInput {
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,
}
#[derive(Clone, Debug, PartialEq, Eq, SpacetimeType)]
pub struct Match3DWorkUpdateInput {
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, SpacetimeType)]
pub struct Match3DWorkPublishInput {
pub profile_id: String,
pub owner_user_id: String,
pub published_at_micros: i64,
}
#[derive(Clone, Debug, PartialEq, Eq, SpacetimeType)]
pub struct Match3DWorksListInput {
pub owner_user_id: String,
pub published_only: bool,
}
#[derive(Clone, Debug, PartialEq, Eq, SpacetimeType)]
pub struct Match3DWorkGetInput {
pub profile_id: String,
pub owner_user_id: String,
}
#[derive(Clone, Debug, PartialEq, Eq, SpacetimeType)]
pub struct Match3DWorkDeleteInput {
pub profile_id: String,
pub owner_user_id: String,
}
#[derive(Clone, Debug, PartialEq, Eq, SpacetimeType)]
pub struct Match3DRunStartInput {
pub run_id: String,
pub owner_user_id: String,
pub profile_id: String,
pub started_at_ms: i64,
}
#[derive(Clone, Debug, PartialEq, Eq, SpacetimeType)]
pub struct Match3DRunGetInput {
pub run_id: String,
pub owner_user_id: String,
}
#[derive(Clone, Debug, PartialEq, Eq, SpacetimeType)]
pub struct Match3DRunClickInput {
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, SpacetimeType)]
pub struct Match3DRunStopInput {
pub run_id: String,
pub owner_user_id: String,
pub stopped_at_ms: i64,
}
#[derive(Clone, Debug, PartialEq, Eq, SpacetimeType)]
pub struct Match3DRunRestartInput {
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, SpacetimeType)]
pub struct Match3DRunTimeUpInput {
pub run_id: String,
pub owner_user_id: String,
pub finished_at_ms: i64,
}
#[derive(Clone, Debug, PartialEq, Eq, SpacetimeType)]
pub struct Match3DAgentSessionProcedureResult {
pub ok: bool,
pub session_json: Option<String>,
pub error_message: Option<String>,
}
#[derive(Clone, Debug, PartialEq, Eq, SpacetimeType)]
pub struct Match3DWorkProcedureResult {
pub ok: bool,
pub work_json: Option<String>,
pub error_message: Option<String>,
}
#[derive(Clone, Debug, PartialEq, Eq, SpacetimeType)]
pub struct Match3DWorksProcedureResult {
pub ok: bool,
pub items_json: Option<String>,
pub error_message: Option<String>,
}
#[derive(Clone, Debug, PartialEq, Eq, SpacetimeType)]
pub struct Match3DRunProcedureResult {
pub ok: bool,
pub run_json: Option<String>,
pub error_message: Option<String>,
}
#[derive(Clone, Debug, PartialEq, Eq, SpacetimeType)]
pub struct Match3DClickItemProcedureResult {
pub ok: bool,
pub status: String,
pub run_json: Option<String>,
pub accepted_item_instance_id: Option<String>,
pub cleared_item_instance_ids: Vec<String>,
pub failure_reason: Option<String>,
pub error_message: Option<String>,
}
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Match3DCreatorConfigSnapshot {
pub theme_text: String,
pub reference_image_src: Option<String>,
pub clear_count: u32,
pub difficulty: u32,
}
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Match3DAgentMessageSnapshot {
pub message_id: String,
pub session_id: String,
pub role: String,
pub kind: String,
pub text: String,
pub created_at_micros: i64,
}
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Match3DDraftSnapshot {
pub profile_id: String,
pub game_name: String,
pub theme_text: String,
pub summary_text: String,
pub tags: Vec<String>,
pub clear_count: u32,
pub difficulty: u32,
}
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Match3DAgentSessionSnapshot {
pub session_id: String,
pub owner_user_id: String,
pub seed_text: String,
pub current_turn: u32,
pub progress_percent: u32,
pub stage: String,
pub config: Match3DCreatorConfigSnapshot,
pub draft: Option<Match3DDraftSnapshot>,
pub messages: Vec<Match3DAgentMessageSnapshot>,
pub last_assistant_reply: String,
pub published_profile_id: Option<String>,
pub created_at_micros: i64,
pub updated_at_micros: i64,
}
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Match3DWorkSnapshot {
pub profile_id: String,
pub owner_user_id: String,
pub source_session_id: String,
pub author_display_name: String,
pub game_name: String,
pub theme_text: String,
pub summary_text: String,
pub tags: Vec<String>,
pub cover_image_src: String,
pub cover_asset_id: String,
pub clear_count: u32,
pub difficulty: u32,
pub config: Match3DCreatorConfigSnapshot,
pub publication_status: String,
pub publish_ready: bool,
pub play_count: u32,
pub updated_at_micros: i64,
pub published_at_micros: Option<i64>,
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
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: String,
pub clickable: bool,
}
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Match3DTraySlotSnapshot {
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, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Match3DRunSnapshot {
pub run_id: String,
pub profile_id: String,
pub status: String,
pub snapshot_version: u32,
pub started_at_ms: i64,
pub duration_limit_ms: i64,
pub server_now_ms: i64,
pub remaining_ms: i64,
pub clear_count: u32,
pub total_item_count: u32,
pub cleared_item_count: u32,
pub tray_slots: Vec<Match3DTraySlotSnapshot>,
pub items: Vec<Match3DItemSnapshot>,
pub failure_reason: Option<String>,
}

View File

@@ -4,6 +4,9 @@ use spacetimedb_lib::sats::de::serde::DeserializeWrapper;
use spacetimedb_lib::sats::ser::serde::SerializeWrapper;
use std::collections::HashSet;
use crate::match3d::tables::{
match3d_agent_message, match3d_agent_session, match3d_runtime_run, match3d_work_profile,
};
use crate::puzzle::{
puzzle_agent_message, puzzle_agent_session, puzzle_runtime_run, puzzle_work_profile,
};
@@ -187,6 +190,10 @@ macro_rules! migration_tables {
puzzle_agent_message,
puzzle_work_profile,
puzzle_runtime_run,
match3d_agent_session,
match3d_agent_message,
match3d_work_profile,
match3d_runtime_run,
big_fish_creation_session,
big_fish_agent_message,
big_fish_asset_slot

View File

@@ -1261,8 +1261,9 @@ fn start_puzzle_run_tx(
}
let entry_profile = build_puzzle_work_profile_from_row(&entry_profile_row)?;
let started_at_ms = micros_to_millis(input.started_at_micros);
let mut run = module_puzzle::start_run_at(input.run_id.clone(), &entry_profile, 0, started_at_ms)
.map_err(|error| error.to_string())?;
let mut run =
module_puzzle::start_run_at(input.run_id.clone(), &entry_profile, 0, started_at_ms)
.map_err(|error| error.to_string())?;
let current_grid_size = run.current_grid_size;
let current_profile_id = entry_profile.profile_id.clone();
hydrate_puzzle_leaderboard_entries(
@@ -1502,13 +1503,11 @@ fn use_puzzle_runtime_prop_tx(
let row = get_owned_run_row(ctx, &input.run_id, &input.owner_user_id)?;
let current_run = deserialize_run(&row.snapshot_json)?;
let next_run = match input.prop_kind.as_str() {
"freezeTime" | "freeze_time" => {
module_puzzle::apply_puzzle_freeze_time_at(
&current_run,
micros_to_millis(input.used_at_micros),
)
.map_err(|error| error.to_string())?
}
"freezeTime" | "freeze_time" => module_puzzle::apply_puzzle_freeze_time_at(
&current_run,
micros_to_millis(input.used_at_micros),
)
.map_err(|error| error.to_string())?,
"hint" => module_puzzle::set_puzzle_run_paused_at(
&current_run,
false,