# Создание многопользовательских модов

## Структура папок и основы файлов

Базовая структура папок и файлов должна выглядеть следующим образом:

```
Resources/
├─ Client/
│  └─ examplePlugin.zip/
│     ├─ scripts/
│     │  └─ modScript.lua
│     └─ lua/
│        └─ ge/
│           └─ extensions/
│              └─ examplePlugin.lua
└─ Server/
   └─ examplePlugin/
      ├─ examplePlugin.lua
      └─ further_lua/
         └─ further.lua
```

Серверный lua — это необходимый минимум, если вы хотите добавлять пользовательские события, вам также понадобится как минимум клиентский lua, а также modscript.lua

Папка Server должна содержать подпапки, по одной для каждого серверного мода. Хорошей практикой является наличие только одного основного файла lua и добавление дополнительных файлов lua в подпапки. Однако вам не обязательно это делать, сервер загрузит файлы lua в алфавитном порядке, если их несколько.

Папка Client содержит zip-файлы, которые отправляются клиенту, который затем загружает их как мод. Любые другие файлы в папке Client вызовут ошибку при запуске сервера, но за исключением этого будут игнорироваться сервером. ModScript.lua будет прочитан BeamNG и укажет игре, какой плагин загружать.

!!!example "" [Загрузите examplePlugin.zip](../../../../assets/content/ResourcesForExamplePlugin.zip)

## Серверный lua

В examplePlugin есть и другие примеры, но вот самый простой, выводящий идентификаторы игроков:

```lua
function onInit() --runs when plugin is loaded

	MP.RegisterEvent("onPlayerAuth", "onPlayerAuth") --Provided by BeamMP

	print("examplePlugin loaded")
end

--A player has authenticated and is requesting to join
--The player's name (string), forum role (string), guest account (bool), identifiers (table -> ip, beammp)
function onPlayerAuth(player_name, role, isGuest, identifiers)
	local ip = identifiers.ip
	local beammp = identifiers.beammp or "N/A"
	print("onPlayerAuth: player_name: " .. player_name .. " | role: " .. role .. " | isGuest: " .. tostring(isGuest) .. " | identifiers: ip: " .. ip .. " - beammp: " .. beammp)
end
```

`onPlayerAuth` срабатывает, как только игрок хочет присоединиться, см. также [onPlayerAuth в справочнике по скриптам](../../../scripting/server/latest-server-reference/#onplayerauth)

Еще один пример использования onPlayerAuth, но он запретит гостям присоединяться к серверу, отправив клиенту ответное сообщение, которое затем будет показано игроку:

```lua
function onPlayerAuth(playerName, playerRole, isGuest, identifiers)
  if isGuest then
    return "No guests allowed, please use a BeamMP account"
  end
end
```

Дополнительную информацию о серверных функциях, предоставляемых BeamMP, можно найти в [последнем справочнике по серверу](../../../scripting/server/latest-server-reference.md)

## Клиентская часть lua

Это в значительной степени соответствует [расширениям BeamNG](https://documentation.beamng.com/modding/programming/extensions/)

```lua
local M = {}

if extensions.isExtensionLoaded("examplePlugin") then
  log("E", "examplePlugin", "examplePlugin loaded on client side")
  return
end

return M
```

Выводит на консоль информацию о том, что examplePlugin был загружен

Более подробную информацию см. в [документации BeamNG по отладочным распечаткам](https://documentation.beamng.com/modding/programming/debugging/#a-add-a-log)

## modScript.lua

Обычно содержит только две строки

```lua
load('examplePlugin')
setExtensionUnloadMode('examplePlugin', 'manual')
```

Вы можете добавить вывод журнала, если хотите видеть в журналах, когда ваш modScript обрабатывается BeamNG

```lua
load('examplePlugin')
setExtensionUnloadMode('examplePlugin', 'manual')
log('I', 'modScript', "examplePlugin loaded")
```
