Resources e mtaxmanifest.lua
Um resource é uma pasta dentro de resources/ contendo um arquivo mtaxmanifest.lua. Ele é a unidade que o servidor inicia, para e reinicia — e cada um roda em sua própria VM Lua, isolada das demais.
Directoryresources/
Directorymeu-resource/
- mtaxmanifest.lua obrigatório
Directoryserver/
- main.lua
Directoryclient/
- main.lua
Directoryassets/
- logo.png
O nome da pasta é o nome pelo qual você inicia o resource no console e no server.cfg.
Categorias
Seção intitulada “Categorias”Uma pasta cujo nome está entre colchetes é uma categoria: ela não é um resource, apenas agrupa outros.
Directoryresources/
Directory“[gameplay]”/
Directoryspawn/
- mtaxmanifest.lua
Directoryrespawn/
- mtaxmanifest.lua
Categorias podem ser aninhadas. No console, usar o nome da categoria aplica o comando a todos os resources dentro dela.
O manifesto
Seção intitulada “O manifesto”mtaxmanifest.lua é um script Lua que apenas declara variáveis — o servidor lê os valores após executá-lo.
resource_name = "meu-resource"resource_version = "1.0.0"resource_author = "Seu Nome"
server_files = { "server/main.lua",}
client_files = { "client/main.lua",}
files = { "assets/logo.png",}Identificação
Seção intitulada “Identificação”| Variável | Tipo | Descrição |
|---|---|---|
resource_name | texto | Nome do resource. |
resource_version | texto | Versão, livre (ex.: 1.0.0). |
resource_author | texto | Autor ou equipe responsável. |
Os três são expostos aos scripts por getResourceInfo.
Listas de arquivos
Seção intitulada “Listas de arquivos”| Variável | Aceita | Onde roda |
|---|---|---|
server_files | apenas .lua | Só no servidor. Nunca é enviado ao cliente. |
client_files | apenas .lua | Baixado e executado no cliente. |
shared_files | apenas .lua | Executado nos dois lados. |
files | qualquer coisa exceto .lua | Assets baixados pelo cliente (imagens, fontes, modelos, sons). |
client_configs | qualquer arquivo exceto .lua | Arquivos XML de configuração que o cliente lê com getResourceConfig (o <config type="client"> do MTA). São baixados como os de files; não é preciso listá-los duas vezes. |
map_files | qualquer arquivo exceto .lua | Interpretado pelo servidor como XML de mapa; nunca é enviado ao cliente. A extensão convencional é .map. Uma entrada é tanto uma string "dir/arquivo.map" quanto uma tabela { src = "dir/arquivo.map", dimension = N, interior = N } — o dimension e o interior informados ali viram os padrões de todos os elementos daquele mapa. |
Uma entrada também pode apontar para um arquivo dentro de outro resource — veja Pegando emprestado de outro resource.
Codificação dos scripts
Seção intitulada “Codificação dos scripts”Os scripts são lidos como UTF-8. Quando um arquivo está salvo em outra codificação, o servidor o converte para UTF-8 — tanto a cópia que ele mesmo executa quanto a cópia que compila para os jogadores — e, para os scripts que executa, imprime um aviso pedindo que você salve o arquivo de novo como UTF-8:
| O arquivo está em | O que acontece |
|---|---|
| UTF-8 com BOM | O BOM é removido. |
| UTF-16 ou UTF-32 com BOM | Convertido para UTF-8. Um arquivo que não decodifica falha ao carregar. |
| UTF-8 inválido (ANSI) | Lido como Windows-1252 e convertido para UTF-8, então os literais de string acentuados mantêm seus caracteres nos dois lados. |
Regras de caminho
Seção intitulada “Regras de caminho”Todo caminho é relativo à pasta do resource e precisa:
- usar
/como separador —\é rejeitado; - não começar com
/; - não conter
..,.ou:, com a única exceção do:resource/inicial de uma entrada emprestada.
Além da validação textual, o servidor resolve o caminho canônico e rejeita qualquer entrada explícita que termine fora da raiz do resource — inclusive por meio de um link simbólico.
As listas aceitam curingas no estilo FiveM:
| Padrão | Significado |
|---|---|
* | Qualquer coisa dentro de um segmento do caminho. |
** | Qualquer coisa, atravessando pastas. |
client_files = { "client/*.lua", -- só os .lua direto em client/ "client/**/*.lua", -- todos os .lua em client/ e subpastas}
files = { "assets/**/*.png", "fonts/*.ttf",}Detalhes que importam:
- A comparação não diferencia maiúsculas de minúsculas.
- O resultado é ordenado alfabeticamente, então a ordem de carregamento dos scripts é estável.
- Caminhos repetidos por padrões sobrepostos (
*.pnge**/*.png) são deduplicados, mantendo a primeira ocorrência. - Um glob que não encontra nada expande para nada — isso não é erro.
- O próprio
mtaxmanifest.luanunca é incluído por um glob. - A expansão não segue links simbólicos; arquivos e diretórios ligados são ignorados pelo glob.
Pegando emprestado de outro resource
Seção intitulada “Pegando emprestado de outro resource”Uma entrada que começa com : aponta para um arquivo que mora na pasta de outro resource:
shared_files = { ":core/lib/class.lua", -- o arquivo pertence ao resource "core" "shared/util.lua", -- este é nosso}
files = { ":brand/assets/**/*.png", -- todos os png que o resource "brand" tem em assets/}O formato é ":<resource>/<caminho>" — o nome do resource, depois um caminho relativo à pasta dele. É aceito em server_files, client_files, shared_files e files.
Declarar já é a permissão inteira. O outro resource não precisa autorizar, não precisa estar rodando e não é avisado — exatamente como no FiveM. Ele só precisa existir.
O que continua igual
Seção intitulada “O que continua igual”- A separação script/asset vale também atravessando a fronteira: um
.luaemprestado vai em uma lista de scripts, um asset emprestado vai emfiles. - O caminho depois do nome do resource segue as mesmas regras de caminho e aceita os mesmos globs.
- Uma entrada explícita mantém o lugar dela na lista, então a ordem de carregamento é exatamente a escrita. Um glob emprestado expande no lugar, em ordem alfabética.
- Duplicatas são removidas, mantendo a primeira ocorrência.
O que muda
Seção intitulada “O que muda”- Um script emprestado roda na sua VM Lua, não na do dono.
getThisResource()dentro dele é o seu resource, e ele enxerga as globais e o ambiente que o seu resource montou. - Os erros apontam para o dono: o chunk se chama
@<dono>/<caminho>, então o stack trace nomeia o arquivo onde ele realmente mora. - Pegar emprestado não inicia, para nem reinicia o outro resource, e reiniciar o dono não recarrega a cópia que o seu resource está rodando.
map_filesnão pode pegar emprestado. Mapas são lidos direto da sua própria pasta, então a entrada é rejeitada na inicialização em vez de silenciosamente resolver para nada.- Um arquivo emprestado nunca chega ao armazenamento da NUI.
nui://<resource>/endereça os arquivos de um resource só, então umui_pagenão pode apontar para um caminho emprestado e a página não consegue carregar um.
A lista inteira é resolvida depois que todas as pastas de resource foram varridas. Se algo estiver errado, o resource que pediu emprestado é rejeitado e o motivo aparece no console:
| Mensagem | Causa |
|---|---|
malformed cross-resource entry | Falta a /, ou o nome do resource ou o caminho está vazio. |
names a resource that does not exist | Nenhum resource com aquele nome foi encontrado. |
borrowed file does not exist | O caminho explícito não é um arquivo na pasta do dono. Um glob que não encontra nada continua sendo válido. |
map_files cannot borrow from another resource | Uma entrada com : em map_files. |
client_configs cannot borrow from another resource | Uma entrada com : em client_configs. |
Lendo um arquivo emprestado pelo Lua
Seção intitulada “Lendo um arquivo emprestado pelo Lua”Declarar ":outro/<caminho>" também dá aos seus scripts acesso de leitura àquele caminho por fileOpen, loadfile e as funções path*. Só a leitura atravessa a fronteira, e só nos caminhos que você declarou. Veja Alcançando outro resource.
Interface (UI)
Seção intitulada “Interface (UI)”files = { "ui/index.html", "ui/style.css",}
ui_page = "ui/index.html"ui_page aponta o HTML de entrada da interface do resource. Ele precisa estar listado em files e não pode ser um .lua. Errando qualquer uma das duas, o resource é recusado com o motivo impresso no console.
Tudo o que a página carrega — folhas de estilo, scripts, imagens, fontes — também precisa estar em files: essa lista é exatamente o que o jogador baixa. O cliente então serve a página da memória em nui://<resource>/, uma origem por resource.
Dali em diante o script conversa com a página usando sendNuiMessage e registerNuiCallback. Veja o guia de NUI para o modelo inteiro, e as funções de NUI para a referência.
Loadscreen
Seção intitulada “Loadscreen”loadscreen = trueMarca o resource como tela de carregamento: ele é baixado antes de todos os outros. É apenas um sinalizador true/false — o HTML da tela vai em ui_page.
A página de carregamento recebe o progresso do download como uma message com type = "loadProgress", carregando pending e total. Ela é aposentada quando o download inicial termina; reiniciar o resource depois não traz ela de volta.
Segurando a tela por conta própria
Seção intitulada “Segurando a tela por conta própria”loadscreen = trueloadscreen_manual_shutdown = trueCom loadscreen_manual_shutdown = true a tela não é encerrada quando o download termina. Ela fica no ar até um script de cliente chamar o shutdownLoadingScreen — que é como você roda uma introdução, ou espera os seus próprios dados ficarem prontos, antes de deixar o jogador entrar.
É um sinalizador true/false, e só faz algo junto de loadscreen = true. Declarado sozinho, o resource ainda sobe, mas o servidor registra um aviso de que o sinalizador não tem efeito.
Exports
Seção intitulada “Exports”exports = { "getPlayerMoney", "setPlayerMoney",}Declara quais funções o resource oferece a outros resources. Cada nome precisa ser um identificador Lua simples: começar com letra ou _ e continuar apenas com letras, números ou _. Os nomes declarados aparecem em getResourceExportedFunctions e podem ser chamados com call.
Um export só pode ser chamado no mesmo lado em que sua função existe: servidor chama servidor e cliente chama cliente. Com a tabela global exports, use sempre : para que o proxy consuma o argumento implícito corretamente:
local saldo = exports.banco:getSaldo(jogador)Resource parado, função não declarada ou falha na chamada devolve false e registra o motivo no debug.
Informações extras
Seção intitulada “Informações extras”resource_info = { description = "Sistema de contas", type = "gameplay",}Pares de texto livres, lidos por getResourceInfo. As chaves name, version e author são preenchidas automaticamente a partir de resource_name, resource_version e resource_author quando você não as declara aqui.
Exemplo completo
Seção intitulada “Exemplo completo”resource_name = "meu-resource"resource_version = "1.2.0"resource_author = "Minha Equipe"
resource_info = { description = "Exemplo de resource completo",}
server_files = { "server/config.lua", "server/main.lua",}
client_files = { "client/**/*.lua",}
shared_files = { "shared/util.lua",}
files = { "ui/index.html", "assets/**/*.png",}
map_files = { "maps/base.map", { src = "maps/escritorio.map", dimension = 5, interior = 3 },}
ui_page = "ui/index.html"
exports = { "getSomething",}