aintaro Posted June 29, 2014 Share Posted June 29, 2014 (edited) Hello, Today I will be explaining why you should stop use setElementData and how to stop using it. Why should you stop using setElementData? As element data is synced to all clients, it can generate a lot of network traffic and consume server CPU. How to stop using setElementData? Example : Lets say you want to save the total time of a player most people will do it like this : local timePlayed = 0 --declare a variable timePlayed for every player function initPlayer() setElementData(thePlayer, "player_time", timePlayed) --we set the elementData player_time to timePlayed end THATS WRONG! This is how you should do it : local playerData = { --declare playerData for all the players data timePlayed = {} --first dataType = timePlayed } function initPlayer() playerData.timePlayed[thePlayer] = 0 --set timePlayed of "thePlayer" to 0 end playerData.timePlayed[thePlayer] = 0 --set timePlayed of "thePlayer" to 0 this will set timePlayed only to thePlayer userdata PROOF : for i = 1, 10000 do setElementData(thePlayer, "test"..tostring(i), 1000) end execute time : 47 ticks for i = 1, 10000 do setElementData(thePlayer, "test"..tostring(i), 1000,false) end execute time : 40 ticks for i = 1, 10000 do playerData[thePlayer][i] = 1000 end execute time : 1 tick thanks for reading, any questions can be posted under! Edited June 29, 2014 by Guest Link to comment
Castillo Posted June 29, 2014 Share Posted June 29, 2014 Do you even know what is setElementData used for? You can disable the synchronization among clients using the fourth argument of the function. Link to comment
aintaro Posted June 29, 2014 Author Share Posted June 29, 2014 Do you even know what is setElementData used for?You can disable the synchronization among clients using the fourth argument of the function. lets say you use it, it's still synced with all server Link to comment
Castillo Posted June 29, 2014 Share Posted June 29, 2014 Still, your "tutorial" is a bit un-explained, you could explain it a bit more, so these who don't know can understand it. 1 Link to comment
aintaro Posted June 29, 2014 Author Share Posted June 29, 2014 Still, your "tutorial" is a bit un-explained, you could explain it a bit more, so these who don't know can understand it. I know i'll expand it when I have some free time But it's important to let people know Link to comment
TheCapn Posted June 30, 2014 Share Posted June 30, 2014 In fact I use whenever is possible Lua table, but however setElementData and getElementData are useful because you can keep the data among the different resources of your server. If you want to set a data on the "main" resource and use it on the resource concerning the vehicule, it's easy with elementData, and you can't do it with tables. Link to comment
RottenFlesh Posted July 2, 2014 Share Posted July 2, 2014 In fact I use whenever is possible Lua table, but however setElementData and getElementData are useful because you can keep the data among the different resources of your server. If you want to set a data on the "main" resource and use it on the resource concerning the vehicule, it's easy with elementData, and you can't do it with tables. Yo can do it with tables, you just have to make an exported function that returns the table with the data. The bad thing is that you would have to do it with each table. But if you are concerned about server performance, you have to consider this system. Link to comment
AfuSensi Posted July 31, 2014 Share Posted July 31, 2014 If i understand it correctly, the table PlayerData has subtables of data ( like the key in setElementData ), and in that subtable there is another subtable with all the players in it? So this is server sided. If i understand that correctly, then i have a question. If the player leaves, how do i destroy the subtables that contain information of that player? Like, if thePlayer leaves, it still has the tables timePlayed = { [thePlayer] = 0 } inside of the table. Link to comment
RottenFlesh Posted July 31, 2014 Share Posted July 31, 2014 If i understand it correctly, the table PlayerData has subtables of data ( like the key in setElementData ), and in that subtable there is another subtable with all the players in it? So this is server sided. If i understand that correctly, then i have a question. If the player leaves, how do i destroy the subtables that contain information of that player? Like, if thePlayer leaves, it still has the tables timePlayed = { [thePlayer] = 0 } inside of the table. player_data = {} function on_join() player_data[source] = "something you want to save" end addEventHandler('onPlayerJoin', root, on_join) function on_quit() player_data[source] = nil end addEventHandler('onPlayerQuit', root, on_quit) This is how you would delete the data Link to comment
Booth Posted August 3, 2014 Share Posted August 3, 2014 Is there a way to make the table available throughout all resources? Link to comment
Booth Posted August 3, 2014 Share Posted August 3, 2014 I don't really know how exactly to export a table, could you help me out? Link to comment
RottenFlesh Posted August 3, 2014 Share Posted August 3, 2014 table = {} function twerk () return table end then add this to the meta.xml file: <export function="twerk" type="server"/> and when you want to get the table from other resource: table = exports.resourceName:twerk() Easy, right? Link to comment
Booth Posted August 3, 2014 Share Posted August 3, 2014 So if the table I have set up is to store all player data whilst the player is actively ingame, is this the right way to structure it? playerData = { SQLID = {}, Username = {}, Password = {} } And will I be able to access these subtables through this exported function? Link to comment
RottenFlesh Posted August 3, 2014 Share Posted August 3, 2014 Yeah, but you need to set the player element as the key for the sub-tables. like this: playerData = {} function set_data(player_element, data_key, data_value) -- export this function if type(player_element) == "nil" or type(data_key) == "nil" or type(data_value) == "nil" then return false end if not playerData[player_element] then playerData[player_element] = {} end playerData[player_element][data_key] = data_value return true end function get_data(player_element, data_key) -- export this function if type(player_element) == "nil" or type(data_key) == "nil" then return false end return playerData[player_element] and playerData[player_element][data_key] or false end function delete_data() -- you have to delete the data when the player quits playerData[source] = nil end addEventHandler('onPlayerQuit', root, delete_data) Then, if you export those functions, you can call them from any resource this way: exports.resourceName:set_data(player, "SQLID", 1231231) exports.resourceName:set_data(player, "Username", "Booth") exports.resourceName:set_data(player, "Password", "12345") exports.resourceName:get_data(player, "SQLID") exports.resourceName:get_data(player, "Username") exports.resourceName:get_data(player, "Password") And this is how you would do a basic good-enough data system. Link to comment
Steph12 Posted August 10, 2014 Share Posted August 10, 2014 Yeah, but you need to set the player element as the key for the sub-tables. like this: playerData = {} function set_data(player_element, data_key, data_value) -- export this function if type(player_element) == "nil" or type(data_key) == "nil" or type(data_value) == "nil" then return false end if not playerData[player_element] then playerData[player_element] = {} end playerData[player_element][data_key] = data_value return true end function get_data(player_element, data_key) -- export this function if type(player_element) == "nil" or type(data_key) == "nil" then return false end return playerData[player_element] and playerData[player_element][data_key] or false end function delete_data() -- you have to delete the data when the player quits playerData[source] = nil end addEventHandler('onPlayerQuit', root, delete_data) Then, if you export those functions, you can call them from any resource this way: exports.resourceName:set_data(player, "SQLID", 1231231) exports.resourceName:set_data(player, "Username", "Booth") exports.resourceName:set_data(player, "Password", "12345") exports.resourceName:get_data(player, "SQLID") exports.resourceName:get_data(player, "Username") exports.resourceName:get_data(player, "Password") And this is how you would do a basic good-enough data system. How to use this clientside? Link to comment
Anubhav Posted August 11, 2014 Share Posted August 11, 2014 playerData = {} function set_data(player_element, data_key, data_value) -- export this function if type(player_element) == "nil" or type(data_key) == "nil" or type(data_value) == "nil" then return false end if not playerData[player_element] then playerData[player_element] = {} end playerData[player_element][data_key] = data_value return true end function get_data(player_element, data_key) -- export this function if type(player_element) == "nil" or type(data_key) == "nil" then return false end return playerData[player_element] and playerData[player_element][data_key] or false end function delete_data() -- you have to delete the data when the player quits playerData[source] = nil end addEventHandler('onClientPlayerQuit', root, delete_data) Link to comment
RottenFlesh Posted August 11, 2014 Share Posted August 11, 2014 playerData = {} function set_data(player_element, data_key, data_value) -- export this function if type(player_element) == "nil" or type(data_key) == "nil" or type(data_value) == "nil" then return false end if not playerData[player_element] then playerData[player_element] = {} end playerData[player_element][data_key] = data_value return true end function get_data(player_element, data_key) -- export this function if type(player_element) == "nil" or type(data_key) == "nil" then return false end return playerData[player_element] and playerData[player_element][data_key] or false end function delete_data() -- you have to delete the data when the player quits playerData[source] = nil end addEventHandler('onClientPlayerQuit', root, delete_data) That will not work, as onClientPlayerQuit is only triggered on remote clients. You have to make this system server side, and the use triggerServerEvent and triggerClientEvent to get the data client-side. Link to comment
Smart. Posted August 21, 2014 Share Posted August 21, 2014 How to use this clientside? Storing such information on client-side is just a big NONO from me, once I had a player modify a variable client sided which caused a massive money glitch, apparently he made it using cheat engine. Not sure if he was bullshitting, it's been fixed or still working but hey, not a risk I'm willing to take. Link to comment
Tails Posted September 20, 2014 Share Posted September 20, 2014 Thanks, good tutorial. So to understand correctly, there is absolutely no use for setElementData or getElementData? Link to comment
Saml1er Posted September 22, 2014 Share Posted September 22, 2014 Thanks, good tutorial. So to understand correctly, there is absolutely no use for setElementData or getElementData? Actually there is but depends on you when or how you use it. If you can do it without elemendata then it's really good but if you can't then it's ok to use it but try to use it in only extreme necessary. Link to comment
Narrator Posted September 25, 2014 Share Posted September 25, 2014 Ok, thanks for tutorial. But.. Is this method really more useful than elementData? What about hackers? Can they hack client variable? Who use it instead of elementData? Sorry for my mistakes if they're. Link to comment
Saml1er Posted September 25, 2014 Share Posted September 25, 2014 Ok, thanks for tutorial. But.. Is this method really more useful than elementData? What about hackers? Can they hack client variable? Who use it instead of elementData? Sorry for my mistakes if they're. I don't know about variables if they can hack it but if a hacker can get access to ftp then yes they can and about element data . It's better to check. https://wiki.multitheftauto.com/wiki/On ... DataChange Link to comment
Narrator Posted September 25, 2014 Share Posted September 25, 2014 Saml1er, i know that protection method, but i talking about hack variables with CheatEngine etc. For example if you want create inventory, will you use this method instead of elementData? Link to comment
Anubhav Posted September 25, 2014 Share Posted September 25, 2014 I'd prefer you to use this at server side and make a trigger! Link to comment
Recommended Posts