MrDj200 0 Posted December 13, 2017 Hello, I need some help with this. I want to save a players position, loadout and maybe group when a player leaves the server. As we have some problems with people crashing or having IP resets or just needing to restart, this would be really neat. I looked at onPlayerDisonnected and the EH PlayerDisconnected, but I don't really know where to save the data, and how to get the position. Any help would be appreciated! -Dj Share this post Link to post Share on other sites
D. Patterson 14 Posted December 15, 2017 https://community.bistudio.com/wiki/profileNamespace If you don't want it to save between actual server restarts, use mission name space. Share this post Link to post Share on other sites
MrDj200 0 Posted December 15, 2017 Not between server restarts, don't want to use a DB, or is the "profileNamespace" able to save things between game restarts(client)? That'd be pretty neat to save some other things... Share this post Link to post Share on other sites
mrcurry 496 Posted December 15, 2017 Just leaving this here so I remember, I'll check back later tonight with solution. Share this post Link to post Share on other sites
MrDj200 0 Posted December 15, 2017 Hmm, I've been playing around with namespaces and just noticed JIP players do not get the missionNameSpace synced? How do I sync that? Share this post Link to post Share on other sites
mrcurry 496 Posted December 31, 2017 Here we go! Half a month late. Written up on December 15, forgotten about until today. Oops. This should save a disconnecting players loadout, position and facing on the server and will broadcast it back to the player when he/she reconnects as long as the mission isn't restarted. It does not handle group at this time since it was a maybe (just make sure you select the same group when reconnecting and you should be good). It's meant to go in the init.sqf, if you got the CfgRemoteExec whitelist enabled you need to add TAG_fnc_loadClientData to it. You could also load TAG_fnc_loadClientData through functions library and put the mission eventhandlers in initServer.sqf instead. Disclaimer: I have not done thorough testing. Just a syntax check and a basic logic check. So there might be some edge cases which might be bugged (It's also perfectly possible I missed something :P). Other than that it should do it's job. EDIT: The below code is broken, BIS_fnc_exportInventory has been updated and I missed to update position and direction after multiple disconnects. See this post for working code. TAG_fnc_loadClientData = { _this params ["_loadoutStr", "_positionASL", "_dir"]; call compile _loadoutStr; player setDir _dir; player setPosASL _positionASL; }; if(isServer) then { addMissionEventHandler [ "HandleDisconnect", { params ["_body", "_id", "_uid", "_name"]; if(!isNull _body) then { //Init storage var if(isNil "TAG_disconnectedLoadouts") then { TAG_disconnectedLoadouts = []; }; //Save loadout as script for easy broadcast private _loadoutStr = [player, "script", false] call BIS_fnc_exportInventory; { private _index = _loadoutStr find _x; if(_index > -1) then { private _strArray = toArray _loadoutStr; _strArray deleteRange [_index, count _x]; _loadoutStr = toString _strArray; }; } forEach ["// Remove existing items","// Add containers","// Add weapons", "// Add items", "// Set identity"]; //Find in storage private _uidIndex = TAG_disconnectedLoadouts find _uid; if(_uidIndex > -1) then { //Found -> update private _loadoutIndex = _uidIndex + 1; TAG_disconnectedLoadouts set [_loadoutIndex, _loadoutStr]; } else { //Not found -> Add new TAG_disconnectedLoadouts pushBack _uid; TAG_disconnectedLoadouts pushBack [_loadoutStr, getPosASL _body, getDir _body]; }; }; false } ]; addMissionEventHandler [ "PlayerConnected", { params ["_id", "_uid", "_name", "_jip", "_owner"]; if(_jip) then { private _clientData = missionNamespace getVariable ["TAG_disconnectedLoadouts", []]; private _uidIndex = _clientData find _uid; if(_uidIndex > -1) then { private _loadoutIndex = _uidIndex + 1; (_clientData select _loadoutIndex) remoteExec ["TAG_fnc_loadClientData", _owner]; }; }; } ]; }; 2 Share this post Link to post Share on other sites
redburn 20 Posted September 15, 2018 On 31/12/2017 at 6:39 AM, mrcurry said: Here we go! Half a month late. Written up on December 15, forgotten about until today. Oops. This should save a disconnecting players loadout, position and facing on the server and will broadcast it back to the player when he/she reconnects as long as the mission isn't restarted. It does not handle group at this time since it was a maybe (just make sure you select the same group when reconnecting and you should be good). It's meant to go in the init.sqf, if you got the CfgRemoteExec whitelist enabled you need to add TAG_fnc_loadClientData to it. You could also load TAG_fnc_loadClientData through functions library and put the mission eventhandlers in initServer.sqf instead. Disclaimer: I have not done thorough testing. Just a syntax check and a basic logic check. So there might be some edge cases which might be bugged (It's also perfectly possible I missed something :P). Other than that it should do it's job. TAG_fnc_loadClientData = { _this params ["_loadoutStr", "_positionASL", "_dir"]; call compile _loadoutStr; player setDir _dir; player setPosASL _positionASL; }; if(isServer) then { addMissionEventHandler [ "HandleDisconnect", { params ["_body", "_id", "_uid", "_name"]; if(!isNull _body) then { //Init storage var if(isNil "TAG_disconnectedLoadouts") then { TAG_disconnectedLoadouts = []; }; //Save loadout as script for easy broadcast private _loadoutStr = [player, "script", false] call BIS_fnc_exportInventory; { private _index = _loadoutStr find _x; if(_index > -1) then { private _strArray = toArray _loadoutStr; _strArray deleteRange [_index, count _x]; _loadoutStr = toString _strArray; }; } forEach ["// Remove existing items","// Add containers","// Add weapons", "// Add items", "// Set identity"]; //Find in storage private _uidIndex = TAG_disconnectedLoadouts find _uid; if(_uidIndex > -1) then { //Found -> update private _loadoutIndex = _uidIndex + 1; TAG_disconnectedLoadouts set [_loadoutIndex, _loadoutStr]; } else { //Not found -> Add new TAG_disconnectedLoadouts pushBack _uid; TAG_disconnectedLoadouts pushBack [_loadoutStr, getPosASL _body, getDir _body]; }; }; false } ]; addMissionEventHandler [ "PlayerConnected", { params ["_id", "_uid", "_name", "_jip", "_owner"]; if(_jip) then { private _clientData = missionNamespace getVariable ["TAG_disconnectedLoadouts", []]; private _uidIndex = _clientData find _uid; if(_uidIndex > -1) then { private _loadoutIndex = _uidIndex + 1; (_clientData select _loadoutIndex) remoteExec ["TAG_fnc_loadClientData", _owner]; }; }; } ]; }; Hello how are you, look I am still learning this scripting and I do not understand much how to put your script to work, could you if it is not too much trouble to explain briefly how to make it work with some quick steps of example? Thanks Share this post Link to post Share on other sites
mrcurry 496 Posted September 17, 2018 On 15/09/2018 at 8:54 AM, redburn said: Hello how are you, look I am still learning this scripting and I do not understand much how to put your script to work, could you if it is not too much trouble to explain briefly how to make it work with some quick steps of example? Thanks I'm pretty sure I mentioned this but it's no trouble. :) Rereading my own instructions I'd say slap the code provided above in your init.sqf inside your mission folder and you should be good. If you do not have your init.sqf then one will not be provided for you, you must create said init.sqf yourself inside your mission folder. If you are unaware how to create a text-file and change it's extension then only The Google can help you. If you are unaware how to google then may whatever diety you choose to worship have mercy on your soul. P.s. Jokes aside, it should be pretty straightforward but let me know if you run into any trouble. ^^ 2 Share this post Link to post Share on other sites
redburn 20 Posted September 18, 2018 On 17/9/2018 at 4:29 AM, mrcurry said: I'm pretty sure I mentioned this but it's no trouble. :) Rereading my own instructions I'd say slap the code provided above in your init.sqf inside your mission folder and you should be good. If you do not have your init.sqf then one will not be provided for you, you must create said init.sqf yourself inside your mission folder. If you are unaware how to create a text-file and change it's extension then only The Google can help you. If you are unaware how to google then may whatever diety you choose to worship have mercy on your soul. P.s. Jokes aside, it should be pretty straightforward but let me know if you run into any trouble. ^^ I only mentioned it because you said that if there were functions you had to do something else, but it´s ok :) Share this post Link to post Share on other sites
Sergeant_Emerald 0 Posted March 11, 2020 Hi, i tried to use your code, and the positioning thing is just working for the first time. The loadout save isn`t working at all. Do you know how to fix it? Share this post Link to post Share on other sites
mrcurry 496 Posted March 18, 2020 On 3/11/2020 at 9:54 PM, Sergeant_Emerald said: Hi, i tried to use your code, and the positioning thing is just working for the first time. The loadout save isn`t working at all. Do you know how to fix it? TAG_fnc_loadClientData = { _this params ["_loadout", "_positionASL", "_dir"]; player setUnitLoadout _loadout; player setDir _dir; player setPosASL _positionASL; }; if(isServer) then { addMissionEventHandler [ "HandleDisconnect", { params ["_body", "_id", "_uid", "_name"]; if(!isNull _body) then { //Init storage var if(isNil "TAG_disconnectedLoadouts") then { TAG_disconnectedLoadouts = []; }; //Get data private _loadout = getUnitLoadout _body; private _position = getPos _body; private _direction = getDir _body; //Find in storage private _uidIndex = TAG_disconnectedLoadouts find _uid; if(_uidIndex > -1) then { //Found -> update private _loadoutIndex = _uidIndex + 1; TAG_disconnectedLoadouts set [_loadoutIndex, [_loadout, _position, _direction]]; } else { //Not found -> Add new TAG_disconnectedLoadouts pushBack _uid; TAG_disconnectedLoadouts pushBack [_loadout, _position, _direction]; }; }; false } ]; addMissionEventHandler [ "PlayerConnected", { params ["_id", "_uid", "_name", "_jip", "_owner"]; if(_jip) then { private _clientData = missionNamespace getVariable ["TAG_disconnectedLoadouts", []]; private _uidIndex = _clientData find _uid; if(_uidIndex > -1) then { private _loadoutIndex = _uidIndex + 1; (_clientData select _loadoutIndex) remoteExec ["TAG_fnc_loadClientData", _owner]; }; }; } ]; }; 1 2 Share this post Link to post Share on other sites
Twiznak 57 Posted March 21, 2020 On 3/18/2020 at 9:06 AM, mrcurry said: TAG_fnc_loadClientData = { _this params ["_loadout", "_positionASL", "_dir"]; player setUnitLoadout _loadout; player setDir _dir; player setPosASL _positionASL; }; if(isServer) then { addMissionEventHandler [ "HandleDisconnect", { params ["_body", "_id", "_uid", "_name"]; if(!isNull _body) then { //Init storage var if(isNil "TAG_disconnectedLoadouts") then { TAG_disconnectedLoadouts = []; }; //Get data private _loadout = getUnitLoadout _body; private _position = getPos _body; private _direction = getDir _body; //Find in storage private _uidIndex = TAG_disconnectedLoadouts find _uid; if(_uidIndex > -1) then { //Found -> update private _loadoutIndex = _uidIndex + 1; TAG_disconnectedLoadouts set [_loadoutIndex, [_loadout, _position, _direction]]; } else { //Not found -> Add new TAG_disconnectedLoadouts pushBack _uid; TAG_disconnectedLoadouts pushBack [_loadout, _position, _direction]; }; }; false } ]; addMissionEventHandler [ "PlayerConnected", { params ["_id", "_uid", "_name", "_jip", "_owner"]; if(_jip) then { private _clientData = missionNamespace getVariable ["TAG_disconnectedLoadouts", []]; private _uidIndex = _clientData find _uid; if(_uidIndex > -1) then { private _loadoutIndex = _uidIndex + 1; (_clientData select _loadoutIndex) remoteExec ["TAG_fnc_loadClientData", _owner]; }; }; } ]; }; Thank You! Share this post Link to post Share on other sites
Noel Collins 0 Posted October 12, 2021 I tried to use the script above over the weekend: - blank mission with one playable character, an arsenal and a vehicle. - The code above copied into in it.sqf. - on joining I walked about 15 metres and to the right, turned 180 from starting orientation, and dripped numerous weapons and items from inventory. - I then disconnected and logged back on. I spawned back in original position, with original gear. Can anyone confirm this script still works, and if there are any other server side settings I need to make it work? Thanks! Share this post Link to post Share on other sites
pierremgi 4853 Posted October 12, 2021 First of all, this code is supposed to save loadout/position/direction on server during the mission on server. So, in multiplayer session, during the session (as far as the server is running the mission). If you want to save something in SP or even hosted MP at home, you must save (what you want) in your profileNameSpace. You can use the MEHs "handleDisconnect" & "playerConnected" as above but your data must be saved in profileNameSpace, not missionNameSpace. 1 Share this post Link to post Share on other sites
Noel Collins 0 Posted October 13, 2021 I was on a hosted server Share this post Link to post Share on other sites
Noel Collins 0 Posted October 24, 2021 So i tried again, changing missionNamespace to profileNamespace. no joy. as per above, hosted server. There is stuff mentioned above about whitelists, etc, which i do not understand. Is there anyone who uses this script that can help? thanks Share this post Link to post Share on other sites
pierremgi 4853 Posted October 24, 2021 3 hours ago, Noel Collins said: So i tried again, changing missionNamespace to profileNamespace. no joy. as per above, hosted server. There is stuff mentioned above about whitelists, etc, which i do not understand. Is there anyone who uses this script that can help? thanks did you change it also in handledisconnect EH ? Without your final code, difficult to help. Share this post Link to post Share on other sites
Noel Collins 0 Posted October 25, 2021 Original Attempt was with code in init.sqf exactly as above on hosted server, with nothing else done. This attempt the same code was as below, only change marked in red.: i dont see a namespace in the handle disconnect EH? thanks TAG_fnc_loadClientData = { _this params ["_loadout", "_positionASL", "_dir"]; player setUnitLoadout _loadout; player setDir _dir; player setPosASL _positionASL; }; if(isServer) then { addMissionEventHandler [ "HandleDisconnect", { params ["_body", "_id", "_uid", "_name"]; if(!isNull _body) then { //Init storage var if(isNil "TAG_disconnectedLoadouts") then { TAG_disconnectedLoadouts = []; }; //Get data private _loadout = getUnitLoadout _body; private _position = getPos _body; private _direction = getDir _body; //Find in storage private _uidIndex = TAG_disconnectedLoadouts find _uid; if(_uidIndex > -1) then { //Found -> update private _loadoutIndex = _uidIndex + 1; TAG_disconnectedLoadouts set [_loadoutIndex, [_loadout, _position, _direction]]; } else { //Not found -> Add new TAG_disconnectedLoadouts pushBack _uid; TAG_disconnectedLoadouts pushBack [_loadout, _position, _direction]; }; }; false } ]; addMissionEventHandler [ "PlayerConnected", { params ["_id", "_uid", "_name", "_jip", "_owner"]; if(_jip) then { private _clientData = profileNamespace getVariable ["TAG_disconnectedLoadouts", []]; private _uidIndex = _clientData find _uid; if(_uidIndex > -1) then { private _loadoutIndex = _uidIndex + 1; (_clientData select _loadoutIndex) remoteExec ["TAG_fnc_loadClientData", _owner]; }; }; } ]; }; Share this post Link to post Share on other sites
mrcurry 496 Posted October 25, 2021 TAG_disconnectedLoadouts also needs to be changed, the script in its current form relies on that global variables are defined in missionNamespace unless otherwise specified. But just changing out which namespace is used is gonna cause undefined behaviour when the same server runs multiple missions running the script. I've been planning to rewrite this using hashmaps anyway so I'll see about writing up a version for profileNamespace too 2 Share this post Link to post Share on other sites
pierremgi 4853 Posted October 26, 2021 Here is my contrib. I added some log lines. Seems to work, but should be tested deeper: TAG_fnc_loadClientData = { params ["_loadout", "_positionASL", "_dir"]; waitUntil {!isNull player}; player setUnitLoadout _loadout; player setDir _dir; player setPosASL _positionASL; }; if (isServer) then { // profileNameSpace setVariable ["TAG_disconnectedLoadouts",nil]; // only for resetting the variable on server. Important if not previously a hashmap ! addMissionEventHandler ["HandleDisconnect", { params ["_body", "_id", "_uid", "_name"]; if(!isNull _body) then { private _loadout = getUnitLoadout _body; private _position = getPos _body; private _direction = getDir _body; if(isNil {profileNameSpace getVariable "TAG_disconnectedLoadouts"}) then { profileNameSpace setVariable ["TAG_disconnectedLoadouts",createHashMapFromArray [[_uid,[_loadout,_position,_direction]]]]; } else { (profileNameSpace getVariable "TAG_disconnectedLoadouts") set [_uid,[_loadout,_position,_direction]]; }; diag_log [_uid,(profileNameSpace getVariable "TAG_disconnectedLoadouts")]; }; false } ]; addMissionEventHandler ["PlayerConnected", { params ["_id", "_uid", "_name", "_jip", "_owner"]; if(_jip) then { private _clientData = profileNamespace getVariable ["TAG_disconnectedLoadouts", []]; if (_clientData isEqualTo []) exitWith {}; private _value = _clientData get _uid; diag_log ["<<<<<after connect>>>>",_value,_this]; [_value,TAG_fnc_loadClientData] remoteExec ["spawn", _owner]; }; } ]; }; 1 Share this post Link to post Share on other sites
Noel Collins 0 Posted November 6, 2021 thanks @pierre MGI the above is my experience, I can script, but im a little out of my depth on this one. what am i missing here? thanks Share this post Link to post Share on other sites
mrcurry 496 Posted November 7, 2021 On 11/7/2021 at 12:06 AM, Noel Collins said: thanks @pierre MGI the above is my experience, I can script, but im a little out of my depth on this one. what am i missing here? thanks So I just test ran @pierremgi's code and had a hiccup. When I copied from his forum post to the init.sqf a "ghost character" showed up which would prevent the script from working. This is why running test-benches with startup parameter -showScriptErrors is important. See image: https://www.dropbox.com/s/c2zewaykupzgwba/mysterycharacter.png?dl=0 Pierre could be messing with us... ...but more likely its an artifact from the forum formatting of the code. So check if you are also getting this in your init-file. To be safe retype "profileNamespace getVariable". After I busted the ghost the code ran fine on my test-bench. If it still doesn't work here's a couple of things you could do: 1. Check your CfgRemoteExec so that "spawn" is allowed. 2. Check the .rpt if some other error is being printed when you disconnect / connect. 3. If running with mods, give it a try without them to see if they are interfering somehow. Share this post Link to post Share on other sites
pierremgi 4853 Posted November 7, 2021 Don't forget to enable the line resetting : profileNameSpace setVariable ["TAG_disconnectedLoadouts",nil]; (just a comment above). why? If your profileNameSpace already have a (bad) variable "TAG_disconnectedLoadouts", that could lead to wrong array. So, reset it, then modify the code as above (comment) in order to increment this variable along with new players. Share this post Link to post Share on other sites
Noel Collins 0 Posted November 9, 2021 On 11/7/2021 at 7:24 PM, mrcurry said: So I just test ran @pierremgi's code and had a hiccup. When I copied from his forum post to the init.sqf a "ghost character" showed up which would prevent the script from working. This is why running test-benches with startup parameter -showScriptErrors is important. Pierre could be messing with us... ...but more likely its an artifact from the forum formatting of the code. So check if you are also getting this in your init-file. To be safe retype "profileNamespace getVariable". After I busted the ghost the code ran fine on my test-bench. If it still doesn't work here's a couple of things you could do: 1. Check your CfgRemoteExec so that "spawn" is allowed. 2. Check the .rpt if some other error is being printed when you disconnect / connect. 3. If running with mods, give it a try without them to see if they are interfering somehow. Thanks, trying that now but no avail. the image you posted has not come through, so i cannot see what you are trying to show. as its sits now in my init.sqf: TAG_fnc_loadClientData = { params ["_loadout", "_positionASL", "_dir"]; waitUntil {!isNull player}; player setUnitLoadout _loadout; player setDir _dir; player setPosASL _positionASL; }; if (isServer) then { profileNamespace setVariable ["TAG_disconnectedLoadouts",nil]; // only for resetting the variable on server. Important if not previously a hashmap ! addMissionEventHandler ["HandleDisconnect", { params ["_body", "_id", "_uid", "_name"]; if(!isNull _body) then { private _loadout = getUnitLoadout _body; private _position = getPos _body; private _direction = getDir _body; if(isNil {profileNamespace getVariable "TAG_disconnectedLoadouts"}) then { profileNamespace setVariable ["TAG_disconnectedLoadouts",createHashMapFromArray [[_uid,[_loadout,_position,_direction]]]]; } else { (profileNamespace getVariable "TAG_disconnectedLoadouts") set [_uid,[_loadout,_position,_direction]]; }; diag_log [_uid,(profileNamespace getVariable "TAG_disconnectedLoadouts")]; }; false } ]; addMissionEventHandler ["PlayerConnected", { params ["_id", "_uid", "_name", "_jip", "_owner"]; if(_jip) then { private _clientData = profileNamespace getVariable ["TAG_disconnectedLoadouts", []]; if (_clientData isEqualTo []) exitWith {}; private _value = _clientData get _uid; diag_log ["<<<<<after connect>>>>",_value,_this]; [_value,TAG_fnc_loadClientData] remoteExec ["spawn", _owner]; }; } ]; }; Share this post Link to post Share on other sites
pierremgi 4853 Posted November 9, 2021 Read above. If you are writing: profileNamespace setVariable ["TAG_disconnectedLoadouts",nil]; you are resetting every time (at launch) your variable. So, the profileNameSpace is just useless! You must reset this at the first time (just because you can't say what this variable is made of after several trials), then delete or unable this line (by comment) in order to keep your data. I'd rather remove this line and warn for running that once, because any further test. Share this post Link to post Share on other sites