Vice City: Multiplayer

Server Development => Community Plugins => Topic started by: habi on Jul 18, 2023, 02:48 PM

Title: Remote Exec - An alternative to Streams
Post by: habi on Jul 18, 2023, 02:48 PM
Remote Exec - An alternative to Streams
Remote Exec

Function Documentation
1. SetRemoteValue( key, value )
In server, if you do SetRemoteValue( "a", 10 ). It is equivalent to a<-10 ( rawset ) on client side. Here 'Remote' means Client.
2. GetRemoteValue( "a" )
If you have a global variable named 'a' in client-scripts, this function fetches its value.
3. GetRemoteValueEx( obj, key )
If you have an object obj (table, class, instance) on client side and has a field key in obj, then this function fetches its value.

//Suppose a<-Vector( 1, 2, 3 ) in client-side.
//To get a.Z
GetRemoteValueEx( GetRemoteValue( "a" ), "Z" )
4. SetRemoteValueEx( obj, key, value )
Performs a rawset on object obj with key and value. I have coded it so that you can perform this on Player, Vehicle, etc classes too.

//Suppose a<-Vector( 1, 2, 3 ) client side
//To set a.Z = 0
SetRemoteValueEx( GetRemoteValue( "a" ), "Z", 0 )
5. CallRemoteFunc( func, arg1, arg2, ... )
Calls the func=GetRemoteValue("funcname") with arguments arg1, arg2 , etc.

//Suppose i want to call function foo("hello", 1, 100.0 )
CallRemoteFunc(GetRemoteValue("foo"),"hello", 1, 100.0)
6. CallRemoteFuncEx( func, env, arg1, arg2, ... )
Now you can specify the 'this' object with the function is called.

//This is very complicated and hence i am not providing an example here
RemoteExec ( ... )
RemoteExec( SetRemoteValue("a",100), FindPlayer(0), true, print)
The above six functions are to be used inside 'RemoteExec'.

RemoteExec( userdata, player, (should_return), (callback_func) )The last two parameters are used for getting the result back to server. They are optional. The callback_func must be a one-parameter function like print. I have managed to include a token with every RemoteExec and client sends the result with this token. Thus that function will be called when the token arrivesinvolves
Checking for error in callback_func
The global variable REMEXEC_ERROR will be set to 1 if client throwed error. This variable is to be used inside the callback as follows:
RemoteExec( GetRemoteValue( myvariable ), player, true, function(res)
{
if(!REMEXEC_ERROR)do_something(res);
});
Metamethods
The userdata returned by functions 2, 3,5-6, supports Get and Call metamethods on them.
long code:
CallRemoteFuncEx(GetRemoteValueEx(GetRemoteValue("Console"), "Print"), GetRemoteValue("Console"), "Hello World" )short code:
local Console=GetRemoteValue("Console");
RemoteExec( Console.Print("Helloworld"), player);
The metamethods add, sub, mul, div, modulo and unary minus are likewise defined. See the immediately following post after this for details.

Download
Download plugin ( store files included ) 51.3 KB below (updated Sep 29):
(https://i.imgur.com/EA45WpM.png) (https://www.mediafire.com/file/a23uw15i6vl5uzc/remexec_v1.1.1_a.7z/file)
Installation - Client Side
store/script/main.nut looks like: (partial code, full files included in archive)
dofile("RemoteExec.nut");
dofile("SendReply.nut");
enum StreamType
{
    RemoteExecute=0x40ffffe1  //Used for executing
    RemoteExecuteSpecial=0x40ffffe2    //Used for execution and return result using token
    Reply=0x40ffffe3    //Used when sending result to server
    CompileString=0x40ffffe4   
    RPrint=0x40ffffe5
}


function Server::ServerData(stream) {
//Warning: We are reading Int and not byte !!!!
local i=stream.ReadInt();
if(stream.Error)
{
    return;
}
if(i==StreamType.CompileString)
{
    local script = compilestring(stream.ReadString());
    try{
        local result=script();
    }catch(e)
    {
       
    }
}else if(i==StreamType.RemoteExecute)
{
    try
    {
        local res=ProcessData(stream);
    }catch(e)
    {
        SendReply(-1, e, true);
    }
}else if(i==StreamType.RemoteExecuteSpecial)
{
    local token=stream.ReadInt();
    try
    {
        local res=ProcessData(stream);
        SendReply(token, res);
    }catch(e)
    {
        SendReply(token, e, true);
    }
}
}

Source-code of plugin (cpp): mediafire-link (https://www.mediafire.com/file/umwuejwf3b8fd4y/remexec-source-v1.1.1-a.7z/file) (updated Sep 29) or github (https://github.com/habi498/Remote-Exec)

The function is able to return values like integer, float, string, null, boolean and arrays. However, classes and tables cannot be returned. In such cases the return value will be typeof(result).

If error occurs while executing them on client side, the error is catched and returned as string, which will be printed on server console "remexec (remote): Error message" and if return callback was specifed, the error message string will be the parameter.
Stream Information
The first bytes of the Streams (ServerData/ClientScriptData) uses the following:

ValueType
0x40ffffe1 - 0x40ffffe5  Integer

Default Callback
When parameter three is set to true, but no callback is given as fourth parameter, then plugin searches for following function in roottable and call it if scripted.
function onRemoteExecReply(token,result)
{
//token - internal number used for identifying streams
//result - the value returned from client
}
Title: Re: Remote Exec - An alternative to Streams
Post by: habi on Jul 29, 2023, 08:31 AM
Update:

Now, you can use
GetRemoteValue("a") + GetRemoteValue("b")
inside the RemoteExec function. (parameter one)
Let us see what this is:
GetRemoteValue("a")  will fetch the value of global variable a from client roottable to server.
GetRemoteValue("b") will fetch the  value of global variable b.

GetRemoteValue("a")+GetRemoteValue("b") will perform an addition on client environment whatever may be variables a and b.

Similary the operations +, -, *, / are valid. Unary minus (-) operator also works.

Rules:
1. The userdata (that returned by GetRemoteValue, CallRemoteFunc, etc) must be the left operand and the integer, float, etc must be on right. This is because of the property of metamethods _add, _sub, _mul, _div, _modulo. So
3 + GetRemoteValue("b") // is not valid GetRemoteValue("b") + 3 // is valid2. Concatenation cannot be performed.
GetRemoteValue("A") + " is the value of variable A" //leads to error CallRemoteFunc( GetRemoteValue("format"), "%d is the value of a", GetRemoteValue("a") )   //is valid
Complete Example
RemoteExec(CallRemoteFunc(GetRemoteValueEx(GetRemoteValue("GUI"),"GetScreenSize")),FindPlayer(0),true,
function(val){::print("The remote screenSize is "+val)});
output:
[SCRIPT]  The remote screenSize is (640, 480, 0)
RemoteExec(GetRemoteValueEx(CallRemoteFunc(GetRemoteValueEx(GetRemoteValue("GUI"),"GetScreenSize")),"Y")*0.96,FindPlayer(0),true,
function(val){::print("screenSize.Y * 0.96 is "+val)});
output:
[SCRIPT]  screenSize.Y * 0.96 is 460.8
Note: I don't know, but it happens once in a while passing wrong values and server crashes.
Title: Re: Remote Exec - An alternative to Streams
Post by: habi on Jul 30, 2023, 08:39 AM
update:
fixed crash occuring when trying to send clientscript data that is too long.
fixed another crash when reading data clientscript data.

i have added proper if statement to check size and index before reading them, like this:
case 's':
if (size < index + 3)return 0;//for reading len
len = swap2(*(uint16_t*)(data + index + 1));
//Check if len is less than size. otherwise it crash server.
if (size < index + 3 + len ) { return 0; }
sq->pushstring(v, (char*)data + index + 3, len); k = 1 + 2 + len; break;
Title: Re: Remote Exec - An alternative to Streams
Post by: PSL on Jul 31, 2023, 02:25 PM
Habi well done, I've been waiting a long time, I can't wait, if there are any questions, I will feedback here.
Title: Re: Remote Exec - An alternative to Streams
Post by: habi on Aug 01, 2023, 07:30 PM
Thank you
Title: Re: Remote Exec - An alternative to Streams
Post by: habi on Aug 02, 2023, 06:56 PM
Update
#1: Found and fixed the bug. i have been 'memcpy' more than size and it was crashing server. it is now fixed
#2: Added _get and _call metamethods. See Example
local Console = GetRemoteValue("Console");
RemoteExec(  Console.Print("Greetings from Liberty City"), player )
(https://i.imgur.com/oS2CzaE.jpg)
the second example is little messy:
local RayTrace = GetRemoteValue("RayTrace");
RemoteExec(  RayTrace(Vector(-1073.56, 63.5817, 11.2329),Vector(-1081.5, 104.404, 11.263),15).Collided,player,true,print)
[SCRIPT]  trueWhen you do GetRemoteValue("getroottable")(), the _call metamethod is evoked and when you get like Console.Print, there _get metamethod will be evoked.

Big-Example
This is client side script i took from:
Quote from: Kelvin Garcia Mendoza on Nov 05, 2020, 06:09 PM_label <- null;

function Script::ScriptLoad()
{
 local
 screenSize          = ::GUI.GetScreenSize(),
 label               = ::GUILabel( ::VectorScreen( ( screenSize.X * 0.005 ), ( screenSize.Y * 0.96 ) ), ::Colour( 255, 255, 255 ), format( "Hey, %s. Welcome to the server!", ::World.FindLocalPlayer().Name ) );
 label.FontName      = "Verdana";
 label.FontSize      = ( screenSize.X * 0.2 );
 label.FontFlags     = GUI_FFLAG_BOLD;
 label.TextAlignment = GUI_ALIGN_LEFT;

 ::_label = label;
}
and when changed
function onPlayerJoin(player)
{
 local table= GetRemoteValue("getroottable")();
 local screenSize          = table.GUI.GetScreenSize();
 local label               = table.GUILabel( table.VectorScreen( ( screenSize.X * 0.005 ), ( screenSize.Y * 0.96 ) ), table.Colour( 255, 255, 255 ), table.format( "Hey, %s. Welcome to the server!", table.World.FindLocalPlayer().Name ) );
 
RemoteExec(SetRemoteValue("mylabel",label),player);

local mylabel=GetRemoteValue("mylabel"); //no neeed of '()' as it is not function
RemoteExec(SetRemoteValueEx(mylabel,"FontName","Verdana"),player);
RemoteExec(SetRemoteValueEx(mylabel,"FontSize", 20),player);

local consttable=GetRemoteValue("getconsttable")();
RemoteExec(SetRemoteValueEx(mylabel,"FontFlags",consttable.GUI_FFLAG_BOLD),player);
RemoteExec(SetRemoteValueEx(mylabel,"TextAlignment",consttable.GUI_ALIGN_RIGHT),player);
}
when called this result:
(https://i.imgur.com/GyBwFnx.jpg)

How is it..?

PS (for newbies, if anybody): You have to load remexec04rel32. Otherwise you get 'Error: the index 'GetRemoteValue' does not exist'
Title: Re: Remote Exec - An alternative to Streams
Post by: PSL on Sep 27, 2023, 03:03 PM
I got Error: spawn cmake ENOENT when I used vs code to convert dll.  I'm very sorry, I was working before and didn't have time to test, I may need to try to convert plugin by myself again.
Title: Re: Remote Exec - An alternative to Streams
Post by: habi on Sep 27, 2023, 03:36 PM
The error spawn cmake ENOENT is discussed here (https://github.com/microsoft/vscode-cmake-tools/issues/350#issuecomment-379042041).

btw, are you compiling the plugin from source?
Title: Re: Remote Exec - An alternative to Streams
Post by: PSL on Sep 28, 2023, 06:30 AM
This is an area I have never touched, but I slowly carved, understand, I saw the tutorial on the network installed mingw64 and gcc, I configured the environment variables according to the tutorial, in cmd test gcc -v is OK, then I do not know what to do, in vs code or display the previous error, I'm really not good at this. And I don't know what source code is.
Title: Re: Building Remote Exec on VSCode
Post by: habi on Sep 28, 2023, 07:58 AM
If on windows, download ninja-win zip from https://github.com/ninja-build/ninja/releases.
Put it in c:\ninja\
Add c:\ninja to PATH environment variable
Close VScode and open again.
Do Ctrl+Shift+P and click CMake:Reset
(https://i.imgur.com/4qqVzgt.png)

Again open Command Palette (Ctrl+Shift+P) and run CMake:Select a Kit. Choose GCC xx mingw-32 xx

Now you can successfully build plugin. To build :
From Command Palette run CMake: Select Variant and choose Release.
Then run CMake: Configure
And finally CMake: Build

If successfully, on windows explorer out/binaries you can see the plugin built by vscode.
(https://i.imgur.com/CIqqlcQ.png)

Note: Ninja builds it on folder build originally. It is then copied to out/binaries
Title: Re: Remote Exec - An alternative to Streams
Post by: PSL on Sep 29, 2023, 01:53 AM
Great, thank you so much, with your help, I successfully generated the dll file.
Console display:  [MODULE]  Remote Exec __REMEXEC_VERSION__ by habi loaded.
I will use this plugin according to the information.
Title: Re: Remote Exec - An alternative to Streams
Post by: habi on Sep 29, 2023, 06:14 AM
Sorry that was a later addition to source code which produced the strange result. It escaped my notice.
I will update the source and binaries.
Find this line (701) main. cpp
fputs("Remote Exec __REMEXEC_VERSION__ by
and replace __REMEXEC_VERSION__ by v1.1.1
fputs("Remote Exec v1.1.1 by

To make it work in linux at the same time, do the same to line ( 704 )

EDIT: Source and binaries updated. Added github (https://github.com/habi498/Remote-Exec) link too.
Title: Re: Remote Exec - An alternative to Streams
Post by: PSL on Nov 03, 2023, 05:37 AM
Why did I return userdata 0x00~~?  Can you check it for me..
client:  abc<-Vector(1,2,3);
server: GetRemoteValueEx(GetRemoteValue("abc"),"Z");  return userdata 0x00~~
plugin dll: https://file.io/z0TLnJrM1LO4
Title: Re: Remote Exec - An alternative to Streams
Post by: habi on Nov 06, 2023, 12:05 PM
GetRemoteValue always return 'userdata'.
print(GetRemoteValue(..)) will show 'userdata 0x..'
1. To obtain value from client in one step is not possible because server has to wait until result arrives.
2. Our main function is 'RemoteExec'.
See:
client:  abc<-Vector(1,2,3);
server:
QuoteRemoteExec( GetRemoteValueEx(GetRemoteValue("abc"),"Z"), FindPlayer(0), true, function(val){ print("The Z co-ordinate is "+val); } );

The parameter true tell client to send back the result.
The fourth parameter function will be called when the result arrives which take time.

you can replace 'one parameter function' with 'print' itself:
QuoteRemoteExec(GetRemoteValueEx(GetRemoteValue("abc"),"Z"), FindPlayer(0), true, print );
So 'print' will be called with the result:
[SCRIPT]  3
This replacement with 'print' will be useful for testing purposes.

The userdata returned is actually a C++ array whose length increases with number of GetRemoteValue used. If you use two GetRemoteValue, then the array contain almost double number of elements.
This pointer/array being used by plugin is not visible to squirrel.
Title: Re: Remote Exec - An alternative to Streams
Post by: PSL on Oct 30, 2024, 09:18 AM
Hello habi, I want to call another player's client function directly through the player's client and return the value, how can I achieve this?

The client has a get function that takes a string as its argument

I made a cross transfer function on the server, but it was very difficult, I sent exec text on the client side to execute this function
Title: Re: Remote Exec - An alternative to Streams
Post by: habi2 on Oct 30, 2024, 10:49 AM
Hi PSL, it is a great idea to get values from another client.
I will check if there is any standard way of doing it and modify code.
Title: Re: Remote Exec - An alternative to Streams
Post by: PSL on Nov 01, 2024, 03:55 AM
Hi Habi. In addition to the client sends text to the server, and then the server compiles and executes the text, such a client-side call to the server is problematic. When the transmitted text needs variables, it is necessary to escape quotes, nesting quotes will cause problems, and the server will report an error that the variable does not exist.
In addition to sending executable text, there are other ways to call server-side functions directly, which has a similar effect.

Title: Re: Remote Exec - An alternative to Streams
Post by: habi2 on Nov 18, 2024, 04:25 PM
Quote from: PSL on Nov 01, 2024, 03:55 AMHi Habi. In addition to the client sends text to the server, and then the server compiles and executes the text, such a client-side call to the server is problematic. When the transmitted text needs variables, it is necessary to escape quotes, nesting quotes will cause problems, and the server will report an error that the variable does not exist.
In addition to sending executable text, there are other ways to call server-side functions directly, which has a similar effect.


Hi PSL, i have not yet made function to call server side functions from client. But here is Remote-Exec v1.1.2 in which client can call other client's functions and get back the return value.

Remote Exec v1.1.2


How to call client side function from another client?

There is this new function called PeerExec

Quote from: PSL on Oct 30, 2024, 09:18 AMHello habi, I want to call another player's client function directly through the player's client and return the value, how can I achieve this?

Suppose you have a function 'test' in clientside:
function test(a,b)
{

}
You are player with id 1 and want to call 'test' in player with id 0 and return value:
PeerExec( GetRemoteValue("test")(15,20), 0, function(result){
print( result );
} );
//15=a, 20=b. 0=player with id 0.
//execution continues but the function is stored and invoked when the result from client 0 arrives.

Documentation
PeerExec( [superblob], target-player-id, func )
[superblob] : One returned by functions like GetRemoteValue, SetRemoteValue, etc.
target-player-id : The ID of the player in which you want to execute the logic.
func : An optional function. If provided will be called with the result of logic you executed in the target-player's script.
For full documentation, see files inside.

Examples client-side

Debugging
Any errors are logged in debuglog.txt in %appdata%/VCMP/04beta folder

Downloads (mediafire)
(https://i.imgur.com/ziz8dUO.png) (https://www.mediafire.com/file/8ruvpg5hsyw20pg/remexec-v1.1.2.7z/file)           
You can get the source (https://www.mediafire.com/file/e0i70rx1ex9qwcv/remexec-v1.1.2-source.7z/file) of this plugin also.

You can read the usage here (http://18.132.205.100/remexec/Usage.html) online and Bytecode Documentation here (http://18.132.205.100/remexec/streamdoc.html) also.
Title: Re: Remote Exec - An alternative to Streams
Post by: PSL on Nov 19, 2024, 09:34 AM
Hi Habi, What a surprise! I did not expect that the suggestions I made were adopted and successfully implemented into such a powerful function. Sincerely thank you heart and professionalism, this plug-in is now invincible! Hats off to you, great plugin creator!
Thank you for listening carefully to my suggestions and taking the trouble to turn them into such practical features, praise for your dedication!
I can't wait to play with this plugin, I will report the results here.
Title: Re: Remote Exec - An alternative to Streams
Post by: habi2 on Nov 19, 2024, 09:30 PM
Hi PSL,
I'm glad that you liked it. You are very much welcome.
Title: Re: Remote Exec - An alternative to Streams
Post by: PSL on Nov 20, 2024, 09:47 AM
Hi Habi, I want to implement it on the client side: UI.Sprite("test").hide();
In Server Side:RemoteExec(CallRemoteFunc(GetRemoteValueEx(GetRemoteValueEx(GetRemoteValue("UI"),"Sprite"),"test"),"hide"),player);
error:remexec (remote): the index 'rawget' does not exist
How do I achieve this?
Title: Re: Remote Exec - An alternative to Streams
Post by: PSL on Nov 20, 2024, 09:54 AM
RemoteExec(CallRemoteFunc(GetRemoteValueEx(CallRemoteFunc(GetRemoteValueEx(GetRemoteValue("UI"),"Sprite"),"test"),"hide")),player);
error:remexec (remote): the index 'fetch' does not exist

This is very close to the answer, I can not find why the failure.
Title: Re: Remote Exec - An alternative to Streams
Post by: habi2 on Nov 20, 2024, 10:29 AM
UI.Sprite("test").hide();

local func= GetRemoteValueEx(GetRemoteValue("UI"),"Sprite")
CallRemoteFuncEx(func, GetRemoteValue("UI"), "test")
Quote from: PSL on Nov 20, 2024, 09:54 AMRemoteExec(CallRemoteFunc(GetRemoteValueEx(CallRemoteFunc(GetRemoteValueEx(GetRemoteValue("UI"),"Sprite"),"test"),"hide")),player);
error:remexec (remote): the index 'fetch' does not exist

This is very close to the answer, I can not find why the failure.
Hi PSL, this is close to answer. It can be fixed by using CallRemoteFuncEx. Then you can pass UI as environment object (this) of the function UI.Sprite. Otherwise you are calling UI.Sprite with roottable as environment object. Many variables coded inside function UI.Sprite will be tried to fetched from roottable instead of class UI.

So the complete correct answer may be:
local func= GetRemoteValueEx(GetRemoteValue("UI"),"Sprite");
local obj= CallRemoteFuncEx(func, GetRemoteValue("UI"), "test"); //environment object=GetRemoteValue("UI")
CallRemoteFuncEx(GetRemoteValueEx(obj, "hide"), obj); //again careful about environment object this = obj =UI.Sprite("test")
I hope this will do the work. Seeing that codes will get bigger there is metamethods available on GetRemoteValue. The interesting alternative:
GetRemoteValue("UI").Sprite("test").hide();
Above code will automatically expand itself.

Please tell me if these worked.
Title: Re: Remote Exec - An alternative to Streams
Post by: PSL on Nov 21, 2024, 01:43 AM
Hi Habi,This approach is feasible: GetRemoteValue("UI").Sprite("test").hide();
However, this method is not feasible

local func= GetRemoteValueEx(GetRemoteValue("UI"),"Sprite");
local obj= CallRemoteFuncEx(func, GetRemoteValue("UI"), "test"); //environment object=GetRemoteValue("UI")
CallRemoteFuncEx(GetRemoteValueEx(obj, "hide"), obj); //again careful about environment object this = obj =UI.Sprite("test"

still prompt remexec (remote): the index 'rawget' does not exist
But thank you for helping me out!
Title: Re: Remote Exec - An alternative to Streams
Post by: PSL on Nov 22, 2024, 01:51 PM
Hi Habi,I found that when the length of the array is more than 310, the length of the array is 315, and it cannot be returned from the client to the server
Title: Re: Remote Exec - An alternative to Streams
Post by: habi2 on Nov 22, 2024, 03:35 PM
Hi PSL, thank you for interest in the plugin. Streams in vc-mp server has a limitation (https://forum.vc-mp.org/index.php?topic=9283.0) that stream length is limited by 4095 bytes even though more bytes correctly arrive at server.

I will see what can be done. May be splitting the packet and joining serverside.
Title: Re: Remote Exec - An alternative to Streams
Post by: habi2 on Nov 26, 2024, 04:34 PM
Hi PSL, the problem with arrays of length more than 310 is resolved:

RemoteExec v1.1.3



Downloads

(https://i.imgur.com/nA8AEXI.png) (https://www.mediafire.com/file/zktriyey03phalj/remexec-v1.1.3.7z/file)

You can get the updated source (https://www.mediafire.com/file/lsdgm0v0ovhgk9u/remexec-v1.1.3-source.7z/file) here.
Title: Re: Remote Exec - An alternative to Streams
Post by: [TDA]Speed on Dec 11, 2024, 11:18 AM
sorry but i dont understand this plugin allows you to use client side scripts with normal server scripts ?
Title: Re: Remote Exec - An alternative to Streams
Post by: habi2 on Dec 12, 2024, 09:21 AM
Thanks for asking. This plugin allows one from server-script to
1. Call client-side functions in client-side scripts
Explanation: Usually on serverside:
local buffer=Stream();
buffer.StartWrite();
buffer.WriteInt(100); 
buffer.WriteString("Hello");
buffer.SendStream(player); //Send stream to a valid player

and on client-side:
function Server::ServerData(stream)
{
local i=stream.ReadInt();
switch(i)
{
case 100: local str=stream.ReadString();
          ::foo(str);
case 101 : //Another function or code

...

}
function foo(msg)
{
Console.Print(msg); //just for example
}

Now using plugin, one can possibly reduce these codes to
local str="Hello";
local buffer=GetRemoteValue("foo")(str); //buffer will be created as userdata. nothing send yet!
RemoteExec(buffer, player); //Call foo(str) client-side if possible. plugin will internally create the stream and send to client.
//The client-side script which comes with the plugin reads the stream and will execute the 'action': in this case is call the 'foo' function with str='Hello'.
I hope everybody understand.
Title: Re: Remote Exec - An alternative to Streams
Post by: [TDA]Speed on Dec 12, 2024, 10:30 AM
Oh okey thanks
Title: Re: Remote Exec - An alternative to Streams
Post by: habi2 on Dec 26, 2024, 10:56 AM
RemoteExec v1.1.4



Downloads

(https://i.imgur.com/0ZKDCWl.png) (https://www.mediafire.com/file/dc0gme1omvxf0u5/remexec-v1.1.4.7z/file)

You can get the updated source (https://www.mediafire.com/file/5cg5vo90u6f80k4/remexec-v1.1.4-source.7z/file) here.

VirusTotal scan report of binaries- 1/63 link (https://www.virustotal.com/gui/file/267484208baa635ee6833204c85cbfc00c0fd4ec42c6a8b180ef415803188d65)


Example Usage
//Written from memory of recent testing
local f=file("image.bmp", "rb");
local c=f.readblob(f.len()); // c is a blob
f.close();
RemoteExec(GetRemoteValue("DrawBitMap")(c), FindPlayer(0)); //calling DrawBitMap( c  ) - a client side function in player with ID 0 's space
For information about DrawBitMap, see this (https://forum.vc-mp.org/index.php?topic=9572) topic.
Title: Re: Remote Exec - An alternative to Streams
Post by: PSL on Feb 02, 2025, 02:06 PM
Hi Habi.
This plugin works well, I've been using it, I'm having some problems right now.
shop <- null;

class Shop {
a = null;
b = null;
constructor(a,b){
}
}

The client has a slot A and a Shop class
I want to implement a = Shop(a,b); But it failed.

My code:
local userData = ::SetRemoteValue( ::GetRemoteValue("shop"), ::CallRemoteFunc( ::GetRemoteValue("Shop"), name, cargo ) );
 ::RemoteExec(userData, player);
Title: Re: Remote Exec - An alternative to Streams
Post by: habi2 on Feb 02, 2025, 04:40 PM
Hi PSL,
I am glad to know that plugin is working fine.

Your code change to this and try:
local userData = ::SetRemoteValue( "shop", ::CallRemoteFunc( ::GetRemoteValue("Shop"), name, cargo ) );
 ::RemoteExec(userData, player);
Title: Re: Remote Exec - An alternative to Streams
Post by: PSL on Feb 03, 2025, 05:24 AM
Thank you. The code you provided worked
Title: Re: Remote Exec - An alternative to Streams
Post by: habi2 on Feb 17, 2025, 07:12 AM
Remote Exec v1.1.6 Released

We are pleased to announce the release of Remote Exec v1.1.6 for VC:MP servers. This version includes improvements and fixes along with the necessary client-side script files for proper functionality.

Changelog:

v1.1.6 (includes v1.1.5 changes, which was not released) 

Download: 

(https://i.imgur.com/6y7KxvB.png) (https://www.mediafire.com/file/748y8ht43hja64p/remexec-v1.1.6.7z/file)  (410.75 KB) (mediafire)

Virus-total scan of 7zip: (1/63) (https://www.virustotal.com/gui/file/019155506187e845915a1f7195e80fb4344a18a41697134eb2db10ef21df2aff)

Source-code: here (https://www.mediafire.com/file/ez6h4dsusk0tgac/remexec-v1.1.6-source.7z/file) (153.23 KB, mediafire)

For installation and usage details, refer to the provided documentation. 

Thank you for your interest in remote-exec.
Title: Re: Remote Exec - An alternative to Streams
Post by: PSL on Feb 17, 2025, 09:34 AM
I can't wait to use it. Well done, Habi bro!
Title: Re: Remote Exec - An alternative to Streams
Post by: habi2 on Feb 17, 2025, 05:56 PM
thank you PSL
Title: Re: Remote Exec - An alternative to Streams
Post by: PSL on Feb 19, 2025, 11:18 AM
Hello, Hibi.
An error occurred with GetRemoteValue("print")("abc") on the client, typeof( GetRemoteValue("print")("abc") ) This returns type null.
When I use Exec(GetRemoteValue("print")("Have a nice day")) the client throws an error PeerExec: superblob expected but got null

    local userData = CallRemoteFunc( GetRemoteValue("print"),"123");
    Exec( userData );  //This is effective
Title: Re: Remote Exec - An alternative to Streams
Post by: habi2 on Feb 19, 2025, 01:11 PM
Hi PSL,
There was a problem with _call metamethod of superblob, that it will fail if the 'this' parameter is not table(eg.roottable). I have fixed the problem, now GetRemoteValue("")() can be used anywhere( table, class or instance) :
Player::PlayerDeath, Player::PlayerShoot, all events of Player ( this = Player, a class )
Like Player, it is available across places where 'this' is class like GUI, KeyBind, Script or Server.

This is updated in the following file:
Download PeerExec.nut (https://www.mediafire.com/file/ncwul8wjpmq7meb/PeerExec.nut/file)

I hope this will solve the problem
Title: Re: Remote Exec - An alternative to Streams
Post by: PSL on Feb 19, 2025, 01:42 PM
After my testing, this problem has been solved
Title: Re: Remote Exec - An alternative to Streams
Post by: habi2 on Feb 19, 2025, 03:44 PM
thank you for testing.