Core Concepts
martini-kit is a host-authoritative, deterministic multiplayer framework that works with any rendering engine. This page explains the core architecture and how all the pieces fit together.
Architecture Overview
┌─────────────────────────────────────────────────────────────┐
│ Your Game Code │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │ Game Logic │ │ Actions │ │ State │ │
│ │ (defineGame) │ │ │ │ │ │
│ └──────────────┘ └──────────────┘ └──────────────┘ │
└─────────────────────────────────────────────────────────────┘
│
↓
┌─────────────────────────────────────────────────────────────┐
│ @martini-kit/core │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │ GameRuntime │ │ Transport │ │ State Sync │ │
│ │ │ │ Layer │ │ (diff/patch) │ │
│ └──────────────┘ └──────────────┘ └──────────────┘ │
└─────────────────────────────────────────────────────────────┘
│
↓
┌─────────────────────────────────────────────────────────────┐
│ Rendering Engine (Optional) │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │ Phaser │ │ Godot │ │ Three.js │ │
│ │ (adapter) │ │ (adapter) │ │ (custom) │ │
│ └──────────────┘ └──────────────┘ └──────────────┘ │
└─────────────────────────────────────────────────────────────┘ Core Principles
1. Host-Authoritative Model
One player (the host) runs the authoritative game simulation. All other players (the clients) receive state updates and mirror what’s happening on the host.
Why?
- Prevents cheating (clients can’t modify game state)
- Simplifies logic (one source of truth)
- Easier to debug (deterministic execution)
2. Declarative State Management
You define your game state as a plain JavaScript object. martini-kit handles all synchronization automatically.
setup: ({ playerIds }) => ({
players: { /* ... */ },
projectiles: [],
score: 0
}) 3. Action-Based Mutations
The only way to change state is through actions. This ensures all state changes are synchronized across all players.
actions: {
move: {
apply(state, context, input) {
state.players[context.targetId].x = input.x;
}
}
} 4. Deterministic Execution
All random operations use seeded random generators to ensure the host and clients stay in sync.
// ❌ Wrong - causes desyncs
const x = Math.random() * 800;
// ✅ Correct - deterministic
const x = context.random.range(0, 800); Key Components
defineGame()
Defines your game logic, state structure, and actions. Framework-agnostic - works with any engine.
GameRuntime
Manages the game loop, action submission, and state synchronization. Created automatically when you initialize your game.
Transport Layer
Handles network communication. Swap between P2P, WebSocket, or local testing without changing game code.
Adapters (Optional)
Framework-specific helpers for Phaser, Godot, etc. Provide automatic sprite syncing, input management, and more.
How It Works
1. Initialization
const game = defineGame({
setup: ({ playerIds }) => ({ /* initial state */ }),
actions: { /* state mutations */ }
});
const runtime = new GameRuntime(game, transport, {
isHost: true,
playerIds: ['player-1', 'player-2']
}); 2. Action Flow
Player Input → submitAction() → Host Applies → Broadcast → Clients Apply - Player presses a key
- Calls
runtime.submitAction('move', { x: 100, y: 200 }) - Host applies action to state immediately
- Host broadcasts action to all clients via transport
- Clients receive and apply the same action
- All players now have identical state
3. State Synchronization
martini-kit uses an efficient diff/patch algorithm to minimize bandwidth:
Host State (t=1) → Diff → Patch → Client State (t=1)
↓ ↓
Host State (t=2) → Diff → Patch → Client State (t=2) Only changed properties are sent over the network.
Framework-Agnostic vs Framework-Specific
Framework-Agnostic (@martini-kit/core)
Works with any rendering engine or no engine at all:
- Game logic (state, actions)
- Player lifecycle
- Networking
- Determinism
- Testing
Framework-Specific (@martini-kit/phaser, etc.)
Engine-specific helpers for common tasks:
- Sprite synchronization
- Input management
- Physics integration
- Camera controls
- UI helpers
Next Steps
- State Management → - How to structure your game state
- Actions → - Understanding the action system
- Determinism → - Why determinism matters
- Transport Layer → - Network communication
- Player Lifecycle → - Managing player join/leave