Voltar ao portfolio

Projeto pessoal / Ferramentas para assets e workflows

AssetGuy

AssetGuy é uma CLI em Rust para consultar, organizar, baixar e instalar os assets que você possui na Fab. Para quem desenvolve na Unreal no Windows, ela permite combinar filtros de versão da engine e estado de download, manter categorias próprias e instalar o asset escolhido num projeto ou engine.

Quando usar o AssetGuy no lugar da biblioteca do launcher?

Se a pergunta é “quais packs eu possuo, compatíveis com esta versão da Unreal, que ainda não baixei?”, navegar por cards exige procurar e conferir cada item. assetguy library engine UE5.8 uncached responde consultando o catálogo já armazenado. Categorias por regras organizam novos assets após o sync; a CLI permite repetir consultas e usar a saída JSON em scripts.

O ganho está no gerenciamento da biblioteca: consultar sem carregar thumbnails ou pedir dados à Fab, separar download de instalação e conferir o destino antes de copiar arquivos. É uma alternativa a esse fluxo do launcher, não uma substituição de toda a aplicação. Fab e Windows são a integração atual; PostgreSQL já permite compartilhar o catálogo, mas o cache compartilhado de arquivos e a GUI ainda são planos.

  • Rust
  • Tokio
  • SQLite
  • PostgreSQL
  • Windows
Terminal do AssetGuy mostrando assets filtrados por compatibilidade com Unreal Engine 5.8 e estado não baixado
Captura existente do projeto: assetguy library engine UE5.8 uncached. O rodapé informa o alcance dos resultados e metadados de engine ausentes; os números pertencem à biblioteca capturada.

01 / Contexto

Uma biblioteca grande torna a seleção de assets trabalhosa

O ponto de partida foi o custo de encontrar um asset numa grade de thumbnails, conferir sua compatibilidade e descobrir se os arquivos já estavam no disco. A interface do launcher reúne essas perguntas na navegação visual. Eu precisava de consultas combináveis sobre a biblioteca possuída, com resultado legível no terminal e utilizável por scripts.

A decisão foi manter um catálogo consultável a partir do estado local do launcher e dos metadados obtidos no sync. Isso acelera o caminho de leitura por evitar a consulta ao marketplace, mas traz uma consequência: o catálogo representa a última sincronização, não o estado remoto em tempo real. Por isso, atualizar os dados é uma operação explícita. Provider, armazenamento, download e instalação têm fronteiras separadas porque mudam por motivos diferentes.

Da sincronização à instalação de um asset

  1. 01

    Sincronização

    assetguy sync registra os assets possuídos e depois enriquece os metadados. Autenticação e rede pertencem a operações explícitas; consultar a biblioteca não dispara uma sincronização.

  2. 02

    Consulta e inspeção

    assetguy library engine UE5.8 uncached filtra o catálogo armazenado. assetguy info "Blockout Tools Plugin" mostra detalhes e versões disponíveis antes de escolher os arquivos.

  3. 03

    Download e instalação

    assetguy download preenche o cache. assetguy add, assetguy new e assetguy install são operações distintas para conteúdo de projeto, projeto completo e plugin de engine; os argumentos identificam o asset e o destino.

O catálogo pode ser consultado sem contactar a Fab. Com SQLite é totalmente local; PostgreSQL consulta o servidor de banco configurado, não o marketplace.

02 / Design e arquitetura

Decisões de arquitetura e suas consequências

Catálogo local

Consultas ao catálogo e operações de rede separadas

assetguy library lê o banco configurado. assetguy sync atualiza esses dados; assetguy search consulta o catálogo público da Fab; assetguy download busca os arquivos. Essa separação explicita o custo de cada ação. assetguy add exige os arquivos no cache e, quando faltam, indica o comando de download em vez de transferir gigabytes silenciosamente.

URLs de thumbnails chegam nos metadados, mas baixar as imagens é opcional: o terminal não as desenha e uma biblioteca grande pode conter gigabytes de imagens. A interface começa pela CLI para estabilizar o comportamento antes que uma GUI dependa dele.

O catálogo pode ficar desatualizado entre sincronizações. Aceitei essa troca para que uma consulta tenha custo previsível e não dependa da disponibilidade do marketplace. Metadados ausentes continuam visíveis: uma listagem vazia não prova que não existam assets compatíveis.

Fronteira do provider

Contratos orientados às operações do provider

A biblioteca possuída, detalhes públicos, busca pública e CDN da Fab têm requisitos de autenticação diferentes. Um cliente HTTP autenticado genérico levaria premissas erradas de uma rota para outra. O contrato de provider descreve operações como assets possuídos, detalhes de listing, autenticação e entrega.

Papéis e capacidades separados permitem explicar pelo nome uma operação sem suporte. Fab é o provider implementado hoje. A fronteira do download é um DownloadPlan: o provider converte o manifesto em plano; busca de chunks e montagem de arquivos usam esse plano sem depender dos tipos da API da Epic.

Essa fronteira permite testar o workflow sem depender dos detalhes HTTP e concentrar mudanças da API da Fab na implementação do provider. Ela ainda não comprova suporte a outra loja: um segundo provider terá de satisfazer esses contratos com seus próprios casos reais.

Escolha de armazenamento

Um backend configurado e quatro papéis de storage

SQLite é o padrão sem configuração; PostgreSQL já está implementado. O backend escolhido guarda catálogo, curadoria e estado de download/instalação. Quatro papéis estreitam o acesso de cada chamador: AssetStore, CatalogWriteStore, CurationStore e DownloadStore. Um download não precisa poder reescrever regras de categorias.

Os contratos de storage usam chamadas síncronas, acompanhando o driver bloqueante do SQLite; operações de provider e rede são assíncronas. SQL específico fica atrás de uma fronteira de dialeto. A escolha do backend é configuração persistente; conexão inválida falha explicitamente em vez de abrir outra biblioteca. Trocar de banco não migra os dados existentes.

Escolhi SQLite como padrão para que o uso individual não exija administrar um servidor. PostgreSQL atende à necessidade de um catálogo comum, com o custo de conexão, credenciais e operação do banco. Compartilhar metadados e caminhos não torna os arquivos disponíveis em outras máquinas; isso exige o cache compartilhado ainda não implementado.

Busca e curadoria

Categorias por regras e filtros independentes

Categorias próprias expressam regras de correspondência em vez de um conjunto congelado de tags. Novos assets sincronizados podem entrar automaticamente na mesma organização. Versão de engine, formato, categoria da loja e estado de cache são filtros separados porque respondem perguntas diferentes.

Versões Unreal são comparadas por componentes: UE4.1 não pode significar também UE4.10. Metadados de engine e formato permanecem separados; um formato Unity não implica que a Fab forneça suas versões. Metadados ausentes e cobertura parcial da busca são informados, evitando interpretar resultado vazio como conhecimento completo do marketplace.

Sincronização

Paginação sequencial, enriquecimento paralelo

O sync primeiro busca a lista possuída, cuja paginação por cursor é sequencial. Depois enriquece cada asset com detalhes usando workers paralelos limitados. O orçamento de requisições controla a pressão sobre a API; não é apresentado como porcentagem da velocidade da conexão.

A lista possuída usa a sessão da conta, enquanto detalhes públicos usam um cliente anônimo. A distinção vem do comportamento observado da API. Um listing público removido ainda pode ser possuído e baixável; um tamanho ausente é desconhecido, não zero. Inspecionar o manifesto é uma operação separada para descobrir tamanhos Unreal.

Montagem do download

Montagem ordenada e memória limitada nos downloads

Downloads buscam chunks em paralelo, mas montam arquivos com um writer ordenado, calculando SHA1 enquanto os bytes são escritos. Arquivos completos e verificados compõem o estado de retomada; a identidade do manifesto impede misturar builds diferentes. Os arquivos saem do diretório parcial somente após concluir o trabalho.

Chunks usados por vários arquivos têm um cache limitado em memória. Como o plano conhece a ordem de escrita, a remoção descarta o chunk cujo próximo uso está mais distante. Isso troca uma eventual nova busca por um teto previsível de memória, sem guardar o asset inteiro duas vezes no disco.

O writer ordenado simplifica a verificação e a retomada, mas pode esperar um chunk atrasado enquanto outros já chegaram. O limite de cache pode exigir buscar um chunk novamente. A escolha prioriza integridade e memória previsível em vez de maximizar paralelismo a qualquer custo.

Instalação controlada

Instalação determinada pelo tipo e pelo manifesto

Content packs entram em Content do projeto; projetos completos podem ser copiados como projetos; plugins de engine seguem os caminhos do manifesto. Dry run permite inspecionar a ação, e colisões exigem force explícito. Cópias são preparadas no volume de destino; staging de engine fica fora da pasta que o scanner de plugins lê.

Instalar plugins exige a raiz exata de uma engine registrada. Os arquivos vêm antes dos registros do launcher; a instalação mantém manifesto, item, lista de instalados e registros EOSH. Backups e leitura de conferência protegem a atualização da lista. O launcher precisa estar fechado porque pode reescrever os registros a partir do estado em memória.

Uma instalação de conteúdo num projeto e uma instalação de plugin na engine afetam estruturas diferentes. Mantê-las como comandos separados torna o destino e o efeito explícitos. A integração com os registros do launcher é a parte mais sensível: copiar a pasta sozinha não basta para que a ferramenta da Epic reconheça a instalação e sua remoção.

Estado e credenciais

Configuração, credenciais e registros com ciclos de vida distintos

A configuração fica no perfil roaming; credenciais OAuth, cache e arquivos de auditoria ficam no perfil local. O login ocorre no navegador e retorna um código de autorização, ocultado na auditoria pela identidade do comando. Senhas de banco são fornecidas separadamente da URL de conexão armazenada.

O estado do launcher é somente leitura durante consulta e sincronização. install, uninstall e repair são as exceções explícitas que escrevem seus registros. A auditoria mensal local registra operações; doctor expõe problemas de integridade e estado sem exigir que um desenvolvedor invente consultas de diagnóstico.

Detalhes de asset no AssetGuy com versões Unreal compatíveis, metadados, tamanho desconhecido e comando de download
Captura existente do projeto: assetguy info "Blockout Tools Plugin". O tamanho desconhecido é explicado em vez de exibido como zero, e o próximo comando aparece junto ao asset.

03 / Por dentro do código

Operações de assets no core; apresentação na CLI

assetguy-core

Contratos de provider, storage, filtros, sincronização, downloads verificados, instalação e integração com launcher. A CLI usa essas operações; uma futura GUI pretende reutilizá-las.

assetguy-cli

Roteia comandos com clap, interpreta keywords combináveis, apresenta tabelas e JSON e informa progresso. A formatação do terminal fica separada das operações sobre os assets.

Tokio / DownloadPlan

Rede assíncrona e pools limitados de workers convivem com montagem ordenada. Manifestos específicos dos providers são traduzidos antes de chegar a essa montagem.

SQLite / PostgreSQL

Dois backends implementados compartilham contratos por papel e testes de conformidade semântica. SQLite também lê dados do launcher e guarda auditoria local, mesmo num build com PostgreSQL.

Como o comportamento é verificado

A validação de desenvolvimento inclui cargo fmt, clippy com warnings como erros, testes unitários e verificações manuais com assets reais. Uma suíte independente do backend verifica a mesma semântica de storage em SQLite e PostgreSQL. Instalação também exige conferir o editor: um teste unitário não comprova sozinho que conteúdo aparece no Content Browser da Unreal ou que o launcher remove um plugin instalado.

04 / Trabalho em andamento

O que está implementado e o que ainda depende de trabalho

Em desenvolvimento

AssetGuy é uma CLI Windows em desenvolvimento inicial, sob licença MIT e sem afiliação com a Epic Games. Consulta, categorias, OAuth, sync, busca pública, downloads, instalação de conteúdo/projetos Unreal, plugins de engine e os dois bancos estão implementados. Nomes de comandos e comportamentos ainda podem mudar antes da 1.0.

As próximas direções são cache de arquivos compartilhado pela equipe, um segundo provider e uma GUI sobre o core existente. O banco compartilhado já existe, mas não disponibiliza sozinho os arquivos dos assets para outras máquinas. Instalação em Unity e Godot é uma meta mais ampla, não uma integração implementada; os caminhos de instalação descritos aqui são da Unreal.

Explore o projeto

O README documenta comandos, filtros, configuração dos bancos, downloads, proteções de instalação e limites atuais. O código mostra as fronteiras entre a CLI, o core e a integração com a Fab.

Leia a documentação no GitHub

Contato

Cidade de Québec, QC, Canadá / Disponível para oportunidades

Estou aberto a oportunidades em desenvolvimento de software, programação de ferramentas e gameplay, além de vagas de artista 3D júnior. Se minha experiência fizer sentido para sua equipe, será um prazer conversar pelos meus perfis nas redes sociais.