games / fivem
Frameworks RP : concepts ESX/QBCore et exports
Explication
Ce que vous allez apprendre
- Comprendre le rôle d'un framework RP (ESX, QBCore) comme socle commun
- Récupérer l'objet joueur côté serveur avec chaque framework (
GetPlayerFromId,GetPlayer) - Utiliser les exports pour partager du code entre ressources indépendantes
- Écrire une ressource "framework-agnostic" qui détecte dynamiquement ESX ou QBCore
- Reconnaître les différences de convention entre les deux écosystèmes
Dans quel contexte ?
Une équipe de développement doit publier une ressource de boutique destinée à être installée sur des centaines de serveurs différents, certains tournant sous ESX, d'autres sous QBCore, sans savoir à l'avance lequel sera présent. Plutôt que d'écrire deux versions séparées à maintenir en parallèle, cette leçon montre comment détecter le framework réellement présent et adapter le comportement en conséquence.
| Concept | ESX | QBCore |
|---|---|---|
| Objet joueur serveur | ESX.GetPlayerFromId(source) | QBCore.Functions.GetPlayer(source) |
| Ajouter de l'argent | xPlayer.addMoney(amount) | Player.Functions.AddMoney('cash', amount) |
Prérequis
Cette leçon suppose d'être à l'aise avec les exports (leçon 2) et les events client/serveur (leçon 4) : les frameworks RP s'appuient massivement sur ces deux mécanismes pour exposer leur API.
Pourquoi ne pas tout réinventer soi-même
Un serveur roleplay a besoin de fonctionnalités communes à quasiment tous les serveurs du genre : gérer des joueurs persistants, de l'argent, des métiers ("jobs"), des permissions. Réécrire tout cela de zéro pour chaque serveur serait une perte de temps considérable, en plus d'être source d'incohérences. Un framework RP, comme ESX ou QBCore, fournit ce socle commun tout fait, sur lequel les développeurs viennent ensuite greffer leurs propres fonctionnalités métier (une boutique, un système de braquage...).
Deux frameworks, une même finalité, des API différentes
ESX et QBCore répondent globalement au même besoin, mais avec des choix de conception et des noms de fonctions différents. Ce n'est pas qu'une question de style : chacun a ses propres conventions bien ancrées dans son écosystème de ressources compatibles. Choisir l'un ou l'autre pour un serveur donné dépend souvent moins de préférences techniques que de l'écosystème de ressources déjà disponibles dans cette communauté.
L'objet joueur : le point d'entrée central
Dans les deux frameworks, la quasi-totalité des actions passe par un objet représentant le joueur (xPlayer en ESX, Player en QBCore), récupéré à partir de son identifiant serveur. C'est par cet objet que l'on consulte ou modifie son argent, son métier, ses données — plutôt que de manipuler directement des requêtes SQL à chaque fois.
Écrire du code compatible plusieurs frameworks
Une ressource destinée à être publiée largement doit parfois fonctionner aussi bien sur ESX que sur QBCore, sans savoir à l'avance lequel sera présent. La technique consiste à détecter au démarrage quel framework est réellement chargé sur ce serveur (GetResourceState), puis à adapter dynamiquement les appels en conséquence — un souci de portabilité qui revient souvent dans des ressources publiées publiquement pour la communauté.
Commandes & code
Frameworks RP : ESX / QBCore
Un framework RP fournit un socle commun (joueurs, argent, jobs, inventaire) que les ressources métier viennent enrichir via des exports.
-- ESX : récupérer l'objet joueur côté serveur
local ESX = exports['es_extended']:getSharedObject()
RegisterNetEvent('technologik:esxExample', function()
local src = source
local xPlayer = ESX.GetPlayerFromId(src)
xPlayer.addMoney(500)
xPlayer.showNotification('Vous avez reçu 500$')
print('Job actuel: ' .. xPlayer.job.name)
end)-- QBCore : équivalent conceptuel avec une API différente
local QBCore = exports['qb-core']:GetCoreObject()
RegisterNetEvent('technologik:qbExample', function()
local src = source
local Player = QBCore.Functions.GetPlayer(src)
Player.Functions.AddMoney('cash', 500)
TriggerClientEvent('QBCore:Notify', src, 'Vous avez reçu 500$')
print('Job actuel: ' .. Player.PlayerData.job.name)
end)-- Exports : exposer des fonctions réutilisables entre ressources indépendantes
-- server/main.lua (dans la ressource "technologik_bank")
local function GetBankBalance(identifier)
return MySQL.scalar.await('SELECT bank FROM users WHERE identifier = ?', { identifier }) or 0
end
exports('GetBankBalance', GetBankBalance) -- rend la fonction accessible aux autres ressources
-- Depuis une AUTRE ressource ("technologik_shop") :
local balance = exports['technologik_bank']:GetBankBalance(identifier)
print('Solde bancaire: ' .. balance)-- Écrire une ressource "framework-agnostic" : détecter le framework présent au démarrage
local Framework = nil
CreateThread(function()
if GetResourceState('es_extended') == 'started' then
Framework = 'esx'
elseif GetResourceState('qb-core') == 'started' then
Framework = 'qbcore'
end
print('Framework détecté: ' .. tostring(Framework))
end)
local function AddPlayerMoney(source, amount)
if Framework == 'esx' then
local xPlayer = exports['es_extended']:getSharedObject().GetPlayerFromId(source)
xPlayer.addMoney(amount)
elseif Framework == 'qbcore' then
local Player = exports['qb-core']:GetCoreObject().Functions.GetPlayer(source)
Player.Functions.AddMoney('cash', amount)
end
end| Concept | ESX | QBCore |
|---|---|---|
| Objet joueur serveur | ESX.GetPlayerFromId(source) | QBCore.Functions.GetPlayer(source) |
| Ajouter de l'argent | xPlayer.addMoney(amount) | Player.Functions.AddMoney('cash', amount) |
| Notification client | xPlayer.showNotification(msg) | TriggerClientEvent('QBCore:Notify', ...) |
Résumé
- Les frameworks RP standardisent joueurs, argent, jobs, mais gardent des API différentes.
exports(...)/exports['res']:Fn()est le mécanisme officiel de partage de code entre ressources.GetResourceStatepermet d'écrire du code compatible plusieurs frameworks sans dépendance dure.
Exercices pratiques
Mission : rendre la boutique compatible avec n'importe quel serveur
Objectif : Comprendre pourquoi une ressource distribuée publiquement ne peut pas dépendre d'un seul framework, et écrire une détection robuste du framework présent.
Contexte
L'équipe technologik publie technologik_shop sur un forum communautaire pour qu'elle soit installée sur des centaines de serveurs indépendants. Certains tournent sous ESX, d'autres sous QBCore, et l'équipe ne peut pas le savoir à l'avance. La première version du code appelait directement ESX.GetPlayerFromId(source), ce qui a fait planter la ressource sur tous les serveurs QBCore l'ayant installée.