Modules
A module is the unit of everything in Shiva. Every feature — players, economy, inventory, custom gameplay — lives in a module.
What's in a Module
my-module/
├── manifest.lua -- name, version, provides, requires
├── config.lua -- server-owner configuration
├── server/
│ ├── init.lua -- registers services and bindings
│ └── services/
│ └── MyService.lua
├── client/
│ └── init.lua
├── shared/
│ ├── models/
│ │ └── MyModel.lua
│ └── locales/
│ └── en.lua
├── migrations/
│ └── 001_create_my_table.lua
└── docs/ -- pulled into shiva-docs at build time
├── config.md
└── events.mdmanifest.lua
lua
return {
name = 'my-module',
version = '1.0.0',
-- Contracts this module provides
provides = {
'IMyContract',
},
-- Contracts this module requires (from other modules)
requires = {
'IPlayer',
'IEconomy',
},
}Lifecycle
Each module goes through three lifecycle phases:
| Phase | When | What to do |
|---|---|---|
init() | Before any module starts | Register bindings, define contracts |
start() | After all modules init | Start timers, subscribe to events, load data |
stop() | Server shutdown | Clean up resources, flush caches |
lua
-- server/init.lua
local M = {}
function M.init(container)
container:bind('IMyContract', require('server.services.MyService'))
end
function M.start(container)
local player = container:make('IPlayer')
player.on('playerConnected', function(playerId)
-- do something
end)
end
return MModule Rules
- One contract per concern — don't cram two unrelated things into one module
- Depend on contracts, not implementations —
container:make('IEconomy'), notrequire('shiva-economy') - No global state — everything goes through the container or event bus
- Config is data — don't put logic in
config.lua
Built-in vs Custom Modules
The 71 default modules in shiva-modules follow the same rules as custom modules. They're not special. You can replace any of them with your own implementation by providing the same contract.