Voxel RPG and survival sandbox in a medieval fantasy world bound by twelve elements and unravelled by a thirteenth. Rust + Vulkan engine, Lua-moddable gameplay, server-authoritative QUIC multiplayer.
  • Rust 98%
  • JavaScript 0.8%
  • GLSL 0.7%
  • Shell 0.5%
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
Serkyo 12452b1b98
All checks were successful
CI / Commit Message Lint (push) Has been skipped
CI / Rust Check, Lint & Test (push) Successful in 42m45s
CI / Dependency Licenses & Advisories (push) Successful in 32s
CI / Lua Lint & Format (push) Successful in 8s
CI / LFS Pointer Guard (push) Successful in 6s
Merge pull request 'feat(server): resolve and persist the world spawn at creation' (#15) from feat/persisted-spawn into dev
Reviewed-on: #15
2026-10-05 22:38:48 +00:00
.forgejo ci(workspace): verify the selene download against a pinned checksum 2026-09-29 09:57:38 +02:00
.opencode/commands chore(workspace): give /adr-new refusal conditions and section guidance 2026-09-12 22:12:48 +02:00
assets feat(shared): name worldgen blocks by content id 2026-09-30 14:08:49 +02:00
crates feat(server): place players and the origin anchor at the stored spawn 2026-10-04 03:45:39 +02:00
docs docs(workspace): document the persisted spawn 2026-10-04 03:47:01 +02:00
LICENSES docs(workspace): include verbatim license texts in LICENSES/ 2026-09-09 13:46:55 +02:00
mods/example_mod chore(workspace): add SPDX identifiers to source files 2026-05-17 21:06:39 +02:00
tools chore(workspace): remove remaining em-dashes from gitattributes and tooling 2026-06-28 03:29:49 +02:00
.gitattributes chore(renderer): compile shaders at build time 2026-08-04 02:41:33 +02:00
.gitignore chore(workspace): ignore remaining headroom MCP state files 2026-09-02 19:08:31 +02:00
AGENTS.md docs(workspace): drop CLAUDE.md now that AGENTS.md loads natively 2026-09-25 04:46:25 +02:00
Cargo.lock feat(scripting)!: register content only from data files 2026-09-30 15:20:38 +02:00
Cargo.toml ci(workspace): lower bevy_ecs opt-level further to fix runner OOM 2026-09-09 21:43:24 +02:00
CLA.md docs(workspace): add CONTRIBUTING.md and CLA 2026-07-09 16:05:31 +02:00
CODE_OF_CONDUCT.md docs(workspace): add the shared cryoforge nexus code of conduct 2026-08-08 00:13:54 +02:00
CONTRIBUTING.md docs(workspace): mark the core team tier closed pending a decision 2026-09-17 15:33:42 +02:00
CREDITS.md docs(workspace): add credits file 2026-09-17 15:32:36 +02:00
deny.toml ci(workspace): add cargo-deny for dependency licenses and advisories 2026-09-08 23:03:11 +02:00
DEVELOPMENT.md docs(workspace): describe data-only content registration 2026-09-30 15:20:38 +02:00
LICENSE.md docs(workspace): include verbatim license texts in LICENSES/ 2026-09-09 13:46:55 +02:00
opencode.json chore(workspace): point opencode at AGENTS.local.md via instructions 2026-09-08 22:51:23 +02:00
README.md docs(workspace): link every root markdown file from the readme 2026-09-26 15:01:01 +02:00
rust-toolchain.toml chore(workspace): pin the Rust toolchain to 1.97.1 2026-09-13 22:17:10 +02:00
rustfmt.toml chore(workspace): configure linters and format codebase 2026-05-12 11:43:17 +02:00
selene.toml fix(workspace): remove std from selene to avoid feature errors 2026-05-12 12:30:52 +02:00
stylua.toml chore(workspace): configure linters and format codebase 2026-05-12 11:43:17 +02:00

Synvael

A voxel RPG sandbox survival game set in Sylenor, a medieval fantasy world bound together by twelve magical elements and slowly being unravelled by a thirteenth.

Half-metre voxels, Souls-like combat with severable limbs, and an elemental magic wheel that punishes overuse. Written in Rust and Vulkan, with gameplay logic in Lua through the same modding API the base game is built on: JSON data packs for content, Lua mods for behaviour, and resource packs for textures and sound.

Important

The canonical repository is git.cryoforgenexus.com/Synvael/synvael. GitHub is a mirror; issues, pull requests, CI, and the CLA check all live on the canonical repository.

Warning

Pre-Alpha. The wire protocol, save records, content IDs, Lua API, and crate boundaries all change without notice, and there is no migration path until a format version increments. What runs today is the code that exists. Everything else is intent.

🌍 Design targets

None of this is implemented yet. The generator currently produces Perlin terrain and nothing else.

  • Three vertical layers. One map location carries a surface biome, a cave biome below, and a floating island biome above, each with its own flora, fauna, magic field, and weather.
  • Grandiose scale. Signature trees clear 32 m, mountain ranges form ridges, and crossing a biome is a journey, with a target view distance of 8 km through a LOD ladder. Twelve Primordials, one per element, roam the world at a size that reshapes the terrain they cross. Rivers need a source, a mouth, and a downhill gradient between them, water with nowhere to go pools into lakes, and flow varies with snowmelt at the source.
  • A world that keeps running. Forests grow, seed, age, self-thin, and recover from fire. Wildlife runs the same cycle, and vegetation density caps herbivores the way prey caps predators.
  • The Corruption. A hive organism seeded at worldgen that grows, builds, and spreads if nothing stops it. It is the central threat of the world.
  • Body-part damage. Damage routes to head, torso, arms, and legs, each tracking Healthy through Damaged, Broken, and Severed. Slashing weapons cut broken limbs into world items. The HUD is a paper doll, not a health bar.
  • The magic wheel. Twelve elements in six opposing pairs. An element's position on the wheel scales its spells and penalises its opposite; a balanced wheel just regenerates faster. Casting too far in one direction overloads.
  • Weight to movement. Everything above walking costs a wind-up, a locked state, or stamina, and air control is near zero. Mantling and climbing need free hands, so traversal depends on limb state.
  • Survival chemistry. A voxel-level pass handles ignition, freezing, steam, gas, current, and thermal spread, feeding body temperature and a hunger/thirst/stamina metabolism.
  • A physical interface. Pixel art on a 960 x 540 canvas at integer scale, animated on a fixed 12 fps step. No minimap, clock, compass, or coordinate readout: every overlay is an instrument the player found and equipped. First or third person out of combat, third person only once a weapon is drawn.
  • Modding in three layers. Blocks, items, recipes, loot tables, and biomes are declarative JSON, so a data pack registers content without writing a line of Lua. Lua mods cover behaviour: spells, mob AI, movesets, stances. Resource packs override textures, sounds, models, and fonts client-side, and a server can push one cosmetic overlay of its own. Everything scopes per world rather than per launcher profile, and mods are always free (packs, ADR-0007).

🔭 What runs today

Subsystem State
Rendering Vulkan 1.3 dynamic rendering through ash, GLSL compiled to SPIR-V at build time, CPU greedy meshing on a worker pool, frustum culling, debug wireframe and vertex-point modes.
Worldgen Seed-deterministic Perlin terrain from a pinned noise version, tuned by assets/data/worldgen/default/ (ADR-0003).
Simulation Authoritative bevy_ecs server on a 20 Hz tick, movement stepped at 60 Hz, with tick-budget reporting.
Chunk streaming Residency reconciled against the union of every client's subscription cylinder, generated off-tick, delivered under a per-tick budget.
Persistence SYNW world metadata plus SYNR/SYNC region files holding baseline-relative sparse edits, flushed by a single save actor (ADR-0009).
Networking QUIC through quinn, versioned handshake, trust-on-first-use certificate pinning, separate input/authority/chunk streams (ADR-0010, ADR-0011).
Movement Fixed-timestep kinematic controller, swept AABB collision, seven-state stance machine, auto-step, client prediction and replay reconciliation (ADR-0013).
Diagnostics GPU, host, network, chunk, frame, and server-tick statistics in an in-client panel and the dedicated server log.
Scripting Not started. crates/scripting is an empty placeholder.

Still ahead: LOD tiers, GPU meshing, palette compression, block breaking and placement, texturing, and every gameplay system.

🚀 Getting started

You need a Rust stable toolchain, Git LFS, a Vulkan-capable GPU on Linux or Windows, and libshaderc (libshaderc-dev on Debian, shaderc on Arch, or the Vulkan SDK on Windows). Without libshaderc the build compiles it from source, which also needs a C++ toolchain, CMake, Python 3, and Ninja. macOS, mobile, consoles, and web are out of scope.

git clone https://git.cryoforgenexus.com/Synvael/synvael.git
cd synvael
git lfs pull
cargo build

The client dials a server and cannot host one in-process yet, so start the server first. Run both from the repository root, since asset paths resolve relative to the working directory.

cargo run --release -p server    # binds 127.0.0.1:25565, pre-warms the spawn region
cargo run --release -p client    # opens the window and connects

Debug builds work (the dev profile optimises dependencies while keeping the overflow checks that chunk-index arithmetic relies on), but worldgen and meshing are heavy enough that anything past a smoke test wants --release.

Controls

WASD to move, mouse to look, Space to jump, Left Shift to sprint, Left Ctrl to crouch, Left Alt to walk, Escape to quit.

Debug affordances sit behind an F1 chord so they cannot collide with movement: F1 + I for the statistics panel, F1 + V for vertex points, F1 + B for triangle edges, F1 + P to force a visible prediction correction. Add Shift to drop the filled pass and leave debug geometry against the clear colour.

Testing and linting

CI enforces all of these. Run them before pushing.

cargo test --workspace
cargo fmt --all -- --check
cargo clippy --all-targets --all-features -- -D warnings
stylua --check assets/scripts/ mods/
selene assets/scripts/ mods/

The workspace opts into Clippy's pedantic group and bans unwrap, expect, and the print macros outside main and tests.

📦 Layout

Six crates under crates/:

Crate Kind Responsibility
client binary Windowing, input, camera, presentation. No simulation logic.
server binary Authoritative simulation: streaming, chunk cache, persistence, player state.
shared library Protocol and core types: voxels, chunks, worldgen, movement, save records, paths.
renderer library Vulkan backend and CPU meshing, decoupled from windowing.
net library QUIC transport, connection lifecycle, wire framing. Owns the async runtime.
scripting library Lua embedding and modding API. Stubbed.

Content sits outside them: assets/data/ for declarative content, assets/scripts/ for base-game Lua, assets/shaders/ for GLSL, mods/ for example mods and fixtures, docs/ for subsystem notes and ADRs.

Saves and player-installed mods resolve at runtime under the per-user data directory ($XDG_DATA_HOME/synvael on Linux, %APPDATA%\Cryoforge Nexus\Synvael\data on Windows). No path is hard-coded.

The stack is ash (Vulkan 1.3), bevy_ecs, winit, glam, quinn with rustls, serde and postcard, zstd, crossbeam-channel, and tracing. mlua and rapier3d are targets, not yet dependencies. The character controller stays outside rapier3d on purpose: a rigid-body solver is neither deterministic nor replayable under reconciliation.

📖 Documentation

To find out Read
Rules that apply to every change DEVELOPMENT.md
How a subsystem works docs/, plus cargo doc --workspace --open
Why a hard-to-reverse choice was made docs/adr/
How to contribute CONTRIBUTING.md
Contributor License Agreement terms CLA.md
Expected conduct in project spaces CODE_OF_CONDUCT.md
Who has contributed CREDITS.md
License terms for code and assets LICENSE.md
Engineering context for AI coding agents AGENTS.md

🤝 Contributing

Contributions are welcome and credited. Synvael is open-source but commercially developed by Cryoforge Nexus, and the terms that follow from that (contributor tiers, the required CLA, and what is and is not accepted) are set out in CONTRIBUTING.md. Read it before opening a pull request.

Work happens on dev; main carries releases. Commits follow Conventional Commits with a crate scope (feat(scripting): ...). Participation is governed by the Code of Conduct.

📜 License

Source code is AGPL-3.0-only. Assets under assets/ are CC-BY-NC-SA 4.0, which permits non-commercial resource packs built from them. The exception is assets/scripts/, which is source code and falls under the AGPL. Full terms are in LICENSE.md.

Copyright © 2026 Cryoforge Nexus.