وضعیت: API داخلیِ پایدار برای رابط فعلی دسکتاپ
مخاطب: توسعهدهندگان رابط، test harnessها و مشارکتکنندگان Rust/Tauri
ورود اصلی: src-tauri/src/main.rs
رابط برنامه با فرمانهای Rust که در tauri::generate_handler! ثبت شدهاند ارتباط برقرار میکند. در Tauri، invoke() یک Promise برمیگرداند و دادههای قابلسریالسازی را بین JavaScript و Rust ردوبدل میکند. 1 تمام فرمانهای این پروژه به state درونپردازهای GameState(Mutex<GameEngine>) دسترسی دارند؛ بنابراین فرمانهای تغییردهندهٔ وضعیت باید بهترتیب منطقی بازی فراخوانی شوند.
import { invoke } from '@tauri-apps/api/core';
const initialState = await invoke('initialize_game');
const nextState = await invoke('send_command', { command: 'take keycard' });نکتهٔ نامگذاری: نام فرمانها همان نام ثبتشده در
src-tauri/src/main.rsاست. آرگومانها در این API تکواژه و سازگار با JavaScript هستند:command،slot،configوpartial. هنگام افزودن نامهای چندکلمهای، قرارداد camelCase را در frontend ثابت نگه دارید؛ Tauri بهطور پیشفرض آرگومانهای JavaScript را با کلید camelCase میپذیرد. 1
| مرحله | فرمان | اثر | کاربرد صحیح |
|---|---|---|---|
| شروع پروندهٔ جدید | initialize_game |
Engine را reset میکند و متن آغازین را بازمیگرداند | فقط زمانی که کاربر «New Game» را انتخاب کرده است |
| خواندن session فعلی | get_game_state |
state فعلی را بدون reset و بدون متن آغازین جدید برمیگرداند | پس از load یا refresh UI |
| اجرای اقدام | send_command |
یک فرمان متنی را پردازش و state بهروز را بازمیگرداند | برای حرکت، برداشتن آیتم، حل معما و غیره |
| بارگذاری | load_game سپس get_game_state |
state ذخیرهشده را جایگزین میکند؛ فرمان دوم آن را نمایشپذیر میکند | هیچگاه پس از load، initialize_game را فراخوانی نکنید |
یک بازی تازه میسازد، جهان، آیتمها، معماها و achievementها را مقداردهی میکند و state کامل با پیامهای intro را بازمیگرداند.
const game = await invoke('initialize_game');
console.log(game.current_room.name);تصویر فعلی بازی را بدون تغییر دادن پیشرفت بازمیگرداند. فیلد messages در این فراخوانی خالی است، مگر آنکه در نسخهٔ آینده قرارداد آن صریحاً تغییر کند.
const game = await invoke('get_game_state');
renderGameState(game);یک فرمان بازی را پردازش و پیامهای تولیدشده، نقشه، inventory و وضعیت بازیکن را برمیگرداند. فرمانهای پشتیبانیشده شامل look، جهتها مانند north، take، drop، use، inventory، examine، read، solve، map، status، hint و restart هستند.
const game = await invoke('send_command', { command: 'take keycard' });
const hasError = game.messages.some((message) => message.msg_type === 'Error');state فعلی را در slot ذخیره میکند. رابط استاندارد سه slot صفر، یک و دو را نمایش میدهد. consumer باید همیشه success را بررسی کند؛ خطای ذخیره در message بازگردانده میشود، نه بهصورت exception قابلاتکا.
const result = await invoke('save_game', { slot: 0 });
if (!result.success) showNotification(result.message, true);یک slot را در Engine فعلی بارگذاری میکند. پس از پاسخ موفق، get_game_state() را فراخوانی کنید تا رابط از state جدید رسم شود.
const result = await invoke('load_game', { slot: 0 });
if (result.success) renderGameState(await invoke('get_game_state'));فهرست metadata slotها را برای صفحهٔ load/save برمیگرداند. این فرمان وضعیت بازی را تغییر نمیدهد.
فایل slot انتخابشده را حذف میکند. پیش از فراخوانی، confirmation رابط کاربر لازم است زیرا عملیات بازگشتناپذیر است.
تنظیمات درون session را بازمیگرداند. برای اعمال تم، اندازهٔ متن و minimap در UI از این فرمان استفاده کنید.
تنظیمات کامل را جایگزین میکند. consumer باید همهٔ فیلدهای GameConfig را بفرستد تا از ناخواستهشدن مقدارهای پیشفرض جلوگیری شود.
const current = await invoke('get_config');
const result = await invoke('update_config', {
config: { ...current, theme: 'retro', font_size: 20 },
});achievementهای فعلی را به آرایهٔ JSON سریالشده تبدیل میکند. UI میتواند از unlocked و hidden برای نمایش استفاده کند.
پیشنهادهای متن را بر اساس پیشوند فرمان، جهت، آیتمهای اتاق و inventory برمیگرداند.
const suggestions = await invoke('get_autocomplete', { partial: 'ta' });| فیلد | نوع JSON | معنا |
|---|---|---|
success |
boolean |
موفقیت یا شکست عملیات ذخیره/بارگذاری/حذف/تنظیمات |
message |
string |
پیام انسانخوان برای نمایش در رابط |
| فیلد | نوع | دامنه/نمونه |
|---|---|---|
text_speed |
number |
تأخیر تایپ بر حسب میلیثانیه؛ نمونه 30 |
sound_volume |
number |
مقدار بین صفر و یک؛ نمونه 0.7 |
music_volume |
number |
مقدار بین صفر و یک؛ نمونه 0.5 |
font_size |
number |
اندازهٔ متن بر حسب پیکسل؛ نمونه 16 |
theme |
string |
cyberpunk، dark یا retro |
show_minimap |
boolean |
نمایش یا پنهانکردن بخش نقشه |
auto_save |
boolean |
ذخیرهٔ خودکار پس از تعداد مشخصی حرکت |
confirm_actions |
boolean |
رزرو برای confirmationهای رابط |
| فیلد | معنا |
|---|---|
messages |
پیامهای تازهٔ حاصل از فرمان؛ هر پیام دارای text، msg_type و timestamp است |
current_room |
اتاق فعال، خروجیهای قابلنمایش، آیتمهای روی زمین، نور و صدای محیط |
inventory |
آیتمهای inventory شامل id، name، description، icon، category و usable |
player |
health، حرکتها، اتاقهای کاوششده، معماهای حلشده، آیتمهای جمعآوریشده و زمان بازی |
map_data |
اتاقها، اتصالها و current_room_id برای minimap |
achievements |
وضعیت unlock و پنهانبودن achievementها |
score، game_over، game_won |
شاخصهای پایان و امتیاز session |
هر آیتم شامل slot، exists، room_name، play_time و timestamp است. برای slot خالی، frontend باید ابتدا exists را بررسی کند و سپس metadata را نمایش دهد.
فرمانهای game معمولاً یک GameResponse با message از نوع Error یا Warning برمیگردانند. فرمانهای فایلمحور یک CommandResult با success: false برمیگردانند. برای خطاهای پیشبینینشدهٔ invoke نیز try/catch نگه دارید؛ Tauri فرمانها را بهصورت Promise فراخوانی میکند و قابلیت بازگرداندن خطاهای سریالپذیر را دارد. 1
try {
const result = await invoke('delete_save', { slot: 2 });
if (!result.success) showNotification(result.message, true);
} catch (error) {
showNotification(`Unexpected desktop API error: ${String(error)}`, true);
}۱. تابع را در src-tauri/src/main.rs یا یک module مشخص تعریف و با #[tauri::command] علامتگذاری کنید.
۲. آن را دقیقاً یکبار به tauri::generate_handler![...] اضافه کنید. فرمانها باید نام یکتا داشته باشند. 1
۳. ورودی را با typeهای serde::Deserialize و خروجی را با typeهای serde::Serialize طراحی کنید. 1
۴. برای behavior جدید، تست واحد در src-tauri/src/game/tests.rs اضافه کنید.
۵. contract این فایل و consumer JavaScript را در یک PR هماهنگ تغییر دهید.
۶. پیش از PR، cargo fmt --all -- --check، cargo test --workspace و cargo clippy --workspace --all-targets -- -D warnings را اجرا کنید.
قاعدهٔ سازگاری: تغییر نام فرمان، حذف فیلد پاسخ یا تغییر semantics
initialize_game/get_game_stateیک breaking change است. این تغییرها باید همراه با migration note در CHANGELOG و بهروزرسانی frontend انجام شوند.