• Из-за обновления 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) последний раз были обновлены:

Есть идея мониторинга количества вызовов эвентов как с клиента так и с сервера. Но...

X-Clusiv

Модератор
Команда форума
Moderator
BackEnd developer
4 Окт 2020
730
329
161
30
Всем привет!
В общем хочу строить метрики основываясь на вызовах эвентов как с сервера так и с клиента.
Первая мысль, это сделать две сущности на сервере, через которые вызывать эвенты.
Ну к примеру:

JavaScript:
//packages
//Прием евентов от клиентов
mp.events.add('server_callEvent', (player, event, ...args)=>{
  mp.events.call(event, player, ...args);
  //сбор данных о вызовах евентов от клиентов
})
//Отправка эвента клиентам(player.callEvent('testEvent', [123]))
mp.Player.prototype.callEvent = (event, args){
  this.call(event, args);
  //сбор данных о отправке евентов клиентам.
}
//С клиента вызов серверных евентов
mp.events.callRemoteCustom = (eventName, ...args) => {
  mp.events.callRemote('server_callEvent', ...[eventName, ...args])
}
Вопрос в том, не будет ли евент 'server_callEvent' как узкое горлышко?
Может кто-то уже пытался реализовать что-то подобное?
Что сам думаю:
По идее, все евенты собираются в некую сущность из которой дергается тот или иной евент при вызове.
Ну и по моему мнению ничего страшного что все летит через один эвент, не должно произойти, так как rage на сколько я понимаю умеет только в один поток...
Тут даже возникает соблазн написать свой обработчик евентов, даже можно какие-нибудь сложные вычисления вытащить в воркеры.
Но это уже совсем другое...
 

LIAS1N

Активный участник
9 Окт 2021
178
31
95
В редаге есть дебагер по эвентам, можешь глянуть и в него встроить метрику
 

X-Clusiv

Модератор
Команда форума
Moderator
BackEnd developer
4 Окт 2020
730
329
161
30
В редаге есть дебагер по эвентам, можешь глянуть и в него встроить метрику
Тут речь не про RedAge. Никогда его не ковырял. А как сам по себе утроен "Дебагер по эвентам", по какому принципу работает?
 

X-Clusiv

Модератор
Команда форума
Moderator
BackEnd developer
4 Окт 2020
730
329
161
30
Ну по идее можно сделать что-то на подобии mp.events.addCustom
JavaScript:
//package
const metric = (eventName, func) => {
    return (...args) => {
        func(...args);
        //функция сбора информации о вызванных евентах(eventName,...args)
    }
}
mp.events.addCustom = (eventName, func) => {
  mp.events.add(eventName, metric(eventName, func));
}
Ну и регистрировать евенты уже не через mp.events.add а через mp.events.addCustom
Конечно понимаю что еще нужно будет переработать mp.events.remove но это уже другой вопрос...
 
Последнее редактирование:

LIAS1N

Активный участник
9 Окт 2021
178
31
95
Тут речь не про RedAge. Никогда его не ковырял. А как сам по себе утроен "Дебагер по эвентам", по какому принципу работает?
Немного поспешил, внимательнее посмотрел твой код, принцип +- такой же. В редаге на сервере кастомный обработчик вызова клиента, и так же на клиенте
 

X-Clusiv

Модератор
Команда форума
Moderator
BackEnd developer
4 Окт 2020
730
329
161
30
Это разве связанные между собой вещи?
А разве нет? Обычно все в js происходит "синхоно", даже в async await. Все кладется в eventLoop.(не берем во внимание воркеры) И по почереди выполняется. Если какая-то функция выполняется другая не начнет свое выполнение. Отличие promise(async await) от простых функций, они просто ложатся также в eventPool и выполняются в свободное процессорное время. После завершения основной функции.
Поэтому я и думаю что нет проблем вызывать все евенты через один кастомный евент, так как всегда(по моему мнению) все выполняется по очереди. Возможно я не прав.
 

ubees

Специалист
11 Фев 2023
492
75
78
40
Ну по идее можно сделать что-то на подобии mp.events.addCustom
JavaScript:
//package
const metric = (func) => {
    return (...args) => {
        func(...args);
        metric(...args);
    }
}
mp.events.addCustom = (eventName, func) => {
  mp.events.add(eventName, metric(func));
}
:unsure: 😐 metric(...args); бесконечная рекурсия
 
  • RoflanEbalo
Реакции: Inoi

UchihaMadara

Гений
FrontEnd developer
27 Окт 2020
912
332
141
А разве нет? Обычно все в js происходит "синхоно", даже в async await. Все кладется в eventLoop.(не берем во внимание воркеры) И по почереди выполняется. Если какая-то функция выполняется другая не начнет свое выполнение. Отличие promise(async await) от простых функций, они просто ложатся также в eventPool и выполняются в свободное процессорное время. После завершения основной функции.
Ты собес решил пройти?) это к @enotit

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

Даже, если можно было бы создавать новые потоки, то eventName какое отношение к этому имеет? Просто как ты у себя в голове это уложил?
 
  • Wow
Реакции: enotit

X-Clusiv

Модератор
Команда форума
Moderator
BackEnd developer
4 Окт 2020
730
329
161
30
Ты собес решил пройти?) это к @enotit


Проблем нет. И то, что ты описал - это несвязанные между собой вещи.

Даже, если можно было бы создавать новые потоки, то какое eventName имеет к этому отношение? Просто как ты у себя в голове это уложил?
Видимо я просто не понимаю твой вопрос...
 

X-Clusiv

Модератор
Команда форума
Moderator
BackEnd developer
4 Окт 2020
730
329
161
30
Реакции: ubees

UchihaMadara

Гений
FrontEnd developer
27 Окт 2020
912
332
141
Видимо я просто не понимаю твой вопрос...
Ну и по моему мнению ничего страшного что все летит через один эвент, не должно произойти, так как rage на сколько я понимаю умеет только в один поток...
Твой тезис выглядит как "Сегодня хорошая погода потому что мимо меня проехала машина".
 
  • RoflanEbalo
Реакции: ubees

koltr

Гуру
BackEnd developer
14 Сен 2020
158
109
121
Интересная задачка, я думаю здесь нужно не рантайм решение, потому что от него смысла нет.

Обрабатывай на клиенте все отправки на сервер callRemote и принятия от сервера add
Храни их в мапе по ключу события и стороны отправки (eventname-server | eventname-client)
По истечению 5-ти минут отправляй результаты на сервер, тем самым у тебя не будет проблем с узким горлышком
 
Реакции: X-Clusiv

X-Clusiv

Модератор
Команда форума
Moderator
BackEnd developer
4 Окт 2020
730
329
161
30
Интересная задачка, я думаю здесь нужно не рантайм решение, потому что от него смысла нет.

Обрабатывай на клиенте все отправки на сервер callRemote и принятия от сервера add
Храни их в мапе по ключу события и стороны отправки (eventname-server | eventname-client)
По истечению 5-ти минут отправляй результаты на сервер, тем самым у тебя не будет проблем с узким горлышком
Ну как обрабатывать метрики, это уже вопрос другой.
А так мысль правильная.
Больше вопрос с том, нет ли каких-то скрытых подводных камней со стороны рейджа.
Вообще понять бы что под капотом рейджа лежит, какова реализация евентной составляющей и оптимизации какие применены к этой системе...
Сейчас пробую через дебагер заглянуть чуть поглубже в рейдж чтобы понять как он регестрирует эвенты внутри, и по какому принципу вызывает их.
 

Inoi

/dev/null
Команда форума
Moderator
VIP
15 Окт 2020
4,273
2,109
208
35
Интересная задачка, я думаю здесь нужно не рантайм решение, потому что от него смысла нет.

Обрабатывай на клиенте все отправки на сервер callRemote и принятия от сервера add
Храни их в мапе по ключу события и стороны отправки (eventname-server | eventname-client)
По истечению 5-ти минут отправляй результаты на сервер, тем самым у тебя не будет проблем с узким горлышком
а не похуй ли на узкое горлышко?
ну как будто бы его проблема не в том что оно одно, а в том что будет за ним - насколько тяжёлые процессы

почему враппер для коллремоута просто не ебануть :unsure:
 

X-Clusiv

Модератор
Команда форума
Moderator
BackEnd developer
4 Окт 2020
730
329
161
30
а не похуй ли на узкое горлышко?
ну как будто бы его проблема не в том что оно одно, а в том что будет за ним - насколько тяжёлые процессы

почему враппер для коллремоута просто не ебануть :unsure:
Да, я как раз хочю понять, если я все вызовы завяжу на один евент, будет ли это проблемой.
Но сейчас подумал почему бы просто не запрототипировать mp.events.add и mp.Players.call не выдумывать велосипед...
Что-то по типу

JavaScript:
// Прототипируем mp.events.add
const originalAdd = mp.events.add;

mp.events.add = function(eventName, handler) {
  const wrappedHandler = function(...args) {
    try {
      // Выполняем оригинальный обработчик
      const result = handler.apply(this, args);
      //Метрика, промитеус или еще что.
      return result;
    } catch (error) {
      throw error;
    }
  };
 
  // Вызываем оригинальную функцию
  return originalAdd.call(this, eventName, wrappedHandler);
};
 

Inoi

/dev/null
Команда форума
Moderator
VIP
15 Окт 2020
4,273
2,109
208
35
Да, я как раз хочю понять, если я все вызовы завяжу на один евент, будет ли это проблемой.
Но сейчас подумал почему бы просто не запрототипировать mp.events.add и mp.Players.call не выдумывать велосипед...
Что-то по типу

JavaScript:
// Прототипируем mp.events.add
const originalAdd = mp.events.add;

mp.events.add = function(eventName, handler) {
  const wrappedHandler = function(...args) {
    try {
      // Выполняем оригинальный обработчик
      const result = handler.apply(this, args);
      //Метрика, промитеус или еще что.
      return result;
    } catch (error) {
      throw error;
    }
  };

  // Вызываем оригинальную функцию
  return originalAdd.call(this, eventName, wrappedHandler);
};
да не должно быть
проблема же не в одном евенте а в том, что внутри него может быть
ну как будто бы

и да ну я примерно об этом и говорю
 
Реакции: X-Clusiv

X-Clusiv

Модератор
Команда форума
Moderator
BackEnd developer
4 Окт 2020
730
329
161
30
Ну и так, немножко подрезюмирую, что интересного удалось понять о евентах в рейдже.
Они просто собираются в своеобразную хеш таблицу => mp.events.binded по сути это объект, в котором ключ это имя евента, а значение это массив, в который при mp.events.add просто пушится функция.
JavaScript:
add: function (event, handler, to_front) {
        if (!handler) {
          if (typeof event == "object") {
            for (key in event) {
              this.add(key, event[key]);
            }
          }
        } else {
          if (!this.binded[event]) {
            this.binded[event] = [];
            mp._events.add(event, new Function(`return this.fire('${event}', arguments);`).bind(this));
          }

          if (to_front)
            this.binded[event].push(handler);
          else
            this.binded[event].push(handler);
        }
      },

И при вызове(mp.events.call) просто проходится по массиву по очереди вызывая функции обработчики.

JavaScript:
fire: function (event, args) {
        let ev = this.binded[event];

        if (ev) {
          if (typeof (args[0]) == 'Object' &&
            args[0].events) {
            args[0].events.invoke(eventName, args);
          }

          let __ev = {
            cancel: false,
            self: null
          };

          for (let _event of ev) {
            __ev.self = _event;
            _event.apply(__ev, args);

            if (__ev.cancel) {
              break;
            }
          }

          if (__ev.cancel) {
            return true;
          }
        }

      },
 
Реакции: enotit

X-Clusiv

Модератор
Команда форума
Moderator
BackEnd developer
4 Окт 2020
730
329
161
30
Ну и так, немножко подрезюмирую, что интересного удалось понять о евентах в рейдже.
Они просто собираются в своеобразную хеш таблицу => mp.events.binded по сути это объект, в котором ключ это имя евента, а значение это массив, в который при mp.events.add просто пушится функция.
JavaScript:
add: function (event, handler, to_front) {
        if (!handler) {
          if (typeof event == "object") {
            for (key in event) {
              this.add(key, event[key]);
            }
          }
        } else {
          if (!this.binded[event]) {
            this.binded[event] = [];
            mp._events.add(event, new Function(`return this.fire('${event}', arguments);`).bind(this));
          }

          if (to_front)
            this.binded[event].push(handler);
          else
            this.binded[event].push(handler);
        }
      },

И при вызове(mp.events.call) просто проходится по массиву по очереди вызывая функции обработчики.

JavaScript:
fire: function (event, args) {
        let ev = this.binded[event];

        if (ev) {
          if (typeof (args[0]) == 'Object' &&
            args[0].events) {
            args[0].events.invoke(eventName, args);
          }

          let __ev = {
            cancel: false,
            self: null
          };

          for (let _event of ev) {
            __ev.self = _event;
            _event.apply(__ev, args);

            if (__ev.cancel) {
              break;
            }
          }

          if (__ev.cancel) {
            return true;
          }
        }

      },
Только не пойму что за to_front вроде никак на логику не влияет наличие или отсутствие этой переменной(может остаточный код который забыли подчистить:unsure:)
 

Inoi

/dev/null
Команда форума
Moderator
VIP
15 Окт 2020
4,273
2,109
208
35
видимо должен был быть unshift если to_front
ну приоритет очереди
а потом забили хуй

хз в чем иначе смысл был
 
Реакции: X-Clusiv