# Módulos e import

> Como organizar o código Lua de um recurso em módulos dentro de modules/ e reaproveitá-los no MY Multiplayer (MYMP) com import.

- **Plataforma**: MY Multiplayer (MYMP) — Lua 5.4
- **Seções**: Documentação › Primeiros passos
- **Idioma**: Português
- **URL**: https://wiki.mymp.gg/pt/docs/modules

No **MY Multiplayer** (**MYMP**), um **módulo** é um arquivo `.lua` dentro da pasta `modules/` de um [recurso](https://wiki.mymp.gg/pt/docs/resources.md). Ele não precisa ser declarado no `meta.xml`: o servidor encontra todos os arquivos automaticamente, compila cada um a cada início do recurso e envia os módulos compartilhados e de cliente junto com ele.

```text
shop/
└── modules/
    ├── money.lua           compartilhado · nome money
    ├── counter.lua         compartilhado · nome counter
    ├── server/
    │   └── main.lua        só no servidor · nome main
    └── client/
        └── ui/
            └── cart.lua    só no cliente · nome ui/cart
```

## Onde cada módulo roda

- `modules/server/`: executa apenas no servidor e nunca é enviado aos jogadores.
- `modules/client/`: executa apenas no cliente.
- Qualquer outro caminho dentro de `modules/`: compartilhado (disponível nos dois lados).

## Nome e resolução de um módulo

O nome do módulo é o seu caminho relativo dentro de `modules/`, sem a extensão `.lua` e sem o prefixo `server/` ou `client/`.

| Arquivo                      | Nome do módulo | Lado          |
| ---------------------------- | -------------- | ------------- |
| `modules/money.lua`          | `money`        | Compartilhado |
| `modules/server/main.lua`    | `main`         | Servidor      |
| `modules/client/ui/cart.lua` | `ui/cart`      | Cliente       |

- **Precedência por lado**: se um lado tiver um módulo próprio com o mesmo nome de um módulo compartilhado, o módulo específico daquele lado vence.
- **Módulo padrão (`main`)**: chamar `import "@shop"` equivale a `import "@shop/main"`.

## Compartilhar código devolvendo uma tabela

A forma mais explícita de expor funcionalidades é agrupar funções e valores em uma tabela local e devolvê-la com `return`. Quem chama `import` recebe essa tabela.

`modules/money.lua`:

```lua
local money = {}

function money.format(value)
    return "$" .. value
end

return money
```

Uso no script importador:

```lua
local money = import "@shop/money"

print(money.format(25))
```

Variáveis declaradas com `local` permanecem privadas ao módulo. Quando um módulo não executa `return`, `import` devolve `true`.

## Compartilhar código por variáveis globais

As variáveis globais criadas pelo módulo são entregues ao ambiente de quem o importou, sem vazar para outros recursos: `import` transfere apenas as globais definidas pelo módulo.

`modules/money.lua`:

```lua
function formatMoney(value)
    return "$" .. value
end

TAX = 0.1
```

Uso no script importador:

```lua
import "@shop/money"

print(formatMoney(25), TAX)
```

### Escolher quais globais importar

Passando uma lista de nomes antes do identificador do módulo, apenas as globais listadas são trazidas. Se o módulo não definir algum dos nomes pedidos, `import` lança um erro.

```lua
import { "formatMoney" } "@shop/money"

print(formatMoney(25))
print(TAX)
```

Nesse exemplo, `formatMoney` fica disponível, mas `TAX` não: o segundo `print` exibe `nil`.

## Execução única e estado por recurso

Um módulo executa **apenas uma vez** dentro de cada recurso que o importa. Importá-lo novamente no mesmo recurso devolve o mesmo resultado em cache, de modo que o estado interno é compartilhado entre scripts daquele recurso.

`modules/counter.lua`:

```lua
local count = 0
local counter = {}

function counter.add()
    count = count + 1
    return count
end

return counter
```

Uso no mesmo recurso:

```lua
local a = import "@shop/counter"
local b = import "@shop/counter"

print(a == b)
print(a.add())
print(b.add())
```

Isso imprime `true`, `1` e `2`, pois `a` e `b` apontam para a mesma tabela. Se outro recurso importar `@shop/counter`, o módulo será executado novamente no estado daquele outro recurso, com sua própria contagem independente.

Como o módulo roda dentro do estado de quem o importou, [variáveis globais](https://wiki.mymp.gg/pt/docs/globals.md) como `resourceRoot`, além dos eventos e timers criados por ele, pertencem ao recurso importador. Este módulo, quando importado pelo recurso `shop`, registra o handler no `resourceRoot` de `shop`:

```lua
addEvent("onShopBuy", true)

addEventHandler("onShopBuy", resourceRoot, function(item)
    print(getPlayerName(client) .. " comprou " .. item)
end)
```

## Importar de outro recurso

```lua
local accounts = import "@accounts/api"

addEventHandler("onPlayerJoin", root, function()
    accounts.load(source)
end)
```

- **No servidor**: se o recurso `accounts` não estiver em execução, `import` o inicia automaticamente antes de carregar o módulo.
- **No cliente**: o recurso alvo já precisa estar carregado naquele cliente.

## Mensagens de erro do import

| Mensagem                                                                              | Causa                                                              |
| ------------------------------------------------------------------------------------- | ------------------------------------------------------------------ |
| `import: "shop/money" is not a module name such as "@resource" or "@resource/module"` | O identificador do módulo não começa com `@`.                      |
| `import: there is no resource called shop`                                            | No servidor, não existe recurso com esse nome.                     |
| `import: shop is not loaded on this client`                                           | No cliente, o recurso ainda não foi carregado.                     |
| `import: shop has no module "money"`                                                  | O recurso não possui um módulo com esse nome.                      |
| `import: @shop/main is client-only`                                                   | O módulo existe apenas no outro lado (neste caso, só no cliente).  |
| `import: @shop/money does not compile: …`                                             | O arquivo do módulo contém erro de sintaxe Lua.                    |
| `import: @shop/money is imported again while it runs (an import cycle)`               | Ciclo de importação: dois módulos importam um ao outro ao iniciar. |
| `import: @shop/money defines no "TAXES"`                                              | Um nome pedido na lista `{ … }` não foi definido como global.      |
