Кастомная реализация вызова js кода на клиенте из C# клиента, которая так же поддерживает результат вызова.
Для начала в index.js или другом файле добавим ивент который будет просто вызывать eval и возвращать результат
в виде json строки.
На стороне клиента создадим .cs файл ExecuteJS.cs
И запишем него код
Апи просто, две функции Execute
Первая предназначена для вызова функций которые хотят получить результат
Вторая просто для вызова кода на клиенте
Пример использования:
Если на клиенте есть условная функция:
То вызов будет таким, где в r будет передано число (<int>) которое вернет функция на клиенте js
Вызов без получения результата.
Пример реализации Strorage на C# с использованием ExecuteJS:
API - две функции, первая для записи по ключу, вторая для чтения
Как юзать:
ExecuteJS Github
Для начала в 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);
}
}
Первая предназначена для вызова функций которые хотят получить результат
C#:
Execute<T>(string code, Action<T> result = null)
C#:
public static void Execute(string code)
Пример использования:
Если на клиенте есть условная функция:
JavaScript:
function test(){
return 228;
}
C#:
ExecuteJS.Execute<int>("test()", (r) => { RAGE.Ui.Console.Log(RAGE.Ui.ConsoleVerbosity.Info, $"Result: {r}"); });
C#:
ExecuteJS.Execute("test()");
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