Enigx 39 Posted July 10, 2020 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
sarogahtyp 1109 Posted July 10, 2020 _nameString = ... <- name of ur desired player _playerObject = allPlayers select ( allPlayers findIf {(name _x) isEqualTo _nameString;} ); 2 Share this post Link to post Share on other sites
gc8 981 Posted July 10, 2020 @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; 1 Share this post Link to post Share on other sites
Enigx 39 Posted July 13, 2020 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
Larrow 2823 Posted July 13, 2020 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 }]; 2 Share this post Link to post Share on other sites
Enigx 39 Posted July 15, 2020 Thanks so much Larrow for your support, I will try this solution too. Share this post Link to post Share on other sites
Enigx 39 Posted September 30, 2020 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
Larrow 2823 Posted October 1, 2020 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
Enigx 39 Posted October 1, 2020 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
Larrow 2823 Posted October 2, 2020 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