Ресурсы и Lua-скрипты MTA:SA — установка и настройка
Ресурсы и Lua-скрипты составляют основу любого сервера Multi Theft Auto: San Andreas. Через них добавляются авторизация, персонажи, работы, транспорт, карты, интерфейсы, административные команды, экономика, инвентарь и другие игровые системы.
Чтобы правильно установить ресурс на MTA:SA Server, недостаточно просто скопировать Lua-файл. Каждый ресурс должен иметь собственную папку или ZIP-архив, обязательный файл meta.xml и корректно указанные серверные, клиентские и общие скрипты.
В этой инструкции разобраны установка готовых ресурсов, создание простого Lua-скрипта, настройка meta.xml, запуск через серверную консоль, автозагрузка вместе с MTA Server, зависимости, права ACL и поиск распространённых ошибок.
Установка серверной программы:
Основные параметры сервера:
Что такое ресурс MTA:SA
Ресурс — это самостоятельный компонент сервера MTA. Он представляет собой папку или ZIP-архив, внутри которого находится файл meta.xml и связанные с ним материалы.
Один ресурс может выполнять небольшую функцию, например выводить приветственное сообщение. Другой ресурс способен содержать полноценный игровой режим с сотнями Lua-файлов, интерфейсами, моделями и подключением к базе данных.
Примеры ресурсов
- система регистрации и авторизации;
- создание игрового персонажа;
- панель администратора;
- таблица игроков;
- спидометр;
- инвентарь;
- автосалон;
- работа таксиста;
- система организаций;
- загрузка карты;
- замена моделей автомобилей;
- подключение к MySQL;
- полноценный Role Play режим.
Состояния ресурса
Ресурс может находиться в одном из основных состояний:
- не обнаружен — сервер ещё не просканировал его папку;
- загружен — ресурс найден, но не запущен;
- запущен — выполняются его Lua-скрипты;
- остановлен — выполнение прекращено;
- ошибка — ресурс не может загрузить
meta.xml, скрипт или зависимость.
Одновременно на сервере могут работать десятки или сотни ресурсов. Они могут обмениваться данными через экспортированные функции, события и общие элементы MTA.
Где находятся ресурсы MTA Server
Ресурсы выделенного сервера размещаются в каталоге:
mods/deathmatch/resources/
Пример пути на Windows
C:\MTA-Server\mods\deathmatch\resources\
При установке серверного компонента вместе с клиентом путь может выглядеть так:
C:\Program Files (x86)\MTA San Andreas 1.6\server\mods\deathmatch\resources\
Пример пути на Linux
/home/mtasa/mta-server/mods/deathmatch/resources/
Группировка ресурсов
Для удобства ресурсы можно распределять по тематическим каталогам:
resources/
├── [core]/
├── [accounts]/
├── [vehicles]/
├── [jobs]/
├── [maps]/
└── [admin]/
Внутри каждой группы находятся отдельные ресурсы:
resources/
└── [core]/
├── database/
│ ├── meta.xml
│ └── server.lua
├── accounts/
│ ├── meta.xml
│ ├── server.lua
│ └── client.lua
└── inventory/
├── meta.xml
└── server.lua
Название группирующей папки обычно заключают в квадратные скобки. Такая папка помогает навести порядок, но сама не является игровым ресурсом.
В каком формате устанавливаются ресурсы
MTA Server поддерживает два основных варианта хранения ресурсов.
Обычная папка
resources/
└── my_resource/
├── meta.xml
├── server.lua
└── client.lua
Папка удобна для разработки, редактирования и поиска ошибок. Изменённые файлы можно сразу сохранить и перезапустить ресурс.
ZIP-архив
resources/
└── my_resource.zip
В корне архива должен находиться meta.xml:
my_resource.zip
├── meta.xml
├── server.lua
└── client.lua
Что лучше выбрать
| Вариант | Преимущества | Недостатки |
|---|---|---|
| Папка | Легко редактировать, тестировать и сравнивать файлы. | Занимает больше места в списке каталогов. |
| ZIP | Удобно переносить и распространять. | Для изменения обычно требуется повторная упаковка. |
Во время разработки используйте обычную папку. ZIP-архив удобнее для распространения законченного ресурса.
Как правильно назвать ресурс
Используйте короткое техническое название латинскими буквами:
database
accounts
character_creator
vehicle_system
taxi_job
miami_hud
Рекомендуется
- использовать латинские буквы;
- разделять слова символом подчёркивания;
- использовать нижний регистр;
- выбирать понятное назначение;
- сохранять одно название во всех зависимостях и экспортах.
Не рекомендуется
Мой скрипт
vehicle.system
new resource
ресурс-авто
script!!!
Названия ресурсов не должны содержать точки. Также лучше избегать пробелов, кириллицы и необычных специальных символов.
Почему название важно
Оно используется:
- в командах
start,stopиrestart; - в строках автозапуска;
- в экспортах функций;
- в зависимостях
include; - в правах ACL;
- в серверных журналах;
- в путях к файлам.
Правильная структура папок ресурса
У небольшого ресурса может быть простая структура:
hello_resource/
├── meta.xml
├── server.lua
└── client.lua
У крупного проекта файлы лучше распределить по назначению:
vehicle_system/
├── meta.xml
├── shared/
│ ├── config.lua
│ └── vehicle_names.lua
├── server/
│ ├── database.lua
│ ├── commands.lua
│ └── vehicles.lua
├── client/
│ ├── interface.lua
│ ├── speedometer.lua
│ └── handling.lua
├── assets/
│ ├── images/
│ │ └── speedometer.png
│ ├── models/
│ │ ├── vehicle.dff
│ │ └── vehicle.txd
│ └── sounds/
│ └── engine.mp3
└── config/
└── settings.xml
Назначение основных файлов
| Файл или каталог | Назначение |
|---|---|
meta.xml |
Описывает содержимое и порядок загрузки ресурса. |
server.lua |
Выполняется только на сервере. |
client.lua |
Отправляется игрокам и выполняется на их компьютерах. |
shared.lua |
Выполняется отдельно на сервере и у клиентов. |
assets |
Изображения, звуки, модели и другие клиентские файлы. |
config |
Настройки ресурса. |
Все файлы, которые MTA должен загрузить или отправить игрокам, необходимо правильно указать в meta.xml.
Как установить готовый ресурс на MTA Server
Шаг 1. Создайте резервную копию
Перед установкой ресурса на действующий сервер сохраните:
- папку текущей сборки;
mtaserver.conf;acl.xml;- базу данных;
- заменяемый ресурс;
- файлы настроек.
Шаг 2. Распакуйте архив отдельно
Не распаковывайте неизвестный архив сразу в рабочую папку. Сначала откройте его в отдельном каталоге и найдите meta.xml.
Шаг 3. Проверьте содержимое
Изучите:
- серверные Lua-файлы;
- подключение к MySQL;
- внешние адреса;
- команды
fetchRemote; - запрашиваемые права ACL;
- DLL- и SO-модули;
- зависимости;
- файл с инструкцией.
Шаг 4. Скопируйте ресурс
Переместите папку в:
mods/deathmatch/resources/
Например:
mods/deathmatch/resources/vehicle_system/
Шаг 5. Обновите список ресурсов
В серверной консоли выполните:
refresh
Шаг 6. Проверьте информацию
info vehicle_system
Шаг 7. Запустите ресурс
start vehicle_system
Шаг 8. Проверьте консоль
После запуска обратите внимание на:
- ошибки чтения
meta.xml; - не найденные файлы;
- ошибки синтаксиса Lua;
- отсутствующие зависимости;
- отказ в правах ACL;
- ошибки подключения к базе;
- предупреждения совместимости.
Двойная вложенность папок ресурса
Одна из самых распространённых ошибок возникает после распаковки архива.
Неправильно
resources/
└── vehicle_system/
└── vehicle_system/
├── meta.xml
├── server.lua
└── client.lua
Внешняя папка не содержит meta.xml, поэтому MTA не распознаёт её как ресурс.
Правильно
resources/
└── vehicle_system/
├── meta.xml
├── server.lua
└── client.lua
Как исправить
- Остановите сервер или ресурс.
- Откройте внешнюю папку.
- Переместите содержимое внутренней папки на один уровень выше.
- Удалите пустой вложенный каталог.
- Выполните
refresh. - Повторите команду запуска.
Как создать первый ресурс MTA
Создайте папку:
mods/deathmatch/resources/hello_resource/
Внутри создайте три файла:
hello_resource/
├── meta.xml
├── server.lua
└── client.lua
Файл meta.xml
<meta>
<info
author="Server Team"
name="Hello Resource"
description="Пример простого ресурса MTA"
type="script"
version="1.0.0"
/>
<script src="server.lua" type="server" />
<script src="client.lua" type="client" cache="false" />
</meta>
После сохранения файлов выполните:
refresh
start hello_resource
Пример серверного Lua-скрипта
Содержимое файла server.lua:
local RESOURCE_NAME = getResourceName(getThisResource())
addEventHandler("onResourceStart", resourceRoot,
function()
outputDebugString(
"[" .. RESOURCE_NAME .. "] Ресурс успешно запущен.",
3
)
end
)
addEventHandler("onResourceStop", resourceRoot,
function()
outputDebugString(
"[" .. RESOURCE_NAME .. "] Ресурс остановлен.",
3
)
end
)
addCommandHandler("hello",
function(player)
if not isElement(player) then
outputDebugString(
"[" .. RESOURCE_NAME .. "] Команда вызвана из консоли.",
3
)
return
end
outputChatBox(
"Привет! Серверный Lua-ресурс работает.",
player,
80,
220,
140
)
end
)
Что выполняет код
- получает название текущего ресурса;
- записывает сообщение при запуске;
- записывает сообщение при остановке;
- создаёт серверную команду
/hello; - отправляет сообщение игроку.
Серверный Lua-файл не скачивается игрокам. В нём должны находиться важная игровая логика, работа с базой данных, начисление денег и проверка прав.
Пример клиентского Lua-скрипта
Содержимое файла client.lua:
addEventHandler("onClientResourceStart", resourceRoot,
function()
outputChatBox(
"Клиентская часть ресурса загружена.",
80,
180,
255
)
end
)
addCommandHandler("screen",
function()
local width, height = guiGetScreenSize()
outputChatBox(
"Разрешение экрана: "
.. tostring(width)
.. "x"
.. tostring(height),
255,
255,
255
)
end
)
Клиентская сторона используется для
- отрисовки интерфейсов;
- работы с камерой;
- получения разрешения экрана;
- замены моделей и текстур;
- воспроизведения звуков;
- локальных визуальных эффектов;
- обработки клавиш;
- работы со встроенным браузером.
Что такое shared-скрипт
Общий файл подключается так:
<script src="shared/config.lua" type="shared" cache="false" />
Он выполняется два раза:
- один раз на стороне сервера;
- отдельно на стороне каждого клиента.
Пример shared/config.lua
PROJECT_NAME = "Miami Role Play"
VEHICLE_LIMITS = {
player = 3,
premium = 6
}
INTERFACE_SETTINGS = {
scale = 1.0,
language = "ru"
}
В shared-файл можно помещать
- названия и идентификаторы;
- общие таблицы конфигурации;
- простые вспомогательные функции;
- настройки интерфейса;
- данные, которые не являются секретными.
В shared-файл нельзя помещать
- пароль MySQL;
- секретные токены;
- скрытые административные ключи;
- алгоритмы, которым клиент не должен доверять;
- данные сторонних API;
- важную проверку экономики.
Shared-код является одновременно клиентским. Параметр cache="false" не превращает его в секретный серверный файл.
Для чего нужен файл meta.xml
meta.xml сообщает серверу, какие файлы относятся к ресурсу и как именно их необходимо загружать.
Через него можно указать:
- название и автора ресурса;
- серверные Lua-скрипты;
- клиентские Lua-скрипты;
- общие скрипты;
- изображения, модели и звуки;
- карты;
- конфигурационные XML-файлы;
- экспортируемые функции;
- зависимости от других ресурсов;
- настраиваемые параметры;
- минимальную версию MTA;
- запрашиваемые права ACL.
Минимальный meta.xml
<meta>
<script src="server.lua" type="server" />
</meta>
Расширенный пример
<meta>
<info
author="Server Team"
name="Vehicle System"
description="Система транспорта"
type="script"
version="1.0.0"
/>
<script src="shared/config.lua" type="shared" cache="false" />
<script src="server/database.lua" type="server" />
<script src="server/vehicles.lua" type="server" />
<script src="client/interface.lua" type="client" cache="false" />
<file src="assets/images/speedometer.png" />
<file src="assets/sounds/engine.mp3" />
<config src="config/settings.xml" type="server" />
<export function="getPlayerVehicles" type="server" />
<include resource="database" />
<min_mta_version both="1.6.0-9.22279.0" />
</meta>
Тег info в meta.xml
Блок info содержит справочную информацию:
<info
author="Server Team"
version="1.2.0"
name="Inventory System"
description="Инвентарь игрового сервера"
type="script"
/>
Основные атрибуты
| Атрибут | Назначение |
|---|---|
author |
Автор или команда разработчиков. |
version |
Версия ресурса. |
name |
Отображаемое название. |
description |
Краткое описание. |
type |
Тип: script, gamemode, map или misc. |
Техническое название ресурса определяется именем папки. Атрибут name внутри info является отображаемым названием и может отличаться.
Подключение Lua-файлов через script
Серверный скрипт
<script src="server.lua" type="server" />
Клиентский скрипт
<script src="client.lua" type="client" />
Общий скрипт
<script src="shared.lua" type="shared" />
Клиентский файл без постоянного кэша
<script
src="client/interface.lua"
type="client"
cache="false"
/>
Порядок подключения
Файлы, содержащие общие функции и конфигурацию, указывайте раньше зависимых скриптов:
<script src="shared/config.lua" type="shared" cache="false" />
<script src="shared/utils.lua" type="shared" cache="false" />
<script src="server/database.lua" type="server" />
<script src="server/main.lua" type="server" />
<script src="client/interface.lua" type="client" cache="false" />
<script src="client/main.lua" type="client" cache="false" />
Что делает cache="false"
Параметр запрещает постоянное сохранение клиентского Lua-файла на диске обычным способом. Однако код всё равно передаётся и выполняется на компьютере игрока.
Поэтому cache="false" не защищает:
- пароли;
- ключи API;
- важную бизнес-логику;
- секретные проверки;
- серверную экономику.
Подключение изображений, звуков и моделей
Клиентские материалы указываются тегом file:
<file src="assets/images/logo.png" />
<file src="assets/sounds/click.mp3" />
<file src="assets/models/vehicle.txd" />
<file src="assets/models/vehicle.dff" />
<file src="assets/models/vehicle.col" />
Файл с отложенной загрузкой
<file
src="assets/models/large_vehicle.dff"
download="false"
/>
Такой файл не загружается автоматически при запуске ресурса. Клиентский скрипт может запросить его позднее через downloadFile.
Пример отложенной загрузки
local FILE_PATH = "assets/models/large_vehicle.dff"
addEventHandler("onClientResourceStart", resourceRoot,
function()
downloadFile(FILE_PATH)
end
)
addEventHandler("onClientFileDownloadComplete", resourceRoot,
function(fileName, success)
if fileName ~= FILE_PATH then
return
end
if success then
outputDebugString(
"Файл модели загружен: " .. fileName,
3
)
else
outputDebugString(
"Не удалось загрузить: " .. fileName,
1
)
end
end
)
Типичные причины ошибки скачивания
- файл не указан в
meta.xml; - путь содержит опечатку;
- на Linux не совпадает регистр букв;
- закрыт HTTP-порт сервера;
- внешний HTTP-сервер не синхронизирован;
- ресурс не был перезапущен после изменения;
- клиент получил старую версию файлов.
Подключение карты и конфигурационного файла
Карта MTA
<map src="maps/miami_city.map" />
Карта в отдельном измерении
<map src="maps/interior.map" dimension="10" />
Серверная конфигурация XML
<config src="config/settings.xml" type="server" />
Клиентская конфигурация
<config src="config/interface.xml" type="client" />
Пример settings.xml
<settings>
<vehicle-limit>3</vehicle-limit>
<starting-money>5000</starting-money>
<language>ru</language>
</settings>
Если ресурс изменяет XML-файл и сохраняет в него данные во время работы, такой изменяемый файл не следует распространять как обычный постоянный файл из meta.xml. Лучше создавать его программно при первом запуске.
Экспорт функций между ресурсами
Экспорт позволяет одному ресурсу вызывать функцию другого.
Функция в server.lua
function getProjectName()
return "Miami Role Play"
end
Экспорт в meta.xml
<export
function="getProjectName"
type="server"
/>
Вызов из другого серверного ресурса
local projectName = exports.server_core:getProjectName()
outputDebugString(
"Название проекта: " .. tostring(projectName),
3
)
Типы экспорта
server— доступен серверным Lua-файлам;client— доступен клиентским Lua-файлам;shared— экспорт создаётся отдельно для обеих сторон.
Перед вызовом проверьте зависимость
local databaseResource = getResourceFromName("database")
if not databaseResource
or getResourceState(databaseResource) ~= "running" then
outputDebugString(
"Ресурс database не запущен.",
1
)
return
end
Зависимости через include
Если ресурс не может работать без другого ресурса, зависимость можно указать в meta.xml:
<include resource="database" />
Зависимость с минимальной версией
<include
resource="server_core"
minversion="1.2.0"
/>
Пример
<meta>
<include resource="database" />
<include resource="server_core" />
<script src="server.lua" type="server" />
</meta>
При запуске зависимого ресурса MTA попытается обеспечить работу включённых ресурсов. Если обязательная зависимость отсутствует или содержит ошибку, основной ресурс может не запуститься корректно.
Не создавайте циклические зависимости
Плохо:
accounts включает characters
characters включает accounts
Лучше вынести общие функции в отдельный ресурс:
server_core
├── accounts
└── characters
Настраиваемые параметры ресурса
Блок settings позволяет объявить параметры, которые серверный администратор сможет изменять через систему настроек MTA.
<settings>
<setting
name="*startingMoney"
value="5000"
friendlyname="Стартовые деньги"
accept="positive number"
desc="Сумма, выдаваемая новому игроку"
/>
<setting
name="*registrationEnabled"
value="true"
friendlyname="Разрешить регистрацию"
accept="true,false"
/>
</settings>
Получение параметра в Lua
local startingMoney = tonumber(
get("*startingMoney")
) or 5000
local registrationEnabled =
get("*registrationEnabled") == true
or get("*registrationEnabled") == "true"
Когда использовать settings
- для простых параметров режима;
- для лимитов;
- для включения и отключения функций;
- для названий и сообщений;
- для параметров, доступных администратору.
Пароли MySQL и другие секреты лучше не размещать в публично доступных настройках ресурса.
Минимальная версия MTA для ресурса
Ресурс может потребовать определённую версию клиента или сервера:
<min_mta_version both="1.6.0-9.22279.0" />
Только сервер
<min_mta_version server="1.6.0-9.22279.0" />
Клиент и сервер отдельно
<min_mta_version
server="1.6.0-9.22279.0"
client="1.6.0-9.22279.0"
/>
Указывайте минимальную версию, на которой ресурс действительно был проверен. Не копируйте случайный номер сборки из чужого проекта.
Команды управления ресурсами MTA
Обнаружить новый ресурс
refresh
Команда повторно сканирует папку ресурсов и находит новые элементы.
Обновить изменённые ресурсы
refreshall
Команда обновляет ресурсы и перезапускает те, в которых были обнаружены изменения. На рабочем сервере она может вызвать кратковременную остановку нескольких систем.
Показать список
list
Получить информацию
info vehicle_system
Запустить
start vehicle_system
Остановить
stop vehicle_system
Перезапустить
restart vehicle_system
Остановить все ресурсы
stopall
Проверить план обновления
check vehicle_system
Команда check относится к механизму обновления ресурсов и показывает изменения, которые могла бы выполнить команда upgrade. Она не заменяет проверку синтаксиса Lua.
Получить список серверных команд
help
Автоматический запуск ресурса вместе с сервером
Откройте файл:
mods/deathmatch/mtaserver.conf
Перед закрывающим тегом </config> добавьте:
<resource
src="vehicle_system"
startup="1"
protected="0"
/>
Основные параметры
| Параметр | Назначение |
|---|---|
src |
Точное название ресурса. |
startup="1" |
Запустить вместе с MTA Server. |
startup="0" |
Не запускать автоматически. |
protected="1" |
Защитить работающий ресурс от обычной остановки. |
protected="0" |
Разрешить остановку командой. |
Пример правильного порядка
<resource src="database" startup="1" protected="1" />
<resource src="server_core" startup="1" protected="1" />
<resource src="accounts" startup="1" protected="0" />
<resource src="characters" startup="1" protected="0" />
<resource src="inventory" startup="1" protected="0" />
<resource src="vehicles" startup="1" protected="0" />
<resource src="roleplay" startup="1" protected="0" />
Сначала запускаются базы, библиотеки и общие системы, а затем зависимые игровые ресурсы.
Как правильно обновить ресурс
Если изменился только Lua-код
- Сохраните резервную копию ресурса.
- Замените изменённые файлы.
- Выполните:
restart vehicle_system
Если изменился meta.xml или добавлены файлы
- Остановите ресурс.
- Замените файлы.
- Выполните:
refreshall
Затем проверьте состояние и при необходимости запустите ресурс:
start vehicle_system
Если используется внешний HTTP-сервер
После изменения клиентских файлов синхронизируйте каталог загрузок. Иначе игроки могут получить ошибку CRC или старую версию материалов.
Перед обновлением базы
Если новая версия ресурса содержит SQL-миграцию:
- создайте дамп базы;
- прочитайте SQL-файл;
- проверьте команды удаления;
- выполните миграцию на тестовой копии;
- только затем обновляйте рабочий сервер.
Как удалить ресурс с сервера
- Проверьте, не зависит ли от него другой ресурс.
- Остановите его:
stop vehicle_system
- Удалите строку автозапуска из
mtaserver.conf. - Сохраните резервную копию данных.
- Удалите папку или ZIP-архив.
- Обновите список:
refresh
Не удаляйте сразу
- ресурс подключения к базе;
- общую библиотеку;
- систему аккаунтов;
- ресурс, экспортируемый другим системам;
- таблицы MySQL без резервной копии.
Права ACL для ресурсов MTA
Некоторые функции MTA защищены системой ACL. Ресурсу могут потребоваться права для запуска других ресурсов, управления аккаунтами, работы с ACL или выполнения административных функций.
Запрос прав в meta.xml
<aclrequest>
<right
name="function.startResource"
access="true"
/>
<right
name="function.stopResource"
access="true"
/>
</aclrequest>
Просмотр запросов
aclrequest list resource_manager
Разрешение одного права
aclrequest allow resource_manager function.startResource
Разрешение всех заявленных прав
aclrequest allow resource_manager all
Отклонение
aclrequest deny resource_manager all
Перезагрузка ACL
reloadacl
Когда ресурсу действительно нужны расширенные права
- собственная административная панель;
- менеджер ресурсов;
- система управления ACL;
- автоматическая регистрация серверных аккаунтов;
- служебный ресурс обновления;
- защищённая системная библиотека.
Не добавляйте неизвестный ресурс в Admin
Строка вида:
<object name="resource.unknown_script" />
внутри группы Admin может дать скрипту значительно больше возможностей, чем ему требуется.
Ресурс подключения к MySQL
Для крупных сборок подключение к базе удобно вынести в отдельный ресурс:
database/
├── meta.xml
└── server.lua
meta.xml
<meta>
<info
author="Server Team"
name="Database"
type="script"
version="1.0.0"
/>
<script src="server.lua" type="server" />
<export
function="getConnection"
type="server"
/>
</meta>
server.lua
local connection = false
addEventHandler("onResourceStart", resourceRoot,
function()
connection = dbConnect(
"mysql",
table.concat({
"dbname=mta_server",
"host=127.0.0.1",
"port=3306",
"charset=utf8mb4"
}, ";"),
"mta_user",
"ЗАМЕНИТЕ_ПАРОЛЬ",
"share=0;autoreconnect=1;batch=1"
)
if connection then
outputDebugString(
"[DATABASE] Подключение установлено.",
3
)
else
outputDebugString(
"[DATABASE] Ошибка подключения.",
1
)
end
end
)
function getConnection()
return connection
end
Получение соединения другим ресурсом
local connection = exports.database:getConnection()
if not isElement(connection) then
outputDebugString(
"Соединение с MySQL недоступно.",
1
)
return
end
Подробное создание базы, пользователя и импорт таблиц рассмотрены отдельно.
Как искать ошибки в Lua-ресурсах
Включение debugscript
Подключитесь к серверу под административным аккаунтом, откройте консоль MTA клавишей F8 и выполните:
debugscript 2
Этот уровень показывает ошибки и предупреждения.
Максимальная информация
debugscript 3
Отображаются:
- ошибки;
- предупреждения;
- информационные сообщения;
- вывод
outputDebugString.
Уровни debugscript
| Команда | Что показывает |
|---|---|
debugscript 0 |
Закрывает окно отладки. |
debugscript 1 |
Только ошибки. |
debugscript 2 |
Ошибки и предупреждения. |
debugscript 3 |
Ошибки, предупреждения и информационные сообщения. |
Очистка окна
cleardebug
Серверный журнал Lua
В mtaserver.conf можно включить запись:
<scriptdebuglogfile>logs/scripts.log</scriptdebuglogfile>
<scriptdebugloglevel>3</scriptdebugloglevel>
Файл будет находиться здесь:
mods/deathmatch/logs/scripts.log
Клиентский журнал
Клиентские Lua-ошибки также сохраняются в журнале MTA:
MTA/logs/clientscript.log
Собственные сообщения отладки
outputDebugString(
"[VEHICLES] Началась загрузка автомобилей.",
3
)
Уровни outputDebugString
outputDebugString("Критическая ошибка", 1)
outputDebugString("Предупреждение", 2)
outputDebugString("Информация", 3)
Проверка переменной
outputDebugString(
"playerId = " .. tostring(playerId),
3
)
Проверка выполнения участка кода
outputDebugString("Шаг 1 выполнен", 3)
local playerData = loadPlayerData(player)
outputDebugString("Шаг 2 выполнен", 3)
Если второе сообщение не появилось, ошибка или остановка выполнения произошла внутри loadPlayerData.
Распространённые ошибки ресурсов MTA
Resource could not be found
Сервер не обнаружил ресурс.
- проверьте папку
resources; - уберите двойную вложенность;
- проверьте наличие
meta.xml; - выполните
refresh; - проверьте название команды;
- уберите точку из имени ресурса.
Couldn't parse meta.xml
Ошибка XML-разметки.
- не закрыт тег;
- не закрыта кавычка;
- использован обычный амперсанд;
- файл содержит лишний текст;
- пропущен корневой тег
meta; - один элемент неправильно вложен в другой.
Couldn't find file
В meta.xml указан отсутствующий файл.
<script src="server/main.lua" type="server" />
Проверьте существование:
resource_name/server/main.lua
Ошибка только на Linux
Linux различает регистр символов:
Client.lua
client.lua
Для Linux это разные файлы. Путь в meta.xml должен полностью совпадать.
Loading script failed
Lua-файл содержит синтаксическую ошибку:
if player then
outputChatBox("Игрок найден", player)
end
В сообщении обычно указываются:
- название ресурса;
- имя Lua-файла;
- номер строки;
- описание ошибки.
attempt to call global — a nil value
Функция не существует или написана с неправильным регистром:
outputChatbox("Текст")
Правильно:
outputChatBox("Текст")
Lua и функции MTA чувствительны к регистру символов.
Bad argument
Функция получила неправильный тип данных:
setPlayerMoney("PlayerName", 5000)
Первым аргументом должен быть элемент игрока, а не его имя:
setPlayerMoney(playerElement, 5000)
attempt to index a nil value
Код пытается получить поле отсутствующей таблицы:
local money = playerData.money
Проверьте значение:
if type(playerData) ~= "table" then
outputDebugString("playerData отсутствует", 1)
return
end
local money = tonumber(playerData.money) or 0
Not enough permissions
У ресурса нет нужного права ACL.
- посмотрите сообщение с названием функции;
- проверьте блок
aclrequest; - разрешите только необходимое право;
- выполните
reloadacl; - перезапустите ресурс.
Ресурс запущен, но ничего не происходит
- обработчик события не зарегистрирован;
- указано неправильное событие;
- клиентский файл объявлен как серверный;
- команда имеет другое название;
- условие всегда возвращает false;
- не запущена зависимость;
- ошибка скрыта без
debugscript; - интерфейс рисуется за пределами экрана.
CRC mismatch
Клиент получил файлы, которые не совпадают с версией сервера.
- перезапустите изменённый ресурс;
- обновите список ресурсов;
- синхронизируйте внешний HTTP-сервер;
- проверьте кэш клиентских файлов;
- убедитесь, что на CDN загружена новая версия.
Download error
- HTTP-сервер MTA отключён;
- закрыт TCP-порт;
- файл отсутствует;
- неверно настроен
httpdownloadurl; - внешний сервер возвращает ошибку 404;
- антивирус блокирует загрузку.
Конфликт команд
Два ресурса могут зарегистрировать одинаковую команду:
addCommandHandler("car", openVehicleMenu)
Используйте уникальные названия или централизованный менеджер команд.
Конфликт обработчиков
При каждом перезапуске ресурс должен правильно создавать и удалять таймеры, обработчики, браузеры и временные данные. Проверяйте, не запускается ли одна система несколько раз.
Безопасность Lua-ресурсов
Не доверяйте данным клиента
Небезопасный серверный обработчик:
addEvent("shop:giveMoney", true)
addEventHandler("shop:giveMoney", root,
function(amount)
givePlayerMoney(client, amount)
end
)
Игрок способен передать произвольную сумму.
Проверяйте источник и данные
addEvent("shop:buyItem", true)
addEventHandler("shop:buyItem", root,
function(itemId)
if client ~= source then
return
end
if type(itemId) ~= "number" then
return
end
itemId = math.floor(itemId)
local item = AVAILABLE_ITEMS[itemId]
if not item then
return
end
local playerMoney = getPlayerMoney(client)
if playerMoney < item.price then
return
end
takePlayerMoney(client, item.price)
giveItemToPlayer(client, itemId)
end
)
Сервер должен самостоятельно проверять
- стоимость предмета;
- баланс игрока;
- расстояние до магазина;
- наличие персонажа;
- уровень доступа;
- частоту события;
- тип и диапазон аргументов;
- результат операции с базой.
Не храните секреты на клиенте
- пароли базы данных;
- ключи платёжных систем;
- токены Telegram;
- секретные адреса API;
- административные пароли;
- закрытые алгоритмы авторизации.
Проверяйте скачанные ресурсы
Обратите внимание на использование:
fetchRemote
loadstring
load
fileCreate
fileDelete
aclCreate
aclGroupAddObject
addAccount
setAccountPassword
startResource
stopResource
Само присутствие функции не доказывает вредоносность, но требует понимания её назначения.
Особая опасность нативных модулей
Файлы .dll и .so выполняют нативный код в операционной системе. Не запускайте модуль, происхождение которого невозможно проверить.
Обновляйте стандартные ресурсы
Старые версии административных и веб-ресурсов могут содержать уже исправленные уязвимости. Перед обновлением создавайте резервную копию и проверяйте совместимость своей сборки.
Оптимизация Lua-ресурсов
Не выполняйте тяжёлый код каждый кадр
Событие onClientRender вызывается постоянно. Внутри него не следует:
- выполнять запросы к базе;
- создавать текстуры;
- загружать файлы;
- запускать большие циклы;
- отправлять серверные события каждый кадр;
- создавать новые таблицы без необходимости.
Создавайте элементы один раз
Неправильно:
addEventHandler("onClientRender", root,
function()
local texture = dxCreateTexture("image.png")
dxDrawImage(0, 0, 300, 200, texture)
end
)
Правильно:
local texture = false
addEventHandler("onClientResourceStart", resourceRoot,
function()
texture = dxCreateTexture("image.png")
end
)
addEventHandler("onClientRender", root,
function()
if isElement(texture) then
dxDrawImage(0, 0, 300, 200, texture)
end
end
)
Не используйте слишком частые таймеры
Нежелательно:
setTimer(updateAllPlayers, 50, 0)
Выбирайте разумный интервал в зависимости от задачи:
setTimer(saveChangedPlayers, 60000, 0)
Не отправляйте лишние данные
- передавайте только изменившиеся значения;
- не отправляйте большие таблицы без необходимости;
- не синхронизируйте секретные серверные данные;
- ограничивайте частоту клиентских событий;
- не используйте element data как универсальную базу данных.
Останавливайте ненужные обработчики
Если интерфейс закрыт, удалите обработчик отрисовки:
removeEventHandler(
"onClientRender",
root,
drawInventory
)
Уничтожайте созданные элементы
if isElement(interfaceBrowser) then
destroyElement(interfaceBrowser)
interfaceBrowser = nil
end
Проверяйте производительность после перезапуска
Убедитесь, что ресурс не создаёт повторно:
- таймеры;
- обработчики;
- автомобили;
- объекты;
- маркеры;
- браузеры;
- соединения с базой.
Резервное копирование ресурсов
Что сохранять
- всю папку ресурса;
meta.xml;- серверные настройки;
- изменяемые XML-файлы;
- SQL-структуру и данные;
- права ACL;
- строки автозапуска;
- список зависимостей;
- используемые модули.
Пример структуры копий
backups/
└── resources/
├── 2026-07-31-before-update/
├── 2026-08-05-stable/
└── 2026-08-12-before-migration/
Не храните единственную копию на сервере
Дополнительно сохраните её:
- на локальном компьютере;
- на другом VPS;
- в защищённом облачном хранилище;
- в закрытом репозитории без паролей.
Не загружайте секреты в Git
Добавьте файлы с паролями в список исключений репозитория или используйте отдельный непубличный конфигурационный файл.
Частые вопросы о ресурсах MTA
Куда устанавливать ресурсы?
В папку mods/deathmatch/resources установленного MTA Server.
Обязательно ли распаковывать ZIP?
Нет. MTA поддерживает ресурсы в папках и ZIP-архивах. Для разработки удобнее использовать папку.
Какой файл является обязательным?
meta.xml. Без него папка не распознаётся как ресурс.
Почему сервер не видит новую папку?
Проверьте наличие meta.xml, двойную вложенность и выполните команду refresh.
Как запустить ресурс?
Введите start название_ресурса в серверной консоли.
Как остановить ресурс?
Используйте stop название_ресурса.
Как применить изменения Lua?
Сохраните файл и выполните restart название_ресурса.
Когда нужен refreshall?
После изменения meta.xml, добавления новых файлов или массового обновления ресурсов.
Чем refresh отличается от refreshall?
refresh обнаруживает новые ресурсы. refreshall также обновляет изменённые и может их перезапустить.
Как добавить ресурс в автозагрузку?
Добавьте строку <resource src="название" startup="1" protected="0" /> в mtaserver.conf.
Что означает server в meta.xml?
Lua-файл выполняется только сервером и не передаётся игрокам.
Что означает client?
Файл скачивается и выполняется на компьютере подключившегося игрока.
Что означает shared?
Скрипт выполняется отдельно на сервере и клиенте.
Защищает ли cache="false" клиентский код?
Он усложняет обычное сохранение файла, но не делает клиентский код секретным.
Как подключить изображение?
Добавьте файл тегом <file src="путь" /> в meta.xml.
Как подключить карту?
Используйте тег <map src="путь_к_карте.map" />.
Как передать функцию другому ресурсу?
Объявите её через export, а затем вызовите через exports.название:функция().
Как указать зависимость?
Добавьте в meta.xml строку <include resource="название" />.
Как выдать ресурсу права?
Проверьте его aclrequest и разрешите только необходимые функции через серверную команду.
Почему функция MTA не работает?
Проверьте регистр букв, сторону выполнения, тип аргументов, минимальную версию MTA и сообщения debugscript.
Как включить окно ошибок?
Авторизуйтесь как администратор и выполните debugscript 2 или debugscript 3 в консоли F8.
Где находятся серверные ошибки?
В консоли MTA Server и журнале mods/deathmatch/logs/scripts.log, если запись включена.
Где находятся клиентские ошибки?
В окне debugscript и файле MTA/logs/clientscript.log.
Почему ресурс работает на Windows, но не на Linux?
Чаще всего не совпадает регистр букв в имени файла или пути, отсутствует библиотека либо используется несовместимый модуль.
Почему после обновления появляется CRC mismatch?
Серверный ресурс или внешний HTTP-каталог содержит файлы другой версии. Перезапустите ресурс и синхронизируйте загрузочный сервер.
Можно ли использовать чужой Lua-скрипт?
Да, если лицензия это разрешает и код проверен. Не запускайте неизвестные скрипты с полными ACL-правами.
Можно ли хранить пароль MySQL в shared.lua?
Нет. Shared-файл выполняется и на клиенте. Пароль должен находиться только в серверной части.
Нужно ли перезапускать весь MTA Server?
Обычно достаточно перезапустить конкретный ресурс. Полный перезапуск нужен после изменения основной конфигурации, модулей или критических систем сборки.
Заключение
Каждый ресурс MTA:SA должен находиться в отдельной папке или ZIP-архиве внутри mods/deathmatch/resources. В его корне обязательно размещается meta.xml, определяющий подключаемые Lua-скрипты, клиентские файлы, карты, настройки, зависимости и экспортируемые функции.
Новый ресурс устанавливается копированием в серверный каталог, после чего выполняются команды refresh и start название. Для применения изменений существующего Lua-кода обычно достаточно команды restart, а после изменения meta.xml используется refreshall.
Важную игровую логику, деньги, права, пароли и работу с базой храните на серверной стороне. Клиентские события и переданные игроком значения всегда должны повторно проверяться сервером.
Для поиска ошибок включите debugscript 2 или debugscript 3, используйте outputDebugString и проверяйте журналы. Особое внимание уделяйте номеру строки, регистру букв, типам аргументов и отсутствующим файлам.
Перед установкой или обновлением неизвестного ресурса создавайте резервную копию, проверяйте запрашиваемые права ACL и не запускайте непроверенные DLL- или SO-модули.
Установка серверной программы:
Настройка основного конфигурационного файла:
Подключение базы данных:
Готовые скрипты и материалы:
Комментарии к инструкции
Обсудите решение, задайте вопрос или дополните инструкцию