Retour au cours

games / fivem

Events : TriggerEvent, RegisterNetEvent, TriggerServerEvent

Leçon 41 exercice

Explication

Ce que vous allez apprendre

  • Déclarer un event réseau avec RegisterNetEvent
  • Choisir entre TriggerServerEvent, TriggerClientEvent et TriggerEvent selon le besoin
  • Comprendre d'où vient la variable implicite source côté serveur
  • Cibler un joueur précis ou tous les joueurs avec TriggerClientEvent
  • Enregistrer plusieurs handlers indépendants sur le même event

Dans quel contexte ?

Un joueur clique sur un bouton "Acheter" dans une boutique en jeu : ce clic doit voyager du client vers le serveur pour être traité, puis le serveur doit répondre à ce client précis (et à lui seul) pour confirmer ou refuser l'achat. Cette leçon donne le vocabulaire exact (TriggerServerEvent, TriggerClientEvent, source) pour faire circuler cette information dans les deux sens, correctement et sans ambiguïté.

Concrétiser le pont entre client et serveur

La leçon précédente a établi que client et serveur sont deux mondes séparés qui ne communiquent que par un canal dédié. Ce canal, ce sont les events : un mécanisme qui permet à un bout de code de "crier" une information (avec un nom et des données), et à un ou plusieurs autres bouts de code d'"écouter" ce cri et d'y réagir, sans que l'émetteur et le récepteur aient besoin de se connaître directement.

Trois familles d'events, trois usages différents

TriggerServerEvent part toujours d'un client et arrive sur le serveur — c'est la façon dont un joueur "annonce" quelque chose au serveur (par exemple : "je veux acheter cet objet"). TriggerClientEvent fait l'inverse : le serveur informe un client précis, ou même tous les clients à la fois. TriggerEvent, enfin, reste purement local : aucun réseau n'est impliqué, c'est juste un moyen de faire communiquer différentes parties du code au sein du même contexte (uniquement client, ou uniquement serveur).

D'où vient "source" ?

Un point qui déroute souvent les débutants : la variable source, utilisée dans un handler serveur, n'est définie nulle part explicitement — elle est fournie automatiquement par FiveM au moment où un event réseau arrive, et contient l'identifiant serveur du joueur qui a déclenché cet event. Cette variable n'a de sens QUE côté serveur et QUE dans le contexte d'un event entrant : l'utiliser ailleurs n'a aucun effet.

Ce qu'on ne peut pas envoyer

Les données transmises via un event doivent pouvoir être "sérialisées" — c'est-à-dire converties en une forme transmissible sur le réseau, comme des nombres, du texte ou des tables simples. Il est impossible d'envoyer une fonction elle-même dans un event : c'est une limite technique à connaître avant de concevoir un système plus avancé.

FonctionDirectionTraverse le réseau ?
TriggerServerEventClient → ServeurOui
TriggerClientEventServeur → Client(s)Oui
TriggerEventLocal (même contexte)Non

Piège fréquent

source n'existe et n'a de sens QUE côté serveur, dans le contexte d'un handler d'event réseau entrant. L'utiliser côté client, ou en dehors d'un handler d'event, ne référence rien de valide.

Commandes & code

Events client/serveur

Le système d'events est le seul canal de communication entre client et serveur (et entre scripts locaux).

lua
-- SERVEUR : écoute un event déclenché par un client
RegisterNetEvent('technologik:buyItem', function(itemName, quantity)
    local src = source -- 'source' est une variable globale implicite = ID de l'émetteur
    print(('Joueur %s achète %dx %s'):format(src, quantity, itemName))
    -- ... logique d'achat réelle (voir leçon Sécurité pour la validation)
end)
lua
-- CLIENT : déclenche l'event serveur ci-dessus
TriggerServerEvent('technologik:buyItem', 'bread', 3)
lua
-- SERVEUR -> CLIENT ciblé (un seul joueur)
TriggerClientEvent('technologik:notify', targetPlayerId, 'Vous avez reçu un message')

-- SERVEUR -> tous les clients (broadcast)
TriggerClientEvent('technologik:serverRestart', -1, 60) -- -1 = tous les joueurs connectés
lua
-- Event purement local (même contexte client OU serveur, aucun réseau impliqué)
RegisterNetEvent('technologik:localUpdate')
AddEventHandler('technologik:localUpdate', function(data)
    print('Mise à jour locale reçue: ' .. tostring(data))
end)

TriggerEvent('technologik:localUpdate', { reason = 'init' })
lua
-- Plusieurs handlers peuvent écouter le même event
AddEventHandler('playerDropped', function(reason)
    print(('Joueur %s déconnecté: %s'):format(source, reason))
end)

AddEventHandler('playerDropped', function(reason)
    -- second handler indépendant, ex: sauvegarde des données
    SavePlayerData(source)
end)

Résumé

  • RegisterNetEvent déclare qu'un event peut être déclenché à travers le réseau.
  • TriggerServerEvent (client → serveur) et TriggerClientEvent (serveur → client) traversent le réseau.
  • TriggerEvent reste local au contexte courant (pas de réseau).
  • source n'existe que côté serveur, dans le contexte d'un event réseau entrant.
  • On ne peut PAS passer de fonctions dans les payloads réseau, uniquement des données sérialisables.

Exercices pratiques

1 disponible
1

Mission : l'achat qui n'arrive jamais au serveur

Objectif : Corriger un mauvais choix de fonction d'event qui empêche un achat d'atteindre le serveur, et raisonner sur les limites du système d'events.

Contexte

Un bouton "Acheter" déclenche côté client : TriggerEvent('technologik:buyItem', 'bread', 3). Le serveur a bien un RegisterNetEvent('technologik:buyItem', function(itemName, quantity) ... end), mais l'achat n'est jamais traité : aucun message d'erreur, juste un clic sans effet visible. Le joueur pense que le bouton est cassé.

Résoudre l’exercice →