Skip to content
GAMPEONCreate
New project
Preview: this works today, but details can still change.

Events

Events are named messages. Any resource can fire an event, and every resource that listens to it runs its handler.

TriggerEvent reaches all resources on the same side (server or client). It never travels over the network.

-- resource A
AddEventHandler('race:finished', function(playerId, timeMs)
print(('Player %d finished in %d ms'):format(playerId, timeMs))
end)
-- resource B, same side
TriggerEvent('race:finished', 12, 83450)

A handler can call CancelEvent() to tell the code that fired the event to skip its default action. That code checks WasEventCanceled() right after TriggerEvent. Other handlers still run. The chat uses this for chatMessage.

-- resource B
TriggerEvent('shop:beforeBuy', source, item)
if WasEventCanceled() then return end

To receive an event from the other side, register it with RegisterNetEvent. Without that call, network events never reach your handlers.

client/main.lua
TriggerServerEvent('myshop:buy', 'water')
server/main.lua
RegisterNetEvent('myshop:buy', function(itemId)
local player = source -- who sent it
-- check and act, see the rules below
end)

The server answers one player, or everyone with -1:

server/main.lua
TriggerClientEvent('myshop:bought', player, 'water')
TriggerClientEvent('chat:announce', -1, 'Shop closes in 5 minutes')

Players can send any event with any arguments. A server handler must assume the worst.

  1. Check every argument. Type, range and length. if type(itemId) ~= 'string' or #itemId > 32 then return end
  2. Never trust amounts or prices from the client. Look them up on the server.
  3. Check permissions with source, not with a player ID sent as an argument.
  4. Copy source into a local before calling Wait, because another event can change it.
  5. Rate-limit expensive actions per player.

Prefix events with your resource name: myshop:buy, not buy. Names are shared by all resources.

Arguments are copied: tables, strings, numbers, booleans and nil work. In local events (TriggerEvent), functions are passed as references, so callbacks like TriggerEvent('esx:getSharedObject', function(obj) ESX = obj end) work; see Exports. Network events cannot carry functions: they arrive as nil.

local handle = AddEventHandler('race:tick', onTick)
-- later
RemoveEventHandler(handle)

See the reference: Events, Built-in events.

Report a problem with this pageOther ways to give feedback