Rat32 Posted March 12, 2017 Share Posted March 12, 2017 Hello. In one server trailers is fixed, not bugged. In clear MTA trailers is lagged. Anybody have idea to fix them with script? Link to comment
Ayush Rathore Posted March 12, 2017 Share Posted March 12, 2017 37 minutes ago, Tasumi said: Hello. In one server trailers is fixed, not bugged. In clear MTA trailers is lagged. Anybody have idea to fix them with script? well whats the error ? what you mean by lagged? Link to comment
3aGl3 Posted March 12, 2017 Share Posted March 12, 2017 59 minutes ago, Ayush Rathore said: well whats the error ? what you mean by lagged? Trailers are handled as empty vehicles in MTA and are only updated according to unoccupied_vehicle_sync_interval. That causes problems for all other players who see you pull that trailer, while for you it seems fine other players see the trailers correct position only every x ms. One fix would be to change the unoccupied_vehicle_sync_interval setting to a lower value but that will cause heavy server load. There is also a bug on the bugtracker but I can't find it. 1 Link to comment
Ayush Rathore Posted March 12, 2017 Share Posted March 12, 2017 14 minutes ago, 3aGl3 said: Trailers are handled as empty vehicles in MTA and are only updated according to unoccupied_vehicle_sync_interval. That causes problems for all other players who see you pull that trailer, while for you it seems fine other players see the trailers correct position only every x ms. One fix would be to change the unoccupied_vehicle_sync_interval setting to a lower value but that will cause heavy server load. There is also a bug on the bugtracker but I can't find it. may be that server is running on an highly configured vps or host as i only know about unoccupied_vehicle_sync_interval setting and in my opinion that's the only way of achieving it 1 Link to comment
Rat32 Posted March 12, 2017 Author Share Posted March 12, 2017 Ough, still bugged :/. Any idea? Link to comment
Ayush Rathore Posted March 12, 2017 Share Posted March 12, 2017 Well no. may be you should ask more experienced scripters. 1 Link to comment
Mr_Moose Posted March 13, 2017 Share Posted March 13, 2017 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 2 Link to comment
3aGl3 Posted March 13, 2017 Share Posted March 13, 2017 (edited) I don't think setting all sync intervals that low is a good idea if you are expecting more than a few players. It might not be notable with 2 players but it sure will be with more... Not to mention that 10 seems a little low, even the player sync is only 100 by default. Edited March 13, 2017 by 3aGl3 1 Link to comment
Mr_Moose Posted March 13, 2017 Share Posted March 13, 2017 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. 1 Link to comment
Rat32 Posted March 18, 2017 Author Share Posted March 18, 2017 On 13.03.2017 at 13:19, Mr_Moose said: 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 Very thanks. Hmm, your code generating errors, "attempt to index global "trailerSyncTimer" in line 6", I tried to download and modify code from github pasted for you, but still not work. I don't have idea to fix this code. Any ideas/fixes? Link to comment
Mr_Moose Posted March 18, 2017 Share Posted March 18, 2017 trailerSyncTimers needs to be initialized, add this: trailerSyncTimers = { } between line 2 and 3 in the first Lua block right before it's being used. Link to comment
Rat32 Posted March 18, 2017 Author Share Posted March 18, 2017 (edited) -- Trailer sync function trailerSyncTimers[client] = setTimer(function(client) trailerSyncTimers = { } -- 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) Same. I don't want to request you to write script for me, but my ideas ended - sorry. Edited March 18, 2017 by Tasumi Link to comment
Rat32 Posted March 18, 2017 Author Share Posted March 18, 2017 1 hour ago, Mr_Moose said: trailerSyncTimers needs to be initialized, add this: trailerSyncTimers = { } between line 2 and 3 in the first Lua block right before it's being used. Link to comment
NeXuS™ Posted March 18, 2017 Share Posted March 18, 2017 Replace trailerSyncTimers[client] = setTimer(function(client) trailerSyncTimers = { } with trailerSyncTimers = { } trailerSyncTimers[client] = setTimer(function(client) 1 Link to comment
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now