Jump to content
thy_

What initial "WaitUntil player" is perfect for multiplayer in Dedicated Server?

Recommended Posts

Gotcha: player is not for Dedicated Server so I am looking for a way to start a few functions files where the target is the multiplayer/coop through hosted and dedicated servers. 

 

Some ideas, but not what I'm looking for (already read!):

 

And this older one (already read!):

 

That said, just to start, this is a init.sqf template I've seen and used:

 

// INIT.SQF HEADER (TARGET IS MISSONS IN HOSTED AND DEDICATED SERVERS / NEVER SINGLEPLAYER):

if (!isDedicated) then
{
	// checking player in hosted servers / and avoid JIP issues (?):
	waitUntil
	{ 																
		!isNull player;
	};
  
	// mission briefing available for all clients:
	[] call compile preProcessFileLineNumbers "briefing.sqf";
};

if (hasInterface) then		
{
	[] spawn
	{
		waitUntil	
		{
			sleep 0.1;	
			!isNull player;	// <--------------------------------- It doesnt look right! It should watch for _x of allPlayers, right?
		};
	};
};

// AND CUSTOM CODE HERE...

 

About the code above, shouldn't that be like this one below?

 

// NOT TESTED!

if (!isDedicated) then
{
	// checking player in hosted servers / and avoid JIP issues (?):
	waitUntil
	{ 																
		!isNull player;
	};
  
	// mission briefing available for all clients:
	[] call compile preProcessFileLineNumbers "briefing.sqf";
};

if (hasInterface) then		
{
	[] spawn
	{
		waitUntil	
		{
			sleep 0.5;	
			count allPlayers < 0;
			systemChat "You're a human player!";
		};
	};
};

// IF IT HAS PASSED BY ONE OF THOSE LOOPINGS ABOVE, CUSTOM CODE TO BE READED HERE...

 

A model will impact positively in, at least, 18 multiplayer missions I've built in the last 3 years. 

 

Share this post


Link to post
Share on other sites

Headless clients do not have an interface, which is what that is checking for. That extra code is completely unnecessary. 

  • Like 2

Share this post


Link to post
Share on other sites

Untested, but should do what you're asking if I understand your question correctly.

 

In initPlayerLocal.sqf

player setVariable ["TAG_playerLoaded", false, true];
addMissionEventHandler ["PreloadFinished", 
{
  player setVariable ["TAG_playerLoaded", true, true];
}];
waitUntil {player getVariable "TAG_playerLoaded"};

// Run code local to each player here after the player has loaded in fully

 

In initServer.sqf

waitUntil {({_x getVariable ["TAG_playerLoaded",false]} count allPlayers) == count allPlayers};

// Run code local to server here after every player has loaded in fully


 

  • Like 2
  • Thanks 1

Share this post


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

Untested, but should do what you're asking if I understand your question correctly.

 

In initPlayerLocal.sqf


player setVariable ["TAG_playerLoaded", false, true];
onPreloadFinished {player setVariable ["TAG_playerLoaded", true, true]; onPreloadFinished ""};
waitUntil {player getVariable "TAG_playerLoaded"};

// Run code local to each player here after the player has loaded in fully

 

In initServer.sqf


waitUntil {({_x getVariable ["TAG_playerLoaded",false]} count allPlayers) == count allPlayers};

// Run code local to server here after every player has loaded in fully


 

 

An addendum to the above, I would recommend primarily using the stackable version instead to avoid cross-compatability issues:

 

addMissionEventHandler ["PreloadFinished", {

 // Stuff

}];

 

 

  • Like 3

Share this post


Link to post
Share on other sites

I modified my example above with the stackable eventhandler mentioned by @mrcurry

 

Spoiler

 

10 hours ago, alpha993 said:

In initPlayerLocal.sqf



player setVariable ["TAG_playerLoaded", false, true];
addMissionEventHandler ["PreloadFinished", 
{
  player setVariable ["TAG_playerLoaded", true, true];
}];
waitUntil {player getVariable "TAG_playerLoaded"};

// Run code local to each player here after the player has loaded in fully

 

In initServer.sqf



waitUntil {({_x getVariable ["TAG_playerLoaded",false]} count allPlayers) == count allPlayers};

// Run code local to server here after every player has loaded in fully


 

 

 

 

 

53 minutes ago, thy_ said:

And what about the init.sqf? Should be empty?

 

It depends on what you want to do with your code.

  1. initPlayerLocal.sqf runs only on clients and player host whenever they connect.
  2. initServer.sqf runs only on a dedicated server or player host.
  3. init.sqf runs on every client, dedicated server, and player host.

So, if the code you want to run after everyone's in should execute on all clients and the server, use init.sqf. If you only want the code to run on the server, use initServer.sqf.

Share this post


Link to post
Share on other sites
7 minutes ago, alpha993 said:

I modified my example above with the stackable eventhandler mentioned by @mrcurry

 

Good one!

 

8 minutes ago, alpha993 said:
  1. initPlayerLocal.sqf runs only on clients and player host whenever they connect.
  2. initServer.sqf runs only on a dedicated server or player host.
  3. init.sqf runs on every client, dedicated server, and player host.

So, if the code you want to run after everyone's in should execute on all clients and the server, use init.sqf. If you only want the code to run on the server, use initServer.sqf.

 

I believe that this is already widespread and there are no questions as to each file's goal. The question - and my fault for not describing it better - is whether some lines of code would be needed to validate the players in the init.sqf itself.

Based on what has already been said, so the init.sqf template for multiplayer on a dedicated and hosted server is blank/empty.

 

Thank you all! I will test these amends and later in the week the results will be here. 

Share this post


Link to post
Share on other sites
On 2/22/2022 at 10:46 AM, thy_ said:

Based on what has already been said, so the init.sqf template for multiplayer on a dedicated and hosted server is blank/empty.

 

As long as you want whatever is in init.sqf to run everywhere (server/headless/all players), yes. But that isn't what your first post appears to suggest.

 

Init.sqf runs every time someone or something connects to the server, including the server itself. One school of thought is to avoid executing anything from init.sqf. Previous titles did not have the benefit of the event scripts we have now (initPlayerLocal/initPlayerServer/initServer.sqf) and so it was common/standard practice to use init.sqf/sqs to call scripts that were similarly localized - sort of an entry hub/sorter. Now, as init.sqf initializes last, it is almost counter-productive to use it for anything that can be dealt with in the aforementioned event scripts.

  • Like 2

Share this post


Link to post
Share on other sites
53 minutes ago, Harzach said:

it is almost counter-productive to use it for anything that can be dealt with in the aforementioned event scripts.

 

Not to mention that splitting your codebase from init.sqf to initServer et. al. helps keep your code clean and readable = easily maintainable! ^^

  • Like 3

Share this post


Link to post
Share on other sites
On 2/22/2022 at 12:46 PM, thy_ said:

Thank you all! I will test these amends and later in the week the results will be here. 

 

Working fine, but the line below just work properly when we set it in init.sqf 😞
There's a way to use briefing and avoid the init.sqf without set the briefing as a function (via description.ext/CfgFunctions)?

[] call compile preProcessFileLineNumbers "briefing.sqf";

 

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

×