Getting Started
Multiplayer game server toolkit with Rust core and Lua scripting
Getting Started
MAEngine is a multiplayer game server toolkit featuring:
- Rust core for networking, ECS, and replication
- Lua scripting for game logic (LuaJIT on server, Lua 5.4 on client)
- QUIC transport with TLS 1.3
- SurrealDB for persistent storage
- Unreal Engine 5 client with WebUI support
Quick Start
Create a Server Script
-- games/my_game/Server/init.lua
Server.Subscribe("Start", function()
Log("Server started!")
end)
Player.Subscribe("Spawn", function(player)
local character = Character.Spawn(Vec3(0, 0, 100))
player:Possess(character)
player:SetValue("score", 0)
end)
Events.SubscribeRemote("PlayerAction", function(player, data)
Log("Received action from player " .. player:GetId())
end)Create a Client Script
-- games/my_game/Client/init.lua
-- Create HUD after brief delay
Timer.Delay(0.5, function()
local hud = WebUI.CreateAtScale("HUD", "hud/index.html")
hud:SetFullscreen(true)
WebUI.ShowViewport(false)
end)
-- Bind to player value changes
local player = Client.GetLocalPlayer()
if player then
player:BindValue("score", function(p, key, new, old)
-- Update HUD when score changes
Log("Score: " .. tostring(new))
end)
end
Input.Register("Fire", "LeftMouseButton")
Input.Bind("Fire", Input.Pressed, function()
Events.CallServer("PlayerAction", { action = "fire" })
end)Run the Server
.\build.bat run -p core-server -- --game my_gameAPI Reference
Server
Server
Server lifecycle and management
Database
SurrealDB persistence
Player
Player management and possession
Entities
Spawning, destruction, custom classes
Client
Client
Local player and client events
WebUI
HTML/CSS/JS interface system
Store
Lua/JS state synchronization
Input
Keyboard and mouse bindings
Trace
Raycasting and collision
Key Concepts
Server vs Client
MAEngine is server-authoritative. The server controls all game logic while clients handle rendering and input.
| Feature | Server | Client |
|---|---|---|
| Runtime | Rust + LuaJIT | UE5 + Lua 5.4 |
| Authority | Authoritative | Predictive |
| Database | Full access | None |
| Entities | Create/Modify/Delete | Read-only |
| WebUI | None | Full access |
| Input | None | Full access |
| Trace | None | Full access |
Event-Driven Architecture
-- Class-level events
Character.Subscribe("Spawn", function(character) end)
Player.Subscribe("Destroy", function(player) end)
-- Instance events
entity:Subscribe("OnHit", function(ent, damage) end)
entity:Fire("OnHit", 25)Value Replication
-- Synced to all clients
entity:SetValue("health", 100)
player:SetValue("score", 50)-- Synced only to the owning player
player:SetPrivateValue("inventory", { items = {} })
player:SetPrivateValue("secret_mission", "Find the key")-- React to value changes
Character.BindValue("health", function(char, key, newVal, oldVal)
if newVal <= 0 then
char:Destroy()
end
end)Remote Events
-- Receive from client
Events.SubscribeRemote("PlayerAction", function(player, data)
-- Validate and process
end)
-- Send to client
Events.CallRemote("UpdateUI", player, { score = 100 })
Events.BroadcastRemote("GameEvent", { message = "Round started!" })-- Send to server
Events.CallServer("PlayerAction", { action = "fire" })
-- Receive from server
Events.SubscribeRemote("UpdateUI", function(data)
hud:CallEvent("SetScore", data.score)
end)IDE Support
Download the EmmyLua type definitions for autocomplete in VS Code or IntelliJ.
Project Structure
games/my_game/
├── Server/
│ └── init.lua # Server-side script (authoritative)
├── Client/
│ ├── init.lua # Client-side script (UE5)
│ └── UI/ # WebUI HTML/CSS/JS files
│ └── hud/
│ ├── index.html
│ ├── style.css
│ └── script.js
├── Shared/
│ └── constants.lua # Shared constants
└── config.toml # Game configuration