Leaderboard
Popular Content
Showing content with the highest reputation on 26/04/20 in all areas
-
I don't think it can be a simple example, but here you go. local bone_attach = {} local bone_attach_render = {} local queue = {} local queueProcessStatus = false local queueNextCycleTime = 0 local tableRemove = table.remove function prepareQueue () queueProcessStatus = true for i=1, #bone_attach do local item = bone_attach[i] if not item.rendered then queue[#queue + 1] = item end end end function processQueue () for i=#queue, math.max(#queue - 50, 1), -1 do local item = queue[i] local element = item.element if isElement(element) and isElementStreamedIn(element) then item.rendered = true bone_attach_render[#bone_attach_render + 1] = item end tableRemove(queue, i) end if #queue == 0 then queueProcessStatus = false end end addEventHandler("onClientRender", root, function () for i=#bone_attach_render, 1, -1 do local item = bone_attach_render[i] local element = item.element if isElement(element) and isElementStreamedIn(element) then else item.rendered = false tableRemove(bone_attach_render, i) end end -- cycle management local timeNow = getTickCount() if not queueProcessStatus then if timeNow > queueNextCycleTime then prepareQueue() queueNextCycleTime = timeNow + 3000 end else processQueue () end end)4 points
-
2 points
-
After a worrying discussion on Discord last night regarding password storage and remember me functionality I've decided to write a tutorial on how it should be done. This guide assumes you are not using MTA's built in account system, but a custom one. Any code shown in this tutorial is purely for illustrative purposes, and is not finished code, you should use it as a guideline, not a solution. The following topics will be discussed in this tutorial: How to hash and salt passwords (register) How to validate a hashed password (login) How to add "remember-me" functionality How to offer password recovery How to migrate from an older hashing algorithm, to a newer one Using a password policy (Extra) How to handle database leaks (Extra) What even is hashing and salting? For the purpose of this tutorial we expect a database structure which is somewhat similar to this: How to hash and salt passwords When you have a user register on your service, that user expects of you to keep their password safe. Whilst it is generally bad practice to use the same password for multiple services there are many users that still do so. Because of this it's crucial that you save the user's passwords in a way that an attacker will be unable to find out the original password the user typed. This includes if they have full access to your database. In order to do this we do what is called "Password hashing" When a user registers, your server receives the user's intended username, (email) and password. Before you save that password to the database you have to hash and salt this, luckily MTA has a function that takes care of this. If you wish to know more about what exactly it does, there's more information at the end of this tutorial. In order to hash this password you use the passwordHash function. This function is relatively slow (by design), so it is highly recommended you pass a callback to this function, so your entire script doesn't wait for it to complete. https://wiki.multitheftauto.com/wiki/PasswordHash local mysqlHandle -- we're assuming this value is set somewhere else in code function register(username, email, password) local player = client passwordHash(password, "bcrypt", {}, function(hashedPassword) -- callback function for hashing the password local handle = dbExec(function(handle) -- callback function for storing the user in the database if (handle) then triggerClientEvent(player, "registrationSuccess") -- inform the user that registration was successful else triggerClientEvent(player, "registrationFailed") end end,mysqlHandle, "INSERT INTO users (email, username, password) VALUES (?, ?, ?)", email, username, hashedPassword) end) end addEvent("passwordTutorial:register", true) addEventHandler("passwordTutorial:register", getRootElement(), register) How to validate a hashed password Once you've saved the hashed pasword to your database you need to do a little bit of additional work when authenticating the user. Luckily MTA offers a passwordVerify() function, which is the counterpart of the previously discussed passwordHash(). What this function does it basically hashes the password in the same way, resulting in the same output hash. https://wiki.multitheftauto.com/wiki/passwordVerify In order to get the account the user is trying to log in to you have to do a query for an account which has the user submitted username, and of which the password matches through passwordVerify. PasswordVerify is also a relatively slow function, thus you should use a callback. function login(username, password) local player = client dbQuery(function (handle) -- callback for the query selecting the user by username local results = dbPoll(handle, -1) if (#results == 0) then triggerClientEvent(player, "loginFailed") return end passwordVerify(password, results[1].password, {}, function(matches) -- callback function for the password verify if (matches) then -- Do anything you wish with the database result to log the player in with the rest of your scripts triggerClientEvent(player, "loginSuccess") else triggerClientEvent(player, "loginFailed") end end) end, mysqlHandle, "SELECT * FROM users WHERE username = ?", username) end addEvent("passwordTutorial:login", true) addEventHandler("passwordTutorial:login", getRootElement(), login) How to add "remember me" functionality When users on your server log in, they often do not want to have to enter their username and password every time they want to log in. In order to satisfy this need you can implement a "remember me" function. What I've seen happen in the past, is people would store the user's password (encrypted) on the client. This is NOT safe, and should never be done! In order to properly use remember me functionality what you would do is upon login in, generate a random string. The longer the better. This random string is what we call an access token. You would then allow the user to log in with such an access token, preferably only once generating a new access token each time one is used. To implement this you would generate that token every time the user logs in, whilst they have "remember me" enabled. You will have to save this token in your database alongside your user. For extra security you could also store the user's serial alongside the access token, you can then validate that the access token is being used from the same device. https://wiki.multitheftauto.com/wiki/Filepath function login(username, password) -- This code should be put in the callback to the dbQuery function, but to keep the example clean that's not shown here if (rememberMe) then local token = generateRandomToken() dbExec(function() triggerClientEvent(player, "loginSuccess", token) end,mysqlHandle, "INSERT INTO access_tokens (user_id, token) VALUES (?, ?)", results[1].id, token) end end function rememberMeLogin(username, accessToken) -- this function handles a user's login attempt dbQuery(function(handle) local result = dbPoll(handle, -1) if (#result == 0) then triggerClientEvent(player, "loginFailed") else -- Do anything you wish with the database result to log the player in with the rest of your scripts triggerClientEvent(player, "loginSuccess") end end,mysqlHandle, "SELECT users.* FROM access_tokens JOIN users ON users.id = access_tokens.user_id WHERE users.username = ?", username) end addEvent("passwordTutorial:loginRememberMe", true) addEventHandler("passwordTutorial:loginRememberMe", getRootElement(), login) How to offer password recovery Offering password recovery requires a little bit more than just your MTA server. Generally password recovery is done with emails. So you would need access to an email server / service which you can use to send an email from an HTTP request. (Like you can do with fetchRemote()). When a user requests a password reset, have them enter the email you registered with. You then fetch a user from the database with this email address. You would then store a password recovery token for this user. This token, just like the remember me token, is a random string. Ideally, you would send the user a link with a password reset form that goes to a webpage where the user can reset their password. You could do this with an external service, like a webserver. Or you could use MTA's Resource web access for it, but if you do make sure you handle permissions properly for anything else that uses this. However another option would be to have the user copy paste the generated token from the email into you server's login window. Which of the two solutions you pick is up to you, my personal preference goes to the one with the link in the email. But in either case the server side logic is the same. When the user attempts to perform password recovery, verify that the token they give you belongs to a user, and then change the password to the newly requested password. Make sure you hash this password the same way you do in your login. function requestPasswordRecovery(email) dbQuery(function (handle)) local result = dbPoll(handle, -1) if (#result == 0) then triggerClientEvent(player, "passwordTutorial:passwordRecoveryRequestFailed") else local token = generateRandomToken() dbExec(mysqlHandle, "UPDATE user_data SET recovery_token = ?", token) -- mail the token to the user, mail implementation depends on the mail server/service you use triggerClientEvent(player, "passwordTutorial:passwordRecoveryRequestSuccess") end end, mysqlHandle, "SELECT * FROM users WHERE email = ?", email) end function recoverPassword(recoveryToken, password) dbQuery(function (handle) local result = dbPoll(handle, -1) if (#result == 0) then -- this is only valid if you have the user request password recovery from ingame triggerClientEvent(player, "passwordTutorial:passwordRecoveryFailed") else passwordHash(password, "bcrypt", {}, function(hashedPassword) -- callback function for hashing the password local handle = dbExec(function(handle) -- callback function for storing the new password in the database if (handle) then -- this is only valid if you have the user request password recovery from ingame triggerClientEvent(player, "passwordTutorial:passwordRecoverySuccess") -- inform the user that registration was successful else -- this is only valid if you have the user request password recovery from ingame triggerClientEvent(player, "passwordTutorial:passwordRecoveryFailed") end end,mysqlHandle, "UPDATE user_data SET password = ? WHERE recovery_token = ?", username, recoveryToken) end) end end, "SELECT * FROM users WHERE recovery_token = ?", recoveryToken) end Besides changing the password, it's important you also delete any access tokens that user might have if you're using remember me functionality. It is also good practice to make recovery tokens expiry after a certain amount of times, and not allow a recovery token to be created whilst one is already in prgoress. This prevents a user from sending a large number of emails from your service. How to migrate from an older hashing algorithm, to a newer one Maybe after reading this topic you realise that your password security is not what it should be. So you want to change your old password hashing / validation logic to the ones explained in this topic. And due to the nature that hashes can not be "unhashed", you can't simply migrate your passwords over. So in order to migrate the passwords what you have to do is when a user logs in, first validate their password with the old hashing algorithm. If this matches, then hash (and salt) it with your new hashing algorithm and save it in your database. Make sure to delete the old password otherwise your password security is not any better than before. Using a password policy Passwords policies are important to prevent your users from picking a password that is too easily cracked / brute forced. Many password policies come in the form of "Must have at least one capital letter, one digit and one number". But that discards that fact that the best way to make your password more difficult to crack, is making your password longer. So in the code snippet below is a function that measures the 'search space' of a password. The search space of a password is the amount of possible passwords there are with a certain combination of characters. In order to use this, you would have to set a minimum password search space when a user registers for an account. This minimum is up for you to set, but be reasonable, you shouldn't expect a user's password to be impossible to remember / create. I recomend playing with the function a bit to see what values you get out of it, and pick something you believe is sensible. function getPasswordSearchSpace(password) local lowerCase = password:find("%l") and 26 or 0 local upperCase = password:find("%u") and 26 or 0 local digits = password:find("%d") and 10 or 0 local symbols = password:find("%W") and 32 or 0 local length = password:len() return (lowerCase + upperCase + digits + symbols) ^ length end -- The below function calls are to indicate the difference in search space for a set of passwords print(getPasswordSearchSpace("a")) print(getPasswordSearchSpace("abc")) print(getPasswordSearchSpace("Abc")) print(getPasswordSearchSpace("Ab!")) print(getPasswordSearchSpace("Ab!0")) print(getPasswordSearchSpace("Mu#9A0h.")) print(getPasswordSearchSpace("This is a demonstration of how easy an incredibly strong password is to remember")) How to handle database leaks If you have reason to believe that your database has been leaked or otherwise compromised, it is important that your first course of action is removing any access tokens stored in your database. Once you have done that you have to inform your users. Whilst when properly hashed and salted it's extremely difficult / time consuming to find out a user's password it is still a possibilty. So you should inform your users of the breach, tell them that their passwords were properly hashed, and they do not need to fear for their passwords immediately. However you should suggest to your users that they change their password either way, just in case. What even is hashing and salting? Hashing has been brought up several times in this tutorial, whilst you do not need to know what it is / does, you might be interested in knowing regardless. I won't be going too far in depth as I simply do not have the knowledge, but the basic idea of hashing is this: When you hash anything, you turn it into a string of characters (or other value) that has no relation to the original input, other than when you hash the original input again, it will always generate the same hash. For example, when you hash the stirng 'banana' using the sha512 hashing algorithm, it will always yield the output: "F8E3183D38E6C51889582CB260AB825252F395B4AC8FB0E6B13E9A71F7C10A80D5301E4A949F2783CB0C20205F1D850F87045F4420AD2271C8FD5F0CD8944BE3" Now hashing can not be reverted, you can not "unhash" a hash, so in order to verify someone's password you hash it again, and see if the two hashes are the exact same. Now this is great, passwords are safely stored. However there is still more to do, salting. Salting is adding some random data to your password prior to hashing it. This prevents when two users (on the same service, or on others) have the same password, that their hashes are also the same. Meaning if one password is compromised, the other password is not. It is important that a salt is random for every user in your application, not one salt for your entire application. Now you might think we didn't do any salting in the code / tutorial above. This is not true, we just didn't do it ourselves. MTA's passwordHash function actually hashes the passwords and salts it, this salt is then stored in the output hash it self, just before the actual password hash. In the case of bcrypt it actually stores a little bit more info in the resulting hash, but you need not worry about that.1 point
-
Help MTA by finding security flaws and working cheats so we can fix them. Vulnerabilities from resources: * €100 - Run arbitrary x86 code in MTA * €50 - Ability to run a compiled script that has not been compiled at https://luac.multitheftauto.com/ (or otherwise authorized by MTA) * €50 - Read directories outside of MTA install directory * €Ask - Other vulnerability you may have found Client cheats: * €30 - Working cheat engine variant * €30 - Other working cheats * €15 - Exploiting (previously unknown) bugs or glitches * €5 - Using a program to gain unfair advantage MTA web sites: * €50 - Serious security breach * €30 - Small security breach * €15 - XSS with exploit potential * €5 - XSS without exploit potential * €Ask - Other vulnerability you may have found Terms: 1) Game vulnerability/cheat must work on latest 1.5 nightly, with all AC detections enabled. 2) Submit your vulnerability/cheat by creating a topic in the Private Bugs board. 3) Only the first person to submit any particular vulnerability/cheat will get the bounty. 4) We reserve the right to change terms in case of abuse or other similar reasons. 5) We only accept PayPal for bounty payments. P.S. The undetectable MTA cheats from BoxyHaxSamp (multihack nbvf, Aim bot, Change Serial) are all scams, so please don't bother reporting them. If you are wondering why MTA pays security researchers/ethical hackers: Note: the MTA AC team uses "method" in 1 breath with "vulnerability" and "technique" MTA has a security-oriented anti cheat that doesn't work by signatures of individual cheats, but patches the underlying method (then considered a vulnerability) used to get cheating functionality. It's complicated to explain and would be an essay, but we summarized it in the below spoiler. Open it to read, especially if you plan to try and hack MTA for the bug bounty program1 point
-
السلام عليكم (المود ما عليه حقوق غير داخل ملفات السكربت الرجاء عدم تغيرها) اليوم انتهيت من مود ممكن فكرته تكون جديدة ويا رب يفيدكم المود عبارة عن لوحة تفتح بامر من اف 8 علي حسب السريال طبعا بتحط سيريالك في ملف VS.Lua عشان تقدر تفتح اللوحة من ذي اللوحة بتقدر تسوي ماركر في الاحداثيات الي تبيها وكمان تعطيها اسم وتقدر تضيف داخلها سيارات علي حسب الايدي ولما يدخل الاعب الماركر تطلعله لوحة يقدر منها يرسبن السيارات الي حطيتها داخل الماركر وتقدر : تحذف الماركر , تعدل علي اسمها , تعدل علي احداثياتها وطبعا الماركرات الي بتسويها بتتحفظ في داتا بيز خاصة لما تطفي المود بعض الصور للتوضيح نيجي للتحميل Vehicle Markers System انشاء الله بسوي تحديثات للمود وبضيف له خواص اكتر لو الفكرة عجبتكم ولقيت عليها اقبال ولو في اي بقات او خطاء يا ريت تنبهوني شكرا1 point
-
sim vc precisa usar um arquivo html, dai adicione esse arquivo no meta.xml do seu resource, depois depende do que vc quer adicionar na hud, por exemplo pra mostrar a vida com um numero de 0 a 100 ou uma barra, vc precisa enviar pro arquivo html essa informação pra dai mostrar na tela: https://wiki.multitheftauto.com/wiki/ExecuteBrowserJavascript veja o exemplo desse link ta praticamente pronto, só substitua ali por https://wiki.multitheftauto.com/wiki/GetElementHealth pra mostrar a vida, depois disso é só seguir o mesmo padrão do exemplo pra outras coisas como colete, arma etc. e pra montar o arquivo html se não tiver experiência, use um editor online de html ou ja baixe um pronto pra pegar pratica1 point
-
tem algumas opções pra fazer isso, primeiro escolher qual vai ser o tipo de programação do visual: cegui: é o padrão de menus do mta, vc encontra os métodos em "gui" na parte client da wiki. Cef (https://wiki.multitheftauto.com/wiki/CEF_Tutorial) é feito em html juntamente com css e dependendo javascript tbm, cef da oportunidade pra um visual mais interessante. Dx é feito com os métodos do próprio mta, exemplo: dxDrawImage e dxDrawText e os outros métodos drawing da wiki client depois de feito o visual, use https://wiki.multitheftauto.com/wiki/AddAccount e https://wiki.multitheftauto.com/wiki/LogIn veja os exemplos da wiki e adapte pra receber o texto do seu painel de login, os dados ficam salvos no arquivo do mta internal.db, se tiver dificuldade baixe algum painel de login em resources do mta pra ter uma ideia de como fazer tbm tem login/criação de conta por mysql, mas esse é bem complicado de fazer pra quem ta começando, requer programas externos etc, mesmo assim se quiser tentar, procure por xampp (exemplo) e https://wiki.multitheftauto.com/wiki/DbConnect e os outros métodos Db do mta.1 point
-
o setClipBoard é client-side, e ele só aceita string(texto). Tente: function ClicarPosicao(button, state) if (button == "left") then local x,y,z = getElementPosition(localPlayer) setClipboard(x..", "..y..", "..z) end end client-side1 point
-
1 point
-
@IIYAMA will you make a simple example as I don't really understand the idea, thank you.1 point
-
Hello. You can use the function engineReplaceModel for replacing an existing object ID with your custom object. Below is an example script which I personally use on my local development server. col = engineLoadCOL ("9504.col") engineReplaceCOL (col, 9504) txd = engineLoadTXD ("9504.txd") engineImportTXD (txd, 9504) dff = engineLoadDFF ("9504.dff") engineReplaceModel (dff,9504,true) ^file is "replace.Lua" The ,true enables alpha transparency. If your model doesn't use alpha you should not have to include it. <meta> <info type="misc" name="models" author="yourname" description="custom models for my server" version="1.5" /> <file src="9504.col" /> <file src="9504.txd" /> <file src="9504.dff" /> <script type="client" src="replace.Lua" /> </meta> ^file is "meta.xml" Simply create those 2 resource files in your resource folder and export the dff, txd, col models there.1 point
-
1 point
-
1 point
-
السلام عليكم اليوم رجعتلكم بمود جديد لسيرفرات الزومبي وعارضه للبيع الي هو مود Mystery Box من كود بلاك اوبس زومبي ولاكن انا سويته ل MTA وسويتله تصميم بالثري دي ماكس من الصفر وحابب ابيعه فيديو للمود : للبيع بـ $10 الي يبي يشتريه يتواصل معي بالخاص1 point
-
1 point
-
@Einheit-101 If we keep looping out of it and only talk about indexing. This below is just an assumption: If this is the userdata key: (which is at the very end just a complex and unique identifier.) "userdata-324ftfdbgfd" And this is the data: table = { ["userdata-424ftfsdgsf"] = true, ["userdata-3sd3524ftfd"] = true, ["userdata-325524ftfdb"] = true, ["userdata-324ftfdbgfd"] = true } Depending on which algorithm is used, the search time variates. (algorithm < which I have no knowledge of) But if I would program this search, I might do it like this in my first try: I know already the type, so my start would be: "userdata-" >>> userdata-424ftfsdgsf userdata-3sd3524ftfd userdata-325524ftfdb userdata-324ftfdbgfd Collect all items with userdata. steps * items >>> userdata-424ftfsdgsf userdata-3sd3524ftfd userdata-325524ftfdb userdata-324ftfdbgfd print(string.byte("3")) -- 51 + update position * 4 + 4 steps >>> userdata-3sd3524ftfd userdata-325524ftfdb userdata-324ftfdbgfd print(string.byte("s")) -- 115 print(string.byte("2")) -- 50 + update position * 3 + 3 steps >>> print(string.byte("4")) -- 52 userdata-325524ftfdb userdata-324ftfdbgfd < found item in table + update position * 2 + 2 steps Lua would probably be better in this then I do. But this has multiple search steps in it, no matter what kind of algorithm you use. table = { true, -- 1 true, -- 2 true, -- 3 true -- 4 } table = { [1] = true, [2] = true, [3] = true, [4] = true } Finding the index in this kind of table should be technically be faster based on two ways. Position of the characters do not matter. It is a single value, the cpu knows very well how to work with that. As with user-data's/strings, not only the position matters, the value is also different: print(string.byte("a")) -- 97 Much complexer values X position. Everything is already placed in order if you keep the table as an clean array. Just as with cleaning your room. After the cleaning, you do not have to look everywhere in your room. You more or less know where to find what and how many things you have of it. Searching for item 4? no, no, no, yes (4 steps) Note: looping to find an item VS using a custom key to find an item is a different subject. If somebody knows how this really works, then that would be nice fun facts.1 point
-
Some crashes in 32 bit Windows are caused by MTA running out of address space. The best solution is to use 64 bit Windows. For 32 bit Windows, these MTA settings may help a little: 1) Settings->Advanced->Fast CJ clothes loading->Off 2) Settings->Advanced->Streaming memory->Min 3) Remove all GTA:SA graphic mods (GTA:SA reinstall is ideal) Or, you could try enabling the 3GB switch in 32 bit Windows Details at this link In summary, for 32 bit Windows 7,8,10: 1) Find C:\Windows\system32\cmd.exe in Windows Explrorer 2) Right click on cmd.exe and select 'Run as Administrator' 3) In the black box enter this command: bcdedit /set IncreaseUserVa 3072 4) Press return 5) Restart computer 6) Pray1 point
-
I would expect that exporting methods for accessing a table would be more expensive than using un-synced element data. Calling methods between resources is a relatively expensive thing to do. setElementData and getElementData are great for syncing little bits of data easily. Unsynced, they're also a good way to share data between resources. If you don't care about doing either of those things, then the method described in the original post is obviously the best way to go - you're keeping your data inside the LUA virtual machine, which is much faster. Overusing synced element data - when you don't actually want to sync that data - is actually going to have quite a bit more of an impact than the original post states as it'll increase the amount of data that has to be sent (increasing bandwidth usage), increase the load on the clients and increase the load on the server (as some of the networking will be asynchronous).1 point
-
Still, your "tutorial" is a bit un-explained, you could explain it a bit more, so these who don't know can understand it.0 points