MAATRIX GAMES / Блог / SA-MP: скриптовые ошибки при запуске gamemode

SA-MP: скриптовые ошибки при запуске gamemode

MAATRIX GAMES

Запустил samp03svr, в консоли пробежала пара строк — и тишина, игроки на сервер зайти не могут, хотя порт вроде открыт. Или хуже: сервер стартует, но через секунду сам себя вырубает без внятного сообщения. В девяти случаях из десяти дело не в сети и не в firewall, а в самом Pawn-скрипте — gamemode или один из filterscript-ов не пережил загрузку. Разберём, как читать лог, где искать виновника и что делать с конфликтами версий плагинов, которые эту картину обычно и вызывают.

Где искать: server_log.txt, а не то, что мелькнуло в консоли

Консоль SA-MP скроллится быстро, и если сервер стартовал и упал за секунду-две, разглядеть причину на лету почти нереально. Весь этот же вывод параллельно пишется в server_log.txt в корне сервера — открывай его сразу после падения и смотри с конца файла, а не с начала:

tail -n 60 ~/sampserver/server_log.txt

При штатной загрузке в конце лога будет что-то вроде:

Filterscripts
---------------
  Loading filterscript 'admin.amx'
  Loading filterscript 'gates.amx'
Loaded 2 filterscripts.

Started server on port: 7777, with maxplayers: 50 lanmode is OFF.

Number of vehicle models: 0

Если вместо этого лог обрывается раньше — на строке загрузки гейммода, на конкретном filterscript-е или сразу после баннера версии — сервер упал именно на этом этапе, и следующая пара строк почти всегда прямо называет причину. Важный нюанс: если правишь server.cfg или пересобираешь .amx, а server_log.txt не создаётся заново — сервер иногда дописывает в старый файл, и можно случайно читать вчерашний краш. Проще всего перед тестовым запуском удалить старый лог или явно проверить дату модификации файла.

Run time error при загрузке: gamemode или filterscript не найден

Самая частая причина, почему сервер вообще не поднимает гейммод — банальная опечатка в server.cfg или отсутствующий скомпилированный файл. В логе это выглядит так:

Unable to load gamemode0: mygamemode

или, если сервер всё же попытался загрузить .amx, но не смог его выполнить:

run time error 19: "file or function is not found"

Причины почти всегда одни из трёх:

  • в gamemode0 mygamemode 1 указано имя без расширения .amx, а сам файл называется иначе (опечатка, регистр — на Linux файловая система регистрозависима, MyGameMode.amx и mygamemode.amx — разные файлы);
  • .amx не лежит в папке gamemodes/ (частая ошибка — забыли скопировать файл после компиляции на локальной машине);
  • компиляция pawncc завершилась с ошибками, и .amx вообще не создался или создался старым — тогда сервер запускает вчерашнюю версию скрипта, а не ту, что правили только что.

Проверить последний пункт просто — сверить время модификации файла с временем последней компиляции:

ls -la gamemodes/mygamemode.amx

Если сервер уже поднимал этот же гейммод раньше (например, отладку делаешь на локальной копии перед деплоем на боевой VPS), базовую установку с нуля разумно свериться со статьёй про установку SA-MP сервера с нуля — там разобран правильный порядок файлов и путей.

Поднять сервер SA-MP за пару минут

Готовый образ MAATRIX GAMES: NVMe, AMD EPYC, DDoS-защита, панель управления. Локации UK, US, RU. Оплата картой РФ, СБП или криптой.

Создать сервер

Порядок загрузки filterscripts и как найти виновника методом исключения

Filterscript-ы грузятся строго в том порядке, в котором перечислены в строке filterscripts конфига, слева направо. Если один из них падает на OnFilterScriptInit (например, обращается к несуществующему native-плагину или читает файл, которого нет), сервер обычно не роняет весь процесс, а просто пропускает загрузку конкретного скрипта — но это не всегда так: некоторые ошибки в критичных для инициализации функциях уводят в краш весь samp03svr.

Если лог не называет виновника явно, самый надёжный способ — бинарный поиск. Берём строку filterscripts:

filterscripts admin gates antycheat spawnselect

Убираем половину скриптов и перезапускаем:

filterscripts admin gates

Если сервер поднялся штатно — проблема в одном из убранных (antycheat или spawnselect), делим их пополам и повторяем. Если не поднялся — проблема осталась среди admin/gates, делим дальше. Три-четыре итерации почти всегда находят конкретный файл даже на списке из 10+ filterscript-ов, и это быстрее, чем вручную разбирать код каждого.

Отдельно стоит помнить: filterscript, который просто не загрузился, не всегда сообщает об этом явно — иногда единственный симптом — отсутствие его функциональности в игре (не работает команда /admin, нет ворот на карте), при этом сервер выглядит запущенным нормально. Тут та же строка Loaded N filterscripts в логе — если число меньше, чем скриптов в конфиге, кто-то не загрузился молча.

Runtime-ошибки во время игры: unknown native, array out of bounds, стек

Отдельный класс проблем — сервер стартует нормально, но падает или сыплет ошибками уже во время работы, когда кто-то заходит на сервер или триггерится конкретная функция. В логе это выглядит как повторяющиеся блоки:

[debug] Run time error 4: "Invalid memory access"
[debug] Run time error 19: "File or function is not found"
[debug] Run time error 21: "Native function calls are not enabled"

Коды встречаются чаще всего такие:

КодЧто означаетТипичная причина
4Invalid memory accessобращение к массиву/пулу игроков за пределами размера, часто с невалидным playerid
19 (в рантайме)native не найденскрипт скомпилирован с инклюдом плагина, а сам .so/.dll плагина не подключён в server.cfg
21native calls not enabledплагин не загрузился до вызова его функции — обычно порядок plugins в конфиге или сам плагин упал при инициализации
29stack/heap collisionрекурсия без выхода или слишком большой локальный массив в функции

Ошибка «unknown native function» — почти всегда про расхождение между тем, с чем скомпилирован .amx, и тем, что реально подключено на сервере в момент запуска. Если гейммод использует, скажем, streamer или sscanf, а в server.cfg строка plugins не содержит соответствующий .so-файл (или файл не той версии), скрипт скомпилируется без единой ошибки — но упадёт в рантайме в первый же момент вызова функции из этого плагина.

crashdetect: точный call stack вместо гадания по логу

Голый server_log.txt часто говорит только «где-то упало», но не называет ни строку, ни функцию. Плагин crashdetect (стандартный инструмент экосистемы SA-MP, идёт вместе со streamer или ставится отдельно) решает это — при краше он пишет полноценный call stack с номерами строк исходника, если гейммод скомпилирован с отладочной информацией.

Ставится как обычный плагин — кладём crashdetect.so (Linux) в папку plugins/ и добавляем в server.cfg:

plugins crashdetect.so

Дальше важный момент: без флага отладки в компиляции crashdetect покажет только адреса в байт-коде, а не читаемые номера строк. Компилировать нужно с -d3:

../pawno/pawncc -d3 mygamemode.pwn

После этого при падении в логе появится что-то вроде:

[debug] Server crashed while executing mygamemode.amx
[debug] AMX backtrace:
[debug] #0 native PlayerName () from samp-server.exe
[debug] #1 0000a4f0 in OnPlayerConnect (playerid=3) at mygamemode.pwn:284

Строка mygamemode.pwn:284 — это конкретная строка исходника, где произошёл сбой, и дальше искать причину уже не вслепую. Для боевого сервера -d3 в проде обычно не оставляют навсегда (небольшой оверхед и вес .amx растёт), но на время отладки конкретного падения это самый быстрый путь к причине.

Конфликт версий: старый .amx против новых плагинов

Отдельная головная боль — когда всё компилируется без ошибок, сервер стартует, но ведёт себя нестабильно или падает время от времени без явной связи с конкретным действием игрока. Частая причина — рассинхрон версий между тем, с чем гейммод писался, и тем, что реально стоит на сервере:

  • .inc-файл не совпадает с бинарником плагина. Если скачал новую версию sscanf.inc, а .so-файл плагина остался старым (или наоборот), сигнатуры некоторых функций могут разойтись — это не всегда даёт ошибку компиляции, но даёт неверные результаты или краш в рантайме.
  • MySQL-плагин разных мажорных веток. Синтаксис вызовов между старыми R33-R39 и более новыми R41+ отличается заметно (thread-based vs новый API), гейммод, написанный под одну ветку, не запустится корректно на плагине другой — обычно это видно сразу по ошибкам unknown native на первом же SQL-запросе.
  • Несколько версий streamer в разных филтрскриптах. Если основной гейммод и один из filterscript-ов компилировались с разными версиями streamer.inc, но на сервере стоит только одна версия .so, тот из скриптов, что рассчитан на другую версию, скорее всего словит ошибки рантайма именно на функциях стриминга объектов.
  • AMX, скомпилированный более новым pawncc, чем поддерживает сервер. Редкая, но встречающаяся ситуация при переносе .amx с более свежего окружения на старый билд сервера — версия формата байт-кода не совпадает. Решение — пересобрать .amx локально тем же pawncc, что лежит в архиве целевого сервера, а не приносить бинарник с чужой машины.

Практическое правило: если правишь include-файлы плагинов, всегда обновляй одновременно и .inc, и соответствующий бинарник плагина, и не смешивай версии между гейммодом и filterscript-ами — держи весь набор инклюдов в одной папке pawno/include/ и подключай к компиляции всех скриптов проекта именно из неё, а не из разных источников. Если только разворачиваешь SA-MP-проект и подбираешь готовый гейммод, стоит заранее свериться с требованиями конкретной сборки — например, в обзоре популярных RP-геймодов вроде Cops and Robbers обычно прямо указано, под какие версии плагинов писался скрипт.

Поднять сервер SA-MP за пару минут

Готовый образ MAATRIX GAMES: NVMe, AMD EPYC, DDoS-защита, панель управления. Локации UK, US, RU. Оплата картой РФ, СБП или криптой.

Создать сервер

Частые вопросы

Сервер запускается, но в игре список серверов его не видит — это тоже скриптовая ошибка?

Нет, это отдельная история про announce 1/query 1 в конфиге и открытые порты, к Pawn-скриптам не относится — если сервер стартовал и держит порт, дело не в gamemode.

Можно ли увидеть причину падения без crashdetect?

Частично да — базовые run time error с кодом пишутся в server_log.txt и без него, но без номера строки исходника искать причину в большом гейммоде долго. crashdetect экономит часы на действительно сложных крашах.

После обновления одного плагина упал весь сервер — как быстро откатиться?

Верни предыдущую версию .so-файла плагина из бэкапа (или пересобери из архива прошлого релиза) и перезапусти — обновления бинарных плагинов SA-MP-экосистемы редко бывают строго обратно совместимы, поэтому такие бинарники стоит держать в отдельной папке с версией в имени на случай отката.

Ошибка «run time error 19» появляется и при загрузке гейммода, и в рантайме — это одно и то же?

Формально один код, но разные ситуации: при загрузке это обычно «файл .amx не найден», в рантайме — «native-функция не найдена», потому что не подключён нужный плагин. Смотри, на каком этапе именно появилась ошибка в логе.

Стоит ли сразу переходить на open.mp, если конфликты версий задолбали?

Как отдельное решение это не панацея — Pawn-скрипты и логика ошибок остаются похожими, но open.mp активнее поддерживается и меньше страдает от разночтений версий классического SA-MP. Если начинаешь новый проект с нуля, а не мигрируешь существующий, присмотреться стоит.