Jump to content
Sign in to follow this  
Tom507

Server sided connection handling

Recommended Posts

I'm making a guerilla style coop mission the code works well in single player but as soon as i go on a Server not verry much happens

I plan on having a persistent server witch initializes with the start so i only have JIPs

I have been trying to just execute code on new Players either by

1. writing them in a list and updating it every 0.1 sec. or (and looping thrue them later)

2. by (Player) execVM ...

i tried playing with waitUntil it doesnt seem to have any effect (apart from delying the script)

i failed with both attempts there must be something im missing maybe locality?

 

here is my code (you can also Just answer my question im shure its a simple one for some of you) :

1. :

while {true} do {
   
    for "_thisPlayerNum" from 0 to (count allPlayers) do {
        _thisPlayer = (allPlayers select _thisPlayerNum);
        if (!isNil "_thisPlayer") then {
            if (alive _thisPlayer) then {

                if (!(_thisPlayer in myLivePlayers)) then {
                    // executed on Player spawn
                        //waitUntil {alive _thisPlayer};
                        myLivePlayers = (myLivePlayers + [_thisPlayer]);
                        _thisPlayer setCaptive true;
                } else {
                    if (!(alive _thisPlayer)) then {
                    // executed on Player death
                        myLivePlayers = (myLivePlayers - [_thisPlayer]);
                        if (_thisPlayer in HostilePlayers) then {
                            TimeLastShot = TimeLastShot - [(TimeLastShot select (HostilePlayers find _thisPlayer))];
                            HostilePlayers = HostilePlayers - [_thisPlayer];
                        };
                    };
                };
                
                if ((_checkNewPlayer != (count allPlayers)) and (_thisPlayer in myLivePlayers)) then {
                    _thisPlayer execVM "GW_3_0_PlayerConnected.sqf";
                };
                _checkNewPlayer = (count allPlayers);
                
            };
        };
    };
    sleep 0.1;
};

2. :

    while {true} do {
        if ((count allPlayers) > 0) then {
            if (_checkNewPlayer < (count allPlayers)) then {
            waitUntil{isNull (allPlayers select ((count allPlayers)-1))}
            (allPlayers select ((count allPlayers)-1)) execVM "GW_3_1_Main.sqf";
            }
            _checkNewPlayer = (count allPlayers);
        };
        sleep 0.1;
    };

I would verry much appreciate your help this holds me back for a week now

THX in advance

Share this post


Link to post
Share on other sites

I saw that but how do i get the Players in to the executed script the ids that that command gives you are as i read in this forum useless

if i were searching for the profile name there is the simple: name (object)

I am searching for a way to reliably get the (object) that is the player into an execVm without delaying the connect handler.

Share this post


Link to post
Share on other sites

btw i know my code is a mess its by far not final i was just trying things

Share this post


Link to post
Share on other sites

The last argument of PlayerConnected is owner ID, which is the same value returned from clientOwner. Depending on what scripts you have being execVM in that loop, may not work like that. You would need to remoteExec the script on that players machine using the owner ID that PlayerConnected returned.

 

The other problem is that loop you have above doesn't handle the JIP queue. It's better to use remoteExec in this case and specify which commands should be added to JIP queue and which ones should not.

  • Like 1

Share this post


Link to post
Share on other sites

OMG thakns I think thats the exact thing im looking for

but it still doesnt work for me shouldn't i be able to access the owner with: _this select 5

like so :

if (isServer) then {
    addMissionEventHandler["PlayerConnected",{_this execVM "GW_3_1_Main.sqf"}];
};

 

this is in GW_3_1_Main.sqf :

thisPlayer = _this select 5;
publicVariable "thisPlayer";

if I watch thisPlayer it returns nothing

 

I'm now even looping the public variable even though it should be JIP proof (so i read)

while {true} do {
    sleep 0.5;
    publicVariable "thisPlayer";
};

still doesn't work

Share this post


Link to post
Share on other sites

I want to get rid of this problem because im annoyed that i can't move on and do the way more interesting stuff that i have planned for my mission please HELP !!!!!!!!

THANKS IN ADVANCE

Share this post


Link to post
Share on other sites

Ok so using the PlayerConnected eventhandler, note that the owner ID is a number. As it's param #5 it is retrieved using _this select 4, 0-based index and all that.

 

//Add eventhandler 
addMissionEventhandler [
	"PlayerConnected", 
	{
		(_this select 4) execVM "yourNameHere.sqf";
	}
];

//yourNameHere.sqf
private _ownerId = _this;
private _player = objNull;
{
	if(owner _x == _ownerId) exitWith { _player = _x; };
} forEach allPlayers;

//Do your stuff

Another method would be to just use remoteExec in initPlayerLocal.sqf:
 

[player, "yourNameHere.sqf"] remoteExec ["execVM", 2];

 

  • Like 1

Share this post


Link to post
Share on other sites

I could punch myself for making such a basic mistake :dummy:.

Sorry that i got so emotional but this basic stuff stopped my advance for a lot of ours.

Thank you so much now i can finally work on the fun stuff.

 

What does this do tho?

8 hours ago, mrcurry said:

{ if(owner _x == _ownerId) exitWith { _player = _x; }; } forEach allPlayers;

 

Why would the server ever have to deal with clients that have the same ID?

isn't the ID given by the server and should therefor be unique?

Edited by Tom507
another question

Share this post


Link to post
Share on other sites

don't get confused by the previous posts just read this one.

I think i spoke too soon because i can't get yours to work

Im confused since it doesn't work either when i do it any other way for example:

handler:

if (isServer) then {
    addMissionEventHandler["PlayerConnected",{_this execVM "GW_3_1_Main.sqf"}];
};

script:

playerId = (_this select 4);

for "_x" from 0 to (count allPlayers) -1 step 1 do {
    
    if (owner _x == playerId) then {
        thisplayer = (allPlayers select _x);
    };
};
sleep 0.5;
publicVariable "thisplayer";
publicVariable "playerId";

it does everything (theoretically) that yours does except stopping the loop

playerId returs the correct 3

but thisPlayer returns nothing

 

 

for some reason i believe the evaluation doesn't work neither in mine nor in yours since if i do this:

private _ownerId = _this;
private _player = objNull;

{
	if(owner _x == _ownerId) exitWith { _player = _x; };
} forEach allPlayers;
playerId = _ownerId ;
thisplayer = _player ;

thisPlayer returns your initialization "<NULL-object>" so the condition never returned true or your exitWith didn't set the variable correctly (yes i changed (_this select 4) every time in the other script)

 

 

this doesn't work at all in the init.sqf:

if (!isServer) then {
    [player, "GW_3_1_Main.sqf"] remoteExec ["execVM", 2];
};

Main:

thisPlayer = _this

publicVariable "thisplayer";
publicVariable "playerId";

i have no idea what could be wrong with that

 

 

stil thanks for the response!

Share this post


Link to post
Share on other sites

The isServer check is redundant when adding the PlayerConnected eventhandler. The EH only fires server-side anyhow.

 

From the biki on PlayerConnected:

Quote

If dedicated server was started without '-autoInit' option and this EH was created on server, on first GUI client this EH also fires against server, but after first client.

 

The reason why you are getting odd results is because of the server overwriting your global var. If you use _player from what I wrote instead of assigning it to a global variable you will have the correct result for each connecting player. Preferably you should test if it's a proper player before continuing. This also helps avoid executing code unnecessarily:

addMissionEventHandler [
	"PlayerConnected",
	{
   		params ["_id", "_uid", "_name", "_jip", "_owner"];
  		if !(_owner isEqualTo 2 || _uid find "HC" == 0) then {
  			private _player = objNull;
  			{
  				if(owner _x isEqualTo _owner) exitWith { _player = _x; };
  			} forEach allPlayers;
  
  			//Do your stuff with _player here but remember that assigning it to a global var will cause it to be overwritten by the next player.
  		};
	}
];

Share this post


Link to post
Share on other sites

thanks for your answer!

i have to admit i was to impatient, to wait for it tho, and started a new thread I'm sorry

and by the way the Reason why the stuff didn't work was not because of global vars(i was alone on my Server anyway), but because of the Player not beeing correctly initialized (thats what you probably ment)

https://community.bistudio.com/wiki/player

KK and Larrow pointed me at the initPlayerServer.sqf wich I got to work in an instant: (code in initPlayerServer.sqf)

params[ "_player", "_didJIP" ];
thisPlayer = _player;
publicvariable "thisPlayer";
// works as smooth as a babys skin and is less expansive (calc time) than what we were attempting

still thanks for your Efforts

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
Sign in to follow this  

×