FRUITZEV FRAMEWORK Sommaire

FRUITZ FA / DOCUMENTATION TECHNIQUE

EV Framework.

Le socle FiveM de Fruitz FA, de la première connexion du joueur à la sauvegarde de son personnage.

01 / DÉMARRAGE

Installer EV

Place la ressource dans resources/[1.Base]/ev. EV dépend de oxmysql, spawnmanager et de OneSync. Prépare une base MariaDB compatible et garde le nom de dossier cohérent avec les appels exports.ev de tes ressources.

  1. Sur une base vierge, importe sql/install.sql. Pour une base existante, vérifie d’abord les migrations.
  2. Renseigne la connexion SQL dans server.cfg avant de démarrer oxmysql.
  3. Active OneSync et démarre les ressources dans cet ordre. Si server.cfg exécute ressources.cfg, place les lignes ensure dans ce dernier.
set onesync on
set mysql_connection_string "mysql://UTILISATEUR:MOT_DE_PASSE@HOTE/BASE?charset=utf8mb4"

ensure oxmysql
ensure spawnmanager
ensure ev

Les identifiants de l’exemple sont à remplacer. La configuration partagée config/config.lua est lue par les clients, donc garde les secrets SQL dans la configuration serveur.

02 / CYCLE DE VIE

Parcours du joueur

Première connexion

Le flux prévu déclenche le spawn avec spawnmanager, puis charge le personnage lié à la licence Rockstar. Sans personnage, l’identité s’ouvre, suivie du créateur de skin. Le point de départ est l’aéroport par défaut.

Reconnexion

EV retrouve le premier personnage par ID pour la licence. Le serveur renvoie la dernière position enregistrée ou le point de départ si aucune position valide n’existe. L’apparence sauvegardée est ensuite appliquée.

Identité
Prénom, nom et nationalité en texte libre de 2 à 32 caractères. Date réelle au format AAAA-MM-JJ, de 1900 à aujourd’hui. Genre H ou F. Les champs sont validés côté serveur et persistés en SQL.
Skin
Modèle Freemode masculin ou féminin, héritage, traits du visage, yeux, cheveux, superpositions et tenue. La création initiale est verrouillée après sauvegarde. Une nouvelle soumission identique peut être acceptée. La boutique met à jour la tenue du skin existant.
Position
Le serveur relève le ped du joueur après le signal de disponibilité du client. Par défaut, il capture toutes les secondes et écrit toutes les 15 secondes. La déconnexion déclenche aussi une sauvegarde.
Personnage
Le parcours actuel utilise un personnage par licence et ne présente aucun écran de sélection. Le réglage MaxCharacters est fixé à 1. Les personnages supplémentaires d’une ancienne installation restent en base jusqu’à leur suppression.

Le diagnostic de la copie locale décrit un blocage dans le fichier chargé au démarrage du client.

03 / RÉGLAGES

Configuration

Les valeurs suivantes proviennent de config/config.lua. Les durées sont en millisecondes.

CléValeur par défautUsage
Locale, Debugfr, falseLangue et diagnostic. Des fichiers fr et en sont fournis.
SaveInterval300 000Intervalle des sauvegardes des données modifiées.
PositionCaptureInterval, PositionSaveInterval1 000, 15 000Capture de la position et persistance SQL.
Spawn-1037.6, -2737.8, 20.17Point de repli à l’aéroport, orientation 330, modèle initial mp_m_freemode_01.
MaxCharacters1Limite du flux actuel.
DefaultGroup, Groupsuser, hiérarchie staffGroupe initial et niveaux de permission.
StartingAccountscash=500, bank=2500, black=0Soldes à la création.
Modulesaccounts, jobs actifsActivation des modules inclus.
RateLimits15 callbacks et 5 actions personnage par 10 sLimites distinctes par source.
CallbackTimeout15 000Délai d’attente côté client.
BootstrapAdminsVideIndications de promotion manuelle en console. Les promotions se font avec setgroup.
SkinWipeQueriesVideRequêtes facultatives de nettoyage de skins externes. Chacune reçoit la licence comme seul paramètre.

04 / FONCTIONNALITÉS

Modules livrés

EV charge ses modules depuis modules/ avec son propre manifeste. Leur activation se règle dans EV.Config.Modules.

ModulePar défautComportement
accountsActifComptes cash, bank et black. Les mutations passent par des montants entiers et des soldes entre 0 et 2 147 483 647. EV.Accounts.Transfer(src, target, amount) est une fonction serveur interne de virement bancaire journalisé.
jobsActifEV.Jobs.Set(src, job, grade) valide le métier et le grade via SQL. Le métier initial est unemployed au grade 0. Le salaire existe comme donnée de grade.
inventory-bridgeDésactivéPoint d’extension livré avec le fournisseur none.
vehiclesDésactivéSquelette pour une future gestion des véhicules.
societyDésactivéSquelette dépendant de accounts et jobs.

Les squelettes nécessitent une implémentation. Le champ salaire ne déclenche aucun versement automatique dans cette version.

05 / ADMINISTRATION

Groupes et commandes

Chaque groupe hérite des permissions des rangs inférieurs. L’alias mod est normalisé en modo. EV conserve le groupe dans le personnage.

GroupeNiveau
user0
helper10
modo20
admin30
superadmin40
gerant50
owner60
setgroup ID groupe en console
Attribue un groupe à un joueur dont le personnage est chargé. Exemple setgroup 12 owner.
/setgroup ID groupe ou /evsetgroup ID groupe
En jeu, à partir de superadmin. La cible et le groupe demandé doivent être strictement sous le rang de l’auteur. L’auto-attribution est réservée à la console via l’ID du joueur.
/mygroup et /evwhoami
Affichent le groupe actuel ou le nom et l’ID du personnage dans le chat.
/wipe ID en jeu ou wipe ID en console
Réservée à la console ou à superadmin et plus. En jeu, les autres cibles de rang égal ou supérieur sont protégées. Le wipe supprime les personnages de la licence, leur identité, leur skin et les données en cascade. Après la suppression, le joueur est déconnecté et invité à revenir pour recréer son personnage.

L’ID demandé est l’ID de session FiveM. La commande wipe efface les données persistantes de la licence ciblée.

06 / PERSISTANCE

Base de données

Objet SQLRôle
ev_charactersLicence Rockstar, identité, skin JSON, groupe, métier, grade, coordonnées et date de création.
ev_accountsSolde de chaque compte par personnage.
ev_jobs, ev_job_gradesCatalogue des métiers, grades, libellés et salaires.
ev_account_ledgerJournal des virements, avec un transfer_id commun au débit et au crédit.
ev_transfer_bankProcédure de virement. Débit, crédit et journal sont validés dans une même transaction. Une erreur entraîne un rollback.

Mettre à niveau une base existante

Vérifie les colonnes déjà présentes et applique, dans l’ordre, les migrations manquantes 002_identity.sql, 003_skin.sql et 004_position.sql. Le pied de install.sql décrit le cas d’un ancien journal sans transfer_id. Le fichier d’installation recrée aussi la procédure de virement.

Tenues et packs moddés

Le JSON du skin contient outfit.components et outfit.props, indexés par emplacement. Une entrée contient drawable et texture. Les entrées avec collection et localDrawable peuvent retrouver leur modèle via sa collection. Le pack correspondant doit être présent sur le serveur.

07 / RÉFÉRENCE LUA

Exports et objets Lua

Serveur

ExportContrat
GetPlayer(source)Objet du personnage chargé ou nil.
GetGroup(source)Groupe du personnage ou nil.
HasPermission(source, group)Booléen selon la hiérarchie. La console, source 0, passe pour un groupe valide.
GetVersion()Version EV sous forme de chaîne.
RegisterCallback(name, fn)Enregistre un handler serveur recevant source puis les arguments.
RegisterModule(name, spec)Export historique. Pour un module avec une fonction d’initialisation, utilise le registre interne depuis un fichier serveur chargé par EV.
PurchaseOutfit(source, outfit, price, account)Réservé à clothingshop. Débite cash ou bank et sauvegarde la tenue dans une transaction. Renvoie true, skin ou false, motif.
local player = exports.ev:GetPlayer(source)
if player and exports.ev:HasPermission(source, 'modo') then
    print(('Personnage #%d'):format(player.characterId))
end

Dans EV, l’objet Player fournit GetAccount(name), SetAccount(name, amount), AddAccount(name, amount), RemoveAccount(name, amount) et Public(). L’instantané public contient source, characterId, firstname, lastname, birthdate, nationality, gender, skin, group, job, grade et accounts.

Client

ExportContrat
GetGroup()Groupe connu localement ou nil avant chargement.
HasPermission(group)Test local pour l’affichage. Le serveur doit vérifier toute action privilégiée.
if exports.ev:HasPermission('helper') then
    -- Afficher les options disponibles dans le menu client.
end

L’événement ev:client:loaded fournit un instantané du personnage à l’ouverture de la session. L’ancienne référence décrit aussi GetPlayerData() pour lire cet instantané et Notify(message, kind) pour afficher une notification. Ces deux exports restent à vérifier après restauration du fichier principal.

08 / COMMUNICATION

Callbacks et événements

Dans EV, EV.Callback.Trigger(name, cb, ...) demande un résultat au serveur. cb(ok, ...) reçoit le statut du transport en premier, puis les valeurs métier renvoyées par le handler. Un refus métier peut donc arriver avec ok == true. En l’absence de réponse, le client reçoit false, 'timeout'.

-- Côté serveur, depuis une ressource qui dépend d’EV.
exports.ev:RegisterCallback('fruitz:profil', function(src)
    local player = exports.ev:GetPlayer(src)
    if not player then
        return false, 'personnage_indisponible'
    end
    return true, player.firstname, player.lastname
end)

Les noms sont limités à 80 caractères à la réception. Les erreurs de transport renvoyées par le serveur sont unknown_callback et internal_error. Les arguments du client doivent être validés dans chaque handler.

Callback natifRôle
spawn:getCalcule la position de spawn pour la licence connectée.
characters:loadCharge le personnage courant.
characters:createValide et sauvegarde la première identité.
skin:saveValide et sauvegarde le skin initial.

Dans l’autre sens, EV.Callback.Trigger(src, name, ...) côté serveur appelle un handler client enregistré via EV.Callback.Register(name, fn). Cet envoi est à sens unique.

Événement réseauUsage
ev:server:callbackDemande client vers serveur, avec ID, nom et arguments.
ev:client:callbackRéponse au client, avec ID, statut de transport et résultats.
ev:client:requestNotification serveur vers handler client.
ev:client:loadedInstantané du personnage au chargement.
ev:client:groupGroupe mis à jour.
ev:client:outfitActualisation de la tenue du personnage.
ev:server:positionReadySignal client permettant au serveur de démarrer la capture de position.

Événements internes au serveur EV

Le bus EV.Events.On(name, handler) et EV.Events.Emit(name, ...) est distinct des événements réseau FiveM.

  • playerLoaded(source, player)
  • playerUnloaded(source)
  • accountChanged(source, name, amount)
  • jobChanged(source, job, grade)
  • permissionChanged(source, group)

09 / ORGANISATION

Ressources et structure

Les ressources Fruitz FA se démarrent séparément. Pour une ressource qui utilise EV, déclare dependency 'ev' dans son manifeste et démarre-la après EV.

Ressource externeFonction
fruitz_hudHUD de Fruitz FA.
fruitz_adminMenu d’administration F10, utilisant les groupes staff EV.
clothingshopBoutiques, essayage et achat. Les packs streamés du groupe [clothing] alimentent le catalogue de vêtements.
fruitz_loadingscreenÉcran de chargement autonome de la base.
config/
Réglages partagés et fichiers de langue.
core/shared/, core/server/, core/client/
Validateurs et utilitaires communs, logique autoritaire et intégration FiveM côté client.
modules/
Modules serveur intégrés. Le registre interne utilise EV.Modules.Register.
web/
NUI d’identité et de création du skin.
sql/, tests/
Schéma, migrations et vérifications techniques.
vitrine/
Documentation autonome. Ouvre index.html dans ton navigateur.

Enregistrer un module interne

Un module fournit un nom, ses dépendances éventuelles et une fonction init(EV). Le registre démarre les dépendances avant le module. Une dépendance absente ou désactivée, un cycle ou une erreur d’initialisation empêche le démarrage du module concerné.

-- Exemple dans un fichier serveur chargé par EV.
EV.Modules.Register('exemple', {
    dependencies = {'jobs'},
    init = function(framework)
        framework.Events.On('jobChanged', function(src, job, grade)
            print(src, job, grade)
        end)
    end
})

10 / DIAGNOSTIC

Dépannage et tests

État de la copie locale. Le fichier core/client/main.lua contient 2 340 octets nuls. Il figure parmi les scripts client du manifeste. Restaure une version valide pour vérifier le spawn, la création de personnage et les exports définis dans ce fichier.

Les journaux EV utilisent le préfixe [EV] suivi d’un objet JSON avec level, action, data, version et timestamp. Cherche l’action et les données associées dans la console serveur.

Échec de connexion FiveM
Vérifie les endpoints TCP et UDP du port de jeu et le port alloué par l’hébergeur. Sur la configuration PrivaHost de Fruitz FA, le jeu utilise 28000 et txAdmin 28001.
Le joueur ne spawn pas
Vérifie le fichier client signalé ci-dessus, le démarrage de spawnmanager, OneSync, la connexion oxmysql et les erreurs côté client dans F8.
Colonne inconnue en SQL
Compare le schéma installé aux migrations d’identité, de skin et de position.
Position de retour à l’aéroport
Vérifie les colonnes de position, la disponibilité du ped OneSync et l’écriture de la position lors d’une session complète suivie d’une reconnexion.
Groupe ou menu F10 indisponible
Vérifie /mygroup, puis le démarrage de fruitz_admin. Le joueur doit avoir terminé le chargement de son personnage.
Tenue modée absente ou différente
Vérifie que le pack est streamé pour le modèle Freemode utilisé et que les références de collection correspondent toujours au pack installé.

Vérifications livrées avec EV

groups.test.lua couvre la hiérarchie. position.test.lua et spawn_client.test.lua ciblent le spawn et la persistance. skin_smoke.lua vérifie le skin.

Pour les virements, le guide de test accompagne CALL_SMOKE_TEST.sql et ledger_audit.sql. Exécute les scénarios de mutation dans une base de test.