• 🏆 Texturing Contest #33 is OPEN! Contestants must re-texture a SD unit model found in-game (Warcraft 3 Classic), recreating the unit into a peaceful NPC version. 🔗Click here to enter!
  • It's time for the first HD Modeling Contest of 2024. Join the theme discussion for Hive's HD Modeling Contest #6! Click here to post your idea!

Desync Debugging

Status
Not open for further replies.
Level 4
Joined
Mar 8, 2006
Messages
27
Is there any effective way to debug desyncs? Like having a breakpoint before the desync or saved logs or something?

I have a fairly non-deterministic and unusual desync, where myself and a friend of mine (and my other account on a VM) never desync (or at least very rarely), but everyone else in the game tends to nearly immediately after the map loads (tested about 3 times).

I've tried removing various parts of the code and trying to narrow down the cause, and tried bisecting it to a specific version via source control but neither have proven to be very successful due to the random nature of the desync. I suspect versions which we deem to be "good" and don't desync were actually bad, just didn't hit whatever weird edge case causes the desync, which leads me even further off track.

Does anyone have any advice around this? I've written everything in lua if it helps. How do people usually go about solving these kind of random, inconsistent desyncs?

Is it possible that people with slower PCs are not able to keep up with the tight loops running on the host (I have a couple of 0.0078125s loops) and therefore fall behind in execution and desync? If this is the case, how would anyone guarantee people not to fall behind? I'd imagine WC3 would somehow ensure each players loops are synced? Maybe slowing down the fastest loop to match the slowest player?

How do triggers actually get synced between players? Is order guaranteed (I expect it has to be, or else we'd see many more desyncs across the board)? Are timers synced & guaranteed to be the same?

For example, if I have a trigger that when a player presses "Q", I create a unit and start a timer for 5 sec, but if the timer has any duration left I don't create the unit, is there a race condition where one player can enter the loop and think the timer is not finished, but another player can enter and think the timer is finished?
 
It is always difficult to debug such issues. Here are all the causes I know for desync.

I am in the same situation as you, trying to debug my desync issues. I think I'll add hooks (=user callbacks on-before a native function is executed):

JASS:
hook <native name> <my log function name>
Where my log function must have the same arguments and return type than the native.

And each time I'll add logs only for player whose name is "Ricola3D". I started it as below. To be continued...

JASS:
library DesyncCheck
    globals
        public integer getLocalPlayerExecCount = 0
        public integer getLocationZExecCount = 0
        public integer smartCameraPanBJExecCount = 0
        public integer getPlayerSlotStateExecCount = 0
        public integer getPlayerControllerExecCount = 0
    endglobals

    private function DebugUserFilter takes nothing returns boolean
        // Filter only players whose user name is a developer
        return ( GetPlayerName(GetEnumPlayer()) == "Ricola3D" )
    endfunction

    private function DebugLog takes string message returns nothing
        local force debugForce = GetPlayersMatching(Condition(function DebugUserFilter))
        call DisplayTimedTextToForce( debugForce, 10.00, message )
        call DestroyForce(debugForce)
        set debugForce = null
    endfunction

    public function onGetLocalPlayer takes nothing returns nothing
        set getLocalPlayerExecCount = getLocalPlayerExecCount + 1
        call DebugLog("getLocalPlayer call number "+I2S(getLocalPlayerExecCount))
    endfunction

    public function onGetLocationZ takes location whichLocation returns nothing
        set getLocationZExecCount = getLocationZExecCount + 1
        call DebugLog("getLocationZ call number "+I2S(getLocationZExecCount))
    endfunction

    public function onSmartCameraPanBJ takes player whichPlayer, location loc, real duration returns nothing
        set smartCameraPanBJExecCount = smartCameraPanBJExecCount + 1
        call DebugLog("SmartCameraPanBJ call number "+I2S(smartCameraPanBJExecCount))
    endfunction

    public function onGetPlayerSlotState takes player whichPlayer returns playerslotstate
        set getPlayerSlotStateExecCount = getPlayerSlotStateExecCount + 1
        call DebugLog("GetPlayerSlotState call number "+I2S(getPlayerSlotStateExecCount))
        return PLAYER_SLOT_STATE_EMPTY
    endfunction

    public function onGetPlayerController takes player whichPlayer returns mapcontrol
        set getPlayerControllerExecCount = getPlayerControllerExecCount + 1
        call DebugLog("GetPlayerController call number "+I2S(getPlayerControllerExecCount))
        return MAP_CONTROL_NONE
    endfunction

    hook GetLocalPlayer onGetLocalPlayer
    hook GetLocationZ onGetLocationZ
    hook SmartCameraPanBJ onSmartCameraPanBJ
    hook GetPlayerSlotState onGetPlayerSlotState
    hook GetPlayerController onGetPlayerController
endlibrary
 
Level 4
Joined
Mar 8, 2006
Messages
27
Thanks for the list - I was aware of most of those things and don't see anything obvious that I've hit (except maybe unit selection, which I'll test).

Just displaying some text won't really work though, once you desync you immediately disconnect and so you won't be able to see it in time. Unless those logs are saved somewhere on disk each game?
 
Just displaying some text won't really work though, once you desync you immediately disconnect and so you won't be able to see it in time. Unless those logs are saved somewhere on disk each game?

I think there is a IO File system made by Nestharus years ago, that can save & read local files, but I never tried it.
Printed text will be visible from the players that are not kicked by the desync, I'm counting of that to the last functions executed before someone desyncs^^
 
Status
Not open for further replies.
Top