-
Posts
140 -
Joined
-
Last visited
Everything posted by AlexTMjugador
-
Firstly, you are asking for support for a resource you shouldn't be using or modifying because it is made by a server which doesn't want you to do that. Secondly, I think this is the wrong section to ask for help in scripting. We have a Scripting subforum. Thirdly, are you complaining about FFS banning you? Providing that you are stealing their scripts, it shouldn't be a surprise to you... Besides that, MTA will not unban you from that server because that is entirely your fault for doing naughty things with their code, and server owners are free to ban everyone they want to even if it is not fair. So I don't think that we are going to help you with that, sorry. Next time use resources you can freely download or, better yet, script your own
-
You can convert the RGB values to hexadecimal values suitable for that function. Look at the RGBToHex useful function in the Wiki.
-
You have to extract the siteM16 texture from the game files and draw it manually on the screen using the dx... family of functions. However, this doesn't take into account clientside modifications, so you might want to disallow clients which have modified that texture so the effect looks consistent. You can use requestPlayerModInfo and onPlayerModInfo for that.
-
Can't report bugs at mantis
AlexTMjugador replied to ManeXi's topic in Site/Forum/Discord/Mantis/Wiki related
Make sure that you have selected the "New issues" project in the menu which is in the up-right corner of the page. You should be able to report issues without any problem then. -
You can try moving the low LOD object too, instead of making your draw-distance script not work with scripted gates. Or even simpler: attach the low LOD object to the main object, like in the Wiki setLowLODElement example.
-
No tienes por qué usar setTimer para eso. Es más rápido guardar la última vez que alguien ha usado el comando y comprobar si pasaron X segundos desde entonces. local limitarATodos = false -- Si esto es true, el límite se aplicará a todos los jugadores por igual, no de manera individual function obtenerJugadorMasRico ( ) local jugadorMasRico = {} for _, jugador in pairs ( getElementsByType( "player" ) ) do local dinero = getPlayerMoney ( jugador ) if dinero > ( jugadorMasRico.dinero or 0 ) then jugadorMasRico.jugador, jugadorMasRico.dinero = jugador, dinero end end return jugadorMasRico.jugador or false end local ultimaVezLlamado = limitarATodos and -math.huge or {} addCommandHandler ( "elmasrico", function ( jugador ) local ahora, puedeUsarComando = getTickCount ( ) if limitarATodos then -- Comprobar que pasaron 20 segundos desde la última vez que un jugador CUALQUIERA usó el comando puedeUsarComando = ( ahora - ultimaVezLlamado ) >= 20 * 1000 else -- Comprobar que pasaron 20 segundos desde la última vez que ESTE jugador usó el comando puedeUsarComando = ( ahora - ( ultimaVezLlamado[jugador] or -math.huge ) ) >= 20 * 1000 end if not puedeUsarComando then -- Dar error y no continuar si no debería de usar el comando outputChatBox ( "Espera unos segundos antes de volver a usar este comando" ) return end -- Podemos usar el comando, así que guardar el momento en el que lo hemos hecho para comprobar la próxima vez if limitarATodos then ultimaVezLlamado = ahora else ultimaVezLlamado[jugador] = ahora end local jugadorMasRico = obtenerJugadorMasRico ( ) if jugadorMasRico then outputChatBox ( getPlayerName( jugadorMasRico ) .. " es el más rico del servidor" ) else outputChatBox ( "Todos son pobres" ) end end ) if not limitarATodos then addEventHandler ( "onPlayerQuit", root, function ( ) ultimaVezLlamado[source] = nil end ) end Puedes cambiar el valor de la variable limitarATodos para decidir si quieres que el límite se aplique a todos por igual o de manera individual. Si vas a usar este código en el lado del servidor, asegúrate de que sustituyes el evento onPlayerQuit por onClientResourceStop y cambias source por localPlayer en la función.
-
B.L.A.S.T. V5!!! ALL NEW!! ALL GOOD!! ALL SPAM!!
AlexTMjugador replied to Mr.Bill's topic in B.L.A.S.T.
A: A question word Q: To be or not to be? -
Puedes probar a modificar la conducción del Uranus hasta que sea como quieres, usando el recurso hedit.
-
Ese código está mal visualmente, seriamente y operacionalmente. Usa este: function obtenerJugadorMasRico ( ) local jugadorMasRico = {} for _, jugador in pairs ( getElementsByType( "player" ) ) do local dinero = getPlayerMoney ( jugador ) if dinero > ( jugadorMasRico.dinero or 0 ) then jugadorMasRico.jugador, jugadorMasRico.dinero = jugador, dinero end end return jugadorMasRico.jugador or false end addCommandHandler ( "elmasrico", function ( ) local jugadorMasRico = obtenerJugadorMasRico ( ) if jugadorMasRico then outputChatBox ( getPlayerName( jugadorMasRico ) .. " es el más rico del servidor" ) else outputChatBox ( "Todos son pobres" ) end end )
-
Yes, YouTube works fine for me because it uses HTML5 and that is not a problem. But there are some important websites that use Flash to display content and don't have plans of changing very soon (example of big site which still uses Flash Player: ok.ru), so requesting an HTML5 version of the site is not an option. I think this is an actual issue with MTA: SA implementation of CEF, because you said that it couldn't detect Flash in-game but it could in Chrome, which is based on Chromium too. I'm going to report this issue in Mantis to see what's going on. EDIT: you can watch and comment the issue here.
-
Here is the resource. If Flash Player is detected when the resource is started, the test web title will read your currently installed Flash Player version. In my case however, even after installing Flash Player from here, it isn't able to read it. Interestingly, if I open the test.htm file bundled with the resource in my browser (Firefox), it works fine. It uses the SWFObject tool to check the version, in case you are wondering, so if Flash Player is installed there should be no problems.
-
I bump this topic because I experience the same issue. I double checked that I have installed Pepper API Flash Player for Chromium and enabled plugins in the settings, but with no sucess. I can provide a test resource if necessary.
-
No problem You might want to add a MyClass:isInstance method to the class, which you can use like isElement, to check if the table is a valid instance of the class or not, and handle deletion better.
-
The object variable will still be a table after that, but an unuseful one in this case (it doesn't get rendered), and you should avoid doing things with it. The optimal thing to do is nil'ing it after calling the destructor. But sadly, it is not possible to delete the object in its own destructor in pure Lua. You can read more about it in this Stack Overflow question.
-
It is necessary to rethink your code then, as event handlers do not allow to pass some variable to the handler function and onClientRender can't trigger for a specific element. This is the code I came across with. It uses a table to save all the instances of the class, so then the onClientRender event handler can iterate over it and do things. Plus it should be more CPU efficient than adding a handler for every instance. Comments in the code explain what the code does and where. -- Class MT local MyClass = {} MyClass.__index = MyClass MyClass.instances = {} -- Call the constructor when calling the MyClass table itself setmetatable(MyClass, { __call = function (cls, ...) return cls.new(...) end, }) function MyClass.new(init) -- Create new table and let it access our class functions and vars local self = setmetatable({}, MyClass) -- Let the object have a value (it is not saved in the class itself) self.value = init -- Add it into the instances table MyClass.instances[self] = true return self end function MyClass:set_value(newval) -- Delete old entry MyClass.instances[self] = nil -- Set our new value self.value = newval -- Update value in table -- You should do something like this for every value change, so onClientRender gets updated data -- Alternatively, I think that you can use metatables and let them handle this for you, but I think it is too complicated MyClass.instances[self] = true end function MyClass:get_value() return self.value end function MyClass:delete() -- Delete from instance table MyClass.instances[self] = nil -- Delete ourselves self = nil end function drawMyClassInsts() for inst in pairs(MyClass.instances) do -- Whatever you want to do here. To get value: -- value = inst.value end end addEventHandler("onClientRender", root, drawMyClassInsts, true, "low-99")
-
As you may already know, self:draw(...) is syntactic sugar for self.draw(self, ...). But self:draw is a expression to call a function, not to refer to a function itself. So self:draw(...) is, in simple terms, like func(...), but self:draw alone does not refer to func because the function arguments are part of its syntax. Therefore, to refer to a function in a method, you have to use self.draw.
-
Pero eso no implica que funcione de igual manera. Lee el recuadro azul que dice "Note" en el artículo de fetchRemote del wiki. Por el motivo que se explica en ese recuadro debes pedir la canción en el servidor y transferirla al cliente de alguna manera, ya que no puedes descargarla directamente desde el cliente.
-
I'm not a pro C++ developer, but clearly you got some things wrong there. DirectX is nothing more than Microsoft Windows' 3D graphics library, so it is not a language by itself, to start with. GTA V, on the other hand, uses DirectX, not OpenGL (have you ever seen the DirectX version option that GTA V has in its graphics settings?). And I have never heard the words "coordination dll". GTA: SA, GTA IV and GTA V are very different games, and making a mod like MTA: SA work with any of them is a very difficult task, because although MTA tries to build its own engine on top of GTA: SA, it still depends on assembly hooks and memory manipulation of the game itself. And, as you can probably conclude, GTA: SA executable and memory has (almost) nothing in common with GTA IV or GTA V ones. Back to the topic, I think that Lua is fine to use as a MTA: SA scripting language. Sure, it is not the fastest and most known thing out there, but it is designed with embedding in mind, it has a good learning curve, it is well documented, it is powerful and, most importantly, safe. C++, on the other hand, is lower-level, and things like memory manipulation are difficult to sandbox without reducing functionality. So, in the end, C++ doesn't simply cut it.
-
¿Cómo es posible que te "funcione bien" si es un código del lado del cliente y usa fetchRemote con una web ajena al servidor? Has puesto el código mal o el título del tema mal, porque algo falla ahí.
-
Mantis Roadmap says that the planned release date for MTA: SA 1.6 is on January 12th, 2017. On the other hand, MTA: SA 1.5.3 is scheduled for release in June 16th, 2016. Of course, that roadmap isn't always day-accurate, but it gives a good idea of when will be future versions released.
-
The best way to read and process whole files
AlexTMjugador replied to AlexTMjugador's topic in Scripting
Making an useful function which handles all of this seems a good idea to me. However, Lua knows almost nothing of the underlying operating hardware, so it can't measure CPU performance and memory availability without doing some kind of stress testing, which is largely impractical. Anyway, that is not a big problem: you can get total CPU and memory usage on the server, and memory consumption on the client, so you can estimate the most appropiate performance/memory balance. Of course, some manual tweaking may be needed under varying hardware configurations and design aspirations, because it can't account for processes outside MTA: SA, besides other factors. Unless you are planning to use the input of another script or program, or you want your code to be usable by another program with that buffer size, modifying it is not an issue. What's more, this Stack Overflow question about hashing huge files in Python shows that there is no standard buffer size for this: some prefer using a 128 byte buffer, others 8192... So there is no way to always avoid shooting yourself, unless you know what are you working with. I will be thinking about making some kind of function which makes all this file reading and processing mess easy to do, and transparent to the newbie (or not so newbie) scripter -
The best way to read and process whole files
AlexTMjugador replied to AlexTMjugador's topic in Scripting
That Stack Overflow question is an interesting read indeed. According to the answer, the best way to deal with very big files (I would say ~50 MB or more, but of course this can vary according to the situation) is splitting them in chunks. This seems logical, as reading a very big file directly into memory will be very demanding and even impossible: for example, if you have a video file of, let's say, 2 GB, you can't even read it in a machine with less than 2 GB RAM, as virtually there is no space. Paging files and such can help, you may say, but I think you can understand what I mean anyway: it is a lame programming practice to read a very big file into memory directly and hoping that the OS will always be happy with that. In fact, that discussion made me think about the fact that while/repeat loops with fileIsEOF aren't as unuseful as I believed, because they may in fact come in handy when talking about huge files. However, that is how things get done when using C or similar languages designed to be lower-level and allow a great degree of functionality to applications, but that can't exactly be ported to Lua. The famous book Programming in Lua, in its chapter 11, explains how does Lua allocate memory when concatenating strings, putting some code examples of good and bad practices. I think we can extract some conclusions from it, after considering some answers to this topic too: Method 2 alone, with the only intention of reading a whole file into memory and not doing anything more, it is definitely a MUSTN'T. Method 1 is very appropiate, CPU wise, when dealing with small or not-so-big files: memory usage does not go very high (if we are talking about very small files, of a few bytes, it is even lower than with other methods), and the overhead introduced by using tables or buffer strings is nonexistent. When memory starts being a concern (that is, the script is working with big or very big files), performance becomes less important and the script should try to lower or at least not raise its memory usage. We do not want it to crash on systems with low free memory, do we? And now is when I suppose that loops and file read buffers have a reason to be: it is no longer suitable to treat a file as a whole, but as chunks, and buffer strings do that. As I concluded, in Lua is a MUSTN'T using a ever growing buffer string which becomes bigger and bigger with each byte read. But at the same time reading the whole huge file is impractical. What we can do in this situation? Although the previously linked Programming in Lua fragment hints that a more efficient approach is something a bit similar (but conceptually very different) to method 3, the whole file is kept in the memory nevertheless, and this is only a partial solution: it skips most of the garbage collector overhead of string concatenating, but it still looks inefficient when a script only cares about isolated chunks. Well, I think that the answer is in Programming in Lua's 21.2.1 section: read the file in "reasonably large chunks" (more chunk size = more performance, but higher memory usage, because we reduce the number of loop iterations at the cost of memory) and do not care about what is before that chunk. But all this reasoning, from my point of view, doesn't answer the initial question: what is the best way to read and process whole files? There is not an only way that will work just fine for every file. The ideal thing is to switch between various methods on operation, depending on what type of file are you dealing with (is it feasible to process the chunks one by one, or is it needed to store the whole file in memory?) and its size. TL;DR: The best way to read and process a whole file that is small is by reading it directly into a string and doing the desired thing with it. However, when memory usage is a concern and/or the file is big, you may have to use other algorithms which are capable of processing a file in isolated chunks, which sacrifice CPU time in exchange of reasonable memory consumption. If you need to store a whole big file in memory and process it in chunks, which is something I think is not very likely, the best way to go is a buffer stack which manages string concatenation efficiently, which is an operation that, when misused, is a major CPU and memory hog due to garbage collection and Lua itself. NEVER use something like buffer = buffer .. fileRead(file, bufferSize) without any further attention. Of course, if someone finds my conclusions incorrect, please reply to this post and expose the reasons for thinking so Talking to Necktrox now, and after writing this huge text, I think that a better approach for computing a whole file MD5, even if it is big or small, would be to think about a file size "red line" (let's say 1 MB, for example) and change the algorithm according to it. You can see it like an "hybrid approach". If the file is smaller than the limit, reading the file into a string directly is the fastest way to do it, and memory consumption is not a problem because that file will take 1 MB or less in memory. But when the file is bigger, it will take more than 1 MB, so chunk processing is the way to go here. My suggestion on buffer size? The one that keeps memory usage nice and constant, so it would be 1 MB minus the bytes that a MD5 hash occupies. What's more, you can make it fancier, and upper or lower the "red line" depending of the file size and the balance between memory consumption and performance you want. I didn't test what I'm saying though, but to me it seems like a pretty straightforward consequence of what I said. -
The best way to read and process whole files
AlexTMjugador replied to AlexTMjugador's topic in Scripting
Yes, that is what the code does, but it is a bit strange nevertheless. If the file is big, that tiny code will be a CPU and memory hog, and I think that unless you are trying to hash something untrustful securely it is not necessary to hash the file by parts. And by the way, if you need more confidence against hash collisions, you can use the SHA512 algorithm MTA provides. -
The best way to read and process whole files
AlexTMjugador replied to AlexTMjugador's topic in Scripting
I don't know if it's fine to reply a post whose last response was two weeks ago for this, but I found some interesting random code on GitHub which uses method 2 I described to compute the MD5 hash of a whole file. That code was crafted by Necktrox, who by the way is someone who certainly has got some insight of how does MTA: SA work and knows how to program. So I want to repeat the question I came across half month ago: why read a whole file by parts using buffers when the script only cares about the entire file? Perhaps it's because some limitation or bug in fileRead, but even though why not use tables when reading by parts is needed? The results of the benchmark I posted are clear too, and you even can test it for yourself. The community and I would be very grateful if someone finally tells us, like in the topic title, what is the best way to read whole files. Right now it makes nonsense to me to use method 2, really, but when I see good scripters using it there should be a reason... or not? -
Scripts are able to read files by using fileOpen and fileRead functions, and there are mainly three methods to get the whole file contents I can think of: reading all the bytes directly into a string, concatenating an arbitrary number of bytes into a buffer string or concatenating an arbitrary number of bytes into a buffer array. Method 1: reading all the bytes directly into a string local file = fileOpen("file.dat", true) fileContents = fileRead(file, fileGetSize(file)) Method 2: concatenating an arbitrary number of bytes into a buffer string local file = fileOpen("file.dat", true) local buffer = "" -- This will have the whole file while not fileIsEOF(file) do buffer = buffer .. fileRead(file, 500) -- Arbitrary bytes to read go here end Method 3: concatenating an arbitrary number of bytes into a buffer array local file = fileOpen("file.dat", true) local buffer = {} while not fileIsEOF(file) do buffer[#buffer + 1] = fileRead(file, 500) -- Arbitrary bytes to read go here end fileContents = table.concat(buffer) I decided to write a script to test out the performance and memory consumption of these methods under varying conditions of file size and buffer size. You can check out the source code in Pastebin. Below there are the results the script outputted to the server console. 2 KB and 5 MB files, 500 bytes buffer for both 2 KB and 5 MB files, 5.000 bytes buffer for both 2 KB and 5 MB files, 5.000 bytes buffer for the smaller, 500 bytes buffer for the bigger Looking at these results, the best way to read everything from a file to a string is method 1. If reading the whole file in parts is required for some reason, method 3 is the way to go. Obviously, method 2 is definitely not the best way to do it and it should be not used. However, these results bring me some questions about the usefulness of while loops with fileIsEOF: Why are Wiki examples using them to output bytes to the console, when it's admittely better to do not use them if the file is small? Why do even developers encourage to use them too, like in this forum post, when they are a slower and do not provide significant-to-none memory savings? In short: why use while loops with fileIsEOF to read and process whole files?