Jump to content
Generalmonimo

Troubles with publicVariable..

Recommended Posts

Public variables are giving me headaches. I tried for hours to make them work in my scripts. Now i wrote a simple test mission to demonstrate what i'm doing and hope someone can point me to what i'm missing here. Hosting this with editor in MP mode.

 

initServer.sqf:

 

systemChat "Init Server";

Counter= 0;
publicVariable "Counter";

while {true} do {
	sleep 10;
	systemChat "Update";
	Counter= Counter + 1;
	publicVariable "Counter";
	
};

initPlayerLocal.sqf:

systemChat "Init Player";
"Counter" addPublicVariableEventHandler {
	hint (str Counter);
};

 

I expected to see a hint with a number increasing its value every 10 seconds. This didn't happen.

 

Output from systemChat as expected:

InitServer

InitPlayer

Update

Update

Update

...

 

Share this post


Link to post
Share on other sites

@Generalmonimo, your computer is the server too when you host the mission in MP mode, so your code won't work in this case. Use this code instead:

if (isServer) then {
    call pubVarEventHandler;
} else {
    publicVariable "Counter";
};

 

Share this post


Link to post
Share on other sites

To clarify: I want to send data from the server to all clients (including me). This data for now is a counter but in my actual script it will be an updated scoreboard. All calculations (in this case incrementing the counter) will be done on the server (thus initServer.sqf) in the 'main'-loop.

To send the data to the client i use publicVariable and i was expecting the event handler for the client (local Player, which while i'm hosting is also me) to fire and show the hint.

 

The isServer condition in my case should be irrelevant because for initServer.sqf it is always true and for initPlayerLocal.sqf always false.

Share this post


Link to post
Share on other sites

@Generalmonimo, when you host the mission in MP mode "server" vars and "client" vars are in the same namespace, so code attached with addPublicVariableEventHandler never fire on your computer, this is why you need to manually call event handler.

 

25 minutes ago, Generalmonimo said:

The isServer condition in my case should be irrelevant because for initServer.sqf it is always true and for initPlayerLocal.sqf always false.

Yea, my mistake. Try this code:

publicVariable "Counter";

if (hasInterface) then {
    call pubVarEventHandler;
};

 

  • Like 1

Share this post


Link to post
Share on other sites

I find using the remoteExec framework and discarding the publicvariable/addpublicvariableeventhandler/publicvariableserver/publicvariableclient system entirely, to be the simplest.

 

for example

 

private _counter = 0;
while {true} do {
	sleep 10;
	systemChat "Update";
	_counter = _counter + 1;
	// remoteExec instead of publicVariable
	[
		Counter,
		{
			if (hasInterface) then {
				hint str _this;
			};
		}
	] remoteExec ['call',0];
};

 

Share this post


Link to post
Share on other sites

Given alternatives reflect different needs and maybe different philosophies.

 

publicVariable:

This is how you ”set a variable value on the other machines”. You also have the possibility to take some action when the value is set, using publicVariableEventHandler.

 

remoteExec:

This is how you ”execute a function on other machines”. Personally I don’t really like this, because if you use it frequently the code tend to be hard to read. The code can make the impression that execution is ”jumping” between clients in an uncontrolled manner.

 

Event based remote executions:

The publicVariable event handling philosophy I find much better, but the syntax is somewhat obscured. So what I do is that I use remoteExec, but I only call ”On” functions all collected in one reciever file. And these ”On” functions always just reflect source machine (server or client) events, and then routes the event to the correct execution path within the target machine. It is never a direct function call.

 

Here’s an example. I never call ”createSomeVehicle”, or ”showMyMessage” on another machine. What I do is telling what is happening on the source machine, like ”onVehicleNeeded” or ”onLocationTaken”. This way I never mix the control flow responsibilities between different machines and methods. And if you want anything more to happen than just a message being shown when a location is taken, simply add one line of code in the onLocationTaken ”event handler.”

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

×