Jump to content
Midnighters

Mission save script not working over server restart

Recommended Posts

Hello all. I had made a script for saving player information on the server's profile.

if (isServer) then {
    addMissionEventHandler["HandleDisconnect",{
		//params ["_unit", "_id", "_uid", "_name"];
		_unit = _this select 0;
		_uid = _this select 2;
		
		diag_log format["%1 %2 %3",_name, _unit, _uid];
        profileNamespace setVariable[_uid,[(getPosATL _unit),(getDammage _unit),(getFatigue _unit),(getStamina _unit),(_unit getUnitTrait "Medic"),(_unit getUnitTrait "Engineer"),(getAllOwnedMines _unit)]];
        saveProfileNamespace;
	
	diag_log (profileNamespace getVariable _uid);
    }];
    ["CH","onPlayerConnected",{
	
		//params ["_id", "_uid", "_name", "_jip", "_owner"];
		_uid = _this select 1;
		
		diag_log format["%1 has connected",_uid];
        {
            if( (getPlayerUID _x) == _uid ) exitWith {
				diag_log 'OK';
                private _variable = (profileNamespace getVariable _uid); 
                _x setPos (_variable select 0);
                _x setDamage (_variable select 1); 
                _x setFatigue (_variable select 2); 
                _x setStamina (_variable select 3); 
                if(_variable select 4) then {_x setUnitTrait["Medic",true];}; 
                if(_variable select 5) then {_x setUnitTrait["Engineer",true];};
          	};
        } forEach allPlayers;
	
    }] call BIS_fnc_addStackedEventHandler;
};

currently the only thing that works is the save whilst the server has not restarted.

once the server restarts, then it's irretrievable. Even though the variable is still stored in the server profile vars.

here is the rpt:

Dropbox - Rpt File

 

Any help on this?

Share this post


Link to post
Share on other sites

Look at the bottom of the RPT file at your diagnostic output and the error. In your on-connection handler _uid never get's properly. Try outputting "_this" somehow and see what it is.

  • Like 1

Share this post


Link to post
Share on other sites
Quote

"<null> has connected"
Error in expression <H","onPlayerConnected",{


_uid = _this select 1;

diag_log format["%1 has conne>
  Error position: <select 1;

diag_log format["%1 has conne>
  Error Zero divisor
 Mission id: 16aca6ad46ddaef2b8a51df82ad2954a5ba193ba
"<null> has connected"

Error in expression <H","onPlayerConnected",{

_uid = _this select 1;
diag_log format["%1 has conne>
  Error position: <select 1;
diag_log format["%1 has conne>
  Error Zero divisor

 

looks like you got some errors, specifically i can see that in the onPlayerConnected portion at the bottom the variables you are checking needs == true added onto the end to actually evaluate if its true or false. 

Share this post


Link to post
Share on other sites

I would try substituting in the mission EH "playerConnected".  imo it's more reliable than bis stacked eventhandlers (not sure why, but I've had similar problems with them in the past.  

 

Try this (untested):

 

if (isServer) then {
    addMissionEventHandler["HandleDisconnect",{
        params ["_unit", "_id", "_uid", "_name"];
        diag_log format["%1 %2 %3",_name, _unit, _uid];
        profileNamespace setVariable [
            _uid,
            [
                getPosATL _unit,
                getDammage _unit,
                getFatigue _unit,
                getStamina _unit,
                _unit getUnitTrait "Medic",
                _unit getUnitTrait "Engineer",
                getAllOwnedMines _unit
            ]
        ];
        saveProfileNamespace;
        diag_log (profileNamespace getVariable _uid);
    }];
    addMissionEventHandler ["PlayerConnected",{
        params ["_id", "_uid", "_name", "_jip", "_owner"];
        diag_log format["%1 has connected",_uid];
        {
            if( (getPlayerUID _x) == _uid ) exitWith {
                diag_log "OK matey";
                private _variable = (profileNamespace getVariable [_uid,"noEntry"]);
                if (_variable != "noEntry") then {
                    _variable params ["_pos","_dam","_fat","_stam","_medic","_eng","_mines"];
                    _x setPos _pos;
                    _x setDamage _dam;
                    _x setFatigue _fat;
                    _x setStamina _stam;
                    if (_medic isEqualType true and {_medic}) then {
                        _x setUnitTrait["Medic",true]
                    };
                    if (_eng isEqualType true and {_eng}) then {
                        _x setUnitTrait["Engineer",true]
                    };
                    // some code for your _mines here!!!!!!
                } else {
                    diag_log format ["no previous entry for %1 on this server.  UID: %2",_name,_uid];
                }
            }
        } forEach allPlayers;
    }]
};

 

edit:  Isn't stamina and fatigue the same thing?  Plus, you saved some mines but don't do anything with the data on login.

 

Also, is this on dedicated or hosted (I'm guessing dedi)?  You may need to adjust where these are in the init based on how you are running your server

 

Share this post


Link to post
Share on other sites
On 8/20/2017 at 2:52 PM, Muzzleflash said:

Look at the bottom of the RPT file at your diagnostic output and the error. In your on-connection handler _uid never get's properly. Try outputting "_this" somehow and see what it is.

the UID returns correctly, just not sure about that UID on the onConnect handler. Seems like it has returned the same so far though.

Share this post


Link to post
Share on other sites
11 hours ago, austin_medic said:

looks like you got some errors, specifically i can see that in the onPlayerConnected portion at the bottom the variables you are checking needs == true added onto the end to actually evaluate if its true or false. 

Yep, I will post a revised version of the script. Changed some things post this version of the script. 

something like this:

_x setUnitTrait["Medic",(_variable select 4)];}

 

Share this post


Link to post
Share on other sites
10 hours ago, das attorney said:

I would try substituting in the mission EH "playerConnected".  imo it's more reliable than bis stacked eventhandlers (not sure why, but I've had similar problems with them in the past.  

 

Try this (untested):

 


if (isServer) then {
    addMissionEventHandler["HandleDisconnect",{
        params ["_unit", "_id", "_uid", "_name"];
        diag_log format["%1 %2 %3",_name, _unit, _uid];
        profileNamespace setVariable [
            _uid,
            [
                getPosATL _unit,
                getDammage _unit,
                getFatigue _unit,
                getStamina _unit,
                _unit getUnitTrait "Medic",
                _unit getUnitTrait "Engineer",
                getAllOwnedMines _unit
            ]
        ];
        saveProfileNamespace;
        diag_log (profileNamespace getVariable _uid);
    }];
    addMissionEventHandler ["PlayerConnected",{
        params ["_id", "_uid", "_name", "_jip", "_owner"];
        diag_log format["%1 has connected",_uid];
        {
            if( (getPlayerUID _x) == _uid ) exitWith {
                diag_log "OK matey";
                private _variable = (profileNamespace getVariable [_uid,"noEntry"]);
                if (_variable != "noEntry") then {
                    _variable params ["_pos","_dam","_fat","_stam","_medic","_eng","_mines"];
                    _x setPos _pos;
                    _x setDamage _dam;
                    _x setFatigue _fat;
                    _x setStamina _stam;
                    if (_medic isEqualType true and {_medic}) then {
                        _x setUnitTrait["Medic",true]
                    };
                    if (_eng isEqualType true and {_eng}) then {
                        _x setUnitTrait["Engineer",true]
                    };
                    // some code for your _mines here!!!!!!
                } else {
                    diag_log format ["no previous entry for %1 on this server.  UID: %2",_name,_uid];
                }
            }
        } forEach allPlayers;
    }]
};

 

edit:  Isn't stamina and fatigue the same thing?  Plus, you saved some mines but don't do anything with the data on login.

 

Also, is this on dedicated or hosted (I'm guessing dedi)?  You may need to adjust where these are in the init based on how you are running your server

 

Yep, I don't know why that was there and I  totally thought I removed that. 

Thanks for this though, I see now this checks to see if the variable exists previous to any connection.

the mines need to be recreated upon login if anything else.

I'm unsure what this does though: 

(profileNamespace getVariable[_uid,"noEntry"]); 

What is no entry for?

And yes, definitely being tested on a dedicated server.

Edited by Midnighters
(forgot to mention that it was being tested on a dedi

Share this post


Link to post
Share on other sites

It's the alternate syntax for getVariable, so if no variable exists, then it uses "noEntry" as the default variable.

 

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

 

If you're on a dedi, I would consider putting it in initServer.sqf, running it from an initialization field on a logic (or other object), or maybe making a function with preinit defined and running it there:

 

https://community.bistudio.com/wiki/Functions_Library_(Arma_3)#Pre_and_Post_Init

 

Share this post


Link to post
Share on other sites
17 hours ago, das attorney said:

It's the alternate syntax for getVariable, so if no variable exists, then it uses "noEntry" as the default variable.

 

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

 

If you're on a dedi, I would consider putting it in initServer.sqf, running it from an initialization field on a logic (or other object), or maybe making a function with preinit defined and running it there:

 

https://community.bistudio.com/wiki/Functions_Library_(Arma_3)#Pre_and_Post_Init

 

Oh okay, thanks for clearing that up.

Yep, it's already running in the initServer.sqf

Share this post


Link to post
Share on other sites
21 hours ago, das attorney said:

Cool beans - so it it working ok now?

Not quite yet.

Going to rewrite this and see what I can do from there.

I'll post final working script if I get it working.

Share this post


Link to post
Share on other sites
11 hours ago, Midnighters said:

Not quite yet.

 

I just checked it on my PC (ran from initServer.sqf) and it's crap as well.  Sorry about that, I should test stuff like this before advising people...

 

allPlayers doesn't pick up a newly connected player object so it never finds the player.

 

I rewrote it (and tested it this time).  Working ok here.


 

// initPlayerLocal.sqf

waitUntil {not isNull player};
player remoteExecCall [
    "fnc_serverGetStats",
    2
]
// initServer.sqf

addMissionEventHandler["HandleDisconnect",{
    params ["_unit", "_id", "_uid", "_name"];
    diag_log format["DISCONNECT: %1 %2 %3",_name, _unit, _uid];
    profileNamespace setVariable [
        _uid,
        [
            getPosATL _unit,
            getDammage _unit,
            getFatigue _unit,
            getStamina _unit,
            _unit getUnitTrait "Medic",
            _unit getUnitTrait "Engineer",
            getAllOwnedMines _unit
        ]
    ];
    saveProfileNamespace;
    diag_log format["DISCONNECT: SAVED %1",profileNamespace getVariable _uid];
}];
fnc_serverGetStats = {
    _uid = getPlayerUID _this;
    diag_log format ["CONNECTED: %1.  UID: %2",_this,_uid];
    private _variable = (profileNamespace getVariable [_uid,[]]);
    if not (_variable isEqualTo []) then {
        diag_log format ["CONNECTED: prev saved variable: %1",_variable];
        _variable params ["_pos","_dam","_fat","_stam","_medic","_eng","_mines"];
        _this setPos _pos;
        _this setDamage _dam;
        _this setFatigue _fat;
        _this setStamina _stam;
        if (_medic isEqualType true and {_medic}) then {
            _this setUnitTrait["Medic",true]
        };
        if (_eng isEqualType true and {_eng}) then {
            _this setUnitTrait["Engineer",true]
        };
        // some code for your _mines here!!!!!!
    } else {
        diag_log format ["CONNECTED: no previous entry for %1 on this server.  UID: %2",name _this,_uid];
    }
}

 

Here is the output from server report file:

 

2017/08/24, 18:50:48 Starting mission:
2017/08/24, 18:50:48  Mission file: respawnPersistenceTest (__cur_mp)
2017/08/24, 18:50:48  Mission world: Malden
2017/08/24, 18:50:48  Mission directory: mpmissions\__cur_mp.Malden\
2017/08/24, 18:50:51 c:\w\stable\futura\lib\network\networkserver.cpp NetworkServer::OnClientStateChanged:NOT IMPLEMENTED - briefing!
2017/08/24, 18:50:51 Attempt to override final function - bis_fnc_storeparamsvalues_data
2017/08/24, 18:50:51 "CONNECTED: B Alpha 1-1:1 (Horde) REMOTE.  UID: 12345678912345678"
2017/08/24, 18:50:51 "CONNECTED: prev saved variable: [[7440.9,10126.6,0.00209808],0,0.360206,20.1919,false,false,[]]"
2017/08/24, 18:51:17 "DISCONNECT: Horde B Alpha 1-1:1 12345678912345678"
2017/08/24, 18:51:17 "DISCONNECT: SAVED [[7441.89,10126.7,0.00200653],0,0.485443,16.2394,false,false,[]]"
2017/08/24, 18:51:23 "CONNECTED: B Alpha 1-1:1 (Horde) REMOTE.  UID: 12345678912345678"
2017/08/24, 18:51:23 "CONNECTED: prev saved variable: [[7441.89,10126.7,0.00200653],0,0.485443,16.2394,false,false,[]]"

 

Here is a test mission:

 

https://drive.google.com/open?id=0B1kzYgzONxC0U0RCVkZmNDNEWlU

 

Enjoy!

  • Like 1

Share this post


Link to post
Share on other sites
5 hours ago, das attorney said:

 

I just checked it on my PC (ran from initServer.sqf) and it's crap as well.  Sorry about that, I should test stuff like this before advising people...

 

allPlayers doesn't pick up a newly connected player object so it never finds the player.

 

I rewrote it (and tested it this time).  Working ok here.


 


// initPlayerLocal.sqf

waitUntil {not isNull player};
player remoteExecCall [
    "fnc_serverGetStats",
    2
]

// initServer.sqf

addMissionEventHandler["HandleDisconnect",{
    params ["_unit", "_id", "_uid", "_name"];
    diag_log format["DISCONNECT: %1 %2 %3",_name, _unit, _uid];
    profileNamespace setVariable [
        _uid,
        [
            getPosATL _unit,
            getDammage _unit,
            getFatigue _unit,
            getStamina _unit,
            _unit getUnitTrait "Medic",
            _unit getUnitTrait "Engineer",
            getAllOwnedMines _unit
        ]
    ];
    saveProfileNamespace;
    diag_log format["DISCONNECT: SAVED %1",profileNamespace getVariable _uid];
}];
fnc_serverGetStats = {
    _uid = getPlayerUID _this;
    diag_log format ["CONNECTED: %1.  UID: %2",_this,_uid];
    private _variable = (profileNamespace getVariable [_uid,[]]);
    if not (_variable isEqualTo []) then {
        diag_log format ["CONNECTED: prev saved variable: %1",_variable];
        _variable params ["_pos","_dam","_fat","_stam","_medic","_eng","_mines"];
        _this setPos _pos;
        _this setDamage _dam;
        _this setFatigue _fat;
        _this setStamina _stam;
        if (_medic isEqualType true and {_medic}) then {
            _this setUnitTrait["Medic",true]
        };
        if (_eng isEqualType true and {_eng}) then {
            _this setUnitTrait["Engineer",true]
        };
        // some code for your _mines here!!!!!!
    } else {
        diag_log format ["CONNECTED: no previous entry for %1 on this server.  UID: %2",name _this,_uid];
    }
}

 

Here is the output from server report file:

 


2017/08/24, 18:50:48 Starting mission:
2017/08/24, 18:50:48  Mission file: respawnPersistenceTest (__cur_mp)
2017/08/24, 18:50:48  Mission world: Malden
2017/08/24, 18:50:48  Mission directory: mpmissions\__cur_mp.Malden\
2017/08/24, 18:50:51 c:\w\stable\futura\lib\network\networkserver.cpp NetworkServer::OnClientStateChanged:NOT IMPLEMENTED - briefing!
2017/08/24, 18:50:51 Attempt to override final function - bis_fnc_storeparamsvalues_data
2017/08/24, 18:50:51 "CONNECTED: B Alpha 1-1:1 (Horde) REMOTE.  UID: 12345678912345678"
2017/08/24, 18:50:51 "CONNECTED: prev saved variable: [[7440.9,10126.6,0.00209808],0,0.360206,20.1919,false,false,[]]"
2017/08/24, 18:51:17 "DISCONNECT: Horde B Alpha 1-1:1 12345678912345678"
2017/08/24, 18:51:17 "DISCONNECT: SAVED [[7441.89,10126.7,0.00200653],0,0.485443,16.2394,false,false,[]]"
2017/08/24, 18:51:23 "CONNECTED: B Alpha 1-1:1 (Horde) REMOTE.  UID: 12345678912345678"
2017/08/24, 18:51:23 "CONNECTED: prev saved variable: [[7441.89,10126.7,0.00200653],0,0.485443,16.2394,false,false,[]]"

 

Here is a test mission:

 

https://drive.google.com/open?id=0B1kzYgzONxC0U0RCVkZmNDNEWlU

 

Enjoy!

Aha! Nice job!

Honestly, this was just off the top of my head. Didn't realize it wasn't working until I looked into it further. Yes it was crap, and this is a good fix for the allPlayers anyways.

Thanks for helping me fix this. 

Share this post


Link to post
Share on other sites

No sorry, I wasn't saying what you were doing was crap; it was what I was doing.   I was blindly assuming that a player is initialised straightaway and not checking it.  And you know what they say about assumption...  xD

 

 

Share this post


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

No sorry, I wasn't saying what you were doing was crap; it was what I was doing.   I was blindly assuming that a player is initialised straightaway and not checking it.  And you know what they say about assumption...

 

 

LOL, all good!

  • Like 1

Share this post


Link to post
Share on other sites

RPT:

"CONNECTED: B Alpha 1-1:1 (Midnight) REMOTE.  UID: 76561198165073007"
"CONNECTED: prev saved variable: [[7482.21,10149.1,0.00159836],0,0.7611,7.53968,false,false,[]]"
 Mission id: 8172d33d07d2f46ad7f4eb1025b362ec3202219d
"CONNECTED: B Alpha 1-1:1 (Midnight) REMOTE.  UID: 76561198165073007"
"CONNECTED: prev saved variable: [[7504.46,10135.4,0.00168991],0,0.433312,17.8847,false,false,[]]"
 Mission id: 0c9cab9108e69f280ebf658b9eab3d58f1083642
"DISCONNECT: Midnight B Alpha 1-1:1 76561198165073007"
"DISCONNECT: SAVED [[7482.21,10149.1,0.00159836],0,0.7611,7.53968,false,false,[]]"

 

Share this post


Link to post
Share on other sites

Hmm ok the variables are saving correctly:

// logged in ran around a bit
2017/08/25,  1:11:39 "CONNECTED: B Alpha 1-1:1 (Horde) REMOTE.  UID: xxxx"
2017/08/25,  1:11:39 "CONNECTED: prev saved variable: [[7441.42,10121.4,0.00206757],0,0,31.56,false,false,[]]"
2017/08/25,  1:12:34 "DISCONNECT: Horde B Alpha 1-1:1 xxxx"
2017/08/25,  1:12:34 "DISCONNECT: SAVED [[7446.75,10310.9,0.00154877],0,0.86,4.4184,false,false,[]]"   <=====================this
//restarted server
2017/08/25,  1:14:55 "CONNECTED: B Alpha 1-1:1 (Horde) REMOTE.  UID: xxxx"
2017/08/25,  1:14:55 "CONNECTED: prev saved variable: [[7446.75,10310.9,0.00154877],0,0.86,4.4184,false,false,[]]"   <===================is found here

But I didn't see it moving me to the right place.  Let me check a bit further - we should be able to clear this up.

Share this post


Link to post
Share on other sites

Ok try this one:

 

I've checked it and restarted the server 4 times now and it updates player position and other goodies ok.  IDK why but for some reason the server wouldn't apply the data, so it's sent back to the players machine and everything is executed there now (which works)!  The data's still stored on the server but the setPos etc is done locally.

 

Here's a test mission (you'll need to export it but it's all zipped up for you to drop into your MPeditor folder:

 

https://drive.google.com/open?id=0B1kzYgzONxC0ZmVHVU9Zb2V6d3M

 

Here's the scripts now as well:

// initserver

addMissionEventHandler["HandleDisconnect",{
    params ["_unit", "_id", "_uid", "_name"];
    diag_log format["DISCONNECT: %1 %2 %3",_name, _unit, _uid];
    profileNamespace setVariable [
        _uid,
        [
            getPosATL _unit,
            getDammage _unit,
            getFatigue _unit,
            getStamina _unit,
            _unit getUnitTrait "Medic",
            _unit getUnitTrait "Engineer",
            getAllOwnedMines _unit
        ]
    ];
    saveProfileNamespace;
    diag_log format["DISCONNECT: SAVED %1",profileNamespace getVariable _uid];
}];
fnc_serverGetStats = {
    _uid = getPlayerUID _this;
    diag_log format ["CONNECTED: %1.  UID: %2",_this,_uid];
    private _variable = (profileNamespace getVariable [_uid,[]]);
    if not (_variable isEqualTo []) then {
        diag_log format ["CONNECTED: prev saved variable: %1",_variable];
        _variable remoteExecCall [
            "fnc_playerSetup",
            _this
        ];
    } else {
        diag_log format ["CONNECTED: no previous entry for %1 on this server.  UID: %2",name _this,_uid];
    }
};

 

// intiPlayerLocal.sqf

fnc_playerSetup = {
    diag_log format ["RECEIVED SERVER DATA: %1",_this];
    params ["_pos","_dam","_fat","_stam","_medic","_eng","_mines"];
    player setPos _pos;
    player setDamage _dam;
    player setFatigue _fat;
    player setStamina _stam;
    if (_medic isEqualType true and {_medic}) then {
        player setUnitTrait["Medic",true]
    };
    if (_eng isEqualType true and {_eng}) then {
        player setUnitTrait["Engineer",true]
    };
};
waitUntil {not isNull player};
player remoteExecCall [
    "fnc_serverGetStats",
    2
];

 

 

:)

  • Like 2

Share this post


Link to post
Share on other sites
2 hours ago, das attorney said:

Ok try this one:

 

I've checked it and restarted the server 4 times now and it updates player position and other goodies ok.  IDK why but for some reason the server wouldn't apply the data, so it's sent back to the players machine and everything is executed there now (which works)!  The data's still stored on the server but the setPos etc is done locally.

 

Here's a test mission (you'll need to export it but it's all zipped up for you to drop into your MPeditor folder:

 

https://drive.google.com/open?id=0B1kzYgzONxC0ZmVHVU9Zb2V6d3M

 

Here's the scripts now as well:


// initserver

addMissionEventHandler["HandleDisconnect",{
    params ["_unit", "_id", "_uid", "_name"];
    diag_log format["DISCONNECT: %1 %2 %3",_name, _unit, _uid];
    profileNamespace setVariable [
        _uid,
        [
            getPosATL _unit,
            getDammage _unit,
            getFatigue _unit,
            getStamina _unit,
            _unit getUnitTrait "Medic",
            _unit getUnitTrait "Engineer",
            getAllOwnedMines _unit
        ]
    ];
    saveProfileNamespace;
    diag_log format["DISCONNECT: SAVED %1",profileNamespace getVariable _uid];
}];
fnc_serverGetStats = {
    _uid = getPlayerUID _this;
    diag_log format ["CONNECTED: %1.  UID: %2",_this,_uid];
    private _variable = (profileNamespace getVariable [_uid,[]]);
    if not (_variable isEqualTo []) then {
        diag_log format ["CONNECTED: prev saved variable: %1",_variable];
        _variable remoteExecCall [
            "fnc_playerSetup",
            _this
        ];
    } else {
        diag_log format ["CONNECTED: no previous entry for %1 on this server.  UID: %2",name _this,_uid];
    }
};

 


// intiPlayerLocal.sqf

fnc_playerSetup = {
    diag_log format ["RECEIVED SERVER DATA: %1",_this];
    params ["_pos","_dam","_fat","_stam","_medic","_eng","_mines"];
    player setPos _pos;
    player setDamage _dam;
    player setFatigue _fat;
    player setStamina _stam;
    if (_medic isEqualType true and {_medic}) then {
        player setUnitTrait["Medic",true]
    };
    if (_eng isEqualType true and {_eng}) then {
        player setUnitTrait["Engineer",true]
    };
};
waitUntil {not isNull player};
player remoteExecCall [
    "fnc_serverGetStats",
    2
];

 

 

:)

sweet! I'll try this out :D

I will make sure to credit  you as well,

as soon as it is working though I'll edit it further and see what I can do.

 

  • Like 1

Share this post


Link to post
Share on other sites

This works great but I am having an issue with it not saving the inventory of the player, can anyone help me out with this?

99% new to this. 😄

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

×