Aller au contenu

Ressources FiveM

medusa-changing-rooms possède les commandes et la logique de placement/édition des vestiaires. medusa-admin expose leur surface World Edit et transmet au terminal NUI une liste de commandes filtrée par permissions pour l'autocomplétion.

medusa-entity-placement centralise les prévisualisations de PNJ et props. medusa-world-props possède la synchronisation et les commandes des objets libres persistants ; medusa-admin ne fournit que leur surface World Edit.

medusa-inventory possède l'inventaire joueur, sa NUI et les raccourcis de barre rapide. Il résout le personnage via medusa-player-utils et délègue toute persistance/concurrence à l'API.

medusa-hud possède l'unique NUI d'affichage permanent. Les ressources métier lui transmettent leurs états par événements client locaux : les buffs alimentent la pile supérieure droite et le système temps/météo alimente l'inlay date/heure inférieur droit.

Au démarrage, entrypoint.sh parcourt le manifeste construit dans l'image et remplace chaque ressource [local] du volume persistant par sa copie embarquée. Une reconstruction déploie donc aussi les modifications et suppressions de fichiers des nouvelles ressources, sans dépendre d'une liste manuelle qui pourrait devenir incomplète. Les ressources tierces restent synchronisées selon leurs règles dédiées.

Sorties du terminal F9

medusa-admin est le consommateur unique de l'événement medusa:terminal:output. Une commande cliente publie localement avec TriggerEvent; une commande serveur cible son joueur avec emitNet. Le payload contient message, un prefix court et un kind parmi output, success, warning ou error. Le client borne le préfixe à 24 caractères et le message à 4096 caractères, puis transmet la ligne à la NUI, même si F9 est fermé afin de conserver l'historique de session.

Les messages administratifs historiques passent par le même writer. medusa-commands y publie les deux formats de /coords, tandis que medusa-core utilise un helper commun pour les résultats de /characters et /mycharacter. Toute nouvelle commande Medusa qui produit un résultat texte doit publier sur ce canal ; les interfaces ouvertes par une commande restent leur propre résultat.

medusa-admin

La NUI medusa-admin sépare data-admin-section (navigation principale) et data-admin-view (sous-section). selectAdminSection filtre les onglets selon le domaine et les permissions déjà calculées ; selectAdminView n'affiche qu'un workspace ingame-<view>-view et ne rafraîchit que le module actif. Les magasins, vestiaires et objets persistants ne partagent donc plus un conteneur World Edit empilé. Ajouter un module consiste à déclarer sa section, son onglet, sa vue et ses métadonnées sans modifier la géométrie générale du panneau.

La sous-navigation utilise un conteneur admin-subnav-track horizontal borné par deux contrôles précédent/suivant. Le track accepte le défilement natif tactile/trackpad, convertit la molette verticale en déplacement horizontal lorsqu’il reste du contenu, et gère Gauche/Droite ainsi que Début/Fin au clavier. selectAdminView replace l’onglet actif dans la zone visible ; les flèches sont désactivées aux extrémités et l’animation respecte prefers-reduced-motion. Les onglets cachés par permission ne participent pas à la largeur navigable.

Le shell visuel utilise une grille à trois zones : rail principal, rail secondaire et workspace. Ses fonds restent confinés au châssis et la racine admin demeure transparente. Les règles AR/VR communes sont normatives dans .agents/AGENTS.md afin que les futures NUI restent cohérentes avec medusa-clothing-shops et medusa-inventory.

La NUI expose openAdminAction, un dialogue asynchrone unique qui construit ses champs avec les API DOM, applique la validation HTML et retourne soit les valeurs saisies, soit null après annulation. Toutes les actions anciennement basées sur confirm ou prompt passent par ce composant.

medusa-admin isole le panneau NUI, le terminal, les outils visuels World Edit et toutes les commandes administratives. Son client possède exclusivement les key mappings et callbacks NUI administratifs. Son serveur réautorise chaque action et appelle l’API interne via medusa-core.

medusa-moderation reste propriétaire du cycle de connexion et du contexte chargé depuis Discord. Il expose uniquement getAdminProfile(source) et listAdminProfiles() au resource admin. Cette frontière évite de dupliquer l’authentification et permet d’ajouter de nouveaux modules au panneau sans modifier le parcours joueur. medusa-admin est démarré après medusa-moderation dans server.cfg.template et synchronisé comme resource local par entrypoint.sh.

Les exports JavaScript sont enregistrés avec global.exports, conformément au runtime FiveM. Les deux resources possèdent un fichier .resource-version : sa progression force entrypoint.sh à remplacer les copies persistées lors d’un déploiement, évitant qu’un nouveau medusa-admin soit associé à une ancienne copie de medusa-moderation.

Le payload ShowID provient de listAdminProfiles() et conserve highest_role. Le client medusa-admin rend séparément l’identité Discord, le personnage actif et ce rôle sans recalculer la hiérarchie côté client.

La commande /car crée le véhicule avec CreateVehicleServerSetter dans medusa-admin/server.js, l’affecte au routing bucket du joueur et active le mode orphelin persistant. Le client reçoit uniquement l’identifiant réseau, attend sa réplication puis place le joueur au volant. Ce flux est compatible avec le verrouillage OneSync strict appliqué par medusa-world-control : aucune entité réseau n’est créée côté client.

La commande /delv est autorisée côté serveur avec ADMIN_ALLOW_DELETE_VEHICLE. Le client parcourt le pool CVehicle, sans exclure les véhicules détruits, et retient l'entité la plus proche à 10 mètres au maximum. Il demande brièvement le contrôle réseau, marque l'entité comme mission, puis appelle DeleteVehicle et DeleteEntity en secours. Un résultat n'est accepté par le serveur que pendant la fenêtre ouverte par la commande ; l'audit vehicle.delete utilise la plaque comme cible et conserve également la distance et l'identifiant réseau.

La commande /tpm est autorisée côté serveur avec ADMIN_ALLOW_TPM, puis le client recherche le blip waypoint de type 8. Sans blip, il renvoie un échec explicite. Sinon, il téléporte le ped ou son véhicule après recherche progressive du sol et chargement des collisions. Le résultat et les coordonnées finales reviennent au serveur pour le message utilisateur et l’audit player.teleport_waypoint ; le serveur revalide la permission avant de les accepter.

La commande /tpc est protégée séparément par ADMIN_ALLOW_TPC. Le serveur analyse la chaîne vec3(x, y, z) ou trois nombres, refuse les valeurs non finies et conserve la destination pendant 15 secondes. Le client téléporte le ped ou son véhicule après demande de collision. Le résultat est corrélé à la demande en attente et l'audit player.teleport_coordinates reprend exclusivement les coordonnées validées et conservées côté serveur.

Les ressources sont classées dans [local], [maps], [mods] et [vehicles]. Les ressources locales implémentent la connexion API, la whitelist, l'accueil, la modération, les commandes, le loading screen, la création/personnalisation, les magasins de vêtements, les tatouages, le spawn et les utilitaires joueurs.

Personnages et apparence

fivem-appearance reste la release amont originale v1.3.1. L'interface Medusa vit dans medusa-character-customization et appelle les callbacks amont afin que les palettes cheveux, reflets, yeux et overlays soient appliquées correctement. medusa-player-utils centralise la correspondance entre source FiveM, compte connecté et personnage actif.

La création initiale et /customization utilisent l'interface locale ; les apparences enregistrées continuent d'être chargées avec les exports amont. Les demandes de recustomisation hors ligne sont persistées côté API.

Magasins de vêtements

medusa-clothing-shops lit ses positions, modèle/scénario de conseillère, distances et blip depuis son config.json. Chaque magasin inscrit un ped géré dans medusa-interactions, sans marqueur au sol. Un MarkerTypeVerticalCylinder turquoise signale le ped à 20 mètres par défaut, avant le popup. Sa boucle de dessin ne s'exécute que pendant le ciblage du ped. Le magasin ouvre medusa-character-customization avec uniquement components et props activés. L'éditeur conserve un snapshot du ped : annuler ou rencontrer une erreur API restaure ce snapshot.

Le NUI sans focus et les notifications appartiennent désormais à medusa-interactions, afin que le même langage puisse être réutilisé pour toute entité ou position. Le bloc popup du config.json des magasins définit l'intégralité des textes, avec surcharge possible dans chaque entrée de shops. Le contexte medusaMode = "clothing-shop" transmis à medusa-character-customization sélectionne les titres, confirmations, télémétrie et libellés vestimentaires. Les deux ressources possèdent un marqueur de version afin que l'entrypoint propage le redesign dans le volume persistant.

medusa-clothing-shops possède aussi une page NUI transparente dédiée à la cabine VR. Le client l'affiche juste avant l'ouverture de l'éditeur et la masque dans son callback, quelle que soit l'issue. Aucun z-index NUI n'est imposé : la pile de focus FiveM conserve l'éditeur interactif au premier plan. pointer-events: none empêche la couche décorative de capturer une entrée. Les couleurs et libellés proviennent de vrOverlay dans le config.json du magasin. Les racines HTML, body et overlay imposent un fond RGBA totalement transparent ; les cadres n'emploient aucun inset sombre susceptible de teinter la vue GTA. Aucun fichier de medusa-character-customization n'est modifié.

medusa-changing-rooms reste lui aussi isolé : il réutilise uniquement les exports d'application de composants/accessoires et le gestionnaire d'interactions. Il ne charge ni ne modifie le NUI, le client ou la configuration de medusa-clothing-shops.

L'appel de l'export d'ouverture est protégé par pcall. Si l'export manque ou lève une erreur, la ressource ferme la surcouche, libère son verrou editorOpen, journalise la cause dans la console client et affiche une notification au joueur ; une tentative suivante reste donc possible.

L'inscription de chaque magasin utilise aussi lockOnAction = true dans medusa-interactions. L'appui sur E suspend donc globalement le scan, le marker, le popup et les nouvelles entrées avant l'ouverture de l'éditeur. L'inscription contient un clientEvent et un payload.shopIndex, jamais un callback Lua non sérialisable. Le gestionnaire local résout le magasin puis libère le verrou via l'export releaseInteraction(id, reason) après sauvegarde, annulation ou erreur.

Le drapeau temporaire debug du magasin ajoute les traces F8 [medusa-clothing-shops][DEBUG] suivantes : interaction_event, open_requested, snapshot_captured, vr_overlay, editor_export_call, editor_export_returned et editor_callback. Si la dernière apparaît immédiatement avec appearance=false, c'est l'éditeur qui se referme ; si editor_export_failed apparaît, son message contient la cause Lua. L'absence de interaction_event situe le problème avant le magasin, dans le gestionnaire d'interactions.

À l'enregistrement, le serveur résout le personnage actif avec medusa-player-utils, valide la forme des composants et props, puis appelle :

PATCH /internal/v1/characters/{character_id}/state
{ "clothing": { "components": [...], "props": [...] } }

PostgreSQL conserve la tenue dans characters.clothing. medusa-spawn la réapplique après l'apparence à chaque session. Aucun accès direct à la base n'est effectué par la ressource.

Contenu et monde

  • medusa-loading-screen charge sa configuration via LOADSCREEN_CONFIG_URL.
  • medusa-spawn fournit le point d'apparition de secours.
  • bob74_ipl est embarqué en version 2.6.1.
  • les véhicules validés résident individuellement sous [vehicles].
  • realistichandlingbyTaira remplace le handling des véhicules vanilla.

Synchronisation du volume

Au démarrage, l'entrypoint copie les ressources embarquées absentes dans fivem_resources. Les ressources versionnées par le projet sont remplacées lorsque leur marqueur change ; les ressources externes inconnues sont préservées. Les dépendances amont gérées disposent de règles séparées. Les façades pinées lc_utils et lc_fuel sont toujours remplacées depuis l’image, avant le fallback d’installation cp -Rn, car leur contrat doit évoluer atomiquement avec medusa-energy. Sans cette règle, une ancienne copie conservée dans le volume désactive volontairement toutes les stations au contrôle de compatibilité.

Véhicules enregistrés

medusa-vehicles est chargé après le cœur, les interactions, l'inventaire, les groupes et la banque, puis avant medusa-admin. Il maintient la correspondance UUID ↔ entité réseau et publie des state bags de corrélation ; l'API reste seule autoritaire pour la clé, le propriétaire et la serrure. Au premier reconcile d'un démarrage de ressource, l'API force les véhicules actifs dans un état verrouillé et la ressource les recrée moteur coupé depuis la dernière position sûre.

medusa-admin conserve actorPayload en discord_role_ids pour ses contrats historiques, mais toutes les routes internes du domaine véhicules utilisent vehicleActorPayload en actor_role_ids. Le placement serrurier ferme F10, attend la mutation API, puis déclenche la resynchronisation des Peds et le message de résultat sans rouvrir automatiquement le panneau.

Les actions F10 GPS et SE TP passent par l'export serveur medusa-vehicles.locateRegistered, qui exige une entité active dans le bucket de l'administrateur. GPS appelle SetNewWaypoint avec les coordonnées serveur. SE TP réutilise l'événement client de /tpc, place le Ped ou son véhicule quatre mètres à côté de la cible, charge les collisions et n'audite qu'un résultat corrélé. restoreRegistered calcule DEVANT MOI depuis le Ped serveur, refuse les occupants et sérialise la restauration par UUID.