• Из-за обновления GTA 5 (был добавлен новый патч) может временно не работать вход в 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/ru/newswire/
    Статус всех служб для Rockstar Games Launcher и поддерживаемых игр: https://support.rockstargames.com/ru/servicestatus


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

Мануал [C#][Client] Кастомный ExecuteJS из поддержкой результата, Storage C#

DaVilka

Гуру
Автор темы
16 Сен 2020
607
228
108
Кастомная реализация вызова js кода на клиенте из C# клиента, которая так же поддерживает результат вызова.
Для начала в index.js или другом файле добавим ивент который будет просто вызывать eval и возвращать результат
в виде json строки.

JavaScript:
mp.events.add("executeJS", (code, id) => {
    let result = eval(code)
    if(id != undefined) mp.events.callLocal("executeJSCallback", id, JSON.stringify(result));
});

На стороне клиента создадим .cs файл ExecuteJS.cs
И запишем него код

Код:
using HardLife.Utils;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;

namespace HardLife.Utils
{
    internal class ExecuteJSDate
    {
        public Type Type { get; private set; }
        public Action<object> Action { get; private set; }
        public ExecuteJSDate(Type type, Action<object> action)
        {
            Type = type;
            Action = action;
        }
    }
}
internal static class ExecuteJS
{
    private static readonly Dictionary<int, ExecuteJSDate> _callback = new Dictionary<int, ExecuteJSDate>();
    private static int _id = 0;
    static ExecuteJS()
    {
        RAGE.Events.Add("executeJSCallback", ExecuteJSCallback);
    }
    private static void ExecuteJSCallback(object[] args)
    {
        //RAGE.Ui.Console.Log(RAGE.Ui.ConsoleVerbosity.Info, $"ExecuteJSCallback: {args[1]}");
        if (_callback.TryGetValue((int)args[0], out ExecuteJSDate data) && data.Action != null)
        {
            object result = Convert.ChangeType(JsonConvert.DeserializeObject((string)args[1]), data.Type);
            data.Action.Invoke(result);
        }
        if (_callback.ContainsKey((int)args[0])) _callback.Remove((int)args[0]);
    }
    public static void Execute<T>(string code, Action<T> result = null)
    {
        void action(object o) => result?.Invoke((T)o);
        _callback.Add(_id, new ExecuteJSDate(typeof(T), action));
        RAGE.Events.CallLocal("executeJS", code, _id);
        _id++;
    }
    public static void Execute(string code)
    {
        RAGE.Events.CallLocal("executeJS", code);
    }
}
Апи просто, две функции Execute
Первая предназначена для вызова функций которые хотят получить результат
C#:
Execute<T>(string code, Action<T> result = null)
Вторая просто для вызова кода на клиенте
C#:
public static void Execute(string code)

Пример использования:
Если на клиенте есть условная функция:
JavaScript:
function test(){
    return 228;
}
То вызов будет таким, где в r будет передано число (<int>) которое вернет функция на клиенте js
C#:
ExecuteJS.Execute<int>("test()", (r) => { RAGE.Ui.Console.Log(RAGE.Ui.ConsoleVerbosity.Info, $"Result: {r}"); });
Вызов без получения результата.
C#:
ExecuteJS.Execute("test()");
Пример реализации Strorage на C# с использованием ExecuteJS:

API - две функции, первая для записи по ключу, вторая для чтения
Как юзать:

Код:
internal class Test
{
    public string Name { get; set; }
    public int Id {  get; set; }
    public bool IsAlive { get; set; }
}
//Записываем обьект с ключем "test"
Storage.Write("test", new Test() { IsAlive = false, Id = 5435, Name = "Hello World" });
//получаем обьект с ключем "test"
Storage.Read("test", (Test t) =>
{
    RAGE.Ui.Console.Log(RAGE.Ui.ConsoleVerbosity.Info, $"Result: {JsonConvert.SerializeObject(t)}");
});
Код:
using Newtonsoft.Json;
using System;

namespace HardLife.Utils
{
    internal static class Storage
    {
        public static void Write<T>(string key, T data)
        {
            ExecuteJS.Execute($"mp.storage.data.{key} = '{JsonConvert.SerializeObject(data)}';");
            ExecuteJS.Execute("mp.storage.flush();");
        }
        public static void Read<T>(string key, Action<T> result)
        {
            ExecuteJS.Execute<string>($"mp.storage.data.{key}", (r) => { result?.Invoke(JsonConvert.DeserializeObject<T>(r)); });
        }
    }
}

ExecuteJS Github
 

Bloodlust

Гуру
25 Апр 2021
308
103
112
Круто
Чисто ради интереса, для чего это может понадобиться?
 

DaVilka

Гуру
Автор темы
16 Сен 2020
607
228
108
Круто
Чисто ради интереса, для чего это может понадобиться?
Ну вопевых storage, его нету на c#, токо js, так же есть не очень популярные апи гта которые работают не корректно на шарпе(не тот типо возаращаемого значения, или вообще не все ref можно передать и тд), а на жс норм
 
  • Like
Реакции: vpn и Bloodlust