Error expired multiplayer object has been used

Ваш ник: Artur Volkonov Ваш игровой логин: Barmaley7156 Описание проблемы: Откуда ни возьмись стали вылетать ошибки Expired multiplayer object has been used. Название ошибки: Callback Invoke Error #10 Доказательства: Дата: 3.05.2021 Сумма ущерба(если имеется): нет.

  • #1

  • Ваш ник: Artur Volkonov
  • Ваш игровой логин: Barmaley7156
  • Описание проблемы: Откуда ни возьмись стали вылетать ошибки Expired multiplayer object has been used. Название ошибки: Callback Invoke Error #10
  • Доказательства:
  • Дата: 3.05.2021
  • Сумма ущерба(если имеется): нет.

Esco Aeiangln

  • #2

Здравствуйте, исправим проблему в ближайшее время.

Содержание

  1. JS Работа дровосека
  2. Вопрос Сохранение данных о персонаже во время выхода из игры.
  3. askjbdaksd
  4. Mafia City RP v2.19.1 — Changelog 2022-5-10
  5. Важно Частые ошибки RAGE:MP и пути их решения (troubleshooting_ru)
  6. Harland David Sanders
  7. Важно Частые ошибки RAGE:MP и пути их решения (troubleshooting_ru)
  8. Yaroslav1243

JS Работа дровосека

Всем привет, на работке в свободное время решил написать небольшую работу для этого замечательного ресурса. Может кому будет интересно, плюс если кто сможет, небольшое код-ревью дать, буду рад критике и советам.
Работа на чистом nodeJs + vue.

Начнём с серверной части, «рассадим» деревья по точкам:
Создадим массив с id-идентификатором дерева(понадобится в дальнейшем), и координатами(место «посадки» дерева)

Для установки деревьев выбрал метод перебора созданного раннее массива allTrees — forEach, в котором создаём дерево для каждого объекта в массиве, а также назначаем каждому дереву собственный id и задаём собственный вариабл с этим же id для его использования уже на клиентской части.
Для визуального восприятия добавим надпись для каждого дерева «Нажмите [Е]».
Ну и немного работы с консолью в конце.
Получилось прекрасно..

Далее, чтобы начать взаимодействовать с этими деревьями нужно перейти в клиентскую часть.
Чтобы устроиться на работу, нужно для начала найти компанию(в данном случае npc), которая даст вам эту самую работу.
Создадим массив обектов(в данном случае, он один), зададим в нём координаты npc, его направление(heading), имя и модель
Почему массив объектов, потому что в дальнейшем можно будет с лёгкостью добавить ещё одного npc.

Вот он. Красавчик стоит, в шлёпках да в футболке, заправленной в трусы, а на футболке той топор нарисован, значит лесоруб, верно?


Теперь для того. чтобы взаимодействовать с данным npc, нужно использовать метод playerEnterColshape, также потребуется метод бинда кнопки mp.keys.bind, при нажатии на которую начнётся то самое взаимодействие.

Источник

Вопрос Сохранение данных о персонаже во время выхода из игры.

askjbdaksd

Участник портала

Всем привет, появился вопрос для разработчиков которые используют mongodb (mongoose).

У меня есть две таблицы: User, Character.
В таблице User я использую ref для сохранения данных о персонаже (в таблице Character), всё это выглядит примерно так:

В таблице Character у меня есть «position», представленный как объект (для сохранения позиции игрока при его выходе из игры).

Так вот, это всё я веду к тому, что при использовании ивента «playerQuit’, я встречаю подобную ошибку: «Expired multiplayer object has been used».
Вот как это выглядит (код):

а причём здесь вообще монго?
не оч выкупаю как её документация тут может помочь

это же ошибка, которая пишет тебе, что ты пытаешься обращаться к объекту, которого нет

не уверен что правильно сформулирую мысль, но

это разве не происходит из-за асинхронного метода?
для ио кода — игрок уже не в пуле — и просто отдаёт тебе андефайнед, насколько я понимаю
наверное, можно сделать проверку с mp.players.exists(player), ну чисто чтобы убедиться

чтобы это обойти — наверное нужен либо конструктор, который соберёт тебе копию с данными о плеере, инфу из которого ты уже будешь сохранять
либо сторить-вытаскивать её гетвариаблами, сначала например, и их уже сохранять
но глобально я не очень понимаю зачем здесь вообще async-await
ты же просто сохраняешь инфу о плеере при выходе — зачем тебе в целом знать, сохранилась она или нет, чего ты ждёшь?

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

Источник

Mafia City RP v2.19.1 — Changelog 2022-5-10

Release Date: 2022-5-10
Version: 2.19.1
Type of Release: General Release + Bug Fixes

Today’s release includes a few bug fixes, lots of QoL, and a new feature.

New Features

  • New group chat (/g for players, /toggchat for players, /toggchat for GLs to disable for entire group) (Tom)

Bug Fixes

  • Fixed dragging stops while entering a vehicle (Josh)
  • Improved player initialization when they join the server (Josh)
  • Fixed respawning in place (Josh)
  • Fixed being able to text while being cuffed (Josh)

Quality Of Life / Improvements

  • Implemented toast notifications for a better user experience & implemented toast notifications for interaction cooldown (Rockhopper)
  • Add load & unload logic for ipls on Dynamic Doors (Josh)
  • Disabled rope functionality on flatbeds (Josh)
  • Updated DM / VDM options of the B Menu to take player ID as input for in game moderation (Rockhopper)
  • You can now discard fish while on a board (Nefarious)
  • NChat bans will no longer show when you have nchat disabled (Tom)

Sentry Issues

  • Resolved an issue with expired multiplayer object has been used with radios (Rockhopper)
  • Resolved an issue with ‘id’ being undefined with the report manager (Rockhopper)
  • Resolved an issue with ‘setVariable’ being null with groups (Rockhopper)
  • Resolved an issue with expired multiplayer object has been used with property manager (Rockhopper)
  • Resolved an issue with ‘currentWeight’ being null with the inventory manager (Rockhopper)
  • Resolved an issue with ‘smodeCheck’ being undefined with the property manager (Rockhopper)
  • Resolved an issue with ‘health’ being undefined with vehicle manager (Rockhopper)

Источник

Важно Частые ошибки RAGE:MP и пути их решения (troubleshooting_ru)

Harland David Sanders

Куратор портала

⚙ Все известные ошибки и способы их решения (листайте страницу и ищите свою проблему).
🖥
Если у вас есть проблема с запуском RAGE:MP и ее нет в списке — пишите в данную тему, постараюсь помочь.

ERROR: Could not access game process. Shutdown Steam/RGS/EGS and try again.
Как и сказано в ошибке: завершите все процессы Steam / Rockstar Game Service / Epic Games Store и попробуйте подключится еще раз. Также некоторым помогает запуск от имени администратора и отключение антивируса (или добавления каталога RAGE:MP в исключения антивируса, часто подобные проблемы возникают на антивирусе Kaspersky).

System.ComponentModel.Win32Exception (0x80004005)
Выключите любые антивирусы или добавьте папку в исключения и попробуйте установить RAGE снова. Эта ошибка чаще всего встречается если антивирус удаляет файлы мультиплеера.
Если отключение антивируса/windows defender не помогла, нажмите пкм на updater.exe и выберите в меню «Troubleshoot compatibility»/»Исправление проблем с совместимостью».

ERROR: Your game version is not supported by RAGE Multiplayer.


Please upgrade to 1.54 (16 March 2021) in order to continue playing.

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

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

Если же обновления GTA V не было, то вы используете старую версию и необходимо обновиться.
Новости и апдейты Rockstar Games — https://www.rockstargames.com/ru/newswire/

(STEAM ONLY) Запускается одиночный режим или запускается сингл вместо мультиплеера.
Выйдите из стима, потом запустите RAGE и дайте ему запустить стим самому, после чего вы с большой вероятностью загрузитесь в мультиплеер.

Игра не запускается или запускается и сразу отключается
Удалите любые моды, установленные в папке GTA.
Пользователям NVIDIA: отключите Nvidia Shadowplay и попробуйте зайти снова.

Игра отключается после захода на сервер (Как только появляется надпись «Multiplayer started»)
Попробуйте переместить папку с RAGE на другой диск (Например, из C: в D:)
Если сервер с войс чатом, отключите любые программы, которые блокируют доступ к микрофону или изменяют ваш голос.

Failed to retrieve the install directory (Не удалось найти путь установки)
Это происходит, когда вы указываете неверную папку с GTA V или исполняемый файл гта/любые другие файлы нужно обновить. Во-первых, убедитесь, что вы указали верную папку с GTAV.exe. Если папка указана верно, то запустите верификацию файлов гта.

RageMP зависает, когда я нажимаю на сервер
Зачастую это происходит когда в папке с гта отсутствует файл GTAV.exe. Если файл присутствует, то проверьте, может ли стим запустить гта 5.

Я запускаю RAGE Multiplayer и ничего не происходит
Выключите любые антивирусы или добавьте папку в исключения, это происходит, когда не хватает каких либо файлов RAGE. Если у вас нет антивируса, переустановите RAGE Multiplayer.

I’m getting frameskipping while playing on any server (Не понял, что такое frameskipping, сами переводите как хотите)
Отключите autohotkey. Если монитор 144Hz, ограничьте fps/hz до 60.

GTA V запускается с черным экраном, а затем внезапно закрывается/вылетает после нажатия «Play Now»
Если это происходит впервые после запуска RageMP или вы только что его переустановили, это происходит из-за того, что кнопка ‘Play Now’ переподключает к последнему серверу, на котором вы играли. Используйте вкладку ‘Servers’ иди ‘Direct Connect’, если подключаетесь впервые, после этого можно использовать «Play Now».

GTA V запускается с черным экраном и отключается.
Возможные программы, из-за которых это происходит:

  • MSI Afterburner
  • AI Suite 3
  • GameFirst V
  • Malwarebytes
  • Norton Security / Antivirus Software
  • RivaTuner Statistics Server (7.2.2)
  • Microsoft Gaming Overlay (или ‘Game Bar’)

Чтобы удостовериться, что это одна из программ выше, откройте файл main_logs.txt в папке GTA V. Если там будет надпись FYDIGF, то необходимо отключить эти программы.

«A legal up to date Grand Theft Auto V copy is required to play RAGE Multiplayer»
Нужно купить лицензионную копию игры.
Если вы приобрели игру и все равно видите эту ошибку, верифицируйте файлы. Если это не помогает, перейдите в папку с гта и удалите Файл ‘GTA5.exe’, затем запустите ‘PlayGTA5.exe’ и загрузитесь в игру. После этого попробуйте зайти через RAGE повторно.

RageMP закрывается сразу после открытия
Выключите любые антивирусы или добавьте папку в исключения, затем перезагрузите компьютер.
Если это не помогло, то, возможно, ваше подключение блокирует cloudflare, попробуйте подключиться через VPN.

Запускается одиночный режим или главное меню
Убедитесь, что пакет Visual C++ redistributable 2015 (https://www.microsoft.com/en-us/download/details.aspx?id=48145) был установлен.
Если он установлен, отключите windows defender.

System.Net.WebException: The remote server returned an error: (403)
Ваш IP был заблокирован, смените его или используйте VPN.

Если ничего выше не помогло, попробуйте сделать следующее:

  1. Переустановите RAGE Multiplayer.
  2. Убедитесь, что игра никак не была модифицирована.
  3. Переустановите GTA V или пройдите верификацию файлов.
  4. Запустите RAGE Multiplayer от имени администратора.
  5. Установите необходимые пакеты:
    https://www.microsoft.com/en-us/download/details.aspx?id=48145
    https://www.microsoft.com/en-us/download/details.aspx?id=53344&desc=dotnet462
  6. Установите RAGE Multiplayer и GTA V на один диск.
  7. Установите RageMP и GTA V на разные диски.
  8. Отключите любые оверлеи (Steam, OBS, Discord overlay, Overwolf).
  9. Убедитесь, что присутствует файл сохранения (запустите одиночную игру и сохраните ее).
  10. Удалите любые моды на GTA V.
  11. Выключите любые антивирусы или добавьте папку в исключения. Добавьте RAGE в исключения Firewall.
  12. Нажмите пкм на ragemp.exe и выберите в меню «Troubleshoot compatibility»/»Исправление проблем с совместимостью».
  13. (NVIDIA USERS) отключите Shadowplay.
  14. (STEAM ONLY) Выйдите из стима, потом запустите RAGE и дайте ему запустить стим самому.

Внимание! Самый важный шаг, когда уже ничего не помогает:

Полностью удаляем отовсюду Rockstar Games Service и Social Club если установлен + очищаем папки в Документах, AppData.
Полностью удаляем все файлы GTA V и начинаем качать заного, дожидаемся окончания загрузки.
Делаем первый пробный вход в СЮЖЕТНЫЙ РЕЖИМ и доходим до момента спавна персонажа, после чего выходим с игры.
Теперь уже подключайтесь через RAGE Multiplayer к любимому серверу, 99% все будет работать.

Источник: https://rage.mp/forums/topic/1816-client-troubleshooting-tips-fixes/

ragemp не запускается ragemp ошибка gta5rp не запускается

Источник

Важно Частые ошибки RAGE:MP и пути их решения (troubleshooting_ru)

Yaroslav1243

Новый участник

⚙ Все известные ошибки и способы их решения (листайте страницу и ищите свою проблему).
🖥
Если у вас есть проблема с запуском RAGE:MP и ее нет в списке — пишите в данную тему, постараюсь помочь.

ERROR: Could not access game process. Shutdown Steam/RGS/EGS and try again.
Как и сказано в ошибке: завершите все процессы Steam / Rockstar Game Service / Epic Games Store и попробуйте подключится еще раз. Также некоторым помогает запуск от имени администратора и отключение антивируса (или добавления каталога RAGE:MP в исключения антивируса, часто подобные проблемы возникают на антивирусе Kaspersky).

System.ComponentModel.Win32Exception (0x80004005)
Выключите любые антивирусы или добавьте папку в исключения и попробуйте установить RAGE снова. Эта ошибка чаще всего встречается если антивирус удаляет файлы мультиплеера.
Если отключение антивируса/windows defender не помогла, нажмите пкм на updater.exe и выберите в меню «Troubleshoot compatibility»/»Исправление проблем с совместимостью».

ERROR: Your game version is not supported by RAGE Multiplayer. Посмотреть вложение 2053
Please upgrade to 1.54 (16 March 2021) in order to continue playing.

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

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

Если же обновления GTA V не было, то вы используете старую версию и необходимо обновиться.
Новости и апдейты Rockstar Games — https://www.rockstargames.com/ru/newswire/

(STEAM ONLY) Запускается одиночный режим или запускается сингл вместо мультиплеера.
Выйдите из стима, потом запустите RAGE и дайте ему запустить стим самому, после чего вы с большой вероятностью загрузитесь в мультиплеер.

Игра не запускается или запускается и сразу отключается
Удалите любые моды, установленные в папке GTA.
Пользователям NVIDIA: отключите Nvidia Shadowplay и попробуйте зайти снова.

Игра отключается после захода на сервер (Как только появляется надпись «Multiplayer started»)
Попробуйте переместить папку с RAGE на другой диск (Например, из C: в D:)
Если сервер с войс чатом, отключите любые программы, которые блокируют доступ к микрофону или изменяют ваш голос.

Failed to retrieve the install directory (Не удалось найти путь установки)
Это происходит, когда вы указываете неверную папку с GTA V или исполняемый файл гта/любые другие файлы нужно обновить. Во-первых, убедитесь, что вы указали верную папку с GTAV.exe. Если папка указана верно, то запустите верификацию файлов гта.

RageMP зависает, когда я нажимаю на сервер
Зачастую это происходит когда в папке с гта отсутствует файл GTAV.exe. Если файл присутствует, то проверьте, может ли стим запустить гта 5.

Я запускаю RAGE Multiplayer и ничего не происходит
Выключите любые антивирусы или добавьте папку в исключения, это происходит, когда не хватает каких либо файлов RAGE. Если у вас нет антивируса, переустановите RAGE Multiplayer.

I’m getting frameskipping while playing on any server (Не понял, что такое frameskipping, сами переводите как хотите)
Отключите autohotkey. Если монитор 144Hz, ограничьте fps/hz до 60.

GTA V запускается с черным экраном, а затем внезапно закрывается/вылетает после нажатия «Play Now»
Если это происходит впервые после запуска RageMP или вы только что его переустановили, это происходит из-за того, что кнопка ‘Play Now’ переподключает к последнему серверу, на котором вы играли. Используйте вкладку ‘Servers’ иди ‘Direct Connect’, если подключаетесь впервые, после этого можно использовать «Play Now».

GTA V запускается с черным экраном и отключается.
Возможные программы, из-за которых это происходит:

  • MSI Afterburner
  • AI Suite 3
  • GameFirst V
  • Malwarebytes
  • Norton Security / Antivirus Software
  • RivaTuner Statistics Server (7.2.2)
  • Microsoft Gaming Overlay (или ‘Game Bar’)

Чтобы удостовериться, что это одна из программ выше, откройте файл main_logs.txt в папке GTA V. Если там будет надпись FYDIGF, то необходимо отключить эти программы.

«A legal up to date Grand Theft Auto V copy is required to play RAGE Multiplayer»
Нужно купить лицензионную копию игры.
Если вы приобрели игру и все равно видите эту ошибку, верифицируйте файлы. Если это не помогает, перейдите в папку с гта и удалите Файл ‘GTA5.exe’, затем запустите ‘PlayGTA5.exe’ и загрузитесь в игру. После этого попробуйте зайти через RAGE повторно.

RageMP закрывается сразу после открытия
Выключите любые антивирусы или добавьте папку в исключения, затем перезагрузите компьютер.
Если это не помогло, то, возможно, ваше подключение блокирует cloudflare, попробуйте подключиться через VPN.

Запускается одиночный режим или главное меню
Убедитесь, что пакет Visual C++ redistributable 2015 (https://www.microsoft.com/en-us/download/details.aspx?id=48145) был установлен.
Если он установлен, отключите windows defender.

System.Net.WebException: The remote server returned an error: (403)
Ваш IP был заблокирован, смените его или используйте VPN.

Если ничего выше не помогло, попробуйте сделать следующее:

  1. Переустановите RAGE Multiplayer.
  2. Убедитесь, что игра никак не была модифицирована.
  3. Переустановите GTA V или пройдите верификацию файлов.
  4. Запустите RAGE Multiplayer от имени администратора.
  5. Установите необходимые пакеты:
    https://www.microsoft.com/en-us/download/details.aspx?id=48145
    https://www.microsoft.com/en-us/download/details.aspx?id=53344&desc=dotnet462
  6. Установите RAGE Multiplayer и GTA V на один диск.
  7. Установите RageMP и GTA V на разные диски.
  8. Отключите любые оверлеи (Steam, OBS, Discord overlay, Overwolf).
  9. Убедитесь, что присутствует файл сохранения (запустите одиночную игру и сохраните ее).
  10. Удалите любые моды на GTA V.
  11. Выключите любые антивирусы или добавьте папку в исключения. Добавьте RAGE в исключения Firewall.
  12. Нажмите пкм на ragemp.exe и выберите в меню «Troubleshoot compatibility»/»Исправление проблем с совместимостью».
  13. (NVIDIA USERS) отключите Shadowplay.
  14. (STEAM ONLY) Выйдите из стима, потом запустите RAGE и дайте ему запустить стим самому.

Внимание! Самый важный шаг, когда уже ничего не помогает:

Источник

/*

    Real synced 3d cef sound for all players in range :)
    Music is linked to a specific vehicle, use remoteId for correct working
        (mp.players.local.vehicle.remoteId)

*/
const localPlayer = mp.players.local;
const camera = mp.cameras.new("gameplay");
let musicPlayer = mp.browsers.new('package://cef/music_browser/index.html');
const maxRange = 60.0;
let id = 0;

const soundManager = 
{
    remove: function (player, id, pause, volume) 
	{
        if (player && musicPlayer) musicPlayer.executeCached(`stopAudio("${id}")`);
		mp.gui.chat.push(`setPaused("${id}", "${pause}")`);
    },
		
    pauseToggle: function (player, id, pause) 
	{
        if (player && musicPlayer) musicPlayer.execute(`setPaused("${id}", "${pause}")`);
    },
    setVolume: function (player, id, volume) 
	{
        if (player && musicPlayer) 
		{
			let cam_pos = camera.getCoord(),
			cam_vector = camera.getDirection(),
			car_pos = mp.vehicles.atRemoteId(parseInt(id)).position,  // can use any coords here(not only veh position)
			car_vector = 
			{
				x: car_pos.x-cam_pos.x, y: car_pos.y-cam_pos.y
			},
			dx = car_vector.x * cam_vector.x + car_vector.y * cam_vector.y,
			dy = mp.game.system.sqrt(cam_vector.x*cam_vector.x + cam_vector.y*cam_vector.y) * mp.game.system.sqrt(car_vector.x*car_vector.x + car_vector.y*car_vector.y);
			// calculates where point is left/right
			let s = cam_vector.x*(car_pos.y-cam_pos.y) - cam_vector.y*(car_pos.x-cam_pos.x),
				a = 1;
			if(s > 0) a = -1
			else if(s < 0) a = 1
			else a = 0;
			let pan = Math.sqrt(1-(dx / dy).toFixed(3)*(dx / dy).toFixed(3))*a;
			musicPlayer.execute(`setVolume("${id}", "${volume}", ${pan});`);
        }
    }
};


mp.events.add(
{
	'createSound': (soundObj, volume) => 
	{
        soundObj = JSON.parse(soundObj);
        id = soundObj.id;
        mp.gui.chat.push(` ${soundObj.id}", "${soundObj.url}", ${soundObj.range}, ${soundObj.startTime}, "${volume}"`);
		if (musicPlayer) musicPlayer.execute(`playAudio("${soundObj.id}", "${soundObj.url}", ${soundObj.startTime}, "${volume}")`);
    },
    'setSoundVolume': (id, volume) => {
        soundManager.setVolume(localPlayer, id, volume);
    },
	'destroySound': (id) => {
        soundManager.remove(localPlayer, id);
	},
    'pauseSound': (id) => {
        soundManager.pauseToggle(localPlayer, id, true);
    },
    'resumeSound': (id) => {
        soundManager.pauseToggle(localPlayer, id, false);
    },
    'audioFinish': (id) => {
		mp.gui.chat.push(`Track {id} finished!`);
		// can be used to play next track
	},
    'audioError': (id, errorData) => {
		mp.gui.chat.push(`Track {id} err!`);
	},
});

/*
mp.game.audio.playSound3D = function (veh_id, url, range=60, volume=1, track_length=180) 
{
    mp.events.callRemote('sound:create', veh_id, url, range, volume, track_length);
	//id += 1;
};
*/
mp.keys.bind(0x51, false, function () 
{
    if (mp.players.local.vehicle)
    {
		let vehicleId = mp.players.local.vehicle.remoteId;
		//mp.game.audio.playSound3D(vehicleId, 'http://60.176.189.89.sta.211.ru/boombox/audio/ATL-Pticy.mp3', 20, 0.5, 10);
		mp.events.callRemote('sound:create', vehicleId, 'http://60.176.189.89.sta.211.ru/boombox/audio/ATL-Pticy.mp3', 20, 0.5, 10);
    }
});

mp.keys.bind(0x45, false, function () 
{
    if (mp.players.local.vehicle)
    {
		let vehicleId = mp.players.local.vehicle.remoteId;
		mp.events.callRemote('sound:destroy', vehicleId);		
    }
});

mp.events.add("playerQuit", (player) => {
    mp.game.graphics.notify(`<C>${player.name}</C> (ID:${player.remoteId}) left the server`);
	let vehicleId = mp.players.local.vehicle.remoteId;
	mp.events.callRemote('sound:destroy', vehicleId);		
});

Client
 

var serverSounds = {};

// every 50ms update volume for all players in veh range
setInterval(function()
{
	setVehPosition();
},50);


function setVehPosition() 
{
    mp.vehicles.forEach((veh) => 
	{
        if(!(veh.id in serverSounds) || serverSounds[veh.id].paused) return;
        let maxRange = serverSounds[veh.id].range;

        serverSounds[veh.id].listeners.forEach(player => 
		{
            let dist = veh.dist(player.position);
            if(dist > maxRange)
			{
                let idx = serverSounds[veh.id].listeners.indexOf(player);
                serverSounds[veh.id].listeners.splice(idx, 1);
                player.call('destroySound', [veh.id]);
            } 
			else 
			{
                let volume = serverSounds[veh.id].volume * (1 - (dist / maxRange));
                volume = volume < 0 ? 0 : volume;
                player.call('setSoundVolume', [veh.id, volume*volume]);
            }
        });
		
        mp.players.forEachInRange(veh.position, maxRange,(player) => 
		{
            if(serverSounds[veh.id].listeners.includes(player)) return;
            let dist = veh.dist(player.position);
            let volume = serverSounds[veh.id].volume * (1 - (dist / maxRange));
            volume = volume < 0 ? 0 : volume;
            serverSounds[veh.id].listeners.push(player);
            player.call('createSound', [JSON.stringify(serverSounds[veh.id]), volume*volume]);
        });
		
		if (serverSounds[veh.id].trackLength <= serverSounds[veh.id].startTime) 
		{
            serverSounds[veh.id].listeners.forEach(player => 
				{
					player.call('destroySound', [veh.id]); 
                });
            delete serverSounds[veh.id]; 
            return;
        }
        serverSounds[veh.id].startTime += 50;
    });
}


mp.events.add(
{
	'sound:create': (player, id, url, range, volume, track_length) => 
	{
		if(id in serverSounds)
		{
			serverSounds[id].listeners.forEach(player => 
			{
				  player.call('destroySound', [id]);
			});
			delete serverSounds[id];
			/*
			serverSounds[veh.id].listeners.forEach(player => 
			{
				player.call('destroySound', [veh.id]); 
            });
            delete serverSounds[veh.id]; 
            return;*/
		}
		serverSounds[id] = 
		{
			id: id,
			url: url,
			volume: volume,
			range: range,
			listeners: [],
			paused: false,
			startTime: 0,
			trackLength: track_length * 1000
		}
	},
	'sound:destroy': (player, id) => 
	{
		if(id in serverSounds)
		{
			serverSounds[id].listeners.forEach(player => 
			{
				  player.call('destroySound', [id]);
			});
			delete serverSounds[id];
			/*
			serverSounds[veh.id].listeners.forEach(player => 
			{
				player.call('destroySound', [veh.id]); 
            });
            delete serverSounds[veh.id]; 
            return;*/
		}
	},
	'sound:pause': (player, id) => {
		if(id in serverSounds){
			serverSounds[id].paused = true;
			serverSounds[id].listeners.forEach(
			    player => {
				    player.call('pauseSound', [id]);
			    }
			);
		}
	},
	'sound:resume': (player, id) => {
		if(id in serverSounds){
			serverSounds[id].paused = false;
			serverSounds[id].listeners.forEach(
			    player => {
				    player.call('resumeSound', [id]);
			    }
		    );
		}
	},
	'sound:setVolume': (player, id, volume) => {
		if(id in serverSounds)
			serverSounds[id].volume = volume;
	}
});

Server

Всем привет, на работке в свободное время решил написать небольшую работу для этого замечательного ресурса. Может кому будет интересно, плюс если кто сможет, небольшое код-ревью дать, буду рад критике и советам.
Работа на чистом nodeJs + vue.

Начнём с серверной части, «рассадим» деревья по точкам:
Создадим массив с id-идентификатором дерева(понадобится в дальнейшем), и координатами(место «посадки» дерева)

JavaScript:

const allTrees = [
  {
    id: 1,
    x: 8.031051635742188,
    y: 10.031051635742188,
    z: 70.78174591064453,
  },
  {
    id: 2,
    x: 48.031051635742188,
    y: 10.031051635742188,
    z: 70.78174591064453,
  },
  {
    id: 3,
    x: 38.031051635742188,
    y: 10.031051635742188,
    z: 70.78174591064453,
  },
  {
    id: 4,
    x: 28.031051635742188,
    y: 10.031051635742188,
    z: 70.78174591064453,
  },
  {
    id: 5,
    x: 18.031051635742188,
    y: 10.031051635742188,
    z: 70.78174591064453,
  },
];

Теперь деревья нужно «рассадить», логичнее всего это делать при загрузке сервера, поэтому используем событие «packagesLoaded»:

JavaScript:

mp.events.add("packagesLoaded", () => {
  console.log(`[INFO] Работа дровосека загружена`);
  allTrees.forEach((tree) => {
    const trees = mp.objects.new(
      "prop_tree_fallen_pine_01",
      new mp.Vector3(tree.x, tree.y, tree.z - 1),
      {
        dimension: 0,
      }
    );
    trees.treeId = tree.id;
    trees.setVariable("treeId", trees.treeId);
    trees.treesLabel = mp.labels.new(
      "Нажмите [Е]",
      new mp.Vector3(tree.x, tree.y + 1.1, tree.z),
      {
        los: false,
        font: 0,
        drawDistance: 20,
        color: [70, 130, 180, 170],
        dimension: 0,
      }
    );
  });
  console.log(`[INFO] Деревьев посажено: ${allTrees.length}`);
});

Для установки деревьев выбрал метод перебора созданного раннее массива allTrees — forEach, в котором создаём дерево для каждого объекта в массиве, а также назначаем каждому дереву собственный id и задаём собственный вариабл с этим же id для его использования уже на клиентской части.
Для визуального восприятия добавим надпись для каждого дерева «Нажмите [Е]».
Ну и немного работы с консолью в конце.
Получилось прекрасно..

1654421270290.png

Далее, чтобы начать взаимодействовать с этими деревьями нужно перейти в клиентскую часть.
Чтобы устроиться на работу, нужно для начала найти компанию(в данном случае npc), которая даст вам эту самую работу.
Создадим массив обектов(в данном случае, он один), зададим в нём координаты npc, его направление(heading), имя и модель
Почему массив объектов, потому что в дальнейшем можно будет с лёгкостью добавить ещё одного npc.

JavaScript:

const lumberjackNpc = [
  {
    x: 18.32457160949707,
    y: 26.563514709472656,
    z: 70.61154174804688,
    heading: "159.72958374023438",
    name: "Логан",
    model: "a_m_m_salton_02",
  },
];

Далее расставим npc всё тем же методом forEach, добавим под него колшейп, дадим класс этому колшейпу, чтобы в дальнейшем определять, что мы стоим перед этим самым npc, повесим над ним пару надписей и добавим блип на карту:

JavaScript:

lumberjackNpc.forEach((lumberjack) => {
  const lumberjackBot = mp.peds.new(
    mp.game.joaat(lumberjack.model),
    new mp.Vector3(lumberjack.x, lumberjack.y, lumberjack.z),
    lumberjack.heading,
    0
  );
  const lumberjackStartColshape = mp.colshapes.newSphere(
    parseFloat(lumberjack.x),
    parseFloat(lumberjack.y),
    parseFloat(lumberjack.z),
    2,
    0
  );
  lumberjackStartColshape.class = "lumberjack";
  mp.labels.new(
    lumberjack.name,
    {
      x: lumberjackBot.position.x,
      y: lumberjackBot.position.y,
      z: lumberjackBot.position.z + 0.9,
    },
    { los: true, font: 0, drawDistance: 20, color: [70, 130, 180, 170] }
  );
  mp.labels.new(
    "[Работа: Лесоруб]",
    {
      x: lumberjackBot.position.x,
      y: lumberjackBot.position.y,
      z: lumberjackBot.position.z + 1.2,
    },
    { los: true, font: 0, drawDistance: 20, color: [255, 255, 255, 170] }
  );
  const lumberjackBlip = mp.blips.new(
    792,
    new mp.Vector3(lumberjackBot.position.x, lumberjackBot.position.y, 0),
    {
      name: "Лесоруб",
      scale: 0.7,
      color: 5,
      shortRange: true,
      dimension: 0,
    }
  );
});

Вот он… Красавчик стоит, в шлёпках да в футболке, заправленной в трусы, а на футболке той топор нарисован, значит лесоруб, верно?

1654421964019.png
Теперь для того. чтобы взаимодействовать с данным npc, нужно использовать метод playerEnterColshape, также потребуется метод бинда кнопки mp.keys.bind, при нажатии на которую начнётся то самое взаимодействие.

JavaScript:

mp.events.add("playerEnterColshape", (shape) => {
  if (shape.class == "lumberjack") { // проверяем, на том ли мы колшейпе
    mp.keys.bind(0x45, true, openLumberjack); // биндим кнопку
  }
});

Также потребуется отвязывать кнопку Е, сделаем это методом playerExitColshape

JavaScript:

mp.events.add("playerExitColshape", (shape) => {
  if (shape.class == "lumberjack") {
    mp.keys.unbind(0x45, true, openLumberjack);
  }
});

Сама функция, отвечающая за показ диалога с Логаном:

JavaScript:

function openLumberjack() {
  if (lumberjackOpened) return;
  browser.execute("windows.lumberjack.lumberjackOpened = true");
  mp.gui.cursor.show(true, true);
  lumberjackOpened = true;
  mp.players.local.freezePosition(true);
}

Для того, чтобы проверять открыт ли диалог с данным npc или нет, создадим переменную lumberjackOpened и назначим ей значение сразу false (мы же не хотим по пустякам вызывать CEF на клиенте?)

JavaScript:

let lumberjackOpened = false;

По быстренькому накидаем страничку с диалогом:

HTML:

<template>
  <div v-if="lumberjackOpened" id="lumberjack" class="lumberjack">
    <h1>Логан</h1>
    <p>
      Приветствую, для работы потребуется только топор и немного терпения,
      дерзай!
    </p>
    <div class="buttons">
      <button v-if="!lumberjackStatus" @click="startLumberjack">
        Принять работу
      </button>
      <button v-if="lumberjackStatus" @click="stopLumberjack">Уволиться</button>
      <button @click="buyHatchet">Купить топор</button>
      <button @click="sell">Продать брёвна</button>
      <button @click="close">Закрыть</button>
    </div>
  </div>
</template>
<script src="./js/Lumberjack.js"></script>
<style src="./css/Lumberjack.css"></style>

css:

CSS:

.lumberjack {
    display: block;
    width: 700px;
    height: 600px;
    box-shadow: 1px black;
    border: none;
    margin: auto;
    margin-top: 100px;
    border-radius: 5px;
    background-color: rgba(0, 0, 0, 0.512);
    text-align: center;
    color: white;
    font-size: 1.3em;
    font-family: 'Courier New', Courier, monospace;
  }
  .lumberjack p {
      border-top: 1px solid white;
      border-bottom: 1px solid white;
      padding: 10px;
      background: #00000085;
  }
  .buttons {
    display: inline-grid;
  }
  .buttons button {
    margin: auto;
    margin-top:5px;
    width: 150px;
    height: 40px;
    border-radius: 5px;
    border: none;
    transition: 0.2s;
    background-color:rgba(20, 20, 20, 0.547);
    color: white;
  }
  .buttons button:hover{
  background-color:grey;
  }

js

JavaScript:

export default {
  name: "Lumberjack",
  data() {
    return {
      lumberjackOpened: false,
      lumberjackStatus: false
    };
  },
  methods: {
    sell() {
      window.mp.trigger("sellLogs");
    },
    stopLumberjack() {
      window.mp.trigger("stopLumberjack");
    },
    startLumberjack() {
      window.mp.trigger("startLumberjack");
    },
    buyHatchet() {
      window.mp.trigger("buyHatchet");
    },
    close() {
      this.lumberjackOpened = false;
      window.mp.trigger("closeLumberjack");
    }
  }
};

Теперь при нажатии на кнопку Е, рядом с npc появится небольшое простое окно:
1654423412339.png

Готово, осталось прописать события, которые мы вызываем при нажатии кнопок.
Закрыть:

JavaScript:

mp.events.add("closeLumberjack", () => {
  closeLumberjack(); // вызываем функцию закрытия окна
});

function closeLumberjack() { // сама функция
  lumberjackOpened = false;
  mp.gui.cursor.show(false, false);
  mp.players.local.freezePosition(false);
}

Принять работу, тут уже потребуется взаимодействие с серверной частью:

Код:

mp.events.add("startLumberjack", () => {
  mp.events.callRemote("server:startLumberjack"); // вызываем событие на сервере
});

Перейдём обратно в серверную часть и пропишем событие server:startLumberjack.

JavaScript:

mp.events.add("server:startLumberjack", (player) => {
  if (player.worker) return player.notify("Вы уже начали работу лесоруба"); // простая проверка на то, работает ли уже персонаж
  player.worker = true; // даём персонажу свойство, по которому определять, работает ли персонаж или нет
  player.notify("Вы устроились лесорубом"); // оповещаем персонажа
  player.setVariable("lumberjack", true); // вешаем на персонажа вариабл, чтобы использовать его на клиенте, для проверки, дровосек ли персонаж
  player.call("lumberJackStatus", [true]); // вызов эвента, который отключает кнопку "Принять работу" и включает кнопку "Уволиться" в диалоге с Логаном
});

То самое событие lumberJackStatus

JavaScript:

mp.events.add("lumberJackStatus", (status) => { // прилетает с сервера status = true или false
  if (status) { // если статус true
    browser.execute(`windows.lumberjack.lumberjackStatus = true`); // прячем кнопку "Принять работу" и показываем "Уволиться"
    setTimeout(() => {
      mp.keys.bind(0x45, true, useHatch); // биндим кнопку Е, для рубки дерева (не придумал ничего лучше, как биндить кнопку после 5 секунд, чтобы успеть отойти от npc, т.к при выходе из колшейпа, отвязывается кнопка Е, может кто подскажет решение получше :D 
    }, 5000);
  } else { // если статус false
    browser.execute(`windows.lumberjack.lumberjackStatus = false`); // прячем кнопку "Уволиться" и показываем "Принять работу"
    mp.keys.unbind(0x45, true, useHatch); // отвязываем кнопку Е
  }
});

Для того, чтобы понимать, где дерево и когда можно использовать кнопку Е для рубки, нужно научиться определять, что перед персонажем стоит нужный нам объект(а дерево — это объект). Для этого используем событие render и метод testCapsule.

JavaScript:

mp.events.add("render", () => {
  if (mp.players.local.getVariable("lumberjack")) {
    const startPosition = mp.players.local.getBoneCoords(12844, 0, 0, 0); // используем голову персонажа как начало "отрезка" поиска
    const endPosition = mp.players.local.getBoneCoords(12844, 0, 1, 0); // конец отрезка примерно на 1 метр, от головы персонажа
    const hitData = mp.raycasting.testCapsule( // "рисуем" невидимый отрезок
      startPosition,
      endPosition,
      0.5,
      mp.players.local
    );
    if (hitData && hitData.entity.type == "object") { // определяем, что отрезок попал на объект
      if (hitData.entity.getVariable("treeId")) { // определяем по заданному ранее вариаблу, что у объекта есть treeId, а значит это дерево
        mp.players.local.hatchReady = true; // задаём персонажу свойство, обозначающее, что он готов рубить дерево
        mp.players.local.treeFor = hitData.entity.getVariable("treeId"); // сохраняем id дерева, для его поиска на сервере
      }
    } else {
      mp.players.local.hatchReady = false; // если луч не коснулся объекта
    }
  }
});

Теперь пропишем функцию useHatch, которую мы биндили ранее:

JavaScript:

function useHatch() {
  if (mp.players.local.hatchReady && mp.players.local.treeFor) { // проверяем свойства, прописанные ранее
    mp.events.callRemote("server:startHatching", mp.players.local.treeFor); // вызываем событие на сервере для рубки, вместе с id дерева
  }
}

Перейдём на серверную часть и пропишем событие server:startHatching

JavaScript:

mp.events.add("server:startHatching", (player, id) => {
  if (!player.worker) return player.notify("Вы не устроились на работу"); // проверка на устроился ли персонаж
  if (!id) return; // ещё одна проверка, вдруг id затерялся
  if (!player.hasHatchet) return player.notify("У вас нет топора"); // проверка на куплен ли топор, вернёмся к этому позже
  player.playAnimation( // проигрывание анимации(да, я использовал анимацию ножа.., но самый терпеливый найдёт анимацию топора)
    "melee@knife@streamed_core",
    "knife_short_range_0",
    1,
    49
  );
  player.call("animActive", [true]); // вызываем событие, которое блокирует движение во время анимации
  setTimeout(() => { // таймаут на 3 с, после которого выполнятся команды ниже
    if (player) { // если игрок всё ещё на сервере, защита от вылета краша сервера
      player.logs += 1; // засчитываем + 1 бревно персонажу
      player.outputChatBox(`У вас ${player.logs} брёвен`); // вывод в чат кол-во брёвен
      player.stopAnimation(); // остановка анимации
      player.call("animActive", [false]); // вызываем событие, которое разрешает движение персонажу
    }
    mp.objects.forEach((object) => { // проходимся по массиву с созданными объектами
      if (object.getVariable("treeId") == id) { // ищем по вариабле, установленной ранее, объект с id, который прилетел с клиента
        object.treesLabel.destroy(); // уничтожаем надпись
        object.destroy(); // уничтожаем сам объект(дерево)
      }
    });
  }, 3000);
  setTimeout(() => { // таймаут на повторную "посадку" дерева
    const fi = allTrees.findIndex((tree) => tree.id == id); // ищем индекс дерева в массиве, по полученному id
    const tr = mp.objects.new(
      "prop_tree_fallen_pine_01",
      new mp.Vector3(allTrees[fi].x, allTrees[fi].y, allTrees[fi].z - 1), // создаём дерево из массива объектов, используя найденный индекс выше
      {
        dimension: 0,
      }
    );
    tr.treeId = allTrees[fi].id; // всё тоже самое, как и при packagesLoaded
    tr.setVariable("treeId", tr.treeId);
    tr.treesLabel = mp.labels.new(
      "Нажмите [Е]",
      new mp.Vector3(allTrees[fi].x, allTrees[fi].y + 1.1, allTrees[fi].z),
      {
        los: false,
        font: 0,
        drawDistance: 20,
        color: [70, 130, 180, 170],
        dimension: 0,
      }
    );
  }, 20000);
});

animActive на клиенте:

JavaScript:

mp.events.add("animActive", (data) => {
  if (data) {
    mp.players.local.freezePosition(true);
  } else {
    mp.players.local.freezePosition(false);
  }
});

Осталось лишь купить топор, и можно даже поработать! Для этого вернёмся на клиент и пропишем событие buyHatchet для созданной ранее кнопки

JavaScript:

mp.events.add("buyHatchet", () => {
  mp.events.callRemote("server:buyHatchet");
});

Перейдём обратно на сервер и пропишем там вызываемое событие:
но для начала пропишем фиксированную сумму за топор

JavaScript:

const hatchetPrice = 300;

JavaScript:

mp.events.add("server:buyHatchet", (player) => {
  if (player.hasHatchet) return player.notify("У вас уже есть топор"); // проверка на купленный топор
  if (player.money < hatchetPrice) // проверка на требуемое кол-во денег у персонажа
    return player.notify("У вас не хватает денег для покупки");
  player.giveWeapon(mp.joaat("weapon_hatchet"), 0); // выдача топора
  player.money -= hatchetPrice; // вычет суммы из денег персонажа за топор
  player.hasHatchet = true; // Свойство, определяющее наличие топора у персонажа
  player.notify("Вы купили топор"); // уведомление
});

Для того, чтобы задать свойства персонажу, такие как деньги и кол-во брёвен, используем событие playerReady

JavaScript:

mp.events.add("playerReady", (player) => {
  player.logs = 0;
  player.money = 300;
});

Отлично, топор можно купить, даже деревья им рубить, осталось только научиться продавать брёвна
Для этого мы возвращаемся на клиент и прописываем там событие sellLogs:

JavaScript:

mp.events.add("sellLogs", () => {
  mp.events.callRemote("server:sellLogs");
});

Переходим на сервер:

JavaScript:

mp.events.add("server:sellLogs", (player) => {
  if (player.logs <= 0) return player.notify("У вас нет бревён для продажи"); // проверка на брёвна
  const sum = player.logs * 300; // рассчитавыем сумму, которую дадим за n-ое кол-во брёвен
  player.money += sum; // плюсуем полученную сумму к уже имеющимся деньгам
  player.outputChatBox(
    `Вы продали ${player.logs} брёвен за ${sum}$. У вас ${player.money}$` // выводим сообщение в чат
  );
  player.logs = 0; // очищаем кол-во брёвен, ведь мы их продали
});

Вот и всё, наработались, теперь осталось уволиться
Для этого опять возвращаемся на клиент и прописываем событие stopLumberjack:

JavaScript:

mp.events.add("stopLumberjack", () => {
  mp.events.callRemote("server:stopLumberjack");
});

Сервер:

JavaScript:

mp.events.add("server:stopLumberjack", (player) => {
  if (player.worker) { // проверка на устройство
    player.worker = false; // свойства устройства на работу переходит в состояние false, что позволит ещё раз принять работу
    player.notify("Вы уволились"); // уведомление
    player.call("lumberJackStatus", [false]); // прячем, показываем кнопки
  } else {
    return player.notify("Вы не начали работу лесоруба"); // на всякий случай, если что-то пойдёт не так
  }
});

Вот и всё, вы уволены, можно пойти попить пивка
Работа готова, вроде всё на месте

Спасибо за внимание!

JavaScript:

let lumberjackOpened = false;
const lumberjackNpc = [
  {
    id: 0,
    x: 18.32457160949707,
    y: 26.563514709472656,
    z: 70.61154174804688,
    heading: "159.72958374023438",
    name: "Логан",
    model: "a_m_m_salton_02",
  },
];
lumberjackNpc.forEach((lumberjack) => {
  const lumberjackBot = mp.peds.new(
    mp.game.joaat(lumberjack.model),
    new mp.Vector3(lumberjack.x, lumberjack.y, lumberjack.z),
    lumberjack.heading,
    0
  );
  const lumberjackStartColshape = mp.colshapes.newSphere(
    parseFloat(lumberjack.x),
    parseFloat(lumberjack.y),
    parseFloat(lumberjack.z),
    2,
    0
  );
  lumberjackStartColshape.class = "lumberjack";
  mp.labels.new(
    lumberjack.name,
    {
      x: lumberjackBot.position.x,
      y: lumberjackBot.position.y,
      z: lumberjackBot.position.z + 0.9,
    },
    { los: true, font: 0, drawDistance: 20, color: [70, 130, 180, 170] }
  );
  mp.labels.new(
    "[Работа: Лесоруб]",
    {
      x: lumberjackBot.position.x,
      y: lumberjackBot.position.y,
      z: lumberjackBot.position.z + 1.2,
    },
    { los: true, font: 0, drawDistance: 20, color: [255, 255, 255, 170] }
  );
  const lumberjackBlip = mp.blips.new(
    792,
    new mp.Vector3(lumberjackBot.position.x, lumberjackBot.position.y, 0),
    {
      name: "Лесоруб",
      scale: 0.7,
      color: 5,
      shortRange: true,
      dimension: 0,
    }
  );
});
mp.events.add("sellLogs", () => {
  mp.events.callRemote("server:sellLogs");
});
mp.events.add("startLumberjack", () => {
  mp.events.callRemote("server:startLumberjack");
});
mp.events.add("stopLumberjack", () => {
  mp.events.callRemote("server:stopLumberjack");
});
mp.events.add("buyHatchet", () => {
  mp.events.callRemote("server:buyHatchet");
});
mp.events.add("closeLumberjack", () => {
  closeLumberjack();
});
mp.events.add("playerEnterColshape", (shape) => {
  if (shape.class == "lumberjack") {
    mp.keys.bind(0x45, true, openLumberjack);
  }
});
mp.events.add("playerExitColshape", (shape) => {
  if (shape.class == "lumberjack") {
    mp.keys.unbind(0x45, true, openLumberjack);
  }
});
mp.events.add("lumberJackStatus", (status) => {
  if (status) {
    browser.execute(`windows.lumberjack.lumberjackStatus = true`);
    setTimeout(() => {
      mp.keys.bind(0x45, true, useHatch);
    }, 5000);
  } else {
    browser.execute(`windows.lumberjack.lumberjackStatus = false`);
    mp.keys.unbind(0x45, true, useHatch);
  }
});
mp.events.add("animActive", (data) => {
  if (data) {
    mp.players.local.freezePosition(true);
  } else {
    mp.players.local.freezePosition(false);
  }
});
mp.events.add("render", () => {
  if (mp.players.local.getVariable("lumberjack")) {
    const startPosition = mp.players.local.getBoneCoords(12844, 0, 0, 0);
    const endPosition = mp.players.local.getBoneCoords(12844, 0, 1, 0);
    const hitData = mp.raycasting.testCapsule(
      startPosition,
      endPosition,
      0.5,
      mp.players.local
    );
    if (hitData && hitData.entity.type == "object") {
      if (hitData.entity.getVariable("treeId")) {
        mp.players.local.hatchReady = true;
        mp.players.local.treeFor = hitData.entity.getVariable("treeId");
      }
    } else {
      mp.players.local.hatchReady = false;
    }
  }
});
function closeLumberjack() {
  lumberjackOpened = false;
  mp.gui.cursor.show(false, false);
  mp.players.local.freezePosition(false);
}
function openLumberjack() {
  if (lumberjackOpened) return;
  browser.execute("windows.lumberjack.lumberjackOpened = true");
  mp.gui.cursor.show(true, true);
  lumberjackOpened = true;
  mp.players.local.freezePosition(true);
}
function useHatch() {
  if (mp.players.local.hatchReady && mp.players.local.treeFor) {
    mp.events.callRemote("server:startHatching", mp.players.local.treeFor);
  }
}

JavaScript:

const hatchetPrice = 300;
const allTrees = [
  {
    id: 1,
    x: 8.031051635742188,
    y: 10.031051635742188,
    z: 70.78174591064453,
  },
  {
    id: 2,
    x: 48.031051635742188,
    y: 10.031051635742188,
    z: 70.78174591064453,
  },
  {
    id: 3,
    x: 38.031051635742188,
    y: 10.031051635742188,
    z: 70.78174591064453,
  },
  {
    id: 4,
    x: 28.031051635742188,
    y: 10.031051635742188,
    z: 70.78174591064453,
  },
  {
    id: 5,
    x: 18.031051635742188,
    y: 10.031051635742188,
    z: 70.78174591064453,
  },
];
mp.events.add("packagesLoaded", () => {
  console.log(`[INFO] Работа дровосека загружена`);
  allTrees.forEach((tree) => {
    const trees = mp.objects.new(
      "prop_tree_fallen_pine_01",
      new mp.Vector3(tree.x, tree.y, tree.z - 1),
      {
        dimension: 0,
      }
    );
    trees.treeId = tree.id;
    trees.setVariable("treeId", trees.treeId);
    trees.treesLabel = mp.labels.new(
      "Нажмите [Е]",
      new mp.Vector3(tree.x, tree.y + 1.1, tree.z),
      {
        los: false,
        font: 0,
        drawDistance: 20,
        color: [70, 130, 180, 170],
        dimension: 0,
      }
    );
  });
  console.log(`[INFO] Деревьев посажено: ${allTrees.length}`);
});
mp.events.add("playerReady", (player) => {
  player.logs = 0;
  player.money = 300;
});
mp.events.add("server:buyHatchet", (player) => {
  if (player.hasHatchet) return player.notify("У вас уже есть топор");
  if (player.money < hatchetPrice)
    return player.notify("У вас не хватает денег для покупки");
  player.giveWeapon(mp.joaat("weapon_hatchet"), 0);
  player.money -= hatchetPrice;
  player.hasHatchet = true;
  player.notify("Вы купили топор");
});
mp.events.add("server:sellLogs", (player) => {
  if (player.logs <= 0) return player.notify("У вас нет бревён для продажи");
  const sum = player.logs * 300;
  player.money += sum;
  player.outputChatBox(
    `Вы продали ${player.logs} брёвен за ${sum}$. У вас ${player.money}$`
  );
  player.logs = 0;
});
mp.events.add("server:startHatching", (player, id) => {
  if (!player.worker) return player.notify("Вы не устроились на работу");
  if (!id) return;
  if (!player.hasHatchet) return player.notify("У вас нет топора");
  player.playAnimation(
    "melee@knife@streamed_core",
    "knife_short_range_0",
    1,
    49
  );
  player.call("animActive", [true]);
  setTimeout(() => {
    if (player) {
      player.logs += 1;
      player.outputChatBox(`У вас ${player.logs} брёвен`);
      player.stopAnimation();
      player.call("animActive", [false]);
    }
    mp.objects.forEach((object) => {
      if (object.getVariable("treeId") == id) {
        object.treesLabel.destroy();
        object.destroy();
      }
    });
  }, 3000);
  setTimeout(() => {
    const fi = allTrees.findIndex((tree) => tree.id == id);
    const tr = mp.objects.new(
      "prop_tree_fallen_pine_01",
      new mp.Vector3(allTrees[fi].x, allTrees[fi].y, allTrees[fi].z - 1),
      {
        dimension: 0,
      }
    );
    tr.treeId = allTrees[fi].id;
    tr.setVariable("treeId", tr.treeId);
    tr.treesLabel = mp.labels.new(
      "Нажмите [Е]",
      new mp.Vector3(allTrees[fi].x, allTrees[fi].y + 1.1, allTrees[fi].z),
      {
        los: false,
        font: 0,
        drawDistance: 20,
        color: [70, 130, 180, 170],
        dimension: 0,
      }
    );
  }, 20000);
});
mp.events.add("server:startLumberjack", (player) => {
  if (player.worker) return player.notify("Вы уже начали работу лесоруба");
  player.worker = true;
  player.notify("Вы устроились лесорубом");
  player.setVariable("lumberjack", true);
  player.call("lumberJackStatus", [true]);
});
mp.events.add("server:stopLumberjack", (player) => {
  if (player.worker) {
    player.worker = false;
    player.notify("Вы уволились");
    player.call("lumberJackStatus", [false]);
  } else {
    return player.notify("Вы не начали работу лесоруба");
  }
});

QV1oiOF.png

Release Date: 2022-5-10
Version: 2.19.1
Type of Release: General Release + Bug Fixes

Today’s release includes a few bug fixes, lots of QoL, and a new feature.

Happy Roleplaying!

New Features

  • New group chat (/g for players, /toggchat for players, /toggchat for GLs to disable for entire group) (Tom)

Bug Fixes

  • Fixed dragging stops while entering a vehicle (Josh)
  • Improved player initialization when they join the server (Josh)
  • Fixed respawning in place (Josh)
  • Fixed being able to text while being cuffed (Josh)

Quality Of Life / Improvements

  • Implemented toast notifications for a better user experience & implemented toast notifications for interaction cooldown (Rockhopper)
  • Add load & unload logic for ipls on Dynamic Doors (Josh)
  • Disabled rope functionality on flatbeds (Josh)
  • Updated DM / VDM options of the B Menu to take player ID as input for in game moderation (Rockhopper)
  • You can now discard fish while on a board (Nefarious)
  • NChat bans will no longer show when you have nchat disabled (Tom)

Sentry Issues

  • Resolved an issue with expired multiplayer object has been used with radios (Rockhopper)
  • Resolved an issue with ‘id’ being undefined with the report manager (Rockhopper)
  • Resolved an issue with ‘setVariable’ being null with groups (Rockhopper)
  • Resolved an issue with expired multiplayer object has been used with property manager (Rockhopper)
  • Resolved an issue with ‘currentWeight’ being null with the inventory manager (Rockhopper)
  • Resolved an issue with ‘smodeCheck’ being undefined with the property manager (Rockhopper)
  • Resolved an issue with ‘health’ being undefined with vehicle manager (Rockhopper)

Last edited: May 10, 2022

⚙️Ниже приведен список распространенных проблем.
💾Если в данном списке не указана какая то частая ошибка и вы знаете ее решение, отпишите мне в ЛС @PRO-RAGE .
🇷🇺Переведено с оф.форума :
Статья на RageMP

1. System.ComponentModel.Win32Exception (0x80004005)
Отключите любое антивирусное программное обеспечение или добавьте исключение в свой антивирус, чтобы он не изменял файлы связанные с RageMP на вашем компьютере.
Если отключение антивируса и защитника Windows по-прежнему не помогло, щелкните правой кнопкой мыши по updater.exe и выберите «Troubleshoot compatibility / Исправление проблем с совместимостью».

2. ERROR: Your game version is not supported by RAGE Multiplayer.
Если GTA V только что обновилась, и у вас будет отображаться данная ошибка, дождитесь обновления RageMP, но если обновления не происходит то обновите самостоятельно, так как вы используете устаревшую версию.
https://support.rockstargames.com/h…27-Verifying-system-files-on-your-PC-for-GTAV

3. System.UnauthorizedAccessException: Access to the path ‘…’ is denied.
Запустите RageMP от имени администратора.

4. Ошибка с отсутствием файла MSVCP140.dll при запуске.
Установите следующие 2 пакета

5. System.Net.WebException: The remote server returned an error: (522) Origin Connection Time-out.(Превышено время ожидания подключения).
Данная ошибка возникает, когда сервера не отвечают, продолжайте проверять сервер на наличие активности, чтобы знать когда он снова доступен.

6. Ошибка — undefined: 0
На данный момент нет четкого ответа на данную ошибку, однако некоторые исправили ее разрешив RageMP добавив его в свой брандмауэр, а некоторые исправили это, закрыв все программы на своем компьютере, чтобы освободить их оперативную память / процессор.
Начиная с ~ 0.3.6: если вы являетесь пользователем Windows 8 / 8.1, и у вас возникает данная ошибка то на данный момент решения нет, так как это может быть конфликт с программным обеспечением которое не поддерживает Windows 8.

7. Game launching into Singleplayer (Запускается одиночный режим вместо мультиплеера).
Для пользователей Steam
— Полностью выйдите из Steam, затем запустите RageMP позвольте RageMP запустить Steam и игру самостоятельно.
Однако это не всегда помогает всем пользователям Steam, для этого убедитесь что у вас есть компонент Visual C ++ 2015.
Если нет то установите: https://www.microsoft.com/en-us/download/details.aspx?id=48145

8. Игра вылетает еще до запуска.
Некоторые пользователи сообщают что если у вас в папке GTA V установлен другой мультиплеер GTA V, вам следует удалить его, скорее всего это исправит эту проблему.
ПОЛЬЗОВАТЕЛИ NVIDIA: отключите Nvidia Shadowplay и посмотрите, решит ли это вылеты, некоторые пользователи сообщили что данный метод им так же помог.

9. Игра вылетает, как только я присоединяюсь к серверу (как только появляется сообщение «Multiplayer started»).
Попробуйте переместить RageMP на другой диск (например, с C: на D: или исключите из пути к RageMP русские буквы)
Если на сервере есть голосовой чат, отключите все, что может блокировать ваш микрофон или какие-либо устройства смены голоса, что бы это не приводило к сбою.

10. System.Net.WebException: удаленный сервер возвратил ошибку: (403) Запрещено.
Ваш IP-адрес заблокирован, если это не сделано по какой либо причине нарушения, вы должны использовать VPN для просмотра списка серверов.
Вы можете отключить VPN, как только начнете подключаться к серверу.

11. Failed to retrieve the install directory (Не удалось получить каталог установки).
Это может возникать если вы выбрали неправильный каталог или у вас есть устаревшие файлы GTAV.exe / GTA V.
Убедитесь, что вы выбрали правильный каталог, он должен содержать файл GTAV.exe.
Если вы уверены, что это правильный путь, вы можете попробовать перепроверить файлы, поскольку у вас может быть устаревший / поврежденный / измененный GTAV.exe, который RageMP не принимает.

12. RageMP зависает каждый раз, когда я нажимаю на сервер.
Данная ошибка возникает когда в каталоге отсутствует файл GTAV.exe.
Для пользователей Steam — Причина может заключаться в том что вы не вошли в Steam, поэтому вы не можете запустить GTA V.

13. Я запускаю RageMP и ничего не происходит.


Ошибка возникает при отсутствии файлов, для этого отключите свой антивирус.
Если у вас его нет, попробуйте переустановить RageMP еще раз.

14. Пропуски кадров при игре на любом сервере.
Если вы пользуетесь Autohotkey, попробуйте выключить его перед запуском RageMP.
А так же если частота вашего монитора 144 Гц, снижение частоты кадров до 60 может исправить потерю.

15. GTA V запускается с черным экраном, а затем внезапно закрывается / вылетает после нажатия кнопки «Play Now / Играть сейчас».
Если это происходит впервые когда вы используете RageMP или вы только что переустановили RageMP, это приведет к сбою вашего клиента, поскольку кнопка «Play Now / Играть сейчас» используется для повторного подключения к вашему последнему подключенному серверу.
Пожалуйста, используйте вкладку «Servers / Серверы» или вкладку «Direct Connect / Прямое подключение», чтобы сначала присоединиться к серверу, затем вы можете использовать кнопку «Play Now / Играть сейчас», чтобы повторно подключиться к вашему последнему подключенному серверу.

16. Моя игра вылетает, когда я нахожусь в зоне строительства / в центре Лос-Сантоса.
Это известная зона крашей многих пользователей.
Посмотрите на изображение ниже, чтобы убедиться, что вас крашит в этой области.

bermuda.jpg

Однако это можно исправить, выполнив следующие действия:
1.Зайдите в Documents / Rockstar Games / GTA V / Profiles.
2.Выделите все папки
3.Этот пункт не обязательно: Отправить -> Сжатая папка (zip) [Чтобы не потерять прогресс кампании]
4.Удалить все папки
5.Перезапустите вашу игру
6.При перезапуске вас спросят, откуда взять файл сохранения, нажмите «Local Only / Только локально».

Если ничего из выше перечисленного не помогло, попробуйте выполнить следующие действия:

  1. Переустановите RageMP.
  2. Убедитесь, что игра никак не была модифицирована.
  3. Переустановите GTA V или пройдите верификацию файлов.
  4. Запустите RageMP от имени администратора.
  5. Установите необходимые пакеты: (Этот и Этот)
  6. Установите RageMP и GTA V на один диск.
  7. Установите RageMP и GTA V на разные диски.
  8. Отключите любые оверлеи (Steam overlay, OBS, Discord overlay, Overwolf).
  9. Убедитесь, что присутствует файл сохранения (запустите одиночную игру и сохраните ее).
  10. Удалите любые моды на GTA V.
  11. Выключите любые антивирусы или добавьте папку в исключения. Добавьте RageMP в исключения Firewall.
  12. Нажмите пкм(правой кнопкой мышки) на ragemp.exe и выберите в меню «Troubleshoot compatibility»/»Исправление проблем с совместимостью».
  13. (NVIDIA USERS) отключите Shadowplay.
  14. (STEAM ONLY) Выйдите из Steam, потом запустите RageMP и дайте ему запустить Steam самому.

На чтение 2 мин Просмотров 1.4к. Опубликовано 05.09.2022

Пользователи довольно часто сталкиваются с проблемами в интернете либо же в скачанных приложениях. Причем это относится и к установкам на ПК, и на смартфонах, а также иных гаджетах. Любители популярной игры GTA 5 не исключение. Они тоже упоминали о сбоях и неполадках данной платформы.

Ошибка Error game injection has timed out GTA 5 Rage Multiplayer: что это?

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

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

Пользователь может перезапустить GTA 5, скачав его заново с того же сайта либо же с нового. Иногда ошибки могут быть связаны с источником, с которого был загружен файл. Именно поэтому это второе, на что необходимо обратить внимание после обнаружения несоответствий. Если же и перезапуск не помог, тогда необходимо проверить свой гаджет на сторонние программы.

Иногда мешать обновления и загрузка могут разные антивирусы и блокировщики рекламы. Тогда рекомендуется, найти их на своём устройстве и на время ограничить деятельность. Если после выполненных действий все заработало как и раньше, тогда дело точно было в этих загрузках. В последующем их можно использовать вне сервиса, а на время игрового процесса выключать.

Иногда проблема стоит в интернет соединении. Даже если все, кроме установки работает, скорости может не хватать для именно её запуска.

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

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

Понравилась статья? Поделить с друзьями:
  • Error expected unqualified id before token ошибка
  • Error expected unqualified id before switch
  • Error expected unqualified id before string constant extern c
  • Error expected unqualified id before return
  • Error expected unqualified id before public