• 🏆 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 - How to reproduce

Status
Not open for further replies.
Hello,

Players on Battlenet experience desync with my map (generaly they are 4-8 players).
I also reproduced it on Battlenet games with other live players.

However I don't have other players to monopolize to test over and over. I need a way to reproduce and test myself, alone. I discovered that with Warcraft 1.31 I can launch many games at once and play my map with them on local network. I tried but could not reproduce so far with 3 local game instances.

So a few questions because so far I can't reproduce the desync:
- Do players ping change something in desync issues ? (with the hypothesis they have a descent ping, < 1s).
- If a scenario cause desync on Bnet, will the same scenario cause desync if player on local network ?
 

Dr Super Good

Spell Reviewer
Level 64
Joined
Jan 18, 2005
Messages
27,198
- Do players ping change something in desync issues ? (with the hypothesis they have a descent ping, < 1s).
Possibly. Although with the lock step model used this should not be the case as clients should pause waiting for the server and all commands are synchronized by the server.
- If a scenario cause desync on Bnet, will the same scenario cause desync if player on local network ?
Also possible.

Be aware that what maps a player plays before joining yours might effect it. Also if they use x86 or x86-64 might effect it.
 
Thanks guys !

Be aware that what maps a player plays before joining yours might effect it. Also if they use x86 or x86-64 might effect it.
You mean game cache corruption because of Widgetizer ? I stopped using Widgetizer for my map (since I switched to Warcraft 1.31.1) :)
About 32 or 64bit, WTF is may impact ?? Well at least I know I reproduced it myself with hosting a map in 64 bits, but I have no ideas if other players were in 32 or 64 bits...



You can desync on local network.
Most desyncs are caused by using certain things unsafely /improperly.
I already removed :
- Almost all GetLocalPlayer (I only keeped the ones that play a sound for 1 player only, nothing more)
- Most of the "Player slot Comparisons"
- All "Pan camera as necessary"
- All terrain deformations

I have no idea of what potential other causes exist..

Can also desync be caused by "Wait" followed by "GetTriggeringUnit()" or similar
(whose returned value may have been changed during the wait) ?
 

Dr Super Good

Spell Reviewer
Level 64
Joined
Jan 18, 2005
Messages
27,198
You mean game cache corruption because of Widgetizer ? I stopped using Widgetizer for my map (since I switched to Warcraft 1.31.1) :)
Yes but just because you do not use it, does not mean others do not. If they play widigitzed map before yours that could easily cause them to OoS.
About 32 or 64bit, WTF is may impact ?? Well at least I know I reproduced it myself with hosting a map in 64 bits, but I have no ideas if other players were in 32 or 64 bits...
A potential cause is the mismatch of 32bit and 64bit builds. Now it is not meant to be a cause as both are meant to produce the same results when running the same map and same inputs. However due to how new the 64bit build is and Warcraft III not being made with 64bit in mind, it is possible that there are bug causing its behaviour to deviate from the 32bit build. Hopefully these are fixed in a future update.
- All "Pan camera as necessary"
This should no longer cause desyncs. The GUI function was fixed.
JASS:
function SmartCameraPanBJ takes player whichPlayer,location loc,real duration returns nothing
    local real dist
	local location cameraLoc = GetCameraTargetPositionLoc()
    if (GetLocalPlayer() == whichPlayer) then
        set dist = DistanceBetweenPoints(loc, cameraLoc)
        if (dist >= bj_SMARTPAN_TRESHOLD_SNAP) then
            call PanCameraToTimed(GetLocationX(loc), GetLocationY(loc), 0)
        elseif (dist >= bj_SMARTPAN_TRESHOLD_PAN) then
            call PanCameraToTimed(GetLocationX(loc), GetLocationY(loc), duration)
        else
        endif
    endif
	call RemoveLocation(cameraLoc)
endfunction
The bug was the cameraLoc location was created locally. It is now created globally and only used locally.
 
I read somewhere that normal "Wait" can cause desync because it uses real time, not game time (when player laggs at the beginning, etc...).
Do you agree with that ? Should I replace all my waits with Game-time waits ?

Also I have a trigger to switch between players main hero and a second hero on stand-by. I have noticied more desyncs when I play this mode with 2 switchable heroes. Could this trigger cause desyncs ?

Info : the Heroes variable is a Unit Array that stores the 1st hero at index "Player id" and the second hero at index "Player id + 8" (since I have 8 players max)

  • DualHeroChange
    • Events
      • Player - Player 1 (Red) Selects a unit
      • Player - Player 2 (Blue) Selects a unit
      • Player - Player 3 (Teal) Selects a unit
      • Player - Player 4 (Purple) Selects a unit
      • Player - Player 5 (Yellow) Selects a unit
      • Player - Player 6 (Orange) Selects a unit
      • Player - Player 7 (Green) Selects a unit
      • Player - Player 8 (Pink) Selects a unit
    • Conditions
      • (Triggering unit) Equal to Heroes[((Player number of (Triggering player)) + 8)]
      • ((Triggering player) controller) Equal to User
      • DualHeroChange[(Player number of (Triggering player))] Equal to True
      • (Heroes[(Player number of (Triggering player))] is paused) Equal to False
      • (Heroes[(Player number of (Triggering player))] is dead) Equal to False
    • Actions
      • Set DualHeroChange[(Player number of (Owner of (Triggering unit)))] = False
      • -------- Save hero position --------
      • Custom script: call RemoveLocation(udg_DualHeroPoint[GetConvertedPlayerId(GetTriggerPlayer())])
      • Set DualHeroPoint[(Player number of (Triggering player))] = (Position of Heroes[(Player number of (Triggering player))])
      • -------- Transfer experience --------
      • Hero - Set Heroes[((Player number of (Triggering player)) + 8)] experience to (Hero experience of Heroes[(Player number of (Triggering player))]), Hide level-up graphics
      • -------- Transfer items --------
      • For each (Integer A) from 1 to 6, do (Actions)
        • Loop - Actions
          • Hero - Give (Item carried by Heroes[(Player number of (Triggering player))] in slot (Integer A)) to Heroes[((Player number of (Triggering player)) + 8)]
      • -------- Switch heroes effectively (hide it for it to loose ennemy focus) --------
      • Unit - Move Heroes[(Player number of (Triggering player))] instantly to SelectAreaCenter
      • Unit - Pause Heroes[(Player number of (Triggering player))]
      • Unit - Make Heroes[(Player number of (Triggering player))] Invulnerable
      • Special Effect - Create a special effect at DualHeroPoint[(Player number of (Triggering player))] using Abilities\\Spells\\Orc\\FeralSpirit\\feralspiritdone.mdl
      • Special Effect - Destroy (Last created special effect)
      • Set Heroes[((Player number of (Triggering player)) + 8)] = Heroes[(Player number of (Triggering player))]
      • Set Heroes[(Player number of (Triggering player))] = (Triggering unit)
      • Unit - Make Heroes[(Player number of (Triggering player))] Vulnerable
      • Unit - Unpause Heroes[(Player number of (Triggering player))]
      • Unit - Move Heroes[(Player number of (Triggering player))] instantly to DualHeroPoint[(Player number of (Triggering player))]
      • Set DualHeroChange[(Player number of (Owner of (Triggering unit)))] = True
 
Last edited:
For your informations, I add many triggers executed each second or when players select a hero, that used this kind of code:
  • MyTrigger
    • Events
      • [...]
    • Conditions
      • ((Triggering player) controller) Equal to User
    • Actions
      • [...]
I removed these conditions by a check "Is unit in group" with a group I initialized at beginning & refresh when a player disconnects. I have no more desync issues.
 

Dr Super Good

Spell Reviewer
Level 64
Joined
Jan 18, 2005
Messages
27,198
I read somewhere that normal "Wait" can cause desync because it uses real time, not game time (when player laggs at the beginning, etc...).
Do you agree with that ? Should I replace all my waits with Game-time waits ?
It should not cause desyncs because the wait is network synchronized by the server. It might if there are bugs but mechanically it is sound.

The issue with it is that it can cause crashes during "waiting for player" stages or massive input lag due to excessive network traffic.
Also I have a trigger to switch between players main hero and a second hero on stand-by. I have noticied more desyncs when I play this mode with 2 switchable heroes. Could this trigger cause desyncs ?
I do not see why it should. If synchronization is working properly (no bugs).
 
Status
Not open for further replies.
Top