Dzsozi (h03) Posted January 21, 2022 Share Posted January 21, 2022 (edited) Hello! I am having a hard time solving this problem, I can't seem to find a solution for it so I came here to ask. First of all, let me provide you with a video of the problem. As you can see, I am working on vehicle model lights, and I would like to make indicators for a vehicle as well as the other lights, but don't mind about them, only the indicators are being a problem for me right now. At the beginning of the video, I turned on the left side, then turned on right side as well, representing a hazard blinker. For the first few blinks they are in sync, but after I alt+tab and use some CPU needy program for example 3ds max, the blinkers go out of sync and each blink on their own. Now my guess is, since I am the one running the server from my PC, and I am running MTA and other programs as well while developing, it of course uses my CPU, so when I alt+tab out of MTA, getTickCount() returns a slightly different value each time, I think that's why it goes out of sync. Just when I started the recording it went out of sync as well, I guess because of heavy CPU usage. My question is, how can I solve a problem like this, is there any way to work around it? I am using a looped timer every 100 ms to check updates on server side, inside that timer I use getTickCount to measure the time past between blinks. Here is my server side code of the timer check part: setTimer(function() for _,vehicle in pairs(getElementsByType('vehicle')) do if getElementSyncer(vehicle) then local lightsData = vehicle:getData("lights") if lightsData then for light, data in pairs(lightsData) do if vehicle.controller then if string.find(light, "brake") then if data.state ~= isVehicleBraking(vehicle) then toggleVehicleLight(vehicle, light, not data.state, false, false, data.broken, data.tag) end end if vehicle.engineState then if string.find(light, "reverse") then if data.state ~= (isVehicleReversing(vehicle) and getControlState(vehicle.controller, "brake_reverse")) then toggleVehicleLight(vehicle, light, not data.state, false, false, data.broken, data.tag) end end end end if string.find(light, "tail") then local tailLightsOn = vehicle.overrideLights == 2 and true or false if data.state ~= tailLightsOn then toggleVehicleLight(vehicle, light, not data.state, false, false, data.broken, data.tag) end end if string.find(light, "fog") then local fogLightsOn = vehicle:getData("vehicle").lights == 2 and true or false if data.state ~= fogLightsOn then toggleVehicleLight(vehicle, light, not data.state, false, false, data.broken, data.tag) end end if tonumber(data.blinkFreq) and VEHICLE_BLINK_TICK[vehicle] and VEHICLE_BLINK_TICK[vehicle][light] and getTickCount() - VEHICLE_BLINK_TICK[vehicle][light].tick > data.blinkFreq then --if data.blink then --VEHICLE_BLINK_TICK[vehicle][light].tick = getTickCount() if data.tag == AEL_TAG then --if not VEHICLE_BLINK_TICK[vehicle][light].step or VEHICLE_BLINK_TICK[vehicle][light].step >= #strobes[vehicle.model][1] then -- VEHICLE_BLINK_TICK[vehicle][light].step = 1 --end if VEHICLE_BLINK_TICK[vehicle][light].step < #strobes[vehicle.model][1] then VEHICLE_BLINK_TICK[vehicle][light].step = VEHICLE_BLINK_TICK[vehicle][light].step + 1 else VEHICLE_BLINK_TICK[vehicle][light].step = 1 end for lightIndex, state in ipairs(strobes[vehicle.model][1][VEHICLE_BLINK_TICK[vehicle][light].step].lights) do if string.find(light, lightIndex) then VEHICLE_BLINK_TICK[vehicle][light].tick = getTickCount() toggleVehicleLight(vehicle, light, (not data.blink) and state or false, data.blink, strobes[vehicle.model][1][VEHICLE_BLINK_TICK[vehicle][light].step].length, data.broken, data.tag) end end else -- HERE IS THE PART THAT IS RESPONSIBLE FOR THE INDICATORS if data.blink then VEHICLE_BLINK_TICK[vehicle][light].tick = getTickCount() toggleVehicleLight(vehicle, light, not data.state, data.blink, data.blinkFreq, data.broken, data.tag) end end --end end end end end end end, 100, 0) Also, I am curious whether I should create this server side or client side. For the first time I did it on client side, but it went out of sync even more and quicker. Thank you for your help! Edited January 21, 2022 by Dzsozi (h03) Link to comment
Moderators IIYAMA Posted January 21, 2022 Moderators Share Posted January 21, 2022 6 hours ago, Dzsozi (h03) said: Also, I am curious whether I should create this server side or client side. For the first time I did it on client side, but it went out of sync even more and quicker. Doing it serverside would be a waste of your network usage. How about you use server time to solve your problem? local duration = 1000 local status = (serverTime % duration) > (duration / 2) Link to comment
Dzsozi (h03) Posted January 21, 2022 Author Share Posted January 21, 2022 So, should I implement your servertimesync resource to my core resources, and make the light checks on client side, using exported servertimesync function? Link to comment
Moderators IIYAMA Posted January 21, 2022 Moderators Share Posted January 21, 2022 7 minutes ago, Dzsozi (h03) said: So, should I implement your servertimesync resource to my core resources, and make the light checks on client side, using exported servertimesync function? You can do that, but you can also keep it a separated resource and include it in your core meta.xml. That way you can use it easier in multiple application-suited-resources. Link to comment
Dzsozi (h03) Posted January 21, 2022 Author Share Posted January 21, 2022 But for sure I have to rework it on client side to make the checks, right? Would it be more efficient? Link to comment
Moderators IIYAMA Posted January 21, 2022 Moderators Share Posted January 21, 2022 19 minutes ago, Dzsozi (h03) said: But for sure I have to rework it on client side to make the checks, right? Would it be more efficient? For the overall synchronisation experience of your server, yes. Take a look at your network usage with and without the blink resource running. You know how to do that right? /shownetstat https://wiki.multitheftauto.com/wiki/Client_Commands#shownetstat 1 Link to comment
The_GTA Posted January 21, 2022 Share Posted January 21, 2022 To answer the original question, you should store the current time in a variable so that it is synchronized for the entire timer callback. setTimer(function() local now = getTickCount() for _,vehicle in pairs(getElementsByType('vehicle')) do (...) Then you should use the "now" variable in the following operations instead of the direct call to "getTickCount", for example... end if tonumber(data.blinkFreq) and VEHICLE_BLINK_TICK[vehicle] and VEHICLE_BLINK_TICK[vehicle][light] and now - VEHICLE_BLINK_TICK[vehicle][light].tick > data.blinkFreq then --if data.blink then The reason for that is that the getTickCount function does fetch the current time point and you seem to be oblivious to the fact that execution of scripts does take time aswell. Please be mindful of this fact. 1 Link to comment
Dzsozi (h03) Posted January 22, 2022 Author Share Posted January 22, 2022 9 hours ago, The_GTA said: To answer the original question, you should store the current time in a variable so that it is synchronized for the entire timer callback. setTimer(function() local now = getTickCount() for _,vehicle in pairs(getElementsByType('vehicle')) do (...) Then you should use the "now" variable in the following operations instead of the direct call to "getTickCount", for example... end if tonumber(data.blinkFreq) and VEHICLE_BLINK_TICK[vehicle] and VEHICLE_BLINK_TICK[vehicle][light] and now - VEHICLE_BLINK_TICK[vehicle][light].tick > data.blinkFreq then --if data.blink then The reason for that is that the getTickCount function does fetch the current time point and you seem to be oblivious to the fact that execution of scripts does take time aswell. Please be mindful of this fact. Thank you so much, this seems to fix the problem. You are absolutely right, it went by me that I should use a variable for the current tick as well. This is what I was looking for, thank you for the help guys. I'm sorry but I don't really want to make this resource depend on another one. However, I will consider making it client side, since as IIYAMA mentioned, /shownetstat gets a little bit higher values, I haven't really used this command before for debugging, so I don't really understand it yet, fortunately packet loss doesn't happen. Thank you for educating me again, have a nice day! 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