Jump to content

Recommended Posts

I have recently created a local server (just hosting from the server browser), this server has some scripts that i don't want to expose to the player (due to them stealing it).

I found out you can use the profileNamespace to save data to the profile of the player and as such i am able to store strings, arrays and stuff like that.

My problem arises after i try to save scripts into the namespace -> saving them using the saveProfileNamespace (script is callable and is fine so far) -> shutting down the server after finishing playing.

Now, when i start the server i am able to load the variables from the namespace and use them, but i can't call\spawn code that i stored inside the profile namespace as it raises this error:

Global namespace not passed during: hint "test"
Error Local variable in global space

in order for you to replicate do the following:
 

1. start the debug console in an editor mission
2. enter these 2 lines:

profileNamespace setVariable ["testFunction",{hint "test";}];

saveProfileNamespace;
3. restart the game
4. start the debug console again
5. enter this line:
[] spawn (profileNamespace getVariable "testFunction");
6. wonder desperately why the function isn't being executed 

  • Sad 1

Share this post


Link to post
Share on other sites

not sure but have you tried saveProfileNamespace ?

Share this post


Link to post
Share on other sites
profileNamespace setVariable ["testFunction","hint 'testing hint'"];
saveProfileNamespace;

[] spawn compile (profileNamespace getVariable "testFunction");

 

Share this post


Link to post
Share on other sites
Just now, davidoss said:

profileNamespace setVariable ["testFunction","hint 'testing hint'"];
saveProfileNamespace;

[] spawn compile (profileNamespace getVariable "testFunction");

 

In this small sample this will work great but my script is several hundred lines long, how could i do the same thing with my file?

just wrap everything inside a string and hope for the best or is there a specific method i should use to do this correctly?

Share this post


Link to post
Share on other sites

Best way is to load extra server mod with  scripts.

This allow you to access serversided files like this:

[] execVM "\myservermod\script.sqf";

 

  • Like 2

Share this post


Link to post
Share on other sites
Just now, Lordeath19 said:

I have recently created a local server (just hosting from the server browser), this server has some scripts that i don't want to expose to the player (due to them stealing it).

I found out you can use the profileNamespace to save data to the profile of the player and as such i am able to store strings, arrays and stuff like that.

My problem arises after i try to save scripts into the namespace -> saving them using the saveProfileNamespace (script is callable and is fine so far) -> shutting down the server after finishing playing.

Now, when i start the server i am able to load the variables from the namespace and use them, but i can't call\spawn code that i stored inside the profile namespace as it raises this error:

Global namespace not passed during: hint "test"
Error Local variable in global space

in order for you to replicate do the following:
 

1. start the debug console in an editor mission
2. enter these 2 lines:

profileNamespace setVariable ["testFunction",{hint "test";}];

saveProfileNamespace;
3. restart the game
4. start the debug console again
5. enter this line:
[] spawn (profileNamespace getVariable "testFunction");
6. wonder desperately why the function isn't being executed 

 

Its an open source community. Why not allow other members to utilize your scripts too? Just saying. 

  • Like 1

Share this post


Link to post
Share on other sites

I'm rather sure that, when you setVariable a code, this code runs and you just record the return value if any (here none).

You need to stringify the code.

profileNameSpace setVariable ["testFunction", " hint 'test' "];   // here str ( {hint "test"}) doesn't work because str also returns a result.

then:

call compileFinal (profileNameSpace getVariable ["testFunction",""] )

 

Just an idea, sorry not tested.

Oups, I didn't see the @Lordeath19  answer. So, confirmed. Not recommended anyway. Your profilenameSpace is not a good place for such big data.

compileFinal is safer.

Imho, saveProfileNameSapce is just a useless command as you "save" what you want when using setVariable in the profileNameSpace.  Long discussion.... But, I never used them from my mods and always kept the data from Arma sessions. So? test with and without. Any difference?

Share this post


Link to post
Share on other sites

Also as sidenote, I would strongly discourage you from doing this, since you'll be polluting user profile with long texts, possibly decreasing user performance not only with your mission, but in arma as general. I don't know how exactly profile values work on backend part, but they're heavily used for UI stuff (the colors and positions of elements are saved using profile values) and having too much data in profile definitely increases load times of everything and sometimes even causes lags.

 

If you really want to do this, send the scripts to user when connecting and save them to mission namesapce, that's much better solution and your scripts will be only stored in memory and erased upon leaving the mission.

Share this post


Link to post
Share on other sites

I would not recommend using the profilenamespace for something like this, If you really would like to hide a script I would just allow -filepatching on the server and let it load the script files from outside of the mission file.

  • Like 2

Share this post


Link to post
Share on other sites
20 hours ago, pierremgi said:

I'm rather sure that, when you setVariable a code, this code runs and you just record the return value if any

This is not true. Code is a data type, setting something to be of said type does not cause it to run.

player setVariable[ "someCode", {hint "hello world"} ];
hint str( player getVariable "someCode" ); //hints {hint "hello world"}
call (player getVariable "someCode"); //hints "hello world"

 

As for the OP,  I agree with the others, saving large pieces of code to profileNamespace is a bad idea. I would suggest either what @genesis92x says or by using a server side mod.

  • Like 2

Share this post


Link to post
Share on other sites
Just now, Larrow said:

This is not true. Code is a data type, setting something to be of said type does not cause it to run.


player setVariable[ "someCode", {hint "hello world"} ];
hint str( player getVariable "someCode" ); //hints {hint "hello world"}
call (player getVariable "someCode"); //hints "hello world"

 

Yep.

The fact is I tested something like:

this setVariable [ "someCode", hint "hello world" ];

My bad.

 

Share this post


Link to post
Share on other sites
On 19.11.2018 at 1:56 AM, pierremgi said:

call compileFinal (profileNameSpace getVariable ["testFunction",""] )

Your compileFinal there is useless and doesn't make any sense. Just use compile.

I remember profileNamespace randomly having problems with code entries if some other mod would spam it with a huge amount of data.

Never tried saving code on it's own.

 

On 19.11.2018 at 1:56 AM, pierremgi said:

compileFinal is safer.

Wat? Care to explain?

 

 

On 18.11.2018 at 7:33 PM, Lordeath19 said:

this server has some scripts that i don't want to expose to the player (due to them stealing it)

Okey.

On 18.11.2018 at 7:33 PM, Lordeath19 said:

you can use the profileNamespace to save data to the profile of the player

So, you don't want to expose the script to the player, but sending it to the player and storing it in HIS profileNamespace sounds like a good idea to you?

 

 

I think the best solution would be to just have your script in a server-side pbo and using CfgFunctions of course.
If you need to execute it on the client, you have to send it over via publicVariable or publicVariableClient.

BUT! At this point you are exposing the script to the player. You can't execute a script on a players machine that he cannot see, if he doesn't know what's inside of the script, how is he supposed to be executing it?

 

 

On 18.11.2018 at 8:01 PM, gc8 said:

not sure but have you tried saveProfileNamespace ?

have you tried reading OP's post?

On 18.11.2018 at 7:33 PM, Lordeath19 said:

2. enter these 2 lines:

profileNamespace setVariable ["testFunction",{hint "test";}];

saveProfileNamespace;

 

  • Like 1

Share this post


Link to post
Share on other sites
50 minutes ago, Dedmen said:

Your compileFinal there is useless and doesn't make any sense. Just use compile.

I remember profileNamespace randomly having problems with code entries if some other mod would spam it with a huge amount of data.

Never tried saving code on it's own.

 

Wat? Care to explain?

 

 

CompileFinal is described in BIKI. This command is supposed to block cheat overriding, which is the first aim of this post, if I'm right.

You protect the code to be over written by remote script.

So, useless or not, I'll bet on this usage here, with no impact on performance (or perhaps positive one!).

In fact, I always use it in all my server scripts. I'll change my mind the day some skilled people will demonstrate it's harmful for whatever reason.

 

See also these posts:

http://killzonekid.com/arma-scripting-tutorials-bis_fnc_compilefinal/

https://forums.bohemia.net/forums/topic/145078-compilefinal-is-nice-but-lets-improve-security-even-more/?page=4  (old one but interesting)

 

  • Like 1

Share this post


Link to post
Share on other sites
3 hours ago, pierremgi said:

You protect the code to be over written by remote script.

How is it going to be overwritten? If you call compileFinal someCode the code is compiled and called in the exact same instance, it is not stored anywhere in its compiled state so cannot be overwritten. So call compileFinal here makes no sense. This is the point @Dedmen is getting at.

  • Like 1

Share this post


Link to post
Share on other sites
13 minutes ago, Larrow said:

How is it going to be overwritten? If you call compileFinal someCode the code is compiled and called in the exact same instance, it is not stored anywhere in its compiled state so cannot be overwritten. So call compileFinal here makes no sense. This is the point @Dedmen is getting at.

 

Thanks for this explanation. I understand you are referring to my " call compileFinal (profileNameSpace getVariable ["testFunction",""] )"  above.

It was just (a bad) example. To be sure I understand, is there  still an interest for something like:

blabla = compileFinal (profileNameSpace getVariable ["testFunction",""];

supposed to be run at mission start,

then, further during the mission:

call blabla (from anywhere)

?

Please, consider that i'm not arguing but I'd like to understand. Thanks for your added comment, more understandable than "makes no sense".

Share this post


Link to post
Share on other sites
2 minutes ago, pierremgi said:

blabla = compileFinal (profileNameSpace getVariable ["testFunction",""];

Ignoring the profileNamespace, which as discussed in this thread as generally a bad idea.

Sure that is totally fine as the compiled string is being stored in the variable blabla and the variable is set as final, cannot be overwritten.

For most general functions I would always recommend CfgFunctions which are always compiled final at mission load. Rather than compiling/preprocessing files your self, but this is still a valid method.

  • Like 2
  • Thanks 1

Share this post


Link to post
Share on other sites
TAG_fnc_something = compileFinal preprocessFileLineNumbers "fn_something.sqf";

Maybe makes sense for this case if you don't use CfgFunctions as @Larrow said but honestly, I personally wouldn't say it makes a huge difference. If a hacker gets access then they usually just run their own code and cause havoc. They wouldn't care about hiding it into a already created function. Rarely see hackers on servers these days, especially with BE filters.

Share this post


Link to post
Share on other sites
On 11/20/2018 at 9:18 PM, Dedmen said:

So, you don't want to expose the script to the player, but sending it to the player and storing it in HIS profileNamespace sounds like a good idea to you?

profile namespace is seperate to each client (and the server as well) so when i store a variable in profilenamespace when the script is executed on the server it will save the variable on the server.

The idea is i store the functions on the server, and then use either remoteExec or some other form of function execution to run the function without exposing said function to the player
 

 

On 11/20/2018 at 9:18 PM, Dedmen said:

I think the best solution would be to just have your script in a server-side pbo and using CfgFunctions of course.
If you need to execute it on the client, you have to send it over via publicVariable or publicVariableClient.

BUT! At this point you are exposing the script to the player. You can't execute a script on a players machine that he cannot see, if he doesn't know what's inside of the script, how is he supposed to be executing it?

I think i am gonna go with this solution and use remoteExec instead of publicVariables.
 

 

Thanks everyone for all the help!

Share this post


Link to post
Share on other sites

Hey,

 

you could setup your CfgFunctions etc. on a server side mod (like in Altis Life with life_server stuff) and add all your client variables there and broadcast them over to the client which is connecting by using publicVariableClient.

I know it works since it got used on a server.

 

Since I don't have the codes right now I can only give you my idea right now.

When client has the initialization part done, he calls a server-side script which broadcasts all the function variables over:

private _unit = param [0, objNull, [objNull]];

{
	(owner _unit) publicVariableClient _x;
} forEach (allVariables missionNameSpace);

 

Hope I was able to help,

 

Regards,

Dusty

  • Confused 1

Share this post


Link to post
Share on other sites
4 hours ago, TheDusty01 said:

} forEach (allVariables missionNameSpace);

NO do NOT EVER do this, broadcasting all missionNamespace variables is a terrible idea. It will broadcast all global variables potentially breaking many systems. As well as ALL functions, BI's and users this is potentially a couple of thousand, they may be safe due to compileFinal but it will still overload the network traffic.

  • Thanks 1

Share this post


Link to post
Share on other sites
On 24.11.2018 at 5:00 AM, Larrow said:

NO do NOT EVER do this, broadcasting all missionNamespace variables is a terrible idea. It will broadcast all global variables potentially breaking many systems. As well as ALL functions, BI's and users this is potentially a couple of thousand, they may be safe due to compileFinal but it will still overload the network traffic.

You you're right with that. Obviously you should filter out variables which you don't need but in practice it works but I can't recommend it either, just a way to do it.

Share this post


Link to post
Share on other sites

Please sign in to comment

You will be able to leave a comment after signing in



Sign In Now

×