• Из-за обновления GTA 5 (был добавлен новый патч) может временно не работать вход в RAGE Multiplayer.

    Ошибка: Ваша версия Grand Theft Auto V не поддерживается RAGE Multiplayer.
    ERROR: Your game version is not supported by RAGE Multiplayer.

    Данная ошибка говорит о том, что GTA V обновилась до новой версии (GTA Online тоже). Вам необходимо обновить саму игру в главном меню вашего приложения (Steam / Epic Games / Rockstar Games).
    Если после этого RAGE:MP все равно не работает - вам нужно дождаться выхода патча для самого мультиплеера (обычно это занимает от нескольких часов до нескольких дней).

    Новости и апдейты Rockstar Games - https://www.rockstargames.com/newswire/
    Статус всех служб для Rockstar Games Launcher и поддерживаемых игр: https://support.rockstargames.com/ru/servicestatus


    Grand Theft Auto 5 (+ GTA Online) последний раз были обновлены:

Вопрос Обязательно ли совершать действия с API в основном потоке?

frytech

Участник портала
15 Янв 2022
128
13
53
1647851792816.png

Есть такой параметр в конфигурации. Если его выставить в false, то серверу не важно, из какого потока я взаимодействую с API. Но если true, то он ругается на такие вещи.
Вопрос заключается в том, оправдано ли в принципе совершать действия с API в разных потоках, или же это нехорошо?
Допустим, полную асинхронность в вызове ивентов на сервере сделать не получится, если, например, проходиться по массиву игроков и высчитывать дистанцию в основном потоке. Подскажите, как лучше делать, кто разбирается :)
 

Sinage

Участник портала
Мошенник
17 Дек 2021
72
20
73
Посмотреть вложение 3954
Есть такой параметр в конфигурации. Если его выставить в false, то серверу не важно, из какого потока я взаимодействую с API. Но если true, то он ругается на такие вещи.
Вопрос заключается в том, оправдано ли в принципе совершать действия с API в разных потоках, или же это нехорошо?
Допустим, полную асинхронность в вызове ивентов на сервере сделать не получится, если, например, проходиться по массиву игроков и высчитывать дистанцию в основном потоке. Подскажите, как лучше делать, кто разбирается :)
На сколько сам знаю, любые действия с API не могут выполняться из какого либо другого потока. Именно поэтому и был создан NAPI.Task.Run зачем его вообще тогда создавать если по твоей логике, отключив предупреждения мы избавимся от болезни? А цикл перебора всех игроков лучше полностью и целиком упаковать в NAPI.Task.Run потому что войти в главный поток один раз будет куда быстрее чем входить каждую итерацию.
 

frytech

Участник портала
15 Янв 2022
128
13
53
На сколько сам знаю, любые действия с API не могут выполняться из какого либо другого потока. Именно поэтому и был создан NAPI.Task.Run зачем его вообще тогда создавать если по твоей логике, отключив предупреждения мы избавимся от болезни? А цикл перебора всех игроков лучше полностью и целиком упаковать в NAPI.Task.Run потому что войти в главный поток один раз будет куда быстрее чем входить каждую итерацию.
Но если отключить в конфиге проверку, то они выполняются, все работают. Вопрос в том, насколько это оправдано. Я вообще не потоки другие использую по сути, а Tasks и async методы. Т.е. явно потоки не создаю, они при необходимости из пула потоков берутся.
Мне просто непонятно, почему не проходиться по всем игрокам в цикле асинхронно относительно основного потока, это же по производительности логичнее.
 

XDeveluxe

⚡️BackEnd Developer
Команда форума
Moderator
High developer
BackEnd developer
30 Авг 2021
2,766
1,581
211
28
Все действия, связанные с RAGE.API должны выполняться ТОЛЬКО и ТОЛЬКО в основном потоке, это прямая обязанность вне зависимости от настроек.
Это было множество раз подтверждено и разработчиками мультиплеера.
Конфиг, который ты прикрепил, только поможет выявить, когда API используется вне основного потока.
Лучше всего это проверяется на сборке Linux, Windows странно обрабатывает эти моменты.

1647853015223.png
 

frytech

Участник портала
15 Янв 2022
128
13
53
Все действия, связанные с RAGE.API должны выполняться ТОЛЬКО и ТОЛЬКО в основном потоке, это прямая обязанность вне зависимости от настроек.
Это было множество раз подтверждено и разработчиками мультиплеера.
Конфиг, который ты прикрепил, только поможет выявить, когда API используется вне основного потока.
Спасибо, на главный вопрос я ответ получил. А не знаешь, с чем это связано?
 

frytech

Участник портала
15 Янв 2022
128
13
53
Все действия, связанные с RAGE.API должны выполняться ТОЛЬКО и ТОЛЬКО в основном потоке, это прямая обязанность вне зависимости от настроек.
Это было множество раз подтверждено и разработчиками мультиплеера.
Конфиг, который ты прикрепил, только поможет выявить, когда API используется вне основного потока.
Лучше всего это проверяется на сборке Linux, Windows странно обрабатывает эти моменты.

Посмотреть вложение 3955
В таком случае не имеет смысла использовать async Task вместо обычных методов для тех же RemoteEvents, например? Раз там по большей части все равно приходится взаимодействовать с основным потоком через NAPI.Task.Run. asynk Task только для взаимодействия с БД разумен в использовании?
 

XDeveluxe

⚡️BackEnd Developer
Команда форума
Moderator
High developer
BackEnd developer
30 Авг 2021
2,766
1,581
211
28
Получить ремоут ивент на сервере ты можешь в асинхронный метод, это будет работать, если внутри нет кода, который взаимодействует с RAGE.API, полезно может быть на авторизации и регистрации, так как там как раз будет взаимодействие с базой данных, плюс запросов может быть много (если проект не маленький).
Отправить ремоут ивент извне главного потока - нельзя, это не будет работать (на Linux'е точно, как я и сказал - Windows как-то странно обрабатывает это, чуть ли не рандомно).
Любое взаимодействие с базой данных всегда должно происходить асинхронно, чтобы не блокировать главный поток на это время.
Почему так сделано в RAGE - Я не могу подсказать, просто как факт принят еще несколько лет назад, что здесь только так и по-другому нельзя. На развёрнутом масштабно проекте всё будет работать хорошо только в случае, если придерживаться того, как должно быть.
 

frytech

Участник портала
15 Янв 2022
128
13
53
Получить ремоут ивент на сервере ты можешь в асинхронный метод, это будет работать, если внутри нет кода, который взаимодействует с RAGE.API.
Отправить ремоут ивент извне главного потока - нельзя, это не будет работать (на Linux'е точно, как я и сказал - Windows как-то странно обрабатывает это, чуть ли не рандомно).
Любое взаимодействие с базой данных всегда должно происходить асинхронно, чтобы не блокировать главный поток на это время.
Почему так сделано в RAGE - Я не могу подсказать, просто как факт принят еще несколько лет назад, что здесь только так и по-другому нельзя. На развёрнутом масштабно проекте всё будет работать хорошо только в случае, если придерживаться того, как должно быть.
Спасибо
 

DaVilka

Старожил
BackEnd developer
16 Сен 2020
759
276
128
В таком случае не имеет смысла использовать async Task вместо обычных методов для тех же RemoteEvents, например? Раз там по большей части все равно приходится взаимодействовать с основным потоком через NAPI.Task.Run. asynk Task только для взаимодействия с БД разумен в использовании?
Имеет смысл еще какой, просто апи рейджа нужно использовать не как методы от которых нужно отталкиваться при разработке, а на оборот, как результат работы собственных методов. На пример, у тебя есть апи машины, что бы ее создать тебе нужно такие то и такие то параметры, обычно эти параметры хранят и используют непонятно как, составляют какие то бесконечные списки хешей, координат и тд, тебе же надо описать свой класс машины, который будет иметь нужные тебе параметры, и из которым именно сервер будет работать, а апишный класс машины использовать как внутриигровой объект, т.е., любые взаимодействия игрока с машиной будут передаваться в серверный класс машины а не рейджовский. Это позволит и использовать апи рейджа в основном потоке, и максимально использовать возможности языка на котором ты пишешь мод, и не городить костыли из .GetData/.SetData, так как свой класс ты можешт расширять сколько угодно
 

DaVilka

Старожил
BackEnd developer
16 Сен 2020
759
276
128
Так же на пример в C# есть такая тема как делегаты, вызов делегата происходит в том потоке в котором он был создан, ты можешь использовать свои таски и потоки а результат передавать в мейн поток где и будет выполнятся результат рейджовским апи
 

frytech

Участник портала
15 Янв 2022
128
13
53
Имеет смысл еще какой, просто апи рейджа нужно использовать не как методы от которых нужно отталкиваться при разработке, а на оборот, как результат работы собственных методов. На пример, у тебя есть апи машины, что бы ее создать тебе нужно такие то и такие то параметры, обычно эти параметры хранят и используют непонятно как, составляют какие то бесконечные списки хешей, координат и тд, тебе же надо описать свой класс машины, который будет иметь нужные тебе параметры, и из которым именно сервер будет работать, а апишный класс машины использовать как внутриигровой объект, т.е., любые взаимодействия игрока с машиной будут передаваться в серверный класс машины а не рейджовский. Это позволит и использовать апи рейджа в основном потоке, и максимально использовать возможности языка на котором ты пишешь мод, и не городить костыли из .GetData/.SetData, так как свой класс ты можешт расширять сколько угодно
А как мне обойти использование GetData/SetData и shared аналоги? Они то в любом случае только в основном потоке выполняются и при любом взаимодействии с машиной мне нужно будет и в shared пихать и вызывать триггер нужный у игроков в зоне стрима, чтобы синхра работала как надо.
 

frytech

Участник портала
15 Янв 2022
128
13
53
Я думал над тем, что зачем мне setdata/getdata, если я могу полностью свои классы сделать, но потом подумал, что я все равно большую часть инфы храню в SharedData для синхронизации, поэтому пока что ничего другого, кроме как использование полей, не придумал (есть класс PlayerData и у каждого его объекта есть поля, вот пример одного из них):

public bool Knocked { get => Player.GetSharedData<bool>("Knocked"); set { Player.SetSharedData("Knocked", value); Utils.TriggerEventToStreamed(Player, "Players::SetKnocked", Player.Handle, value); } }
 

DaVilka

Старожил
BackEnd developer
16 Сен 2020
759
276
128
Я думал над тем, что зачем мне setdata/getdata, если я могу полностью свои классы сделать, но потом подумал, что я все равно большую часть инфы храню в SharedData для синхронизации, поэтому пока что ничего другого, кроме как использование полей, не придумал (есть класс PlayerData и у каждого его объекта есть поля, вот пример одного из них):

public bool Knocked { get => Player.GetSharedData<bool>("Knocked"); set { Player.SetSharedData("Knocked", value); Utils.TriggerEventToStreamed(Player, "Players::SetKnocked", Player.Handle, value); } }
Ну тут я не могу дать простой ответ, возможно в твоем случае более оправдано использовать SetSharedData для синхры, но я считаю что если делать нормальную систему верификации то тут не обойтись без серверной системы стрима, которая каким либо образом выдавала бы нужную инфу игроку в нужной зоне/близь лежащих зонах информацию
 

frytech

Участник портала
15 Янв 2022
128
13
53
Ну тут я не могу дать простой ответ, возможно в твоем случае более оправдано использовать SetSharedData для синхры, но я считаю что если делать нормальную систему верификации то тут не обойтись без серверной системы стрима, которая каким либо образом выдавала бы нужную инфу игроку в нужной зоне/близь лежащих зонах информацию
Думаешь лучше будет сделать свою систему передачи данных об игроке другому игроку, когда тот входит в его зону стрима? Без использования SharedData дефолтной?
 

DaVilka

Старожил
BackEnd developer
16 Сен 2020
759
276
128
Думаешь лучше будет сделать свою систему передачи данных об игроке другому игроку, когда тот входит в его зону стрима? Без использования SharedData дефолтной?
Тут как я думаю сама система местоположения игрока и окружающих его вещей/действий должна быть реализована на много глубже чем предоставляет апи рейджа, иначе ты получишь "гта онлайн" где любой залетный может скачать чит и прописать себе миллиард. Ты должен присекать возможности различных хаков, телепорта, спавна тачек, спидхаков и тд, а что бы их пресечь тебе необходимы собственные реализации разных процессов, что бы верифицировать телепорт тебе нужна своя система перемещения игрока, может он туда пройти или телепортироваться или не может. На фоне этих реализаций передача информации игроку о другом игроке у тебя появится "сама по себе".

Так же, если ты пишешь на шарпе, я бы рекомендовал по максимуму отделится от статический классов и от наследования GTANetworkAPI.Script, наследовать его только в мейн класе, и классах враперах нативных апи, а весь мод писать чисто на динамических классах. Лично я заморочился и переписал стандартные рейджовские ивенты на делегаты, как это сделано в альтв, таким образом я могу получить доступ к нативным ивентам из динамического класса, который не наследует Scripts.
 

frytech

Участник портала
15 Янв 2022
128
13
53
Тут как я думаю сама система местоположения игрока и окружающих его вещей/действий должна быть реализована на много глубже чем предоставляет апи рейджа, иначе ты получишь "гта онлайн" где любой залетный может скачать чит и прописать себе миллиард. Ты должен присекать возможности различных хаков, телепорта, спавна тачек, спидхаков и тд, а что бы их пресечь тебе необходимы собственные реализации разных процессов, что бы верифицировать телепорт тебе нужна своя система перемещения игрока, может он туда пройти или телепортироваться или не может. На фоне этих реализаций передача информации игроку о другом игроке у тебя появится "сама по себе".

Так же, если ты пишешь на шарпе, я бы рекомендовал по максимуму отделится от статический классов и от наследования GTANetworkAPI.Script, наследовать его только в мейн класе, и классах враперах нативных апи, а весь мод писать чисто на динамических классах. Лично я заморочился и переписал стандартные рейджовские ивенты на делегаты, как это сделано в альтв, таким образом я могу получить доступ к нативным ивентам из динамического класса, который не наследует Scripts.
Так это все и так понятно, мне не ясно только, что лучше использовать, SharedData из коробки или свою систему хранения информации
 

DaVilka

Старожил
BackEnd developer
16 Сен 2020
759
276
128
Так это все и так понятно, мне не ясно только, что лучше использовать, SharedData из коробки или свою систему хранения информации
если ты не собираешься строить геосетку и отталкиваешься только от зоны стрима, то в таком случае лучше SharedData. Просто то что я описал выше практически полностью исключает текстовые идентификаторы, даже ивенты используют айдишники, а не имена(лично у меня в моде не используются вообще getdata/setdata/shareddata ни в каком виде если это возможно), да и в реализации гораздо сложнее, если ты не продумывал архитектуру то лучше юзать то что есть
 

frytech

Участник портала
15 Янв 2022
128
13
53
если ты не собираешься строить геосетку и отталкиваешься только от зоны стрима, то в таком случае лучше SharedData. Просто то что я описал выше практически полностью исключает текстовые идентификаторы, даже ивенты используют айдишники, а не имена(лично у меня в моде не используются вообще getdata/setdata/shareddata ни в каком виде если это возможно), да и в реализации гораздо сложнее, если ты не продумывал архитектуру то лучше юзать то что есть
Спасибо за помощь)
 

Nelox

Активный участник
5 Май 2021
136
33
90
К примеру я когда то убрал большинство setdata/getdata (пока что только для Entity.Player игроков) и храню все в Main.Players[player] данные. Когда то тесты знакомый проводил, вроде быстрее работает) Ну а по факту хотя бы выполняет свои функции и не мешает потоку
но ведь примеры разные. Ты просто создал кастомный класс для своей информации на СЕРВЕРНОЙ и используешь его там. А автор выше( фрайтеч) говорит про синхру с клиентом, где юзает шейрдата. Разные 2 примера