Виправлення багу з «невидимками» та розсинхронізацією віртуальних світів

Технічний посібник з усунення багу з невидимими гравцями та розсинхронізації віртуальних світів у SA:MP/CRMP за допомогою правильного використання інструментів Incognito Streamer.

20.05.2026 Українська

Виправлення багу з «невидимками» та розсинхронізацією віртуальних світів

Один із найстаріших і найдратівливіших багів у SA:MP/CRMP — це поява так званих «невидимок». Гравець заходить в інтер'єр, на спавн або телепортується на захід, але не бачить інших учасників, кастомні об'єкти (стіни, двері, меблі) або машини, хоча для адміністраторів і за логами сервера він перебуває в правильному місці. Буває і зворотна ситуація: гравця вбиває «невидимий» супротивник, який насправді стоїть прямо перед ним.

В основі цієї проблеми лежить розсинхронізація між трьома компонентами: мережевим рушієм самого SA:MP, функцією SetPlayerVirtualWorld та плагіном Incognito Streamer. У цій статті ми розберемо технічний виворіт цього багу і навчимося правильно оновлювати позиції гравців та зони стріму.

Анатомія багу: Чому ламається стрімер?

Стандартний серверний рушій SA:MP має жорсткі ліміти на кількість об'єктів (1000) і транспорту, які он може одночасно надіслати клієнту. Щоб обійти це обмеження, абсолютно всі сучасні моди використовують плагін Incognito Streamer. Він постійно відстежує координати кожного гравця і «підсовує» його клієнту тільки ті об'єкти, які знаходяться в радіусі його видимості (Stream Distance).

Розсинхронізація та поява «невидимок» відбуваються через порушення хронології мережевих пакетів при різкій зміні координат або віртуального світу (Virtual World). Типовий сценарій багів виглядає так:

  1. Скрипт викликає функцію телепортації гравця в інтер'єр (змінює координати через SetPlayerPos та віртуальний світ через SetPlayerVirtualWorld).
  2. Сервер моментально відправляв плагіну Incognito Streamer сигнал: «Гравець змінив світ та позицію, онови для нього об'єкти!».
  3. Стрімер починає судорожно вивантажувати старі об'єкти з пам'яті клієнта та завантажувати нові.
  4. Збій синхронізації: Клієнт гравця (сам ПК) через мережеву затримку (пінг) або довге провантаження текстур ще не встиг обробити пакет про зміну координат від сервера. Для клієнта він все ще летить десь у повітрі або перебуває на старому спавні.
  5. Об'єкти нового інтер'єру створюються стрімером там, куди гравець ще «не долетів» на думку його комп'ютера. Клієнт вважає ці об'єкти занадто далекими і просто їх ігнорує. Гравець падає крізь невидимі текстури.

Як робити НЕ МОЖНА (Класичний багований код)

Більшість розробників використовують моментальне перенесення, яке і народжує розсинхрон:

public OnPlayerPickUpDynamicPickup(playerid, pickupid)
{
    if(pickupid == pickup_enter_ls_news)
    {
        SetPlayerVirtualWorld(playerid, 15);
        SetPlayerInterior(playerid, 3);
        SetPlayerPos(playerid, 823.12, -1324.44, 15.40);
    }
    return 1;
}

Правильний алгоритм: Заморожування та форсування стріму

Щоб гарантовано уникнути багів провантаження, професійна архітектура телепортації повинна складатися з чотирьох етапів: заморожування гравця, плавна зміна даних, примусове оновлення стрімера (Force Update) та розморожування після мережевого відгуку.

Реалізація безпечної функції телепортації (Впроваджуємо у свій мод):

stock TeleportPlayerSecure(playerid, Float:x, Float:y, Float:z, interior, virtual_world)
{
    TogglePlayerControllable(playerid, false);

    SetPlayerInterior(playerid, interior);
    SetPlayerVirtualWorld(playerid, virtual_world);
    SetPlayerPos(playerid, x, y, z);

    Streamer_UpdateEx(playerid, x, y, z, virtual_world, interior, streamer_type:STREAMER_TYPE_OBJECT);

    SetTimerEx("UnfreezeTeleportedPlayer", 400, false, "d", playerid);
    return 1;
}

forward UnfreezeTeleportedPlayer(playerid);
public UnfreezeTeleportedPlayer(playerid)
{
    if(!IsPlayerConnected(playerid)) return 1;
    TogglePlayerControllable(playerid, true);
    return 1;
}

Додаткова оптимизація параметрів Стрімера

Сам плагін Incognito Streamer має файл конфігурації streamer.cfg (або налаштовується через Pawn-скрипт в OnGameModeInit). За замовчуванням його параметри розраховані на слабкі сервера, що викликає затримки провантаження на великих проєктах.

Для моментального провантаження текстур і гравців додайте в OnGameModeInit такі налаштування:

  • Streamer_TickRate(20); — швидкість роботи стрімера (в мілісекундах). За замовчуванням встановлено 50мс. Зниження до 20мс змусить стрімер перевіряти координати гравців частіше, що прибере затримки появи об'єктів перед автомобілем, що швидко рухається.
  • Streamer_SetVisibleItems(STREAMER_TYPE_OBJECT, 700); — скільки об'єктів стрімер може одночасно показати гравцеві. Не виставляйте більше 900, інакше ліміт самого SA:MP (1000) буде перевищено, і гра почне крашитися.

Розсинхронізація транспорту та гравців («Невидимки» в ПВП)

Якщо з об'єктами все зрозуміло, то чому стають невидимими самі гравці або машини? За це відповідає внутрішній радіус стрімінгу SA:MP (він жорстко зашитий у клієнт і дорівнює приблизно 150-200 метрам).

Якщо ви змінюєте віртуальний світ гравця занадто часто или використовуєте динамічні зони (наприклад, для зон каптів або інтер'єрів будинків), рушій SA:MP може порахувати, що гравці перебувають у різних підсвітах, навіть якщо ID світу збігається. Це відбувається, якщо ви викликаєте SetPlayerVirtualWorld в один і той же тік із створенням кастомного 3D-тексту або іконки.

Тип розсинхронізації Причина виникнення Спосіб лікування
Провал під текстури інтер'єру Об'єкти не встигли створитися в новому віртуальному світі до моменту падіння гравця Використання зв'язки Streamer_UpdateEx + короткочасна заморозка (Freeze)
Невидимі кари / човни Транспорт був створений у світі 0, а потім перенесений у світ гравця без оновлення стріму машин Використовуйте на сервері LinkVehicleToInterior для примусової прив'язки авто до інтер'єрів.
Невидимі гравці на каптах Перевантаження мережевого каналу пакетами (Packet Loss) через флуд функціями анімацій Обмежуйте частоту виклику циклів, які перевіряють координати гравців (не частіше 1 разу на секунду замість кожного тіку).

Резюме: Щоб назавжди позбавити гравців від «невидимок», привчіть свій ігровий мод давати клієнту невелику фору (паузу в 300-400мс) на завантаження оточення при кожному масштабному переміщенні віртуальними світами хостингу.

Схожі статті

Захист сервера SA:MP від Flood-атак та нелегітимних пакетів на рівні Pawn

Технічний посібник із налаштування захисту серверів SA:MP від мережевого флуду, злому діалогів та нелегального спавну об'єктів за допомогою Pawn.RakNet та Nex-AC.

Читати далі

Борьба з витоками пам'яті (Memory Leaks) в AMX-скриптах

Технічний посібник із пошуку та усунення витоків пам'яті в серверних скриптах SA:MP/CRMP AMX, фокусуючись на очищенні кешу MySQL, об'єктах Стрімера та стеку.

Читати далі

Організація правильного кешування даних (PlayerInfo) в RAM

Технічний посібник зі створення високопродуктивної архітектури кешування в оперативній пам'яті за допомогою масиву PlayerInfo в Pawn для зниження дискового навантаження I/O.

Читати далі