Skip to main content
TRACK B·FIVEM FUNDAMENTALS·Verified June 2026 · Lua 5.4 · ox_lib 3.x
Learning with an AI assistant?
Copies this lesson plus 2026 ground rules (no lua54 'yes', Cfx.re Portal, correct callback signatures) as a ready-to-paste mentor prompt.

Crossing the wall: TriggerServerEvent and TriggerClientEvent

Last lesson was about events on one side. This lesson is about sending a message across the wall. The client asks. The server checks. The server answers the player who asked, and can also tell everyone else. That small pattern sits underneath many real FiveM features.

You'll learn
TriggerServerEvent -> TriggerClientEvent -> RegisterNetEvent -> the source variable -> one client vs all clients
Time
~28 minutes
Outcome
A working ping-pong feature: client asks, server answers the one player who asked, and broadcasts a notice to everyone, with validation and authority intact.
BEFORE YOU START

Build it

Make the resource folder

The server has one folder for this lesson.

Inside your server's resources folder, create this folder:

code
resources/qu_trigger_server_client_event

Create the files

Every file named in the manifest exists.

Create this exact file layout:

code
resources/qu_trigger_server_client_event/
fxmanifest.lua
server.lua
client.lua

Write fxmanifest.lua

FiveM knows which files to load.

Open fxmanifest.lua and paste this:

code
fx_version 'cerulean'
game 'gta5'

client_script 'client.lua'
server_script 'server.lua'

Older tutorials add a lua54 'yes' line here. As of June 2025 that setting is deprecated and ignored: Lua 5.4 is now the only Lua runtime, so you leave it out.

Write the lesson code

The topic is now represented by runnable code.

Open server.lua and paste this:

code
RegisterNetEvent('qu_trigger_server_client_event:ping', function(message)
local src = source
if type(message) ~= 'string' or #message > 40 then return end

print('[qu_trigger_server_client_event] server got ' .. message .. ' from ' .. GetPlayerName(src))

-- Answer only the player who asked (a single server id targets one client).
TriggerClientEvent('qu_trigger_server_client_event:pong', src, 'server received ' .. message)

-- Tell everyone on the server (-1 broadcasts to all clients).
TriggerClientEvent('qu_trigger_server_client_event:notice', -1, GetPlayerName(src) .. ' pinged the server')
end)

Open client.lua and paste this:

code
RegisterCommand('pingserver', function(_, args)
TriggerServerEvent('qu_trigger_server_client_event:ping', table.concat(args, ' '))
end, false)

RegisterNetEvent('qu_trigger_server_client_event:pong', function(reply)
print('[qu_trigger_server_client_event] pong: ' .. reply)
end)

RegisterNetEvent('qu_trigger_server_client_event:notice', function(text)
print('[qu_trigger_server_client_event] notice: ' .. text)
end)

Start and test it

The expected proof appears in the correct console.

Open server.cfg and add this line:

code
ensure qu_trigger_server_client_event

Save, then run:

code
restart qu_trigger_server_client_event

Join the server, open F8, and run this test:

code
/pingserver hello

The pong line lands only in your F8 because the server targeted your server id. The notice line lands in every connected player's F8 because the server passed -1. That difference is the whole point of this lesson, and the next section explains exactly how the server knows who to send to.

CLIENT
the player's game
network
SERVER
validate here
✓ trust boundary
A client TriggerServerEvent crosses the network wall once. The server is the only side you can trust to check the request, so validation lives there.

Keep reading the full lesson

Sign in to start, then unlock every step of this lesson and the full FiveM School with a membership.

Still ahead in this lesson
  • How it works
  • If something went wrong
  • What you can do now
  • Try it yourself

The remainder of TriggerServer and TriggerClientEvent is available to FiveM School members.