尚未偵測到更新。GitHub 發布版本後會顯示在這裡。
個人 GitHub 帳號下公開儲存庫的擁有者可以登入並驗證所有權,自行管理介紹,無需管理員核准。
登入並產生驗證檔案,在 30 分鐘內將其提交至此儲存庫的預設分支。其他分支或分叉儲存庫中的檔案無效。然後在下方檢查檔案,即可無需管理員核准直接管理專案。請保留檔案以維持管理權限。
如需登入,將前往登入頁面。登入後請回到此處,再次點擊所選的驗證按鈕。
在專案資料夾中執行 /nomorevibe verify,即可驗證所有權並自行管理介紹。
一分鐘完成驗證It is allowed to rob caravans
翻譯準備中
正在載入完整 README。
檢視完整 README ↗🎮 Live app: https://korovany.aimost.pl/ · 📚 Docs: https://flopsstuff.github.io/korovany/
3D action game / browser SPA.
Stack: TypeScript · React 19 · Babylon.js · Redux Toolkit · Vite 6. App deploys to Cloudflare Pages; docs deploy to GitHub Pages — both via GitHub Actions.
git lfs install # one time per machine (binary assets use Git LFS)
npm install
npm run dev # dev server (http://localhost:5173)
npm test # run the test suite (Vitest)
npm run build # type-check + production build into ./dist
npm run preview # serve the production build locally
npm run docs:dev # preview the documentation site
These apply to every contributor — human or agent. Full version:
docs/guide/project-rules.md. For automated
contributors see AGENTS.md and CLAUDE.md.
strict, no any. React function components only; 3D via
Babylon.js; shared state via Redux Toolkit slices in src/store/.flo-<issue>-<slug>); keep main green and deployable;
reference the issue in commits.npm test
runs in CI and must pass.docs/ in the same change;
it auto-publishes to GitHub Pages..gitattributes): source binaries in
/assets, bundled assets in src/assets/.src/app/ app shell & composition src/store/ Redux Toolkit store + slices
src/engine/ Babylon Engine/Scene lifecycle src/scenes/ Babylon scenes & canvas wrapper
src/game/ engine-agnostic game logic src/components/ reusable React UI
src/assets/ bundled assets src/hooks/ shared React hooks
assets/ source binaries (Git LFS) src/types/ shared types
public/ static files served as-is docs/ VitePress docs → GitHub Pages
See docs/guide/architecture.md for where new code belongs.
The game renders into a full-window 3D canvas — the document never scrolls
and there is no max-width container (src/styles/global.css resets
html/body/#root and hides overflow). React overlays sit above the canvas for
the HUD, main menu, and pause screen. The app boots into the main menu; New
Game enters play, Continue resumes the latest save (see
Saving progress), ESC toggles playing ⇄ paused, M
(or the HUD Travel button) opens the world map (see
World map & fast-travel), and B spends a carried
bandage to stop bleeding from a severed limb (see
docs/guide/health-system.md).
The Babylon Engine/Scene lifecycle lives in src/engine/,
not inline in a component. createGameEngine(canvas) owns engine + scene
creation, the high-DPI resize handler (setHardwareScalingLevel(1 / devicePixelRatio)
so the canvas stays crisp on retina), the render loop, and dispose().
src/scenes/GameCanvas.tsx is a thin React wrapper
that mounts the engine against a ref'd canvas and disposes it on unmount.
New Game drops the player into the forest with a HUD objective — Raid 3
caravans — and a running Score (kills + loot). Raiding all three caravans
shows an explicit win screen; dying shows a lose screen. Both offer
Restart (a fresh run) and Main Menu. The win/lose decision is a pure,
unit-tested state machine (src/game/objective/objectiveMachine.ts) that drives
the app phase into won/lost; per-run progress and score live in
gameSlice. Full details: docs/guide/objective-loop.md.
A bottom-centre minimap radar shows the player (with a facing indicator), the
caravans to raid (gold), and threats (red) on a top-down map of the play area, so
the objective is always findable. Live positions stay scene-owned and are pushed
to the HUD on a throttled ~10 Hz bridge (no per-frame Redux/React updates). Full
details: docs/guide/minimap.md.
The world has four zones (Human lands, Empire, Forest, Mountains). During
play, press M or click the HUD Travel button to open the world-map overlay
and fast-travel between the zones that have a playable scene. Selecting a
zone shows a Travel/Cancel confirm; on confirm the player is teleported to that
zone's spawn and its scene is mounted.
E3.1 ships Forest (the vertical slice) and a Human-lands stub as
available; Empire and Mountains are listed but locked until their scenes
exist. The zone registry lives in src/game/world/ and the
current zone id is persisted in saves. Full details:
docs/guide/world-map.md (lore/layout targets in
docs/guide/world-specs.md).
Raiding caravans (the "грабить корованы" loop) drops loot the player collects into a carried inventory, shown in a HUD panel below the health bar while playing (E3.4).
itemId → count map plus one equipped slot
lives in src/game/economy/; the Redux integration is
src/store/inventorySlice.ts. Item display
names/flags come from the static catalog in
src/game/economy/items.ts — the save stores only
ids + counts, so adding a lootable good is a catalog entry with no schema bump.pickUpLoot({ itemId, count });
the HUD panel reflects the carried stacks, marks the equipped item, and shows an
explicit empty state before any loot is collected.Money is gold pieces — and gold is just a carried item, so looted coin is
spendable coin (no separate wallet, no save-schema bump). Each catalog item has a
base value; merchants sell at that value and buy back at a markdown.
buy / sell
transactions move goods + gold and return a typed success/failure result —
both in src/game/economy/.buyItem / sellItem reducers and selectGold /
selectInventory selectors in
src/store/inventorySlice.ts. Failed trades are
a no-op.docs/guide/economy.md.Binary game assets (GLB models, textures, audio) are stored in Git LFS — run
git lfs install once before cloning or committing.
meshy-3d skill: python tools/meshy-3d/meshy.py …
(text/image → GLB via the Meshy API; needs MESHY_API_KEY). See
tools/meshy-3d/SKILL.md.public/models/; Cloudflare
Pages serves them from its CDN at /models/<name>.glb.loadModel(scene, '/models/x.glb')
(src/scenes/modelLoader.ts), which normalizes
scale (longest side ≈ 2 units) and grounds the model on import. The returned
root is a clean placement node; scene code may set root.position without
erasing the internal grounding offset.Rationale and the import contract: docs/decisions/0001-asset-hosting.md
and 0002-glb-import-contract.md.
Player progress survives a browser reload. A small versioned snapshot — the
player's transform (position + yaw), health (current + max), zone id,
carried inventory, and character progression — is persisted to the browser's
IndexedDB (korovany-save database, one autosave slot).
clearSave(), or clearing the site's browser data).
Nothing is uploaded; saves are local to the browser.The schema is forever — fields are never renamed; format changes bump
SAVE_VERSION and add a migration. SAVE_VERSION is currently 3 (v2 added
inventory; v3 added progression; older saves migrate forward with empty /
baseline values). Full details, slot
model, and the test approach (fake-indexeddb):
docs/guide/save-system.md.
The game gives audible feedback for every action — enemy hit, enemy kill,
player taking damage, swing, win, and lose — through a tiny raw Web Audio bus
(src/game/audio/). SFX are synthesized procedurally (no
sample files, no Git LFS payload, no third-party licensing); the bus subscribes
to the existing combat event bridge rather than scattering playback calls.
Escape). Both persist
across reloads in localStorage under the korovany-audio key
({ muted, volume }; default { false, 0.7 }).AudioContext is created/resumed only on the first user gesture
(click or keypress) to respect browser autoplay policy — no autoplay warnings.Full design, the event map, and how to add a sound:
docs/guide/audio.md.
Two independent targets, both on push to main (details:
docs/operations/deployment.md):
.github/workflows/deploy.yml
(cloudflare/wrangler-action). PRs build + test but don't deploy. The deploy
step skips gracefully until the Cloudflare secrets exist, then activates
automatically; workflow_dispatch allows manual runs..github/workflows/docs.yml (VitePress).| Secret | What it is |
|---|---|
CLOUDFLARE_API_TOKEN | Cloudflare API token with the Cloudflare Pages: Edit permission |
CLOUDFLARE_ACCOUNT_ID | Your Cloudflare account ID |
Stored as GitHub Actions secrets (not project env vars) because the deploy
runs on GitHub's runners. Full credential playbook:
docs/operations/cloudflare-deploy.md.