Módulos e import
Cómo dividir el código Lua de un recurso en módulos dentro de modules/ y reutilizarlos en MY Multiplayer (MYMP) con import.
En MY Multiplayer (MYMP), un módulo es un archivo .lua dentro de la carpeta modules/ de un recurso. No necesita declararse en meta.xml: el servidor los descubre automáticamente, compila cada uno cada vez que inicia el recurso y envía los módulos compartidos y de cliente junto con él.
Dónde se ejecuta cada módulo
modules/server/: se ejecuta solo en el servidor y nunca se envía a los jugadores.modules/client/: se ejecuta solo en el cliente.- Cualquier otra ruta dentro de
modules/: compartido (disponible en ambos lados).
Nombre y resolución de módulos
El nombre de un módulo es su ruta relativa dentro de modules/, sin .lua y sin el prefijo server/ o client/.
| Archivo | Nombre del módulo | Lado |
|---|---|---|
modules/money.lua |
money |
Compartido |
modules/server/main.lua |
main |
Servidor |
modules/client/ui/cart.lua |
ui/cart |
Cliente |
- Prioridad por lado: si un lado tiene un módulo propio con el mismo nombre que uno compartido, gana el módulo específico de ese lado.
- Módulo predeterminado (
main):import "@shop"equivale aimport "@shop/main".
Compartir código devolviendo una tabla
La forma más clara de exponer código consiste en reunir lo que ofrece el módulo en una tabla local y devolverla con return. Quien llama a import recibe esa tabla.
modules/money.lua:
local money = {}
function money.format(value)
return "$" .. value
end
return moneyEn el script que importa:
local money = import "@shop/money"
print(money.format(25))Todo lo declarado como local en el módulo permanece privado dentro de él. Un módulo sin return hace que import devuelva true.
Compartir código mediante globales
Las globales creadas por el módulo pasan a quien lo importó sin filtrarse a otros recursos: import entrega únicamente las globales que el módulo definió.
modules/money.lua:
function formatMoney(value)
return "$" .. value
end
TAX = 0.1En el script que importa:
import "@shop/money"
print(formatMoney(25), TAX)Elegir qué globales importar
Con una lista de nombres antes del identificador, solo llegan las globales indicadas. Si el módulo no define alguna de ellas, import lanza un error.
import { "formatMoney" } "@shop/money"
print(formatMoney(25))
print(TAX)Aquí formatMoney existe, pero TAX no: el segundo print muestra nil.
Ejecución única y estado por recurso
Un módulo se ejecuta una sola vez en cada recurso que lo importa. Importarlo de nuevo dentro del mismo recurso devuelve el mismo resultado almacenado, por lo que el estado del módulo se comparte dentro de ese recurso.
modules/counter.lua:
local count = 0
local counter = {}
function counter.add()
count = count + 1
return count
end
return counterEn el mismo recurso:
local a = import "@shop/counter"
local b = import "@shop/counter"
print(a == b)
print(a.add())
print(b.add())Esto imprime true, 1 y 2, ya que a y b son la misma tabla. Otro recurso que importe @shop/counter vuelve a ejecutar el módulo en su propio estado y mantiene su propia cuenta.
Como el módulo se ejecuta dentro del estado de quien lo importó, variables globales como resourceRoot, además de los eventos y timers que cree, pertenecen al recurso importador. Este módulo, importado por shop, asocia el handler al resourceRoot de shop:
addEvent("onShopBuy", true)
addEventHandler("onShopBuy", resourceRoot, function(item)
print(getPlayerName(client) .. " compró " .. item)
end)Importar desde otro recurso
local accounts = import "@accounts/api"
addEventHandler("onPlayerJoin", root, function()
accounts.load(source)
end)- En el servidor: si el recurso
accountsno está en ejecución,importlo inicia antes automáticamente. - En el cliente: el recurso de destino ya tiene que estar cargado en ese cliente.
Mensajes de error de import
| Mensaje | Causa |
|---|---|
import: "shop/money" is not a module name such as "@resource" or "@resource/module" |
El nombre del módulo no empieza con @. |
import: there is no resource called shop |
En el servidor, no existe un recurso con ese nombre. |
import: shop is not loaded on this client |
En el cliente, el recurso todavía no se cargó. |
import: shop has no module "money" |
El recurso no tiene ningún módulo con ese nombre. |
import: @shop/main is client-only |
El módulo solo existe en el otro lado (aquí, solo en el cliente). |
import: @shop/money does not compile: … |
El módulo contiene un error de sintaxis Lua. |
import: @shop/money is imported again while it runs (an import cycle) |
Ciclo de importación: dos módulos se importan entre sí al iniciarse. |
import: @shop/money defines no "TAXES" |
Un nombre de la lista { … } no corresponde a una global del módulo. |