構建與貢獻
構建
需要 Windows x64、xmake、MSVC 14.4x 或更新的 Visual Studio 生成工具,以及 LLVM(clang-cl)。
tools/build.ps1 會找到它們,缺的用 winget 安裝,然後構建:
pwsh -NoProfile -File tools/build.ps1 # [-Mode debug]手動構建:
xmake f -a x64 -m release -p windows --target_type=client -y
xmake -y # -> bin\BeDD\(DLL、manifest 以及 client\ 里的所有文件)模組打包器從 git describe 讀取版本號,所以倉庫至少要有一個提交。
tools\dev.ps1 [-Trace] 是一個試驗場:它拿到共享的 e2e 鎖(%APPDATA%\levilauncher.exe\bei-e2e.lock),把模塊部署進 BeDD 找到的實例
(新電腦上先準備好,見在新電腦上準備),沒有管理窗口時先啟動它,通過 LeviLauncher 啟動遊戲(遊戲顯示在管理窗口裡),並把每次前臺和光標鎖定的變化記錄到
tools\out\desktop-watch.log,直到遊戲退出或 tools\out\dev.stop 存在(tools\out\dev.restart 會重新部署並重啟,不釋放鎖)。
它最後總會關掉遊戲、刪掉模塊並釋放鎖。
文檔與展示素材
docs/ 是文檔站點(https://docs.levimc.org/BeDD/,由 .github/workflows/docs.yml 用 levimc-kit 構建;cd docs; npm ci; npm run build)。
docs/public/showcase/ 存放站點的展示內容和 README 裡的圖片。
tools/showcase/record.ps1 [-KeepOpen] 重新錄製桌面視頻:在共享 e2e 鎖(以及每個克隆的 hi<N>-e2e.lock)下,它準備三個克隆實例
(-hi2..-hi4,其他模組挪開),恢復 tools/showcase/fixtures/Showcase.zip 存檔,在它自己的管理窗口裡啟動遊戲(BEDD_MANAGER_PIPE,這樣別的測試的遊戲不會進畫面)
並進入世界,在屏幕外、不搶焦點的控制台窗口裡運行 demo.ps1,然後用 ffmpeg 的 gfxcapture(Windows.Graphics.Capture:直接錄窗口自己的畫面,被擋住也不影響)
錄下管理窗口和這個控制台,存為 tools/showcase/out/take-<n>-manager.mkv 和 take-<n>-terminal.mkv。不會有窗口挪到你面前,也不會搶焦點。
帶 -KeepOpen 時,創建 tools/showcase/out/take 開始下一次錄製,tools/showcase/out/stop 結束。
tools/showcase/encode.ps1 把一次錄製拼成左邊管理窗口、右邊終端的畫面,剪成 MP4、WebP 和封面圖。
源碼結構
| 文件 | |
|---|---|
src/BeDD.h | 共享狀態,以及下面各部分的聲明 |
src/Mod.cpp | 入口、配置、虛擬按鍵/光標狀態 |
src/Window.cpp | 窗口查找、子類化、合成事件分發、焦點屏蔽、讓窗口留在屏幕外 |
src/ApiHooks.cpp | user32 鉤子(光標、按鍵狀態、前臺、激活、原始輸入) |
src/GameInputHooks.cpp | GameInput v2 鉤子(虛擬鼠標、鍵盤讀數) |
src/Audio.cpp | FMOD 鉤子:靜音遊戲的主通道組(mute) |
src/NetHooks.cpp | 只用本機網絡(loopbackOnly:沒有防火牆提示,不查詢本機以外的服務器) |
src/Pipe.cpp | 控制管道和協議 |
src/Manager.cpp | 與會話管理窗口的連接 |
src/Trace.cpp | trace 模式的輸入日誌 |
src/MoveInput.cpp | input 操作:在客戶端的 ClientInputUpdateSystem 裡覆蓋移動,帶死人開關 TTL(gameHooks) |
src/Send.cpp | send 操作(allowSend):允許列表內的服務端方向數據包,在客戶端線程上由本地玩家發送 |
src/GameState.cpp、src/Look.cpp | world 快照和絕對 look(gameHooks) |
src/GameActions.cpp | slot、action 和按刻計算的 button 操作(gameHooks) |
src/Stack.cpp | stack 操作(allowStack):由本地客戶端發送的物品堆請求 |
src/TapSink.h | 所有 tap 發佈者共用的幀類型和 sink 鏈(保持逐字節一致) |
src/Tap.cpp、src/Tap.h | tap 管道:幀格式、標記、寫線程、tap 操作 |
src/NetTap.cpp | 遠程服務器連接上的 tap 抓取,以及 blob 緩存開關 |
src/TapLoopback.cpp | 單人世界和局域網主機世界裡的 tap 抓取(重新序列化的包) |
src/TapJournal.cpp | tap 的加入日誌(給晚到讀取方的壓縮回放) |
src/MemoryOperators.cpp | 讓 new/delete 走 LeviLamina 的分配器(LeviLamina 要求) |
client/ | PowerShell 客戶端、框架墊片、遊戲啟動(Start-BeDDGame.ps1)、管理窗口(BeDDManager.ps1)、克隆腳本和準備腳本(BeDDSetup.psm1、Initialize-BeDD.ps1:找到遊戲實例並補齊新電腦缺的東西),都和 DLL 放在一起發佈 |
掛鉤遊戲或 LeviLamina 的符號時,先查 %LOCALAPPDATA%\.xmake\packages\l\levilamina\<version>\<hash>\include 下的 SDK 頭文件。
只調用 MCAPI、MCFOLD 和 MCTAPI 函數。
Pull request
- Fork 倉庫,從
main建分支。 - 每個 pull request 只做一件事。說明它做了什麼、你怎麼測試的。
- 遵循現有風格:C++20、倉庫裡的
.clang-format和.editorconfig,代碼和註釋用英文。 - 在遊戲裡測試:
tools/dev.ps1 -Trace,然後通過BeDD.psm1驅動遊戲,檢查輸入有效、遊戲從不搶前臺(tools/out/desktop-watch.log), 真實輸入也到不了遊戲。 - CI 通過後才能合併。
提交信息用祈使語氣("Add wheel tilt",而不是 "Added …")。對用戶可見的改動,在 CHANGELOG.md 的 Unreleased 下記一筆。
另見 CONTRIBUTING.md。參與貢獻即表示你同意你的貢獻以本項目的許可證 LGPL-3.0-or-later 授權。