Onesync

From FiveM Wikipedia

OneSync

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

Стоит отметить, что OneSync бесплатен до 48 слотов, после этого вы должны получить один из следующих уровней. от Patreon начиная с . FiveM Element Club Argentum 💿

Что такое OneSync: Бесконечность?

  • Режим, позволяющий (до) 2048 игроков с момента недавнего коммита. Есть серверы, обрабатывающие более 1000 одновременных игроков.
  • Для этого он использует следующие технологические изменения:
    • Расширение длины идентификатора объекта с 8192 () до 65535 (), из следующей фиксации.1 << 13(1 << 16) - 1
    • Выбраковка игроков/транспортных средств. Никакие сущности не будут создаваться на клиентах за пределами «зоны фокусировки», которая в настоящее время жестко закодирована до 424 единиц вокруг игрока.
    • Отбраковка игроков. Игроки не будут созданы/удалены локально за пределами зоны фокусировки. Это означает, что все итерации проигрывателя должны происходить на стороне сервера.
  • Он также имеет немного лучшую производительность, чем «простой» OneSync в настоящее время из-за отбраковки игроков, и работает вокруг так называемой «ошибки смешивания голов».

Как осуществляется синхронизация?

Большая часть данных синхронизации обрабатывается через игрока, игровые события обрабатываются через этого игрока, это игрок, зарезервированный для каждого отдельного клиента, и он используется для записи данных синхронизации на сервер, чтобы позже быть проанализированным через узлы синхронизации для синтаксического анализа.31

Что такое узлы синхронизации и как их интерпретировать?

Узлы синхронизации — это узлы данных синхронизации, сетевые сущности зависят от них для передачи данных другим клиентам / игрокам на сервере. Самый простой из них, который мы можем найти, это .CSectorPositionDataNode

Мы должны предупредить вас, что то, что ждет впереди, немного техническое и просто представлено в образовательных целях о том, как анализировать игровой код и создавать PR (pull-запрос), если вы хотите внести свой вклад в код-базу.

Этот узел данных синхронизации используется для обмена данными о местоположении сектора с другими клиентами о конкретной сущности, синтаксический анализ показан ниже. Стоит отметить, что код, записанный ниже, написан путем обратного проектирования игрового кода (более того, путем чтения метода VMT (Virtual Method Table), который является методом, который будет смещен на 8 от VMT).ParseNodeCommonDataOperations<class CSectorPositionDataNode, class IProximityMigrateableNodeDataAccessor>read

VMT игры: 9Til977.png Метод чтения: TPIzQMg.png Игра с чтением позиции: 5BX8krM.png Обратный код (от SyncTrees_Five.h)::

struct CSectorPositionDataNode
{
	float m_posX;
	float m_posY;
	float m_posZ;

    // Parse/deserialize incoming data
	bool Parse(SyncParseState& state)
	{
		auto posX = state.buffer.ReadFloat(12, 54.0f);
		auto posY = state.buffer.ReadFloat(12, 54.0f);
		auto posZ = state.buffer.ReadFloat(12, 69.0f);

		m_posX = posX;
		m_posY = posY;
		m_posZ = posZ;

		state.entity->syncTree->CalculatePosition();

		return true;
	}

    // continues...
};

Метод выше десериализует все соответствующие данные об этом конкретном узле, это полезно, так как позже его можно использовать для создания собственных носителей сервера, взгляните на пример ниже (из ServerGameState_Scripting.cpp):Parse

fx::ScriptEngine::RegisterNativeHandler("GET_ENTITY_COORDS", makeEntityFunction([](fx::ScriptContext& context, const fx::sync::SyncEntityPtr& entity)
{
    float position[3];
    entity->syncTree->GetPosition(position);

    scrVector resultVec = { 0 };
    resultVec.x = position[0];
    resultVec.y = position[1];
    resultVec.z = position[2];

    return resultVec;
}));

Как вы можете видеть, прямой доступ к отображению информации о его местоположении через нативный на сервере, поэтому вся та работа, которую мы бы сделали раньше, явно действует сейчас (из SyncTrees_Five.h):entity->syncTree->GetPosition(position)CSectorPositionDataNode

virtual void GetPosition(float* posOut) override
{
    auto [hasSdn, secDataNode] = GetData<CSectorDataNode>();
    auto [hasSpdn, secPosDataNode] = GetData<CSectorPositionDataNode>();
    // continues...
}

Что такое выбраковка?

Отбраковка используется, чтобы избежать отправки большого количества данных синхронизации на сервер (таких как население среди других), тем самым уменьшая нагрузку на сервер, это то, что позволяет OneSync обрабатывать много клиентов. Отбраковка имеет диапазон для каждого конкретного игрока, и сущности отбраковываются игрокам в пределах этого радиуса. Он был представлен в следующем коммите и имел несколько итераций. Можно сказать, что в некотором смысле он «скрывает» сущности. Существуют нативные элементы, такие как SetEntityDistanceCullingRadius и SetPlayerCullingRadius, для изменения радиуса отбраковки по умолчанию.

Когда сущность выходит за пределы диапазона, она больше не контролируется ее первоначальным владельцем. Это означает, что любая сущность, которая будет находиться вне сферы действия, будет отбракована и перенесена/отвергнута. По умолчанию для радиуса отбраковки установлено значение 424 units

Рекомендации

Созданные сервером сущности, а не клиентские сущности

OneSync позволяет создавать сущности на сервере, такие как Peds, Vehicles и Objects среди других. Одним из преимуществ этого является то, что сервер позволяет вызывать собственные компоненты через RPC (Remote Procedure Call) для выполнения действий с клиентом без необходимости запрашивать контроль над сущностью у клиента.

Например:

local vehicle = CreateVehicle(GetHashKey("blista"), 2204.795, -887.9213, 1461.224, 90.0, true, true, true)
local ped = CreatePed(4, GetHashKey("a_m_y_acult_01"), GetEntityCoords(GetPlayerPed(source)), GetEntityHeading(GetPlayerPed(source)), true, true)
TaskWarpPedIntoVehicle(ped, vehicle, 1) -- perhaps teleport a ped into a vehicle?
SetEntityVelocity(vehicle, 0.0, 0.0, 99.0) -- Fly high!

Мне нужны постоянные сущности, как это сделать?

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

Блокировка сущностей

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

local vehicle = CreateVehicle(GetHashKey("blista"), 2204.795, -887.9213, 1461.224, 90.0, true, true, true)

-- Essentially, we set the routing bucket at id 1 to 'strict' and then we set other entities to this as well as the player bucket so they can't create entities client-side.
SetRoutingBucketEntityLockdownMode(1, "strict")
SetPlayerRoutingBucket(source, 1) -- Now the given player (source) won't be able to create entities client-side
SetEntityRoutingBucket(vehicle, 1) -- Set the routing bucket of this vehicle to the same bucket the player is in
SetRoutingBucketPopulationEnabled(1, false) -- Let's disable population for everything inside this bucket!

Ведра и почему вы должны их использовать

Серверные версии с идентификатором конвейера 3245 и выше добавили функциональность «корзины маршрутизации», которая по своей концепции похожа на функциональность «измерения» или «виртуального мира», наблюдаемую в предыдущих сетевых реализациях GTA, отличных от Rockstar.

Можно назначить игрока или сущность в корзину маршрутизации, и они будут видеть только сущности (и игроки), принадлежащие к одной корзине маршрутизации. В дополнение к этому, каждая корзина маршрутизации будет иметь свою собственную «мировую сетку» для определения владельцев популяции, поэтому, даже если у вас включена популяция, вы не заметите ничего необычного при использовании корзин маршрутизации.

Примеры использования:

  • Многорежимные серверы, на которых вы хотите, чтобы разные игры продолжались, не влияя на другие игры
  • Сессионные/партийные системы
  • «Экран персонажа» инстансируется иначе, чем игровой процесс

Примеры использования явно не включают интерьеры. Интерьеры должны использовать традиционные «скрытые» нативные функции или будущую поддержку политики маршрутизации 3D-области, которая также позволит указать любую «инстансированную» зону для серверов в стиле MMO, чтобы сервер мог иметь область карты, «выделенную» игроку / стороне в миссии, но при этом иметь возможность видеть все, что происходит за пределами этой зоны. источник

Каждая корзина может иметь разные правила, они называются «режимами блокировки» и описаны ниже:

Режим Значение
strict Никакие сущности не могут быть созданы клиентами вообще.
relaxed Блокируются только принадлежащие скриптам сущности, созданные клиентами.
inactive Клиенты могут создать любую сущность, которую они хотят.

Существуют различные типы нативов для маршрутизации корзин (вы можете щелкнуть по ним, чтобы прочитать их документы):

Native
GET_ENTITY_ROUTING_BUCKET
GET_PLAYER_ROUTING_BUCKET
SET_ENTITY_ROUTING_BUCKET
SET_PLAYER_ROUTING_BUCKET
SET_ROUTING_BUCKET_ENTITY_LOCKDOWN_MODE
SET_ROUTING_BUCKET_POPULATION_ENABLED

Примерный пример:

SetRoutingBucketEntityLockdownMode(1, "strict") -- Set the lockdown mode to strict
SetRoutingBucketPopulationEnabled(1, false) -- Let's disable population for everything inside this bucket!
SetPlayerRoutingBucket(source, 1) -- Now the given player (source) won't be able to create entities client-side

Использование государственных пакетов

Государственные пакеты позволяют устанавливать атрибуты сущностям и разрешать другим клиентам доступ к ним, вы можете прочитать больше о государственных пакетах здесь.


Справочник по сценариям