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.
No MY Multiplayer (MYMP), um módulo é um arquivo .lua dentro da pasta modules/ de um recurso. 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.
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): chamarimport "@shop"equivale aimport "@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:
local money = {}
function money.format(value)
return "$" .. value
end
return moneyUso no script importador:
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:
function formatMoney(value)
return "$" .. value
end
TAX = 0.1Uso no script importador:
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.
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:
local count = 0
local counter = {}
function counter.add()
count = count + 1
return count
end
return counterUso no mesmo recurso:
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 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:
addEvent("onShopBuy", true)
addEventHandler("onShopBuy", resourceRoot, function(item)
print(getPlayerName(client) .. " comprou " .. item)
end)Importar de outro recurso
local accounts = import "@accounts/api"
addEventHandler("onPlayerJoin", root, function()
accounts.load(source)
end)- No servidor: se o recurso
accountsnão estiver em execução,importo 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. |