# Modules and import

> How to split a resource's Lua code into modules under modules/ and reuse them across MY Multiplayer (MYMP) resources using import.

- **Platform**: MY Multiplayer (MYMP) — Lua 5.4
- **Sections**: Documentation › Getting started
- **Language**: English
- **URL**: https://wiki.mymp.gg/en/docs/modules

In **MY Multiplayer** (**MYMP**), a **module** is a `.lua` file inside a [resource](https://wiki.mymp.gg/en/docs/resources.md)'s `modules/` folder. It does not need to be listed in `meta.xml`: the server discovers every module automatically, compiles each one whenever the resource starts and sends shared and client modules to players along with the resource.

```text
shop/
└── modules/
    ├── money.lua           shared · name money
    ├── counter.lua         shared · name counter
    ├── server/
    │   └── main.lua        server only · name main
    └── client/
        └── ui/
            └── cart.lua    client only · name ui/cart
```

## Where each module runs

- `modules/server/`: runs on the server only and is never sent to players.
- `modules/client/`: runs on the client only.
- Anywhere else inside `modules/`: shared (available on both sides).

## Module naming and resolution

A module's name is its relative path inside `modules/`, without `.lua` and without a leading `server/` or `client/`.

| File                         | Module name | Side   |
| ---------------------------- | ----------- | ------ |
| `modules/money.lua`          | `money`     | Shared |
| `modules/server/main.lua`    | `main`      | Server |
| `modules/client/ui/cart.lua` | `ui/cart`   | Client |

- **Side precedence**: if a side has its own module with the same name as a shared one, that side's module wins.
- **Default `main` module**: `import "@shop"` is shorthand for `import "@shop/main"`.

## Sharing code by returning a table

The clearest pattern is to gather exported functions and values into a local table and `return` it. The caller receives that table from `import`.

`modules/money.lua`:

```lua
local money = {}

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

return money
```

Importing script:

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

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

Anything declared `local` inside the module stays private to it. A module with no `return` makes `import` return `true`.

## Sharing code through globals

Globals defined by a module are copied into the importing resource's environment without leaking anywhere else: `import` hands over only the globals the module defined.

`modules/money.lua`:

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

TAX = 0.1
```

Importing script:

```lua
import "@shop/money"

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

### Selecting specific globals

Passing a table of names before the module path imports only those listed globals. If the module does not define one of them, `import` raises an error.

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

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

Here `formatMoney` is imported while `TAX` is not: the second `print` outputs `nil`.

## Single execution per importing resource

A module runs **only once** inside each resource that imports it. Importing it again within the same resource returns the cached result, so state kept inside the module is shared across that resource's scripts.

`modules/counter.lua`:

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

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

return counter
```

Within the same resource:

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

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

This prints `true`, `1` and `2` because `a` and `b` reference the same table. Another resource that imports `@shop/counter` runs the module in its own Lua state and keeps an independent count.

Because a module runs inside the importer's state, [global variables](https://wiki.mymp.gg/en/docs/globals.md) such as `resourceRoot`, as well as any events and timers the module creates, belong to that importing resource. When imported by `shop`, this module attaches the handler to `shop`'s `resourceRoot`:

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

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

## Importing from another resource

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

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

- **On the server**: if the `accounts` resource is not running, `import` starts it first.
- **On the client**: the target resource must already be loaded on that client.

## Errors raised by import

| Message                                                                               | Cause                                                           |
| ------------------------------------------------------------------------------------- | --------------------------------------------------------------- |
| `import: "shop/money" is not a module name such as "@resource" or "@resource/module"` | The module specifier does not start with `@`.                   |
| `import: there is no resource called shop`                                            | On the server, no resource exists with that name.               |
| `import: shop is not loaded on this client`                                           | On a client, the target resource has not been loaded yet.       |
| `import: shop has no module "money"`                                                  | The resource has no module with that name.                      |
| `import: @shop/main is client-only`                                                   | The module only exists on the other side (here, client-only).   |
| `import: @shop/money does not compile: …`                                             | The module file has a Lua syntax error.                         |
| `import: @shop/money is imported again while it runs (an import cycle)`               | Circular import: two modules import each other during startup.  |
| `import: @shop/money defines no "TAXES"`                                              | A name in the `{ … }` list is not a global defined by the file. |
