RE:NODE

Руководства11 мин чтения

OneSync, слоты игроков и culling в FiveM

Как OneSync меняет сервер FiveM: лимиты в 32 и 48 слотов, радиус culling, routing buckets, население, entity lockdown и выбор реального числа слотов.

0 прочтений

Без OneSync сервер FiveM ограничен 32 игроками из-за собственной peer-to-peer сети GTA V. С set onesync on сервер становится главным по сущностям, потолок поднимается далеко выше всего, что ролевой сервер реально способен вытянуть, а игроки получают только то, что находится рядом с ними. Два числа, которые определяют ваше реальное число слотов, лежат в другом месте: уровень слотов, привязанный к вашему ключу Cfx.re (бесплатный уровень исторически заканчивался на 48), и сколько времени основного потока и sync thread оставляют свободным ваши ресурсы. В этой статье - что меняет OneSync, какие convar им управляют, culling и routing buckets, entity lockdown и как выбрать число слотов, которое вы сможете удержать.

Что на самом деле меняет OneSync#

Мультиплеер GTA V создавался для сессий на несколько десятков игроков, где каждый клиент владеет частью сущностей и сам рассказывает о них остальным. FiveM без OneSync сохраняет эту модель: сервер пересылает трафик, но кто о чём знает, решает собственная синхронизация игры, и лимит в 32 игрока - часть этой модели.

OneSync заменяет её состоянием на стороне сервера. Каждую сетевую сущность - игроков, машины, педов, объекты - отслеживает FXServer, который знает, где каждая находится и какой клиент сейчас ею владеет. Клиенты по-прежнему симулируют сущности, которыми владеют, но кто какие обновления получает, решает сервер. Из этого следуют четыре практических последствия:

  • Становятся возможны слоты сверх 32. Потолок движка с OneSync исчисляется четырёхзначными числами. Использовать его не стоит никому.
  • Сервер видит всё. Серверные скрипты могут прочитать педа и координаты любого игрока через GetPlayerPed(source) и GetEntityCoords, а без OneSync это работало только на клиенте.
  • Клиенты видят только то, что рядом. Игроки и сущности за пределами радиуса culling клиенту вообще не отправляются.
  • Сервер может отклонять сущности. Раз сервер главный, он может запретить клиентам создавать сущности, и это самая полезная античит-настройка, которая есть в FiveM.

Для современного сервера OneSync не опционален. Актуальные фреймворки, инвентари и большинство ресурсов последних лет рассчитывают на него, и многие без него работают неправильно.

Convar#

server.cfg
set onesync onset onesync_population trueset onesync_forceMigration truesv_maxclients 48
ConvarЗначенияЧто делает
onesyncon, legacy, offМодель синхронизации. on - это то, что старые руководства называют Infinity
onesync_populationtrue, falseРазрешает ли сервер фоновый трафик и пешеходов
onesync_forceMigrationtrue, falseПередаёт сущности другому игроку, когда их владелец уходит
sv_maxclientsчислоЧисло слотов, которое объявляется и соблюдается

legacy - исходная реализация OneSync, оставленная ради совместимости. У неё ниже потолок, и она отправляет каждому клиенту больше данных; выбирать её для нового сервера незачем. Очень старые руководства используют onesync_enabled 1 и onesync_enableInfinity 1. Это устаревшие написания onesync on, и если вы их найдёте, их нужно удалить.

О том, как читаются эти настройки, нужно знать две вещи. OneSync должен быть определён до того, как сервер закончит запуск, поэтому его изменение требует полного перезапуска сервера - перезапуск ресурса ничего не даст. А у txAdmin в тех версиях, где она есть, есть собственная настройка OneSync на странице настроек FXServer, которую он передаёт в командной строке; если в server.cfg написано другое, побеждает одно из двух, и вы можете смотреть не на то, что победило. Задавайте её в одном месте. Остальной файл разобран в статье о server.cfg в FiveM.

sv_maxclients тоже требует полного перезапуска. Ресурс hardcap из стандартных данных сервера - это то, что отказывает игрокам, когда сервер заполнен; держите его в списке ensure, если его не заменяет ресурс очереди.

Лимиты слотов: движок, лицензия и реальность#

Есть три лимита, наложенных друг на друга, и побеждает самый низкий.

ЛимитЗначениеЧем задаётся
Без OneSync32Сеть GTA V
Ключ без платного уровня48 (исторически)Лицензирование Cfx.re
Более высокие уровни64 и вышеПодписка Cfx.re, привязанная к ключу
Потолок движка OneSyncЧетырёхзначные числаFXServer
Что ваш сервер способен вытянутьОбычно 48-128Ваши ресурсы и CPU

Спотыкаются обычно о лицензионный уровень. Годами бесплатный ключ позволял до 48 слотов с OneSync, а для большего числа слотов нужен был уровень подписки Cfx.re (продаётся как Element Club), привязанный к аккаунту, которому принадлежит ключ. Cfx.re уже меняла названия и пороги этих уровней, поэтому проверяйте актуальные цифры в портале Cfx.re, а не доверяйте числу с форума - включая это. Если задать sv_maxclients выше, чем позволяет ваш ключ, сервер скажет об этом при запуске.

Лимит реальности - тот, что действительно важен. Слот - это обещание, что на сервере может находиться ещё один человек и остальным от этого не станет хуже. На ролевом сервере с двумястами ресурсами каждый дополнительный игрок добавляет работы каждому циклу по игрокам, каждому событию, которое рассылается всем, и каждой сущности, которую он приносит с собой. Сервер примет 128 подключений задолго до того, как сможет нормально их обслуживать.

Тип сервераКомфортное число слотовТипичный объём RAMПримечания
Freeroam, дрифт, гонки32-642-3 GBМало ресурсов, дёшево на игрока
Ролевой на ESX или QBCore48-644-6 GBОбычный случай
Большой ролевой64-1288-12 GBНужны профилирование и дисциплина

Начните с меньшего, чем кажется нужным, следите за графиком тиков в txAdmin и за hitch warning в консоли в часы пик и поднимайте число, когда цифры говорят, что можно. Уменьшить число слотов после того, как сообщество к нему привыкло, гораздо труднее, чем увеличить. Общий аргумент изложен в статье о том, сколько игроков помещается на сервер, а как читать данные о тиках, показано в статье о производительности сервера FiveM.

Culling: что видит каждый игрок#

С включённым OneSync каждому клиенту отправляются только игроки и сущности в пределах радиуса culling вокруг его собственной позиции - по умолчанию это около 424 единиц. За пределами этого радиуса сущность для клиента не существует.

сущности в радиусетолько его радиусFXServerзнает все сущностиИгрок Aв радиусеИгрок Bна другом конце картыБлижние сущностиотправляются A
OneSync отправляет клиенту только то, что в радиусе

Именно поэтому OneSync вообще масштабируется, и именно поэтому многие старые клиентские скрипты на нём ведут себя странно:

  • Списки игроков на клиенте неполные. GetActivePlayers() на клиенте возвращает только игроков в радиусе. Скорборд, построенный на этой функции, показывает горстку имён на сервере с шестьюдесятью игроками. Стройте списки игроков на сервере и отправляйте их вниз.
  • Метки дальних игроков требуют сервера. Клиент не может поставить метку на педа, которого ему не отправили. Ресурсы меток для полиции и EMS, которые работают с OneSync, по таймеру отправляют координаты с сервера.
  • Поиск дальних сущностей на клиенте не срабатывает. NetworkGetEntityFromNetworkId на клиенте ничего не возвращает для сущности вне его радиуса. Делайте работу на сервере или ждите, пока сущность окажется в радиусе.

FXServer даёт серверные natives для изменения радиуса - SetPlayerCullingRadius для одного игрока и SetEntityDistanceCullingRadius для одной сущности. У них есть применение (админ в режиме наблюдения, вертолёт, который должно быть видно издалека), но широкое увеличение радиуса отправляет больше данных каждому клиенту и стоит времени синхронизации, так что используйте их для конкретных случаев, а не как общую настройку.

Routing buckets: отдельные миры на одном сервере#

Routing bucket - это отдельный экземпляр мира. Игроки и сущности в bucket 3 не видят ничего в bucket 0 и не могут с этим взаимодействовать, даже стоя в той же точке. Все начинают в bucket 0.

lua
-- server side: put a player and their vehicle into a private instanceSetPlayerRoutingBucket(source, 3)SetEntityRoutingBucket(vehicle, 3)-- an empty instance with no ambient traffic and no client-created entitiesSetRoutingBucketPopulationEnabled(3, false)SetRoutingBucketEntityLockdownMode(3, "strict")

Ролевые серверы используют buckets для выбора персонажа, интерьеров квартир, где у каждого игрока своя копия, админского наблюдения и ивентов, которые не должны мешать основному городу. Они дешёвые: пустой bucket ничего не стоит, а игроки в разных buckets не синхронизируются друг с другом. Не забывайте возвращать игроков в bucket 0, когда они покидают экземпляр: игрок, застрявший в bucket, видит пустой город и сообщает, что сервер сломан. GetPlayerRoutingBucket(source) скажет, где находится человек.

Население и число сущностей#

Фоновый трафик и пешеходы - это сущности, а в OneSync это сущности, которые отслеживает сервер. Оживлённый город с шестьюдесятью игроками может нести их тысячи, и каждая стоит времени sync thread. Этим управляют следующие настройки:

  • `onesync_population false` полностью отключает фоновое население. Город пуст, и сервер несёт только те сущности, которые создают скрипты. Несколько серьёзных ролевых серверов работают именно так и спавнят трафик только там, где он важен.
  • Natives плотности на клиенте. SetVehicleDensityMultiplierThisFrame, SetPedDensityMultiplierThisFrame и их родственники уменьшают население, не отключая его. Их нужно вызывать в каждом кадре, и это одно из законных применений цикла с Wait(0).
  • Население по bucket. SetRoutingBucketPopulationEnabled отключает население в конкретных экземплярах.

Сущности, которые создают скрипты, - вторая половина. Машины, заспавненные из гаражей и так и не убранные, пропы, оставленные работами, педы из миссий, которые никто не закончил, - всё это остаётся в состоянии сервера. Сущностям, созданным сервером, на сборках, которые это поддерживают, можно через SetEntityOrphanMode указать, что делать, когда рядом никого нет; в остальных случаях убирайте их сами. Если hitch warning sync thread растут с аптаймом, первый подозреваемый - накопление сущностей, а плановый рестарт - грубое решение, пока вы ищете виноватый ресурс. О выборе времени - в статье о расписаниях рестартов, которые помогают.

Здесь важен и onesync_forceMigration true. Когда игрок, владеющий сущностью, отключается, сервер передаёт её другому игроку поблизости, а не удаляет. Без этого машина, которую кто-то вёл, может исчезнуть в тот момент, когда у водителя вылетела игра.

Entity lockdown#

Поскольку в OneSync сервер главный, он может запретить клиентам создавать сущности. Это sv_entityLockdown:

РежимЧто могут создавать клиентыКогда использовать
inactiveВсё что угодноНикогда на публичном сервере
relaxedТолько фоновое население, не сущности скриптовБольшинство серверов
strictНичегоСерверы, где каждая сущность приходит с сервера
config
set sv_entityLockdown "relaxed"

По умолчанию стоит inactive, что позволяет чит-меню спавнить любую машину, педа или проп. relaxed блокирует сущности, созданные клиентскими скриптами, сохраняя фоновый трафик, и останавливает большую часть спавн-спама, которым запоминается визит читера. strict блокирует всё, поэтому фоновое население тоже пропадает, и каждую машину, которую получает игрок, должен создать сервер.

Lockdown - это ещё и фильтр для ваших ресурсов. Гараж, работа или админ-меню, которые спавнят машины на клиенте, ломаются при relaxed. Решение - создавать сущность на сервере и передавать клиенту network ID:

lua
-- server sidelocal veh = CreateVehicleServerSetter(model, "automobile", x, y, z, heading)local netId = NetworkGetNetworkIdFromEntity(veh)TriggerClientEvent("garage:vehicleReady", source, netId)

CreateVehicleServerSetter - более новый серверный native для создания машин, и для них он предпочтительнее старого серверного CreateVehicle; проверьте, что ваша сборка сервера его поддерживает. Большинство актуальных фреймворков и гаражей уже работают так. Включить lockdown на тестовом экземпляре или для отдельного bucket через SetRoutingBucketEntityLockdownMode - дешёвый способ найти, какие из ваших ресурсов так не умеют. Остальные защитные настройки описаны в статье о вариантах античита для FiveM.

State bags#

OneSync также включает state bags: данные «ключ-значение», привязанные к сущности, игроку или серверу целиком и автоматически синхронизируемые с клиентами.

lua
-- serverPlayer(source).state:set("job", "police", true)   -- true = replicated to clientsEntity(vehicle).state:set("fuel", 64.0, true)GlobalState.weather = "RAIN"-- clientlocal fuel = Entity(vehicle).state.fuel

Они заменяют множество написанных вручную событий в духе «разошли всем новое значение». Но дешёвыми они будут ровно настолько, насколько вы их такими сделаете: state bag, который меняется в каждом кадре на сотне машин, - это сотня обновлений за кадр для sync thread. Пишите при изменении, а не по таймеру. И state bag, который может записать клиент, - это данные под контролем клиента: серверные скрипты не должны доверять значениям, которые клиентам разрешено задавать.

Устранение неполадок#

`sv_maxclients` выше 32 игнорируется. OneSync выключен или задан там, где это не срабатывает. Убедитесь, что в выводе при запуске есть onesync on, и перезапустите весь сервер.

Сервер при запуске отказывается принимать число слотов. Уровень вашего ключа этого не позволяет. Уменьшите sv_maxclients или смените уровень на аккаунте, которому принадлежит ключ.

Скорборд показывает всего нескольких игроков. Он построен на клиенте через GetActivePlayers(). Перенесите его на сервер.

После включения lockdown гаражи перестали спавнить машины. Они создают машины на клиенте. Обновите ресурс или переведите его на создание на сервере.

Машины исчезают, когда водитель отключается. Включите onesync_forceMigration.

Задержки sync thread с каждым часом всё хуже. Накопление сущностей. Посчитайте, что скрипты спавнят и никогда не удаляют, подумайте об уменьшении фонового населения и перезапускайте сервер по расписанию, пока это исправляете.

FAQ#

OneSync Infinity по-прежнему отдельная настройка?

Нет. set onesync on - это то, что раньше называлось Infinity. Старый convar onesync_enableInfinity устарел, а legacy существует только ради совместимости со старыми ресурсами.

Сколько слотов можно использовать с бесплатным ключом FiveM?

Исторически - 48 с включённым OneSync. Для большего числа нужен был уровень подписки Cfx.re на аккаунте, которому принадлежит ключ. Cfx.re уже меняла эти пороги, поэтому актуальную цифру проверяйте в портале.

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

Это culling в OneSync, работающий как задумано. Каждый клиент получает только сущности в пределах примерно 424 единиц. Всё, чему нужны дальние игроки, - метки, скорборды, - нужно строить на сервере.

Делает ли большее число слотов сервер медленнее?

Само по себе нет: пустой слот ничего не стоит. Стоят игроки, которые эти слоты занимают, потому что циклы по игрокам, рассылаемые события и сущности, которые приносит каждый игрок, добавляют работы основному потоку и sync thread.

Стоит ли отключать фоновое население?

На оживлённом ролевом сервере это стоит проверить. Это убирает большую долю сущностей и работы синхронизации ценой пустого города. Многие серверы вместо этого снижают плотность через клиентские natives, что сохраняет часть трафика за малую долю стоимости.


Комментарии

Полностью анонимно: без аккаунта, без почты, без cookie. Мы храним имя, которое вы ввели, текст и время - больше ничего. Количество ссылок ограничено, разметка не отображается.

0/2000