⚠️ Early Development: This project is in a very early stage and is currently more of a proof-of-concept than a production-ready engine.
An Undifferentiated Game Engine Core
Staminal is a modular game engine written in Rust where the core provides only the platform (networking, virtual filesystem, security) while all game logic is delivered through Mods. Inspired by stem cells, the engine remains "undifferentiated" — it doesn't dictate what kind of game you build.
Clients declare their intent (e.g., INTENT: "main:login:survival"), and the server responds by sending the necessary mods. This allows a single server to host multiple game modes or entirely different games.
Mods are sandboxed scripts that define game logic. Currently supported:
- JavaScript (QuickJS runtime)
Planned runtimes: Lua, C#, Rust, C++
- Bootstrap mods: Entry points that start game logic (
onBootstrap()) - Library mods: Utility modules imported by other mods (
onAttach()only)
Each mod can have separate scripts for client and server:
mods/my-mod/
├── mod.json # Mod manifest
├── client/ # Client-side scripts (UI, rendering, input)
│ └── index.js
└── server/ # Server-side scripts (game state, validation)
└── index.js
Mods can import from each other using the @mod-id syntax:
import { helper } from '@my-utility-mod';Built on Bevy, the engine exposes a complete Entity-Component-System API to mods:
- Spawn entities with components
- Query entities by component filters
- Declare systems with built-in behaviors (gravity, velocity, follow, orbit, etc.)
- Define custom components with JSON schemas
- Use formula-based systems with mathematical expressions
- Window management (create, resize, fullscreen, multi-window)
- UI nodes (text, images, buttons with hover/pressed states)
- Font loading and text rendering
- Per-window camera system
- Path validation prevents directory traversal attacks
- Mods can only access permitted directories (
data_dir,config_dir) - Symlinks are resolved and validated
staminal/
├── apps/
│ ├── stam_server/ # Dedicated server (Linux)
│ ├── stam_client/ # Game client (Linux, macOS, Windows planned)
│ └── shared/
│ ├── stam_protocol/ # Network protocol definitions
│ ├── stam_schema/ # JSON schema validation
│ └── stam_mod_runtimes/ # Mod runtime engines
├── mods/ # Game mods
└── docs/ # Documentation
- Rust (latest stable)
- Node.js (for npm scripts, it will removed in favor of cargo scripts in the near future)
Always use npm scripts to run the server and client — they set required environment variables:
# Install dependencies
npm install
# Start the server
npm run server:debug
# Start the client (in another terminal)
npm run client:debug| Variable | Description |
|---|---|
STAM_URI |
Server connection URI (stam://user:pass@host:port) |
STAM_LANG |
Locale code (e.g., en-US, it-IT) |
STAM_HOME |
Data directory path |
STAM_GAME |
Game to connect to (by game_id or game_name). If not specified, connects to the first available game. |
STAM_LOG_LEVEL |
Log level (trace, debug, info, warn, error) |
STAM_LOGDEPS |
Enable external dependency logs (0 or 1) |
During development, logs are written to:
- Server:
apps/stam_server/stam_server.log - Client:
apps/stam_client/stam_client.log
Mods have access to these global objects:
| Object | Purpose |
|---|---|
System |
Mod info, events, game context, lifecycle |
Graphic |
Window management, graphic engine control |
World |
ECS operations (spawn, query, systems) |
File |
Secure file read/write |
Locale |
Localization and translations |
Resource |
Asset loading (images, fonts) |
Network |
requests, downloads and multiplayer packets |
Process |
Application paths and environment |
console |
Standard logging |
const button = await World.spawn({
Node: { width: 200, height: 50 },
Button: true,
BackgroundColor: "#4A90D9",
Text: "Click Me"
});
await button.on("click", () => {
console.log("Button clicked!");
});See the docs/ folder for detailed documentation:
This project is licensed under CC BY-NC-SA 4.0 (Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International).
See LICENSE.md for details.