abadabadu Posted May 3, 2014 Share Posted May 3, 2014 Hello, i doubt with choosing setElementData or triggerServerEvent. As i can see on source code, setElementData is nothing but "OnElementDataChange" event + triggerServerEvent function made in sourcecode by developers themself. https://code.google.com/p/mtasa-blue/source/browse/trunk/MTA10_Server/mods/deathmatch/logic/CElement.cpp void CElement::SetCustomData ( const char* szName, const CLuaArgument& Variable, CLuaMain* pLuaMain, bool bSynchronized, CPlayer* pClient, bool bTriggerEvent ) { assert ( szName ); if ( strlen ( szName ) > MAX_CUSTOMDATA_NAME_LENGTH ) { // Don't allow it to be set if the name is too long CLogger::ErrorPrintf ( "Custom data name too long (%s)\n", *SStringX ( szName ).Left ( MAX_CUSTOMDATA_NAME_LENGTH + 1 ) ); return; } // Grab the old variable CLuaArgument oldVariable; const SCustomData * pData = m_pCustomData->Get ( szName ); if ( pData ) { oldVariable = pData->Variable; } // Set the new data m_pCustomData->Set ( szName, Variable, pLuaMain, bSynchronized ); if ( bTriggerEvent ) { [size=6][b] // Trigger the onElementDataChange event on us CLuaArguments Arguments; Arguments.PushString ( szName ); Arguments.PushArgument ( oldVariable ); Arguments.PushArgument ( Variable ); CallEvent ( "onElementDataChange", Arguments, pClient );[/b][/size] } } My questions 1)If so, even user can make absolutly the same in lua script using tables+register some event like "onCustomMadeDataChangeEvent"+triggerServerEvent/triggerClientEvent functions ? 2) And main: what should i prefer: ready to use "setElementData" or selfmade but doing exactly the same system with triggerServerEvent/triggerClientEvent? First desire is to use setElementData becouse it made in source via c++. BUT! As we can see here CLuaArguments Arguments; Arguments.PushString ( szName ); [b]Arguments.PushArgument ( oldVariable );[/b] Arguments.PushArgument ( Variable ); CallEvent ( "onElementDataChange", Arguments, pClient ); Arguments.PushArgument ( oldVariable ); means we transfer old value EVERYTIME to EVERYCLIENT when element data changed? So, if so, in selfmade triggerServerEvent + arguments i can send only new value value (skip oldValue), saving some bandwidth in each event, each client. Someone can say that it is not critical, but it means that we save 50% bandwidth. Did i understand it correctly? Thanks! Link to comment
abadabadu Posted May 3, 2014 Author Share Posted May 3, 2014 Some new investigation gives answers Looks like setElementData does NOT transfer oldValue. https://code.google.com/p/mtasa-blue/source/browse/trunk/MTA10/mods/deathmatch/logic/rpc/CElementRPCs.cpp void CElementRPCs::SetElementData ( CClientEntity* pSource, NetBitStreamInterface& bitStream ) { unsigned short usNameLength; if ( bitStream.ReadCompressed ( usNameLength ) ) { // We should never receive an illegal name length from the server if ( usNameLength > MAX_CUSTOMDATA_NAME_LENGTH ) { CLogger::ErrorPrintf ( "RPC SetElementData name length > MAX_CUSTOMDATA_NAME_LENGTH" ); return; } SString strName; CLuaArgument Argument; if ( bitStream.ReadStringCharacters ( strName, usNameLength ) && Argument.ReadFromBitStream ( bitStream ) ) { pSource->SetCustomData ( strName, Argument, NULL ); } } } Its just set new value, then triggers on(Client)DataChange event giving to that event new and old value (on that machine where event called). I still need confirmation and advice... Link to comment
MTA Team sbx320 Posted May 3, 2014 MTA Team Share Posted May 3, 2014 You're correct on what you stated above. onClientElementDataChange won't send the old value, since the client already knows it. I'd suggest you to use a custom system based upon triggerClientEvent, since element datas have a few issues: They're synced to everyone Whenever you change an Elementdata on the server/client the information will be synced to any connected client. This is often not necessary, but simply a waste of bandwidth. Why would a remote player be required to know the exact amount of fuel in a vehicle far away? That information is only useful for the driver of the vehicle, so you'd waste a ton of bandwidth which could be used by MTA for better synchronization. Anyone can modify them Without some additional security scripts (which is easily possible, but often overlooked) any client can modify Elementdatas of any element. This allows cheaters with modified clients to cheat themselves various things like money or even admin rights. Link to comment
abadabadu Posted May 3, 2014 Author Share Posted May 3, 2014 Thanks for answer. Anyone can modify them Without some additional security scripts (which is easily possible, but often overlooked) any client can modify Elementdatas of any element. This allows cheaters with modified clients to cheat themselves various things like money or even admin rights. Didnt devepolers fix it in 1.1? Still can see addEventHandler('onElementDataChange', root, function(dataName, oldValue ) if getElementType(source)=='player' and checkClient( false, source, 'onElementDataChange', dataName ) then setElementData( source, dataName, oldValue ) return end end ) in admin/server/admin_server.lua. But saw some posts from developers about fixing problem with fake client+setElementData in 1.1 and above. Isnt it correct? But, basing on wiki, triggerServerEvent can be faked too, like setElementData. In case with triggerServerEvent i still must to control who does that (like in system with setElementData). Does it mean triggerServerEvent does not free me from writing exactly the same (in base) some additional security scripts? Does that mean that saving bandwidht is only one real reason to use triggerServerOnly not setElementData. Link to comment
abadabadu Posted May 4, 2014 Author Share Posted May 4, 2014 Keep talking to myself I prefer to use custom system based upon triggerClientEvent. I thought that "setElementData VS trigger*Event" is "bandwidth VS CPU" (in case all another things 100% the same - mean in case i really need to sync data with every client does not matter using trigger*event or setElementData), but... Using setElementData we not only transfer more bytes, we need to process them, so every byte(packet, message?) needs CPU time. So CPU "argument" suffering too))) Even trigger*Event force u to write your overcode, debug it, maintain it, even the same already done in setElementData its better way to prefer trigger*Event becouse it let u save bandwith+some CPUtime wasting to deal with that packets (in case you really have possibility to do it in your mode - not everytime its possible, but in 99% cases i think...). I still need confirmation and advice... Link to comment
MTA Team sbx320 Posted May 5, 2014 MTA Team Share Posted May 5, 2014 Didnt devepolers fix it in 1.1? There are always new cheats being developed. The Anticheat is constantly updated, but you can never be aware of all cheats out there at all times. You can't ever trust a client. The security advantage of a custom system based upon event triggers is that by default you do not have an insecure system. With ElementDatas you need to take action to prevent cheaters. With custom event triggers you might as well chose to not allow clients to change certain data by simply not implementing the corresponding events serverside. Link to comment
Arran Posted June 25, 2014 Share Posted June 25, 2014 They're synced to everyoneWhenever you change an Elementdata on the server/client the information will be synced to any connected client. This is often not necessary, but simply a waste of bandwidth. Why would a remote player be required to know the exact amount of fuel in a vehicle far away? That information is only useful for the driver of the vehicle, so you'd waste a ton of bandwidth which could be used by MTA for better synchronization. That's why I made this request: http://bugs.mtasa.com/view.php?id=7950 Link to comment
Recommended Posts