PlayDeck
Home / Course / Environment & Your First Server
Track A · Module 0

Environment & Your First Server

Every roleplay server you have ever played started as an empty folder and a server artifact. Before you write a single line of gameplay, you need a server you control, an editor that catches mistakes before the server does, and a way to connect and actually see results. Get these three right once, and the rest of Track A becomes "edit, save, test" instead of "why won't this boot."

The four pieces, and why each exists

A FiveM dev environment is not one program. It is four, and knowing what each does saves you hours of confused googling later.

You are running a server and a client on the same machine. That is normal for development and exactly how you will test everything in this track.

Install FXServer and txAdmin

Download the latest recommended FXServer artifact for your OS, unzip it into an empty folder (e.g. C:\FXServer\server), make a second empty folder for your server data (e.g. C:\FXServer\data), and run the server binary once. txAdmin prints a local URL with a one-time PIN — open it in your browser.

The setup recipe asks which framework to scaffold. Pin one and never mix: this track uses Qbox (a modern, maintained fork in the QBCore family) on top of the ox stack — ox_lib, ox_inventory, ox_target. That is a deliberate, current-best choice, not nostalgia for old ESX tutorials.

Because the exact buttons and folder layout shift between artifact versions, do not memorize steps from any tutorial — including this one. Follow the official, versioned walkthrough and treat it as the source of truth:

➡️ Official guide: Setting up a server with txAdmin

When txAdmin finishes, you have a running server and a resources/ folder. That folder is your workshop.

VS Code: your safety net

Install VS Code and add a Lua language extension (the popular "Lua" extension by sumneko/LuaLS is the standard pick). Open your resources/ folder as your workspace — not individual files — so the extension can see your whole project and resolve references between files.

Why bother? FiveM Lua has no compiler yelling at you before runtime. The extension fills that gap: undefined globals, mismatched parentheses, and shadowed variables get flagged as you type. That feedback loop is the single biggest speedup for a beginner. A red squiggle in the editor is a bug you never had to chase in a live console.

Your first resource — and your first AI guardrail

A resource is a folder with a manifest plus your scripts. Create resources/[local]/playdeck_hello/ and add two files.

-- fxmanifest.lua
-- Every resource needs this manifest. The server reads it to learn which
-- files to load and on which side (client or server).
fx_version 'cerulean' -- required: the manifest schema version FiveM expects
game 'gta5'           -- this targets GTA V (FiveM), not RedM

author 'PlayDeck'
description 'Proof-of-life resource for Module 0'
version '1.0.0'

-- server_script runs ONLY on the server: the trusted side. Gameplay
-- decisions belong here because clients can be modified by players.
server_script 'server.lua'
-- server.lua — runs on the trusted server process.

-- onResourceStart is a real FiveM server event. It fires for every
-- resource, so we filter for our own before doing anything.
AddEventHandler('onResourceStart', function(resourceName)
    if resourceName ~= GetCurrentResourceName() then
        return
    end
    print('[playdeck_hello] Server is alive. Module 0 wired up correctly.')
end)

-- A server-side command to confirm the loop end to end.
-- The final `false` means it is not admin-restricted (fine for now).
RegisterCommand('alive', function(source)
    -- source 0 = server console; source > 0 = a connected player's id
    if source == 0 then
        print('[playdeck_hello] pong (from console)')
    else
        print(('[playdeck_hello] pong for player %d'):format(source))
    end
end, false)

In the txAdmin console, run ensure playdeck_hello, then alive. You should see the startup line and a pong. Connect your game client to localhost and type /alive in chat — same proof, now end to end.

The AI guardrail starts here. When you ask AI to write FiveM code, it will confidently invent natives and exports that do not exist, blend ESX, QBCore, and Qbox into one file that compiles in no framework, and lean on deprecated patterns. Three habits keep you safe: pin one framework and reject any answer that mixes them; verify every native against the official native reference; and paste pure-Lua logic into the PlayDeck sandbox to prove it runs before it ever touches your server. Every native in the example above is real and verifiable — check them and build the habit.

Practice

No FiveM needed. Paste this into the PlayDeck browser sandbox and press Run. It models the most important rule in this whole track — the server never trusts the client — using plain Lua.

-- Mimics a SERVER deciding whether to trust a value a client sent.
local function serverGrantMoney(balance, clientClaims)
    -- Never trust the client's number. Validate type and range first.
    if type(clientClaims) ~= 'number' or clientClaims <= 0 then
        return balance, 'rejected: bad amount'
    end
    if clientClaims > 500 then
        return balance, 'rejected: over server limit'
    end
    return balance + clientClaims, 'ok'
end

print(serverGrantMoney(100, 250))    -- ok -> 350
print(serverGrantMoney(100, 999999)) -- rejected: over limit
print(serverGrantMoney(100, -5))     -- rejected: bad amount

Your task: lower the limit to 200, then add a fourth rule that rejects non-integer amounts (hint: compare clientClaims to math.floor(clientClaims)). Run it and confirm each case prints what you expect.

Recap

Next module: we structure a real resource and start writing gameplay.

Learn it by building it

PlayDeck is an original course on building GTA roleplay scripts with AI — Lua, frameworks, NUI, debugging, and a browser sandbox to test every lesson without booting the game.

Browse the course