Из-за обновления 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) последний раз были обновлены:
Вы используете устаревший браузер. Этот и другие сайты могут отображаться в нём некорректно. Вам необходимо обновить браузер или попробовать использовать другой.
Обновление 0.3.0 — большое обновление C#, этап второй.
Добавлены короткий серверный API, поддержка асинхронных обработчиков, перехват урона, огня и взрывов. Расширено событие отключения игрока и управление отображением интерфейсов.
Добавлен класс Api — аналог Alt в alt:V по назначению.
Это короткая точка доступа к серверному C# SDK: создание и поиск сущностей, события, метаданные, ресурсы, RPC и другие операции.
В классе 215 публичных методов с учётом перегрузок, 49 событий и 11 свойств. Группированный API через Server также остаётся доступен.
C#:
using System.Threading;
using System.Threading.Tasks;
using Mint.Server;
using Mint.Server.Events;
using Mint.Server.Players;
using Mint.Server.Shared;
// Создание транспорта.
var vehicle = Api.CreateVehicle("sultan", new Vector3(100, 200, 30));
// Поиск игрока и отправка клиентского события.
var player = Api.GetPlayerById(1);
if (player is not null)
Api.EmitClient(player, "notification", "Привет!");
// Событие всем игрокам.
Api.EmitAllClients("announcement", "Сервер обновлён!");
// Типизированные метаданные.
Api.SetMeta("weather", "CLEAR");
var weather = Api.GetMeta<string>("weather");
// Экспорт функции для других ресурсов.
Api.Export("sum", (int a, int b) => a + b);
Примеры подписок ниже размещаются в OnStart() ресурса. Добавлена поддержка асинхронного выполнения в C#.
Она встроена в основной SDK: отдельная библиотека и классы вроде AsyncPlayer не требуются.
Обработчики могут возвращать Task или ValueTask, ожидать запрос к БД, HTTP или другую асинхронную операцию. После обычного await выполнение продолжается в контексте ресурса, где снова доступна работа с SDK.
C#:
Api.OnClientAsync("request", async (IPlayer player, string message) =>
{
await Task.Delay(1000); // Например, ожидание запроса к БД.
if (!player.Valid) return;
Api.EmitClient(player, "response", $"Получено: {message}");
});
Для отмены ожидания при остановке ресурса можно добавить CancellationToken. Runtime передаёт его автоматически — отправлять токен с клиента не нужно.
Поддерживаются асинхронные серверные и клиентские события, одноразовые подписки, обработчики через атрибуты и RPC. Для обращения к SDK из стороннего потока используется Api.Dispatcher.InvokeAsync(...).
Ограничения:
async void не поддерживается.
OnStart, OnTick, OnStop и хуки IModule остаются синхронными.
RunAsync не переносит вычисления в отдельный поток. Для тяжёлых вычислений используется Task.Run, внутри которого нельзя напрямую обращаться к живым сущностям.
После await сущность могла быть удалена или игрок мог отключиться — проверяйте Valid.
Асинхронные результаты межресурсных exports пока не поддерживаются.
Добавлены серверные события fire, explosion и weaponDamage.
Они доступны в C# и JavaScript. fire позволяет разрешить или запретить создание пожара. Обработчик получает отправителя запроса, позицию и сущность, к которой привязан огонь. Для огня на земле сущность равна null. explosion позволяет разрешить или запретить взрыв. Передаются отправитель запроса, тип взрыва, позиция и множитель урона.
У обоих событий false запрещает эффект. Отправитель запроса не обязательно является виновником; для серверного источника он может быть null. Изменение урона через эти два события пока не поддерживается. Отмена fire не тушит уже существующий пожар.
Примеры на C#:
C#:
// Разрешить огонь на сущностях, запретить отдельные пожары на земле.
Api.OnFire += (reporter, position, entity) =>
{
Api.Log($"Пожар: {position}, сущность: {entity?.Id}");
return entity is not null;
};
// Запретить взрывы ракет.
Api.OnExplosion += (reporter, type, position, damageScale) =>
{
Api.Log($"Взрыв: {type}, множитель урона: {damageScale}");
return type != ExplosionType.Rocket;
};
Примеры на серверном JS:
JavaScript:
import * as mint from 'mint-server';
mint.on('fire', (reporter, position, entity) => {
return entity != null;
});
mint.on('explosion', (reporter, type, position, damageScale) => {
return type !== 4; // 4 — взрыв ракеты.
});
Также можно поджечь колесо автомобиля или запустить таймер его взрыва. Создаваемые эффекты проходят соответствующие серверные проверки.
C#:
// vehicle и player — действующие сущности.
vehicle.Wheels.SetWheelOnFire((byte)0, true);
vehicle.Weapons.SetTimedExplosion(true, player, 3000);
weaponDamage позволяет отменить попадание или изменить величину урона.
Добавлена обработка обычных ударов ближнего боя, включая кулаки и холодное оружие.
Обработчик получает атакующего, цель, хеш оружия, урон, смещение точки попадания относительно цели и идентификатор кости GTA.
Пример на C#: запрет ударов кулаками и уменьшение остального поддерживаемого урона вдвое.
В JS false отменяет попадание, число заменяет урон, true или отсутствие возвращаемого значения сохраняет его.
Перехват охватывает поддерживаемые попадания из ручного огнестрельного оружия и обычные melee-удары по игрокам и динамическим серверным педам с назначенным владельцем. Транспорт и объекты как цели, урон взрывов и парные добивания пока не входят в это покрытие.
Величина damage передаётся в расчёт GTA: итоговая потеря HP также зависит от брони и других игровых модификаторов.
Все три события требуют синхронного решения — async и await в их обработчиках не поддерживаются. В событие playerDisconnect добавлен снимок последних известных серверу данных игрока.
Теперь параметры события:
Код:
player, reason, snapshot
player — уже недействительная сущность отключившегося игрока.
reason — причина отключения.
snapshot — неизменяемый снимок данных, сохранённый до очистки сессии.
Снимок можно читать после await, например при сохранении персонажа.
| C# | JS | Данные |
|---|---|---|
| Id | id | ID игрока |
| Name | name | Имя |
| Position | position | Позиция |
| Rotation | rotation | Поворот в радианах |
| Velocity | velocity | Скорость |
| Dimension | dimension | Измерение |
| Model | model | Хеш модели |
| Health, MaxHealth | health, maxHealth | Здоровье и его максимум |
| Armor, MaxArmor | armour, maxArmour | Броня и её максимум |
| CurrentWeapon | currentWeapon | Хеш текущего оружия |
| VehicleId | vehicleId | ID транспорта либо null |
| Seat | seat | Место в транспорте либо null; водитель — 1 |
| Interior | interior | Интерьер |
| IsDead | isDead | Состояние смерти |
Пример на C#:
Существующие C#-обработчики необходимо обновить с учётом третьего параметра. Для CEF WebView, RmlDocument и TextLabel добавлено свойство showOnPauseMenu.
Оно определяет, продолжит ли объект отображаться при открытой игровой карте или меню паузы. По умолчанию — false.
Переход на нативную синхронизацию.
Переход проводился точечно, что бы избежать переноса всей нативной сети. Основной акцент был сделан именно на синхронизации между игроками и игровыми сущностями.
Из-за технических ограничений максимальное количество игроков в зоне стрима было временно уменьшено до 64, а онлайна до 1000.
Старая система синхронизации была удалена, но ещё не полностью. В связи с этим после обновления могут встречаться отдельные баги и нестандартное поведение.
Исправления:
Исправлены призрачные авто.
Исправлен туман войны.
Исправлена проблема с weaponDamage, из-за которой урон в некоторых случаях не проходил.
Переход на нативную синхронизацию.
Переход проводился точечно, что бы избежать переноса всей нативной сети. Основной акцент был сделан именно на синхронизации между игроками и игровыми сущностями.
Из-за технических ограничений максимальное количество игроков в зоне стрима было временно уменьшено до 64, а онлайна до 1000.
Старая система синхронизации была удалена, но ещё не полностью. В связи с этим после обновления могут встречаться отдельные баги и нестандартное поведение.
Исправления:
Исправлены призрачные авто.
Исправлен туман войны.
Исправлена проблема с weaponDamage, из-за которой урон в некоторых случаях не проходил.
Параметр resourcesPath заменён на resources для явного указания загружаемых ресурсов. Ресурсы размещаются в постоянной папке resources рядом с серверным TOML.
Код:
resources = ["chat", "npc", "core"]
Отсутствующий или пустой список означает запуск без ресурсов.
Добавлен параметр dlcWhitelist, который задаётся в корне серверного TOML.
Пустой список или отсутствие настройки сохраняет штатный выбор DLC GTA. Непустой список разрешает только перечисленные штатные DLC; пользовательские DLC добавляются отдельно.
Указываются имена папок DLC без префикса dlc_, суффикса CRC и полного пути.
Код:
dlcWhitelist = ["mpheist", "mpapartment"]
Добавлена секция [pools] в клиентском client.toml — ограниченный аналог настройки пулов через gameconfig. Пока настраивается только на стороне клиента.
Значения задают количество элементов пула. Ниже приведён пример настройки, а не значения по умолчанию:
Код:
[pools]
# Записи метаданных игровых ресурсов
MetaDataStore = 7000
# Словари текстур
TxdStore = 110000
# Фрагментные модели, включая модели с разрушаемыми частями
FragmentStore = 62000
# Словари анимаций
AnimStore = 22000
# Ресурсы интерфейса Scaleform
ScaleformStore = 1200
# Данные подбираемых предметов
CPickupData = 1100
Изменять настройки нужно при закрытой GTA. Они применяются при следующем запуске игры; переподключения к серверу недостаточно.
Добавлен параметр cdnEnabled, включающий загрузку клиентских ресурсов с CDN. Для включения нужны корректный cdnUrl и заранее подготовленная публикация ресурсов. При cdnEnabled = false ресурсы собирает и раздаёт сервер.
Добавлен параметр encryptResources, управляющий шифрованием публикуемых клиентских ресурсов: stream/DLC, клиентских скриптов и UI.
Оба параметра задаются в корне серверного TOML и по умолчанию выключены:
Код:
cdnEnabled = false
encryptResources = false
При debug = true настройки CDN и шифрования игнорируются.
Добавлена секция [overrides] в stream-манифесте для замены файлов GTA по виртуальному пути. Формат: MOUNT_PATH = REPLACEMENT_PATH.
Путь к файлу замены указывается относительно корня ресурса. Файл должен входить в client-files, например:
Код:
client-files = ["replaces/**"]
Поддерживаются XML, META, DAT, YTD, YDR, YFT, YDD и YMT. Расширения исходного и заменяемого файлов должны совпадать.
Один и тот же файл замены нельзя одновременно объявлять в [meta]: он уже обслуживается через boot override.
Overrides пока несовместимы с включённым шифрованием ресурсов: при encryptResources = true и debug = false сервер отклоняет такую публикацию.
Изменение dlcWhitelist или [overrides] требует перезапуска GTA.
Поддержка [pools], dlcWhitelist и [overrides] реализована для GTA 3889.
Добавлены консольные команды:
quit — закрывает GTA/клиент.
disconnect — отключается от сервера или отменяет текущее подключение.
Оптимизировано появление сущностей в зоне стриминга: создание распределяется по кадрам, устранена повторная переустановка хуков при появлении и удалении сущностей.
Браузер лаунчера был вынесен из ядра клиента в угоду более удобного расширения функционала клиента игры.
Добавлен API лаунчеру для пользовательских приложений.
Обмен данными происходит через stdin/stdout в формате JSON, а активация использования апи происходит передачей параметра лаунчеру Launcher.exe --api,
после чего лаунчер запустится скрытно и будет ждать команд.
После запуска лаунчер сообщает о готовности: {"event":"ready","commands":["settings.get","settings.set","servers.list","update","prepare","launch","cancel","trust.confirm","shutdown"]}
Каждый запрос содержит:
id - положительное целое число, уникальное для запроса;
command - название команды;
остальные поля - параметры команды.
Команды: settings.get - получить настройки client.toml. {"id":1,"command":"settings.get"}
settings.set - изменить переданные настройки.
Доступные поля: playerName, gameDirectory, voiceVolume, microphoneVolume, microphoneEnabled, discordEnabled.
Громкость задаётся целым числом от 0 до 100. {"id":2,"command":"settings.set","settings":{"playerName":"Player","voiceVolume":80}}
servers.list - получить список серверов в result.servers. {"id":3,"command":"servers.list"}
update - проверить и установить обновления MiNT без запуска GTA. {"id":4,"command":"update"}
prepare - проверить и загрузить ресурсы выбранного сервера.
Не обновляет MiNT, не требует установленной GTA и не запускает игру. {"id":5,"command":"prepare","server":"127.0.0.1:22005"}
launch - обновить MiNT, подготовить ресурсы сервера и запустить GTA.
Предварительный prepare необязателен. Если ресурсы уже подготовлены, используется подходящий кеш. {"id":6,"command":"launch","server":"127.0.0.1:22005"}
Дополнительные поля launch: --gameDirectory - папка игры. Без неё используется сохранённый путь и автопоиск. Если GTA не найдена, возвращается ошибка без диалога выбора папки. --offline - пропустить обновление MiNT. Проверка ресурсов сервера выполняется. {"id":7,"command":"launch","server":"127.0.0.1:22005","gameDirectory":"D:\\Games\\GTA V","offline":true}
cancel - запросить отмену активной операции по id. {"id":8,"command":"cancel","targetId":7}
trust.confirm - ответить на запрос подтверждения изменения ключа сервера. targetId - id операции, requestId - строка из события trust.required. {"id":9,"command":"trust.confirm","targetId":7,"requestId":"1","accepted":true}
error.code предназначен для обработки в программе, error.message - сообщение.
Основные результаты: update - status: ready либо skipped при offline: true; prepare - status: ready; launch - status: handedOff после первого успешного подключения; cancel - status: cancelling; итог отменяемой операции приходит отдельно после очистки; trust.confirm - status: accepted, решение принято в обработку; shutdown - status: stopped, затем процесс завершается.
Промежуточные события содержат event и id соответствующего запроса.
progress - прогресс обновления, подготовки ресурсов или запуска.
stage: update, prepare или launch.
phase уточняет текущую работу.
completedBytes и totalBytes показывают прогресс текущей фазы, totalBytes: null - неизвестный объём.
События запуска могут содержать message вместо счётчиков. {"id":5,"event":"progress","stage":"prepare","phase":"resources","completedBytes":5000,"totalBytes":10000}
trust.required - требуется решение пользователя о смене ключа сервера.
Содержит requestId, server, previousKey и candidateKey.
Покажите пользователю сервер и оба ключа, затем отправьте trust.confirm с accepted: true или false.
Одновременно выполняется одна операция. Пока она активна, обычные команды получают BUSY, cancel, trust.confirm и shutdown остаются доступны.
После итогового ответа API продолжает принимать команды. Результат операции определяется её JSON-ответом, а не кодом выхода процесса.
Python:
import itertools
import json
import subprocess
LAUNCHER = r"D:\MiNT\Launcher.exe"
def main():
with subprocess.Popen(
[LAUNCHER, "--api"],
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
creationflags=subprocess.CREATE_NO_WINDOW,
) as process:
ids = itertools.count(1)
def send(command, **arguments):
request_id = next(ids)
payload = {"id": request_id, "command": command, **arguments}
process.stdin.write((json.dumps(payload, ensure_ascii=False) + "\n").encode("utf-8"))
process.stdin.flush()
return request_id
def receive():
line = process.stdout.readline()
if not line:
raise RuntimeError("MiNT API закрыл соединение до получения ответа")
return json.loads(line.decode("utf-8"))
def request(command, **arguments):
request_id = send(command, **arguments)
while True:
message = receive()
if "ok" in message:
if not message["ok"]:
error = message["error"]
raise RuntimeError(f"{error['code']}: {error['message']}")
if message["id"] == request_id:
return message["result"]
# Ответ trust.confirm тоже проходит через этот цикл.
elif message.get("event") == "progress":
stage = message.get("stage", "")
if "message" in message:
print(stage, message["message"])
else:
done = message.get("completedBytes", 0)
total = message.get("totalBytes")
print(stage, message.get("phase", ""), f"{done}/{total or '?'} байт")
elif message.get("event") == "trust.required":
print("Изменился ключ сервера:", message["server"])
print("Предыдущий:", message["previousKey"])
print("Новый:", message["candidateKey"])
accepted = input("Принять новый ключ? [да/нет]: ").strip().lower() == "да"
send("trust.confirm", targetId=message["id"],
requestId=message["requestId"], accepted=accepted)
try:
ready = receive()
if ready.get("event") != "ready":
raise RuntimeError(f"API не готов: {ready}")
try:
for server in request("servers.list")["servers"]:
host = server["host"]
address = f"[{host}]" if ":" in host else host
print(f"{server['name']} — {address}:{server['port']}")
except RuntimeError as error:
print("Список серверов недоступен:", error)
endpoint = input("Адрес сервера (host:port): ").strip()
request("prepare", server=endpoint)
print("Ресурсы готовы. Запускаю GTA...")
result = request("launch", server=endpoint)
print("Результат запуска:", result["status"])
request("shutdown")
finally:
try:
process.stdin.close()
except BrokenPipeError:
pass
for _ in process.stdout:
pass
process.wait()
if __name__ == "__main__":
try:
main()
except KeyboardInterrupt:
print("Операция остановлена.")
except (OSError, RuntimeError) as error:
print("Ошибка:", error)
Расширен [pools](gameConfig) из 6 до 21 свойств и вынесен на сервеную сторону
Добавлена outline система:
JavaScript:
export interface IOutlineOptions {
/** Стиль. По умолчанию: 'contour'. */
style?: 'contour' | 'glow' | 'fill';
/** Режим видимости. По умолчанию: 'xray'. */
mode?: 'visible' | 'xray';
/** RGBA: целые значения 0–255. По умолчанию: (0, 255, 255, 230). */
color?: IRGBA;
/** Толщина/радиус 1–8 пикселей. По умолчанию: 2. Для fill игнорируется. */
width?: number;
}
export class Outline {
constructor(options?: IOutlineOptions);
readonly valid: boolean;
readonly size: number;
/** Присваивание заменяет настройки; пропущенные поля получают defaults. */
options: IOutlineOptions;
/** Entity или GTA scriptID, не сетевой ID. */
add(target: Entity | number): boolean;
remove(target: Entity | number): boolean;
has(target: Entity | number): boolean;
/** Убирает все цели, сохраняя группу и настройки. */
clear(): void;
/** Удаляет группу и освобождает слот. */
destroy(): void;
}
/** Упрощённая подсветка одной цели. Следующий вызов заменяет предыдущую. */
export function setOutline(
target: Entity | number,
options?: IOutlineOptions,
): boolean;
/** Очищает одиночную подсветку текущего ресурса. */
export function clearOutline(): void;
На данный момент имеет несколько стилей(style), "contour" - чёткий внешний контур, "glow" - мягкое внешнее свечение и "fill" - заливка силуэта цветом, mode, "visible" - учитывает глубину и "xray" - рисуется по верх всего color{ r, g, b, a } - цвет, включая прозрачность width - число от 1–8, толщина контура или радиус свечения в пикселях
JavaScript:
import * as mint from 'mint-client';
const selected = new mint.Outline({
style: 'glow',
mode: 'visible',
width: 6,
color: new mint.RGBA(0, 255, 180, 220),
});
mint.on('keyup', key => {
if (key === mint.KeyCode.F6) {
selected.clear();
if (!selected.add(mint.Player.local)) {
mint.logWarning('Не удалось добавить игрока в подсветку.');
}
const vehicle = mint.Player.local.vehicle;
if (vehicle && !selected.add(vehicle)) {
mint.logWarning('Не удалось добавить машину в подсветку.');
}
} else if (key === mint.KeyCode.F9) {
selected.clear();
}
});
source - Игрок, отправивший серверу запрос попадания target - Сущность, получающая попадание weaponHash - Хеш оружия damage - Входная величина урона; окончательная потеря HP зависит от расчёта GTA offset / shotOffset - Точка попадания в локальных координатах цели bodyPart - Область тела из BodyPart, например Head = 20, Unknown = -1 sourceEntity - источник попадани
Изменен серверный контракт: вместо прежнего boneId передаётся BodyPart, также добавлен sourceEntity.
Добавлены серверные ивенты о фактическом нанесении урона:
Доработана сборка ресурсов:
самостоятельные streaming-ассеты теперь собираются без фиктивной metadata
фикс маленького размера ресурса
Добавлен и интегрирован game-data.json который содержит информацию о штатных машинах, персонажах, оружии, одежды, скелетах моделей, палитру и категории колёс
Оптимизация клиента и исправления синхронихации:
Убраны лишние чтения состояний сущностей и часть работы на каждом кадре что увеличило фпс
Исправлена причина причина фризов связанная с аудио.
Исправлено зависание при запуске клиента
Исправлен разрыв соединения спавне авто с неверным хешем
Подняты лимиты контроллеров до количества сущностей в зоне стрима
убрана команда disconnect MiNT Multiplayer v0.6.0-dev