• Announcements

    • jhxp

      Forums are online again after a maintenance.   18/03/17

      MTA Forums maintenance is completed, although some automatic time-heavy tasks are still in process and will be finished eventually in background. Expect some features such as Forum Search to not display all results until all processes are finished. Please let us know if you spot a forum feature that worked correctly before the maintenance but does not work anymore now. Thanks. --MTA Team
    • jhxp

      Multi Theft Auto: San Andreas 1.5.4 is out!   21/04/17

      Click the link in the announcement for more details.  

Mr_Moose

Members
  • Content count

    872
  • Joined

  • Last visited

  • Days Won

    1

Mr_Moose last won the day on November 5 2016

Mr_Moose had the most liked content!

Community Reputation

38 Good

4 Followers

About Mr_Moose

  • Rank
    Road Dawg
  • Birthday 26/10/93

Details

  • Gang
    RageQuit community
  • Location
    RageQuit office
  • Occupation
    Software developer
  • Interests
    Programming, Web design, building and running servers using lightweight Linux distrubutions.

Recent Profile Visitors

876 profile views
  1. About the project GTW-RPG is one of the oldest open source RPG game modes for MTA, initially launched in year 2012 and currently at version 3.0. Right now we're building v4.0 which provides a lot of new features, including a project wide system for language translations. Now this job is easy script wise but requires a high amount of time to make sure everything is correct which is why we've decided to spend 0.1 BTC (~$115) to finally fix the translations. About the job The job includes, not only the actual translations but most important the conversation from the current system in where all text is hard coded into the files to a table with a strict structure holding ID's and corresponding text in multiple languages (organized by language) which is then dynamically collected from the files itself. GTW-RPG has 45 resources in the affected folder and on average 40 static strings in each resource that needs to be converted. Due to the open source nature of the project we'll pay per resource (even at string level) so that multiple users can contribute and still get their fair share of the money listed above. How to participate Simply fork the GTW-RPG v4.0 development branch, implement the new language system (or add translations to already existing implementations) then do a push to the project, if approved (yes there are some conditions, see below for more details) we'll ask for a BTC address via Github to where we can send your payment within 48 hours. How o implement the new language system: This is a detailed description of the job, step by step: Add the file lang.lua to the resource if it's not there, it should have the same structure as this example: Add an entry for lang.lua in meta.xml right below the info line, like this: <info author="GTWGames" version="98" name="GTWaccounts" decription="Account system with GTW GUI" type="script" /> <!-- Language support: must be located at the top --> <script src="lang.lua" type="shared" /> Localize all static string outputs in each file of the resource you're dealing with, GUI elements(), outputChatBox(), exports.GTWtopbar:dm() etc and replace them with this line: lang_txt[getElementData(source, "GTWcore.language") or r_lang]["msg_CHANGE_THIS_TO_IDENTIFIER"] * GTWcore.language holds a language value like: en_US in standard ISO format, this is used to identify the language in the file lang.lua. r_lang holds the default server language set in GTWcore and last but not least, the value msg_CHANGE_THIS_TO_IDENTIFIER must be an identifier for the string to load at the specific position in the code, change this to a non conflicting relevant value and make sure it's the same for all languages, i.e: -- Language text storage for this resource lang_txt = { -- English/Simplified English ["en_US"] = { ["msg_welcome"] = "This is a welcome message in English", }, -- English/English ["en_UK"] = { ["msg_welcome"] = "This is a welcome message in Brittish English", }, } Test with /debugscript 3 and look for error in server log. Any syntax errors or issues with the structure will lead to a rejection of your pull request. Please note that we do accept not fully accurate translations, minor spelling errors etc but issues with the code structure or introduced errors is strictly forbidden. The job is available from this exact moment and forth as long there is money left, I'll keep this topic updated after each approved contribution. Payouts are made with Bitcoins only and will be listed here for maximum transparency and lowest possible fees. Requirements Your work will be open source and a part of the GTW-RPG project on Github Your push must be to the v4.0-development branch The code structure must be strictly according to specification, tested and working, see GTWantispam for an example of a finished conversation The job must be 100% finished for a resource in order for a push to be approved, and for you to be paid A finished conversation of a resource with static strings must contain all current English translations You should have decent knowledge in Lua and Github and have a working BTC wallet The commit message should be: misc: language update for NAME_OF_RESOURCE The commit must not contain anything outside of specification If you're interested, start a topic in the issues page: https://github.com/404rq/GTW-RPG/issues and let me know which resources you plan to work on so that we don't get any duplicates.
  2. It's probably best to ask the devs how objects actually are loaded internally, but I'm guessing it's all based on the already existing systems in GTA sa. No matter if you're using custom objects or built in objects the loading time should be equal. So to figure out why .lua maps would be slower than .map maps (which does seems to be the case when loading maps with over 1000 objects or so). I've had a deeper look on the code itself to see what's differ. This line here: <object id="object (a51_jetdoor) (1)" breakable="true" interior="0" collisions="true" alpha="255" model="3095" doublesided="true" scale="1" dimension="0" posX="2522.3999" posY="-1273.19995" posZ="32.9" rotX="0" rotY="270" rotZ="359.75"></object> Corresponds to this line in Lua code: {3095,2522.3999,-1273.19995,32.9,0,270,359.75,1,0,0,255,true,true,true} Note that the first line in the Lua code is the model number and not the ID from the map file saying "object (a51_jetdoor) (1)". Now that wouldn't be there if it wasn't used for something right? It's possible that MTA when loading a .map file into memory process the data within by sorting, hashing or indexing in a way that makes it faster to find and load a specific object during stream in. While in the converted Lua code you need to loop through the whole table in order to find the specific object you want to load. Obviously that will have a negative impact on the CPU. Luckily since we're dealing with Lua it wouldn't be that hard to process the data differently, like only loading the 1000 objects that is close to a player instead of say 50´000 objects at once, a timer could also be used to load blocks of objects with a few seconds delay between each block. In any case there need to be an index so I'll guess I'll add a few different versions, one with index from 1 to N and one with a hash sum of the ID as index so that all of you with big maps can test the difference in performance, it might even be possible to make the .lua maps load faster than .map maps. The plan is to make all additional features optional and select able, for now I've disabled that line.
  3. Any ideas why .lua maps would be more laggy than regular .map maps? I think that depends on which properties are included in the conversation. This tool tries to detect as many properties as possible unlike the other converters. Thanks to xeon17 I found some more properties that I don't have in my own maps which I initially tested with such as LOD objects, collisions, and radius. Anyway, if the conversation is 100% accurate and the same mechanism is used to render the maps no matter if the source is .lua or .map it shouldn't be any difference. If .lua maps does get more laggy than .map maps then I might as well create a map minimize tools which compress and removes default values.
  4. Download the v4.0-beta branch instead: https://github.com/404rq/GTW-RPG/tree/v4.0-development GTWgui is not used in v3.0 so the function causing that error can safely be removed, mod-shop is a compiled resource which also appears to be abandoned. It's easy to decompile but it it wouldn't be right to do that, which leaves us with no other option than including a different mod system or skip the mod system resource completely.
  5. Back in the past there was a website that could convert maps created with the official in game map editor to a corresponding Lua script. Unfortunately tho that website appears to be down by now, so I've created my own converter using some regular expressions to find properties in a map file and generate a corresponding Lua script. Here's how it looks: So why would you convert your maps to Lua then? well there are many reasons, for instance: Reduce file size, converted Lua files is around 20% the size of it's corresponding map file. Ability to use the local cache, obviously a good thing since players won't have to download your maps every time they connect. Easy to customize, only one line needs to be changed to make all objects double sided, breakable etc.. (optional) Attach a discrete blip to each map object so that players can see where custom mappings exist. Since it uses regular expressions it will try to convert any input, no matter if the syntax is right or wrong. All properties from your map files are supported including, position (x,y,z), rotation (x,y,z), interior, dimension, breakable objects, double sided objects, blips and removal of world objects. The site is encrypted with SSL/TLS and nothing is logged or saved to prevent anyone from stealing your valuable maps. Here's the link to the site: https://lua.wuss.pw/
  6. Alright, the easiest way then would be to use default options and create a new user, make sure you mark the checkbox "create a database with the same name and grant all privileges".
  7. The file db.sql contains all database tables and structures required. Currently these won't be created automatically when using MySQL so you'll have to import that file into your database. What management software are you using? PhpMyAdmin, MySQL workbench, command line or anything else. Methods to setup a database properly varies between these.
  8. Error 10061 is a database error, see this thread for more details: http://stackoverflow.com/questions/119008/cant-connect-to-mysql-server-on-localhost-10061
  9. trailerSyncTimers needs to be initialized, add this: trailerSyncTimers = { } between line 2 and 3 in the first Lua block right before it's being used.
  10. Thanks to lower operational costs we are now lowering our prices, especially on our big plans. Here's some examples: Compute VPS (squirrel) 25 GB SSD, M.2 storage 1 vCore at @2.4GHz (Intel) 1,024 MB RAM Backup & live snapshots (from $0.002/hour) Dedicated low latency DDoS protection (from $0.015/hour) For reasonable $0.009 per hour Compute VPS (hedgehog) 40 GB SSD, M.2 storage 1 vCore at @2.4GHz (Intel) 2,048 MB RAM Backup & live snapshots (from $0.0034/hour) Dedicated low latency DDoS protection (from $0.015/hour) For reasonable $0.017 per hour (save $0.001 per hour compared to squirrel) Compute VPS (rabbit) 60 GB SSD, M.2 storage 2 vCore at @2.4GHz (Intel) 4,096 MB RAM Backup & live snapshots (from $0.0064/hour) Dedicated low latency DDoS protection (from $0.015/hour) For reasonable $0.032 per hour (save $0.004 per hour compared to squirrel) Compute VPS (beaver) 100 GB SSD, M.2 storage 4 vCore at @2.4GHz (Intel) 8,192 MB RAM Backup & live snapshots (from $0.0124/hour) Dedicated low latency DDoS protection (from $0.015/hour) For reasonable $0.062 per hour (save $0.010 per hour compared to squirrel) www.99stack.com
  11. That's strange, I was somehow convinced that all those calculations was the reason for the FPS drops. Have you considered using icon shaders on default blips instead? from what I can see this is some kind resource for managing custom blips, and those are usually pretty resource hungry no matter how you implement them.
  12. Processing blips all over the map is a heavy task, maybe you could process blips within a distance of 180 distance units only (same size as the radar area). Try replacing line 4-5: if (localPlayer ~= getElementAttachedTo(blip) and getElementInterior(localPlayer) == getElementInterior(blip) and getElementDimension(localPlayer) == getElementDimension(blip)) then local blipDistance = getDistanceBetweenPoints2D(blipX, blipY, playerX, playerY) with this: local blipDistance = getDistanceBetweenPoints2D(blipX, blipY, playerX, playerY) if blipDistance < 180 and (localPlayer ~= getElementAttachedTo(blip) and getElementInterior(localPlayer) == getElementInterior(blip) and getElementDimension(localPlayer) == getElementDimension(blip)) then
  13. Well there's a few things you can do to optimize but I can't guarantee that it would make any big difference, but it's still worth a try tho. First of all, in this case you can replace ipairs with pairs which is slightly faster. As long as you don't need to process your blips in a certain order that change should be safe. for _, blip in pairs(getElementsByType('blip', resourceRoot, true)) do The function getElementsByType can also be instructed to look into this resource only (or further down the element tree), in case that you have blips in other resources that shouldn't be processed by this loop. Last but not least since this appears to handle the mini map, you may want to look for streamed in blips only as well (all blips within a 180m radius from a player).
  14. The only reason for choosing 10ms is that you'll get 1 update per frame on a server running at 100FPS. In reality however default FPS rate for a server is 36 (27.77..ms sync interval) and most displays today runs at 60FPS (16.66..ms sync interval). My test server runs at 60FPS so in my case I wouldn't have noticed any difference if I've used say 20ms, other than support for more players and objects before noticing any lag. I did try this with Crystals bot resource however and 50-75 bots works just fine with a 10ms sync interval, first after spawning more than 75 bots and vehicles I did notice some lag. Without testing I think a 100ms sync interval should be sufficient as well. Luckily it's easy to change these values while testing what works best for individual servers.
  15. This is a complex problem but you can make it work almost perfect in most cases. Changing unoccupied_vehicle_sync_interval like 3aGl3 suggested (and the other sync intervals too) is a good start. I'm using 10ms on all of them except lightweight sync where 100ms is used: <!-- Player sync interval. Default: 100 --> <player_sync_interval>10</player_sync_interval> <!-- Lightweight (player) sync interval. Used when players are far apart. Default: 1500 --> <lightweight_sync_interval>100</lightweight_sync_interval> <!-- Camera sync interval. Default: 500 --> <camera_sync_interval>10</camera_sync_interval> <!-- Ped sync interval. Default: 400 --> <ped_sync_interval>10</ped_sync_interval> <!-- Unoccupied_vehicle sync interval. Default: 400 --> <unoccupied_vehicle_sync_interval>10</unoccupied_vehicle_sync_interval> <!-- Keysync mouse rotation sync interval. For limiting key sync packets due to mouse movement. Default: 100 --> <keysync_mouse_sync_interval>10</keysync_mouse_sync_interval> <!-- Keysync analog movement sync interval. For limiting key sync packets due to joystick movement. Default: 100 --> <keysync_analog_sync_interval>10</keysync_analog_sync_interval> This high sync intervals are barely noticeable on the server's CPU usage (Debian 8.7, mtasa-1.5.3), same applies for the network speed (Avg: 30 kBit/s) with 2 players online. Now this isn't everything you need, you would also need something that detects and update differences in positioning. Here's one potential solution, first the server side code which will obtain the current coordinates of a first (and a second trailer attached to an invisible Tanker semi truck attached to the first trailer). Coordinates server side will match the element syncer which should be the player who is driving the big rig. -- Trailer sync function trailerSyncTimers[client] = setTimer(function(client) -- Sync first truck trailer if there is any if vehicles and vehicles[client] and isElement(vehicles[client]) and isElement(getElementData(vehicles[client], "GTWvehicles.attachedTrailer")) then local tx,ty,tz = getElementPosition(getElementData(vehicles[client], "GTWvehicles.attachedTrailer")) local trx,try,trz = getElementRotation(getElementData(vehicles[client], "GTWvehicles.attachedTrailer")) setElementData(getElementData(vehicles[client], "GTWvehicles.attachedTrailer"), "GTWvehicles.trailer.location", toJSON({tx,ty,tz, trx,try,trz})) else killTimer(trailerSyncTimers[client]) end -- Sync first truck trailer if there is any if trailers and trailers[client] and trailers[client][1] and isElement(trailers[client][1]) and isElement(getElementData(trailers[client][1], "GTWvehicles.second_trailer")) then local tx,ty,tz = getElementPosition(getElementData(trailers[client][1], "GTWvehicles.second_trailer")) local trx,try,trz = getElementRotation(getElementData(trailers[client][1], "GTWvehicles.second_trailer")) setElementData(getElementData(trailers[client][1], "GTWvehicles.second_trailer"), "GTWvehicles.trailer.location", toJSON({tx,ty,tz, trx,try,trz})) end end, 250, 0, client) Now on the client side. This is where the coordinates are obtained from the trailer object itself which we set on the server earlier. Here's where we'll look for the big changes like if the trailer is rotated ~45 degrees for a player looking at the rig from the outside while everything looks perfectly normal to the driver. We'll also check for differences in positioning, in this case a distance of 20 units are used while the difference in rotation are π/6 rad (30 degrees) setTimer(function() for k,v in pairs(getElementsByType("vehicle", root, true)) do if getVehicleType(v) == "Trailer" and getElementData(v, "GTWvehicles.trailer.location") and getElementData(v, "GTWvehicles.towingVehicle") and getElementData(v, "GTWvehicles.towingVehicle") ~= getPedOccupiedVehicle(localPlayer) then local data = fromJSON(getElementData(v, "GTWvehicles.trailer.location")) --outputChatBox("Trailer "..k.." is streamed in at position: {"..math.floor(data[1])..", ".. -- math.floor(data[2])..", "..math.floor(data[3]).."} with rotation: {"..math.floor(data[4])..", ".. -- math.floor(data[5])..", "..math.floor(data[6]).."}") local tx,ty,tz = getElementPosition(v) local trx,try,trz = getElementRotation(v) --local sx,sy,sz = getElementVelocity(v) --outputChatBox("Updated trailer position for player: "..getPlayerName(localPlayer)..", Diff: x: ".. -- math.floor(math.abs(tx-data[1])).." sx: ("..math.floor(sx).."), y: ".. -- math.floor(math.abs(ty-data[2])).." sy: ("..math.floor(sy).."), z: ".. -- math.floor(math.abs(tz-data[3])).." sz: ("..math.floor(sz).. -- "), Diff rot: rx: "..math.floor(math.abs(trx-data[4])).. -- ", ry: "..math.floor(math.abs(try-data[5]))..", rz: "..math.floor(math.abs(trz-data[6]))) local t_tower = getElementData(v, "GTWvehicles.towingVehicle") if t_tower and isElement(t_tower) then setTimer(attachTrailerToVehicle, 100, 1, t_tower, v) end local t2_tower = getElementData(t_tower, "GTWvehicles.second_tower") if t2_tower and isElement(t2_tower) then setTimer(attachTrailerToVehicle, 100, 1, t2_tower, v) end if math.abs(tx-data[1]) > 20 or math.abs(ty-data[2]) > 20 or math.abs(tz-data[3]) > 20 or (math.abs(trz-data[6]) > 30 and math.abs(trz-data[6]) < 150) then --outputChatBox("Old pos: "..math.floor(tx)..", "..math.floor(ty)..", "..math.floor(tz)) setElementPosition(v, data[1],data[2],data[3]) setElementRotation(v, data[4],data[5],data[6]) --local tx,ty,tz = getElementPosition(v) --outputChatBox("New pos: "..math.floor(tx)..", "..math.floor(ty)..", "..math.floor(tz)) end end end end, 500, 0) Next thing to do here would be to not allow an element to stream out. This is slightly easier tho since you only need to pass the newly created trailer element (and the semi truck) to the client and then use setElementStreamable client side. Here's an example I've been using to solve this issue with trains carrying 20-30 trailers. Server: triggerClientEvent(root, "GTWvehicles.onStreamOut", root, vehicles[client]) Client: function check_stream_out(c_train) setElementStreamable(c_train, true) end addEvent("GTWvehicles.onStreamOut", true) addEventHandler("GTWvehicles.onStreamOut", root, check_stream_out) This code is a part of https://github.com/404rq/GTW-RPG/tree/v4.0-development and might need a few adjustments to work in your server but it shows the principles. vehicles[client] contains the semi truck and trailers[client][1] contains the first trailer. The trailer can identify it's tower from it's element data set to: GTWvehicles.towingVehicle which is set upon creation. If you're having any trouble, try changing the values in this line, that's pretty much how aggressive the sync will be, if it's too aggressive you may experience other issues: if math.abs(tx-data[1]) > 20 or math.abs(ty-data[2]) > 20 or math.abs(tz-data[3]) > 20 or (math.abs(trz-data[6]) > 30 and math.abs(trz-data[6]) < 150) then I hope this works for you too