Retour au portfolio

Projet personnel / Outils pour assets et workflows

AssetGuy

AssetGuy est une CLI Rust pour consulter, organiser, télécharger et installer les assets que vous possédez sur Fab. Pour le développement Unreal sous Windows, elle combine filtres de version du moteur et état de téléchargement, conserve des catégories personnelles et installe l’asset choisi dans un projet ou un moteur.

Quand utiliser AssetGuy à la place de la bibliothèque du launcher ?

Pour répondre à « quels packs possédés sont compatibles avec cette version d’Unreal et ne sont pas encore téléchargés ? », une grille impose de chercher et vérifier chaque élément. assetguy library engine UE5.8 uncached interroge le catalogue enregistré. Les catégories par règles organisent les nouveaux assets après sync ; la CLI rend les requêtes répétables et fournit du JSON aux scripts.

L’intérêt est la gestion de bibliothèque : consulter sans charger les vignettes ni demander des données à Fab, séparer téléchargement et installation, et inspecter la destination avant copie. C’est une alternative à ce parcours du launcher, pas un remplacement de toute l’application. Fab et Windows fonctionnent aujourd’hui ; PostgreSQL permet déjà un catalogue partagé, tandis que cache de fichiers partagé et GUI restent prévus.

  • Rust
  • Tokio
  • SQLite
  • PostgreSQL
  • Windows
Terminal AssetGuy montrant les assets filtrés par compatibilité Unreal Engine 5.8 et état non téléchargé
Capture existante du projet : assetguy library engine UE5.8 uncached. Le pied indique la portée des résultats et les métadonnées manquantes ; les chiffres concernent la bibliothèque capturée.

01 / Contexte

Les grandes bibliothèques compliquent la sélection d’assets

Le point de départ était l’effort pour trouver un asset dans une grille, vérifier sa compatibilité et déterminer si ses fichiers étaient déjà sur disque. Le launcher réunit ces questions dans la navigation visuelle. Je voulais des requêtes combinables sur la bibliothèque possédée, lisibles au terminal et utilisables dans des scripts.

J’ai choisi un catalogue interrogeable à partir de l’état local du launcher et des métadonnées obtenues pendant sync. Éviter les appels au marketplace allège la lecture, mais implique que le catalogue reflète la dernière synchronisation et non l’état distant en temps réel. Sa mise à jour est donc explicite. Provider, stockage, téléchargement et installation sont séparés parce qu’ils évoluent pour des raisons différentes.

De la synchronisation à l’installation d’un asset

  1. 01

    Synchronisation

    assetguy sync enregistre les assets possédés puis enrichit leurs métadonnées. Authentification et réseau relèvent d’opérations explicites ; consulter la bibliothèque ne déclenche pas de synchronisation.

  2. 02

    Consultation et inspection

    assetguy library engine UE5.8 uncached filtre le catalogue enregistré. assetguy info "Blockout Tools Plugin" montre détails et versions disponibles avant de choisir les fichiers.

  3. 03

    Téléchargement et installation

    assetguy download remplit le cache. assetguy add, assetguy new et assetguy install sont des opérations distinctes pour le contenu de projet, un projet complet et un plugin de moteur ; leurs arguments identifient l’asset et la destination.

Le catalogue se consulte sans contacter Fab. Avec SQLite, tout est local ; PostgreSQL interroge le serveur configuré, pas le marketplace.

02 / Conception et architecture

Décisions d’architecture et leurs conséquences

Catalogue local

Requêtes au catalogue séparées des opérations réseau

assetguy library lit la base configurée. assetguy sync la met à jour ; assetguy search consulte le catalogue public Fab ; assetguy download récupère les fichiers. Cela explicite le coût de chaque action. assetguy add exige les fichiers en cache et, s’ils manquent, indique la commande de téléchargement au lieu de transférer silencieusement des gigaoctets.

Les URL des vignettes arrivent avec les métadonnées, mais télécharger les images reste facultatif : un terminal ne les affiche pas et une bibliothèque peut en contenir des gigaoctets. La CLI permet de stabiliser le comportement avant qu’une GUI en dépende.

Le catalogue peut devenir obsolète entre synchronisations. J’ai accepté ce compromis pour rendre le coût des requêtes prévisible et indépendant de la disponibilité du marketplace. Les métadonnées absentes restent visibles : une liste vide ne prouve pas qu’aucun asset compatible n’existe.

Frontière du provider

Contrats centrés sur les opérations du provider

Bibliothèque possédée, détails publics, recherche et CDN de Fab ont des exigences d’authentification différentes. Un client HTTP authentifié générique transporterait de mauvaises hypothèses entre ces routes. Le contrat décrit plutôt des opérations : achats, détail d’un listing, authentification et livraison.

Les rôles et capacités séparés permettent de nommer une opération non prise en charge. Fab est le provider implémenté aujourd’hui. La frontière du téléchargement est DownloadPlan : le provider traduit son manifeste en plan ; récupération et assemblage utilisent ce plan sans dépendre des types de l’API Epic.

Cette frontière permet de tester les parcours sans les détails HTTP et concentre les changements de l’API Fab dans son provider. Elle ne prouve pas encore le support d’une autre boutique : un second provider devra satisfaire ces contrats sur ses propres cas réels.

Choix du stockage

Un backend configuré et quatre rôles de stockage

SQLite est le choix sans configuration ; PostgreSQL est déjà implémenté. Le backend choisi conserve catalogue, classement et état des téléchargements/installations. Quatre rôles limitent les accès : AssetStore, CatalogWriteStore, CurationStore et DownloadStore. Un téléchargement n’a pas besoin de réécrire les catégories.

Les contrats de stockage utilisent des appels synchrones adaptés au driver SQLite bloquant ; les opérations réseau et provider sont asynchrones. Le SQL spécifique passe par une frontière de dialecte. Le backend est une configuration persistante ; une connexion invalide échoue explicitement sans ouvrir une autre bibliothèque. Changer de base ne migre pas les données existantes.

SQLite est le défaut pour éviter l’administration d’un serveur en usage individuel. PostgreSQL apporte un catalogue commun au prix de connexions, identifiants et exploitation du serveur. Partager métadonnées et chemins ne rend pas les fichiers accessibles sur d’autres machines ; cela demande le cache partagé encore absent.

Recherche et classement

Catégories par règles et filtres indépendants

Les catégories personnelles expriment des règles plutôt qu’un ensemble figé de tags. Les nouveaux assets synchronisés peuvent rejoindre automatiquement ce classement. Version du moteur, format, catégorie du marketplace et état du cache sont des filtres distincts.

Les versions Unreal sont comparées par composants : UE4.1 ne doit pas signifier UE4.10. Moteur et format restent distincts ; un format Unity n’implique pas des versions Unity fournies par Fab. Métadonnées absentes et couverture partielle sont signalées, évitant de confondre un résultat vide avec une connaissance complète du marketplace.

Synchronisation

Pagination séquentielle, enrichissement parallèle

Le sync récupère d’abord la liste possédée, dont les curseurs imposent une pagination séquentielle. Il enrichit ensuite les assets avec des workers parallèles limités. Le budget de requêtes contrôle la pression sur l’API sans prétendre représenter un pourcentage du débit réseau.

La liste possédée utilise la session du compte ; les détails publics utilisent un client anonyme, selon le comportement observé de l’API. Un listing retiré peut rester possédé et téléchargeable ; une taille absente est inconnue, pas nulle. L’inspection du manifeste permet séparément de connaître les tailles Unreal.

Assemblage du téléchargement

Assemblage ordonné et mémoire bornée des téléchargements

Les téléchargements récupèrent les chunks en parallèle mais assemblent les fichiers avec un writer ordonné, calculant SHA1 pendant l’écriture. Les fichiers terminés et vérifiés composent l’état de reprise ; l’identité du manifeste évite de mélanger des builds. Les fichiers quittent le répertoire partiel après achèvement.

Les chunks réutilisés disposent d’un cache mémoire borné. Le plan connaissant l’ordre d’écriture, l’éviction retire le chunk dont la prochaine utilisation est la plus éloignée. Une récupération supplémentaire occasionnelle permet un plafond mémoire prévisible sans stocker deux fois l’asset entier sur disque.

L’écriture ordonnée simplifie la vérification et la reprise, mais peut attendre un chunk retardé alors que d’autres sont arrivés. La limite du cache peut imposer de récupérer à nouveau un chunk. Le choix privilégie intégrité et mémoire prévisible plutôt que le parallélisme maximal.

Installation contrôlée

Installation selon le type et le manifeste

Les packs de contenu vont dans Content ; les projets complets peuvent être copiés comme projets ; les plugins suivent les chemins du manifeste. Dry run prévisualise l’action et les collisions exigent force explicite. Les copies sont préparées sur le volume de destination ; le staging moteur reste hors du scanner de plugins.

L’installation exige la racine exacte d’un moteur enregistré. Les fichiers précèdent les enregistrements du launcher : manifeste, item, liste des installations et EOSH sont maintenus. Sauvegardes et relecture protègent la liste. Le launcher doit être fermé car il peut réécrire ces fichiers depuis son état en mémoire.

Installer du contenu dans un projet et un plugin dans un moteur touche des structures différentes. Des commandes séparées rendent destination et effet explicites. Les registres du launcher sont l’intégration la plus sensible : copier un dossier ne suffit pas pour que l’outil Epic reconnaisse installation et suppression.

État et identifiants

Configuration, identifiants et registres aux cycles de vie distincts

La configuration reste dans le profil itinérant ; identifiants OAuth, cache et audit dans le profil local. Le login utilise le navigateur et renvoie un code masqué dans l’audit selon l’identité de la commande. Les mots de passe du stockage sont fournis séparément de l’URL enregistrée.

L’état du launcher est en lecture seule pour consultation et synchronisation. install, uninstall et repair sont les exceptions explicites qui écrivent ses enregistrements. L’audit mensuel local conserve les opérations ; doctor expose les problèmes d’intégrité sans demander au développeur d’inventer des requêtes de diagnostic.

Détail d’un asset avec versions Unreal compatibles, métadonnées, taille inconnue et commande de téléchargement
Capture existante : assetguy info "Blockout Tools Plugin". La taille inconnue est expliquée plutôt qu’affichée comme zéro, avec la prochaine commande.

03 / Dans le code

Opérations sur les assets dans le core ; présentation dans la CLI

assetguy-core

Contrats provider, stockage, filtres, sync, téléchargements vérifiés, installation et intégration launcher. La CLI utilise ces opérations ; une future GUI doit les réutiliser.

assetguy-cli

Route les commandes avec clap, analyse les mots-clés combinables, affiche tableaux, JSON et progression. Le formatage reste distinct des opérations sur les assets.

Tokio / DownloadPlan

Réseau asynchrone et pools limités côtoient un assemblage ordonné. Les manifestes des providers sont traduits avant d’arriver à ce chemin.

SQLite / PostgreSQL

Deux backends partagent les contrats par rôle et une suite de conformité sémantique. SQLite lit aussi les données du launcher et conserve l’audit local, même avec PostgreSQL.

Comment le comportement est vérifié

Les contrôles incluent cargo fmt, clippy avec avertissements traités comme erreurs, tests unitaires et validations manuelles sur de vrais assets. Une suite indépendante du backend vérifie les mêmes règles de stockage dans SQLite et PostgreSQL. L’installation exige aussi une vérification dans l’éditeur : un test unitaire ne prouve pas que le contenu apparaît dans Unreal ni que le launcher peut retirer un plugin.

04 / Travail en cours

Ce qui est implémenté et ce qui reste à construire

Travail en cours

AssetGuy est une CLI Windows en développement initial, sous licence MIT et sans affiliation à Epic Games. Consultation, catégories, OAuth, sync, recherche publique, téléchargements, installation de contenu/projets Unreal, plugins et deux backends sont implémentés. Commandes et comportement peuvent évoluer avant 1.0.

Les prochaines directions sont un cache de fichiers partagé, un second provider et une GUI sur le core existant. La base partagée existe déjà mais ne rend pas les fichiers accessibles aux autres machines à elle seule. L’installation Unity et Godot est un objectif plus large ; les chemins fonctionnels décrits ici concernent Unreal.

Explorer le projet

Le README couvre commandes, filtres, configuration des bases, téléchargements, protections d’installation et limites actuelles. Le code montre les frontières entre CLI, core et intégration Fab.

Lire la documentation sur GitHub

Contact

Québec, QC, Canada / Ouvert aux opportunités

Je suis ouvert aux possibilités en développement logiciel, en programmation d'outils et de gameplay, ainsi qu'aux postes d'artiste 3D junior. Si mon expérience peut répondre aux besoins de votre équipe, je serai heureux d'échanger avec vous sur mes réseaux sociaux.