Jump to content
Enigx

Identify the player that has a specific name

Recommended Posts

Hi, I'm trying to write a script to teleport player in MP from a list box to my position

I have the list with all the name and can select them, but it seems the selection gives me back only the "string" of the name and not the player as "entity". 

So the question is,  is there a way to "identify" the player that has a specified name? So that I can use the string for something like that

 

(<player having _Namestring>) setPos (getpos player);

 

where the last "player" is me, who called the script.

Thanks in advance

Share this post


Link to post
Share on other sites
_nameString =  ... <- name of ur desired player
  
_playerObject = allPlayers select ( allPlayers findIf {(name _x) isEqualTo _nameString;} );

 

  • Like 2

Share this post


Link to post
Share on other sites

@sarogahtyp that , or you can keep separate list of the players:

 


 

listedPlayers = [];



// For each listed player

listedPlayers pushback _plr;

_ctrl lnbAddRow [name _plr];



// Get the player object

_plr = listedPlayers select _selectionIndex;

 

  • Like 1

Share this post


Link to post
Share on other sites

Thanks to all.

I tried 

On 7/10/2020 at 2:49 PM, sarogahtyp said:

_nameString =  ... <- name of ur desired player
  
_playerObject = allPlayers select ( allPlayers findIf {(name _x) isEqualTo _nameString;} );

 

and it works!!

Thanks again for your help.

Share this post


Link to post
Share on other sites

Why search for the player by name? When you can add a reference to the object when you fill the listbox. Like I showed you in your other post.

Spoiler

createDialog "RSCDisplayCommon";
waitUntil{ !isNull ( uiNamespace getVariable[ "RscDisplayCommon", displayNull ] ) };
_display = uiNamespace getVariable "RscDisplayCommon";

_playerList = _display ctrlCreate[ "ctrlListbox", 10000 ];
_playerList ctrlSetPosition[ -0.3, 0.02, 0.48793, 0.744756 ];
_playerList ctrlCommit 0;
{
	_index = _playerList lbAdd name _x;
	_playerList lbSetData[ _index, _x call BIS_fnc_objectVar ]; //Add reference to units vehicleVarName
} forEach ( allPlayers - [ player ] );
_playerList lbSetCurSel 0;

_button = _display ctrlCreate[ "ctrlButton", 10001 ];
_button ctrlSetPosition[ 0.625, 0.2, 0.423497, 0.276817 ];
_button	ctrlCommit 0;
_button ctrlSetText "Teleport Unit";

_button ctrlAddEventHandler[ "ButtonClick", {
	params[ "_button" ];
	
	_playerList = ctrlParent _button displayCtrl 10000;
	_selectedIndex = lbCurSel _playerList;
	
	_curName = _playerList lbText _selectedIndex;
	hint _curName;	
	
	_objectName = _playerList lbData _selectedIndex;	//Get saved vehicleVarName	
	_object = missionNamespace getVariable _objectName;	//Get object
	_object setPosATL ( player getPos[ 5, getDir player ] ); //Teleport object to 5m infront of the user
	
}];

 

 

  • Like 2

Share this post


Link to post
Share on other sites

Thanks so much Larrow for your support, I will try this solution too. 

Share this post


Link to post
Share on other sites

Hi Larrow,

sorry if I'm going back to this topic, but I have a question on your solution.

 

On 7/13/2020 at 11:51 PM, Larrow said:

Why search for the player by name? When you can add a reference to the object when you fill the listbox. Like I showed you in your other post.

  Hide contents


createDialog "RSCDisplayCommon";
waitUntil{ !isNull ( uiNamespace getVariable[ "RscDisplayCommon", displayNull ] ) };
_display = uiNamespace getVariable "RscDisplayCommon";

_playerList = _display ctrlCreate[ "ctrlListbox", 10000 ];
_playerList ctrlSetPosition[ -0.3, 0.02, 0.48793, 0.744756 ];
_playerList ctrlCommit 0;
{
	_index = _playerList lbAdd name _x;
	_playerList lbSetData[ _index, _x call BIS_fnc_objectVar ]; //Add reference to units vehicleVarName
} forEach ( allPlayers - [ player ] );
_playerList lbSetCurSel 0;

_button = _display ctrlCreate[ "ctrlButton", 10001 ];
_button ctrlSetPosition[ 0.625, 0.2, 0.423497, 0.276817 ];
_button	ctrlCommit 0;
_button ctrlSetText "Teleport Unit";

_button ctrlAddEventHandler[ "ButtonClick", {
	params[ "_button" ];
	
	_playerList = ctrlParent _button displayCtrl 10000;
	_selectedIndex = lbCurSel _playerList;
	
	_curName = _playerList lbText _selectedIndex;
	hint _curName;	
	
	_objectName = _playerList lbData _selectedIndex;	//Get saved vehicleVarName	
	_object = missionNamespace getVariable _objectName;	//Get object
	_object setPosATL ( player getPos[ 5, getDir player ] ); //Teleport object to 5m infront of the user
	
}];

 

 

 

Is it possible to use it to identify the clientID of the selected player?

I want to execute an sqf on a client pc from mine. So,  before the }]; of your script, add something like that

_clientID = owner _object;
 ["anyfile.sqf"] remoteExec ["execVM", _clientID];
 
 ["file executed on your pc"] remoteExec ["hint",_clientID];

Is it _object also local to the selected client?

 

I have found a method as in one of my post , but sometime it doesn't work due to difficulty to propagate steamUID between clients (as written in BIKI page)

 

My difficulty is to find the clientID number and there isn't a clear explanation on web to do that (or I didn't find/understand). 

 

Thanks for feedbacks

Share this post


Link to post
Share on other sites
16 hours ago, Enigx said:

My difficulty is to find the clientID number and there isn't a clear explanation on web to do that

There is no need to find the client number, just use the players object as the remoteExec target.

["anyfile.sqf"] remoteExec ["execVM", _object];  //Will execute where _object is local

Although this will still not work as the command execVM is not remote executable (you can find what commands are remote executable by looking at what is listed in the config under CfgRemoteExecCommands).

 

Now you could just replace it with the function BIS_fnc_execVM, but I see security issues. How do you know if a client is allowed to run your function giving them admin privileges? It's conceivable that without any checks in place a rogue player could just run the function from their own client.

The easiest method would be to place something in the top of the script to make sure it is remotely executed from a trusted source( a current admin/server ), but now you need to know, on that particular client who is a trusted admin (passing admin IDs to clients as per your referenced post is not a good idea as a rogue player could just inject their ID into it).

For me the only secure way to do this is by the server, by making the server authoritative for anything admin related. e.g

Spoiler

//initServer.sqf

call compileFinal "TAG_adminsIDs = [ /* array of admin steam IDs */ ]";
TAG_connectedAdminOwners = [ 2 ]; //Server is always an admin
TAG_tempAdminOwners = [];

addMissionEventHandler[ "PlayerConnected", {
	params[ "_id", "_uid", "_name", "_jip", "_owner" ];
	
	//If connecting client is an admin
	if ( _uid in TAG_adminsIDs ) then {
		
		//Add them to the array
		TAG_connectedAdminOwners pushBackUnique _owner;
		
		//If they Joined In Progress
		if ( _jip ) then {
			
			//Apply Admin menu
			[] remoteExec[ "TAG_fnc_applyAdminSelfMenu", _owner ];
		};
	};
}];

addMissionEventHandler[ "PlayerDisconnected", {
	params[ "_id", "_uid", "_name", "_jip", "_owner" ];
	
	//If they are an admin
	if ( _owner in TAG_connectedAdminOwners ) then {
		
		//Remove them from the connected array 
		TAG_connectedAdminOwners - [ _owner ];
	};
	
	//If they are a temp admin
	if ( _owner in TAG_tempAdminOwners ) then {
		
		//remove them from the temp admin array
		TAG_tempAdminOwners - [ _owner ];
	};
}];

//Server authoritative function for applying temp admin privilege
TAG_fnc_giveTempAdminSelfMenu = {
	params[ "_tempAdmin" ];
  
	if !( isServer ) exitwith {};
	
	//If this function is remote executed AND the caller is NOT a full admin
	if ( isRemoteExecuted && { !( remoteExecutedOwner in TAG_connectedAdminOwners ) } ) exitWith {
		//unauthorised call to function
		//Kick the caller
		_name = name ( allPlayers apply{ _x, owner _x } select{ remoteExecutedOwner == ( _x select 1 ) } select 0 select 0 );
		serverCommand format[ "#kick %1", _name ];
	};
	
	//Add temp admin to the array
	TAG_tempAdminOwners pushBackUnique owner _tempAdmin;
	
	//Remote apply admin menu
	[] remoteExec[ "TAG_fnc_applyAdminSelfMenu", _tempAdmin ];
};

//Wait for mission to start
waitUntil{ time > 0 };

//Apply admin menu to all connected admins
[ false ] remoteExec[ "TAG_fnc_applyAdminSelfMenu", TAG_connectedAdminOwners ];




//initPlayerLocal.sqf

TAG_fnc_applyAdminSelfMenu = {
	params[ [ "_isTempAdmin", true ] ]
	
	//Only the server is allowed to call this function
	if ( !isRemoteExecuted || ( isRemoteExecuted && !( remoteExecutedOwner == 2 )) ) exitWith {};
	
	//Make sure client is in a state ready to apply addAction
	waitUntil{ time > 0 && !isNull findDisplay 46 };
	
	if !( _isTempAdmin ) then {
		
		//Only allow full admins to grant admin privileges
		player addAction[ "Grant Admin privilege", {
				params [ "_target", "_caller", "_id", "_args" ];
				
				//Tell server to grant temp admin privilege to the clients cursorObject
				[ cursorObject ] remoteExec[ "TAG_fnc_giveTempAdminSelfMenu", 2 ];
			},
			[],
			1,
			false,
			true,
			"",
			"!isnull cursorObject && { isPlayer cursorObject && { alive cursorObject }}"
		];
	};
	
	//All other actions allowed for both temp and full admins
	
	player addAction[ "Teleport to cursor", {
		params[ "_target", "_caller", "_ID", "_args" ];
		
		_pos = screenToWorld[ 0.5, 0.5 ];
		if !( _pos isEqualTo [0,0,0] ) then {
			_caller setPosATL _pos;
		};
	}];
};

 

Not tested, more just to show an idea.

 

Now a rogue player could possibly inject themselves into TAG_connectedAdminOwners and remoteExec the server function passing themself, but this would only ever give them temp admin privileges.

You could possibly negate this by securing command usage (publicVariable, setVariable) via CfgDisableCommands, but this does require careful consideration of what commands, and their locality, you use throughout your mission.

Another thing to consider is moving your server authoritative functions/code into their own addon that only the server has access to and loads. As is above initServer.sqf will be part of your mission pbo, allowing anyone who has downloaded the mission to extract it and see how to possibly get around your protection.

 

Keep in mind I do not have much experience with securing servers, so all of the above you can consider as me just thinking through the problem out loud.

Share this post


Link to post
Share on other sites

Thank you for your answer. Don't worry, your arguments out loud are welcome :-)
I understand your security doubts, but I think this is not the case as I only use the system for my clan missions.
I certainly did not know that some functions are not remote executable. Now it is clearer.
I'll try to use this solution directly:

["anyfile.sqf"] remoteExec ["BIS_fnc_execVM", _object];

For a general remote executable function do you think that the following works?

... player selected in _object 

TargetFunction ={     
    player call FUN_fnc_addPersonalMenu; // or any code
    hint "This message is visible only to the target client";
}; 
[] remoteExec ["TargetFunction", _object]; 
hint format["You have assigned the menu to %1", name _object]; // this message is visible only to the caller

Can I put this code in the same sqf or have I to define the "TargetFuction" external and initiate it by the "class CfgRemoteExec"?

Thanks again for your patience.

Share this post


Link to post
Share on other sites
13 hours ago, Enigx said:

I certainly did not know that some functions are not remote executable. Now it is clearer.

Some commands are not remote executable, execVM is a script command.

Most functions are remote executable, unless you have specifically disable their usage via CfgRemoteExec or some form of BE(BattleEye) filter.

 

13 hours ago, Enigx said:

For a general remote executable function do you think that the following works? 


... player selected in _object 

TargetFunction ={     
    player call FUN_fnc_addPersonalMenu; // or any code
    hint "This message is visible only to the target client";
}; 
[] remoteExec ["TargetFunction", _object]; 
hint format["You have assigned the menu to %1", name _object]; // this message is visible only to the caller

Can I put this code in the same sqf or have I to define the "TargetFuction" external

The function will need to be defined somewhere so any targets already have it defined before you remote execute it. Either initPlayerLocal.sqf or through the functions library ( CfgFunctions ).

If you ever use the JIP argument of remoteExec then the function will definitely need defining through CfgFunctions so its available when the client connects, as JIP REs are processed before any event scripts( initPlayerLocal ) have been executed.

 

As you have shown above, the function is defined just before you RE it. In which case the target client likely has not had the function defined on their machine.

The "TargetFunction" argument of remoteExec does not pass the function along with the RE, it is just a name(String) of a function to run on the target machine when the target processes the received RE.

 

Hope that makes sense.

 

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

×