Core Concepts
Server and Client
Where Engine runs, how the client gets its own copy of Engine, which modules exist on which side, and how to write modules that work on both.
Two entry points
Engine has one entry point for each side:
| Side | Require | Contains |
|---|---|---|
| Server | ServerScriptService.Engine | Server services and systems, shared services, all packages. |
| Client | ReplicatedStorage.Engine | Client services and systems, shared services, all packages. |
local Engine = require(game:GetService("ServerScriptService"):WaitForChild("Engine"))local Engine = require(game:GetService("ReplicatedStorage"):WaitForChild("Engine"))ReplicatedStorage.Engine does not exist in your place file. When a server starts, the Loader script boots Engine, and Engine builds the client copy: the client modules, the shared modules and the configuration clients need. Server-only code is never sent to clients. Use WaitForChild so client scripts wait until it exists.
Warning
On the server, always require ServerScriptService.Engine, never ReplicatedStorage.Engine. Requiring the client copy on the server loads a second, separate instance of every shared module, with its own state.
Realms
Each reference page shows where the module runs:
| Badge | Meaning |
|---|---|
| Shared | One module that runs on both sides. Some members work on one side only; the page says which. |
| Server | Server only. Getting it from the client errors. |
| Server, Client | Two halves with different APIs. Get each from its own side. |
Examples of Server, Client modules: DataService (profiles on the server, a read-only copy of your own data on the client), EconomySystem (balances on the server, live balances on the client), ModerationSystem (sanctions on the server, your own moderation state on the client).
Modules that run on both sides
A ModuleScript in ReplicatedStorage that both sides require (shared remote definitions, for example) should pick the right entry point:
local RunService = game:GetService("RunService")
local Engine = if RunService:IsServer()
then require(game:GetService("ServerScriptService"):WaitForChild("Engine"))
else require(game:GetService("ReplicatedStorage"):WaitForChild("Engine"))Trust nothing from the client
Everything an Engine client half sends to the server is checked again there: purchases, reward claims, reports and commands are validated, permission-checked and rate-limited on the server. Follow the same rule in your own code:
- Define remotes with a
Schemaand aRateLimitin NetworkService. - Decide outcomes on the server (damage, rewards, positions) and send results to clients.
- Never put secrets in modules the client can see: webhook URLs, keys and server-only settings belong in server-only configuration.
Configuration on the client
Only configuration modules that belong to a module present on the client (plus General) are copied to ReplicatedStorage.Engine. Server-only modules' settings, such as StatisticsService webhook URLs or CryptographyService keys, stay on the server. See Configuration.