Jump to content
kibaBG

Saving player position with profilenamespace

Recommended Posts

Hi, I am trying to save players position on a mission map using prifilenamespace of each player. Its working fine in editor, but refuse to work on dedicated server ... I wonder where is the problem?
 

//PERSISTENT PLAYER POS AND RATING
//saves players pos and rating every five min 
//loads players pos and rating when they join server 
//initServer.sqf
[]execVM "stats.sqf"; 
//stats.sqf
while {true} do {
_kibaPos = getPosATL kiba3x;
profileNamespace setVariable ["KIB_kibaPos", _kibaPos];
_kibaRating = rating kiba3x;
profileNamespace setVariable ["KIB_kibaRating",_kibaRating];
_kavhanPos = getPosATL kavhan;
profileNamespace setVariable ["KIB_kavhanPos", _kavhanPos];
_kavhanRating = rating kavhan;
profileNamespace setVariable ["KIB_kavhanRating", _kavhanRating];
_konalPosition = getPosATL konal;
profileNamespace setVariable ["KIB_konalPos", _konalPosition];
_konalRating = rating konal;
profileNamespace setVariable ["KIB_konalRating", _konalRating];
sleep 300;
};
//initPlayerLocal.sqf 
//playable units are given variable names "kiba3x","kavhan","konal" in the editor 
if ((str player) == "kiba3x") then {
_kibaPos = profileNamespace getVariable "KIB_kibaPos"; 
player setPosATL _kibaPos;
_kibaRating = profileNamespace getVariable "KIB_kibaRating";
player addRating _kibaRating;
} else {
if ((str player) == "kavhan") then {
_kavhanPos = profileNamespace getVariable "KIB_kavhanPos"; 
player setPosATL _namalskPos;
_kavhanRating = profileNamespace getVariable "KIB_kavhanRating";
player addRating _kavhanRating;
} else {
_konalPos = profileNamespace getVariable "KIB_konalPos"; 
player setPosATL _konalPos;
_konalRating = profileNamespace getVariable "KIB_konalRating";
player addRating _konalRating;
};
};

 

Share this post


Link to post
Share on other sites
1 hour ago, kibaBG said:

Its working fine in editor, but refuse to work on dedicated server ... I wonder where is the problem?

The problem is that a server and clients have their own profile namespaces, therefore you should request data from the server:

// initServer.sqf

sendDataToClient = {
    private ["_data", "_varNames"];

    params ["_player"];

    _data = [];

    _varNames = switch (vehicleVarName _player) do { 
        case "kiba3x": { ["KIB_kibaPos", "KIB_kibaRating"] }; 
        case "kavhan": { ["KIB_kavhanPos", "KIB_kavhanRating"] }; 
        default { ["KIB_konalPos", "KIB_konalRating"] };
    };

    {
        _data pushBack (profileNamespace getVariable _x);
    } forEach _varNames;

    missionNamespace setVariable ["clientData", _data, if (_player == player) then { false } else { owner _player }];
};


// initPlayerLocal.sqf

if (isServer) then {
    [player] call sendDataToClient;
} else {
    [player] remoteExecCall ["sendDataToClient", 2];
};

waitUntil { !(isNil "clientData") };

clientData params ["_position", "_rating"];

clientData = nil;

player setPosATL _position;
player addRating _rating;

 

  • Like 1
  • Thanks 1

Share this post


Link to post
Share on other sites

//initServer.sqf

KIB_fnc_getPlayerData = {
	params[ "_player" ];
	
	if ( vehicleVarName _player == "" ) then {
		_player setVehicleVarName format[ "Player_%1", getPlayerUID _player ];
		_player call BIS_fnc_objectVar;
	};
		
	[
		profileNamespace getVariable[ format[ "KIB_%1Pos", vehicleVarName _player ], getPosATL _player ], 
		profileNamespace getVariable[ format[ "KIB_%1Rating", vehicleVarName _player ], 0 ]
	] remoteExec[ "KIB_fnc_setPlayerData", remoteExecutedOwner ];
};

KIB_fnc_savePlayerData = {
	params[ "_player" ];
	
	profileNamespace setVariable[ format[ "KIB_%1Pos", vehicleVarName _player ], getPosATL _player ];
	profileNamespace setVariable[ format[ "KIB_%1Rating", vehicleVarName _player ], rating _player ];
	
};

KIB_fnc_updatePlayerData = {
	params[ "_player" ];
	
	while { true } do {
		[ _player ] call KIB_fnc_savePlayerData;
		sleep 300;
	};
};

//initPlayerLocal.sqf

KIB_fnc_setPlayerData = {
	params[ "_position", "_rating" ];
	
	//Only allow execution from the server
	if ( isMultiplayer && { !isRemoteExecuted || { remoteExecutedOwner isNotEqualTo 2 }} ) exitWith {};
	
	//Set rating, not add to what they already have
	player addRating ( _rating - rating player );
	player setPosATL _position;
	
	//Only once saved/defaults have been applied start saving data
	[ player ] remoteExec[ "KIB_fnc_updatePlayerData", 2 ];
};


params[ "_player" ];

[ _player ] remoteExec[ "KIB_fnc_getPlayerData", 2 ];

 

  • Like 2
  • Thanks 1

Share this post


Link to post
Share on other sites

Thank you @Larrow ! Thank you @Schatten ! I would never think of such complex script and it working perfectly on dedicated. The only question I have is how to delete the players data on the server to restart all players positions?   

 

KIB_fnc_deletePlayerData = {
	params[ "_player" ];
	
	profileNamespace setVariable[ format[ "KIB_%1Pos", vehicleVarName _player ], nil ];
	profileNamespace setVariable[ format[ "KIB_%1Rating", vehicleVarName _player ], nil ];
	
};

 

Share this post


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

The only question I have is how to delete the players data on the server to restart all players positions?

Just remotely execute your function on server side whenever you need this.

  • Thanks 1

Share this post


Link to post
Share on other sites
On 4/19/2024 at 6:37 PM, kibaBG said:

The only question I have is how to delete the players data on the server to restart ALL players positions

I have changed the saved data from the server's profileNamespace to missionProfileNamespace instead. Just a better idea all around...

  1. you can use this system on multiple missions without it interfering with each other, or even share if needed
  2. you can use allVariables command on it to collect all data for deletion.

I have changed the data from a single var for each piece of information ( e.g KIB_#_Pos, KIB_#_Rating ) to KIB_playerData_# ( where # is the reference to the player, as per previous either varName or uid ) which is an array holding ALL the data for that player. Makes it easier to find/delete without having to poll multiple vars.

 

I have made an action menu for the logged in admin so they can manage the data...

  • "Show Admin Menu" -                    Will display the options below

  • "Delete Players Position" -             Will delete the position data for the current player you are looking at

  • "Delete Players Rating" -                Will delete the rating data for the current player you are looking at

  • "Delete Players Data" -                   Will delete all data for the current player you are looking at

  • "Delete All Players Positions" -     Will delete position data for all currently connected players

  • "Delete All Players Ratings" -        Will delete rating data for all currently connected players

  • "Delete All Players Data" -             Will delete all data for all currently connected players

  • "Delete ALL Data" -                         Will delete all data EVERYTHING that has ever been saved

  • "Close Admin Menu" -                    Will remove the options above other than Show Menu just so you can clear the clutter from your action menu

Spoiler

//initServer.sqf

KIB_fnc_getPlayerData = {
	params[ "_player" ];

	if ( vehicleVarName _player == "" ) then {
		_player setVehicleVarName format[ "Player_%1", getPlayerUID _player ];
		_player call BIS_fnc_objectVar;
	};

	missionProfileNamespace getVariable[ format[ "KIB_playerData_%1", vehicleVarName _player ], [ getPosATL _player, rating _player ] ]
		remoteExec[ "KIB_fnc_setPlayerData", remoteExecutedOwner ];

	if ( admin owner _player == 2 ) then {
		[] remoteExec[ "KIB_fnc_applyAdminMenu", remoteExecutedOwner ];
	};
};

KIB_fnc_savePlayerData = {
	params[ "_player" ];

	missionProfileNamespace setVariable[ format[ "KIB_playerData_%1", vehicleVarName _player ], [ getPosATL _player, rating _player ] ];

};

KIB_fnc_updatePlayerData = {
	params[ "_player" ];

	KIB_playerData_updatePeriod = 300;	//Change this for number of seconds between player data saves

	if ( isNil "KIB_playerData_updateEH" ) then {
		KIB_playerData_players = [ _player ];
		KIB_playerData_nextUpdate = time;
		KIB_playerData_updateEH = addMissionEventHandler[ "EachFrame", {
			if ( time >= KIB_playerData_nextUpdate ) then {
				{
					[ _x ] call KIB_fnc_savePlayerData;
				}forEach KIB_playerData_players;
				saveMissionProfileNamespace;
				KIB_playerData_nextUpdate = time + KIB_playerData_updatePeriod;
			};
		}];
	}else{
		KIB_playerData_players append [ _player ];
	};

};

KIB_fnc_deletePlayerData = {
	params[
		[ "_who", true, [ "", objNull, true, [] ] ],
		[ "_what", [ true, true ], [ [] ] ]
	];
	_what params[ [ "_delPos", true, [ true ] ], [ "_delRank", true, [ true ] ] ];

	if ( isMultiplayer && { isRemoteExecuted && { admin remoteExecutedOwner isNotEqualTo 2 } } ) exitWith {
		"SERVER: You are not a signed in admin" remoteExec[ "hint", remoteExecutedOwner ];
	};

	_fnc_getWho = {
		params[ "_who" ];

		switch ( true ) do {
			case ( _who isEqualType "" ) : {
				[ _who ];
			};
			case ( _who isEqualType objNull && { isPlayer _who } ) : {
				[ vehicleVarName _who ];
			};
			case ( _who isEqualType true ) : {
				if ( _who ) then {
					allVariables missionProfileNamespace select{ _x select[ 0, 15 ] == "KIB_playerData_" } apply{ _x select[ 15, count _x ] };
				}else{
					KIB_playerData_players apply{ vehicleVarName _x };
				};
			};
		};
	};


	if ( _who isEqualType [] ) then {
		_who = _who apply{ ( _x call _fnc_getWho ) #0 };
	}else{
		_who = _who call _fnc_getWho;
	};

	KIB_playerData_nextUpdate = time + 1e10;

	{
		_data = missionProfileNamespace getVariable format[ "KIB_playerData_%1", _x ];
		if ( _delPos ) then {
			_data set[ 0, nil ];
		};
		if ( _delRank ) then {
			_data set[ 1, nil ];
		};
		missionProfileNamespace setVariable[ format[ "KIB_playerData_%1", _x ], _data ];
	}forEach _who;

	saveMissionProfileNamespace;

	KIB_playerData_nextUpdate = time;
};


//initPlayerLocal.sqf

KIB_fnc_setPlayerData = {
	params[ "_position", "_rating" ];

	//Only allow execution from the server
	if ( isMultiplayer && { !isRemoteExecuted || { remoteExecutedOwner isNotEqualTo 2 }} ) exitWith {};

	if !( isNil "_position" ) then {
		player setPosATL _position;
	};

	if !( isNil "_rating" ) then {
		//Set rating, not add to what they already have
		player addRating ( _rating - rating player );
	};

	//Only once saved/defaults have been applied start saving data
	[ player ] remoteExec[ "KIB_fnc_updatePlayerData", 2 ];

};

KIB_fnc_applyAdminMenu = {

	//Only allow execution from the server
	if ( isMultiplayer && { !isRemoteExecuted || { remoteExecutedOwner isNotEqualTo 2 }} ) exitWith {};

	player addAction[ "Show Admin Menu", {
			params [ "_target", "_caller", "_id", "_args" ];

			[] call KIB_fnc_showAdminMenu;
		},
		[],
		1,
		false,
		false,
		"",
		"isNil 'KIB_adminActionIDs'"
	];
};

KIB_fnc_showAdminMenu = {
	params[ [ "_show", true ] ];

	if !( call BIS_fnc_admin == 2 ) exitWith {
		hint "You need to be a logged in admin to apply this menu";
	};

	if ( _show ) then {
		KIB_adminActionIDs = [];
		{
			_x params[ "_title", "_code", [ "_condition", "true" ] ];

			KIB_adminActionIDs append[
				player addAction[ _title, {
						//params [ "_target", "_caller", "_id", "_args" ];
						params [ "", "", "", "_args" ];

						_this call ( _args #0 );
					},
					[ _code ],
					1,
					false,
					true,
					"",
					_condition
				]
			];
		}forEach[
			//[ title, code, condition ]
			[ "Delete Players Position", { [ cursorObject, [ true, false ] ] remoteExec[ "KIB_fnc_deletePlayerData" ] }, "!isNull cursorObject && { cursorTarget isKindOf 'Man' && isPlayer cursorObject }" ],
			[ "Delete Players Rating", { [ cursorObject, [ false, true ] ] remoteExec[ "KIB_fnc_deletePlayerData" ] }, "!isNull cursorObject && { cursorTarget isKindOf 'Man' && isPlayer cursorObject }" ],
			[ "Delete Players Data", { [ cursorObject ] remoteExec[ "KIB_fnc_deletePlayerData" ] }, "!isNull cursorObject && { cursorTarget isKindOf 'Man' && isPlayer cursorObject }" ],
			[ "Delete All Players Positions", { [ false, [ true, false ] ] remoteExec[ "KIB_fnc_deletePlayerData", 2 ] } ],
			[ "Delete All Players Ratings", { [ false, [ false, true ] ] remoteExec[ "KIB_fnc_deletePlayerData", 2 ] } ],
			[ "Delete All Players Data", { [ false ] remoteExec[ "KIB_fnc_deletePlayerData", 2 ] } ],
			[ "Delete ALL Data", { [ true ] remoteExec[ "KIB_fnc_deletePlayerData", 2 ] } ],
			[ "Close Admin Menu", { [ false ] call KIB_fnc_showAdminMenu } ]
		];
	}else{
		{
			player removeAction _x;
		}forEach KIB_adminActionIDs;
		KIB_adminActionIDs = nil;
	};
};

params[ "_player" ];

[ _player ] remoteExec[ "KIB_fnc_getPlayerData", 2 ];

 

Again totally untested, let me know if there are any problems.

 

Update: New version that saves players starting position, added options to admin menu to reset position/rating.

TEST MISSION

  • Thanks 1

Share this post


Link to post
Share on other sites

@Larrow Unfortunately, I cannot make it work and save players position ...

Share this post


Link to post
Share on other sites

Strange, I have just tested it on my dedicated with no issues.

Are you seeing any errors in the server or clients RPT? Is it maybe a copy and paste issue from the forum inserting hidden characters?

Share this post


Link to post
Share on other sites

Hi, I just tested it again but its not working. How I am testing: I start the dedi server and the headless, login as admin, choose the mission ("NightZ"), spawn, wait for 10 min on some place, then get out of server, turn down server and repeat. Its no loading the player's position. I am adding the rpt log: https://drive.google.com/file/d/1ajWGH5oQj0jw1YlMfZnYiz9lheSuIHg1/view?usp=sharing

Maybe the issue is I am using Grad Persistence script to save the player's loadout? I have turned off the option to save player's position in description.ext
 

class CfgGradPersistence {
    missionTag = "NightZ";
    loadOnMissionStart = 1;
    missionWaitCondition = "true";
    playerWaitCondition = "true";

    saveUnits = 0;
    saveVehicles = 1;
    saveContainers = 1;
    saveStatics = 0;
    saveGradFortificationsStatics = 0;
    saveMarkers = 0;
    saveTasks = 0;
    saveTriggers = 0;

    savePlayerInventory = 1;
    savePlayerDamage = 0;
    savePlayerPosition = 0;
    savePlayerMoney = 0;

    saveTeamAccounts = 0;
	saveTimeAndDate = 1;
};

It's not loading player's position anyway ...

 

UPDATE: 
@Larrow 's script works flawlessly, my problem was the dedicated server profile and connected client profile were the same preventing any changes to it. Big thanks to @Larrow who helped me to solve the problem!

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

×