• 🏆 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!

Can this desync?

Status
Not open for further replies.
Level 13
Joined
Oct 18, 2013
Messages
691
JASS:
function PlayMusicExt takes string Normal, string External returns nothing
local integer i=0
local string s=""
       loop
        exitwhen i>11 
                if GetLocalPlayer()== Player(i) then
           if GetSoundFileDuration(External) > 0 then
          set s=External
          else
          set s=Normal
          endif
          endif 
        set i=i+1
      endloop
      call StopMusic(false)
      call PlayMusic(s)
      
endfunction
 
Last edited:
Level 14
Joined
Jul 1, 2008
Messages
1,314
I would set the StopMusic/PlayMusic calls into the GetLocalPlayer() block to be sure, it does not desync. I dont know what happens, if you do this to a computer player though.

edit: sry did not see waterknights response.
 
Level 26
Joined
Aug 18, 2009
Messages
4,097
I would set the StopMusic/PlayMusic calls into the GetLocalPlayer() block to be sure, it does not desync. I dont know what happens, if you do this to a computer player though.

How would putting it into the async block diminish the chance for desync? You cannot apply it to a computer player. For explanation:

All the human players (clients) join the same game, which is of the same map. They all got the same map script and execute it. Since they follow the same instructions and are determined, this keeps the game in sync. GetLocalPlayer however defies this by introducing dependence on local information. For the client that hosts player 0 it returns player 0, for the one that hosts player 1 it returns player 1 etc. The computer players are no own game instances, they do not execute any script or anything on their own. They are just part of the environment every client realizes locally but normally in an equal fashion.

The above scenario could basically semantically be expressed as:

The script player 0 got to execute:

JASS:
function PlayMusicExt takes string Normal, string External returns nothing
local integer i=0
local string s=""
       loop
        exitwhen i>11
                if Player(0)== Player(i) then
           if GetSoundFileDuration(External) > 0 then
          set s=External
          else
          set s=Normal
          endif
          endif
        set i=i+1
      endloop
      call StopMusic(false)
      call PlayMusic(s)
     
endfunction

The script player 1 got to execute:

JASS:
function PlayMusicExt takes string Normal, string External returns nothing
local integer i=0
local string s=""
       loop
        exitwhen i>11
                if Player(1)== Player(i) then
           if GetSoundFileDuration(External) > 0 then
          set s=External
          else
          set s=Normal
          endif
          endif
        set i=i+1
      endloop
      call StopMusic(false)
      call PlayMusic(s)
     
endfunction

Here the GetLocalPlayer-block is unnecessary, though. The loop over all clients neutralizes the local block since every client got their exact match. It can be simply rewritten as:

JASS:
function PlayMusicExt takes string Normal, string External returns nothing
    local string s = Normal

    if (GetSoundFileDuration(External) > 0) then
        set s = External
    endif

    call StopMusic(false)
    call PlayMusic(s) 
endfunction
 
Last edited:
Level 13
Joined
Oct 18, 2013
Messages
691
I just made it so that I can feed a sound file that's in the map, and a sound file that the player will only have if they installed my soundpack.

So, another desync question;

call PlaySound(udg_Sound)

If only players with the soundpack have the sound, can this desync?
 

Dr Super Good

Spell Reviewer
Level 64
Joined
Jan 18, 2005
Messages
27,198
If only players with the soundpack have the sound, can this desync?
It should not, as sounds are pretty much asynchronous as is.

One just has to be careful with sound handles and path strings as both those trigger objects can cause a desync. If the sound is the same between players, or even exists, should not matter as long as a sound object exists for all players.
 
There is no much you can do wrong in regards to using external sounds, as long as you don't use the "KillSoundWhenDone" native.

I highly recommend initializing all strings globally. Never initialize a new string inside a local block. For some reason, this can cause desyncs eventually. And the annoying part about this is that this string-based desync almost never happens instantly, but after a longer game session, which makes it hard to find the issue once people start to report desyncs.

As a rule of thumb: Always define filepaths as constant global variables, then just use one or the other in a local block.
 
Level 19
Joined
Dec 12, 2010
Messages
2,069
There is no much you can do wrong in regards to using external sounds, as long as you don't use the "KillSoundWhenDone" native.

I highly recommend initializing all strings globally. Never initialize a new string inside a local block. For some reason, this can cause desyncs eventually. And the annoying part about this is that this string-based desync almost never happens instantly, but after a longer game session, which makes it hard to find the issue once people start to report desyncs.

As a rule of thumb: Always define filepaths as constant global variables, then just use one or the other in a local block.

I do rely on async strings both on dota & lod. so far (3 years) no desyncs whatsoever. Strings aren't agents, and only reason they are cached in some way is to improve WC3' perfomance. C doesn't really like to work with strings, so devs opted it via caching. Any given player could have totally different set of strings given. Just think about translations, customkeys, etc. Strings cannot cause desync whatsoever, unless proved wrong.
 

Dr Super Good

Spell Reviewer
Level 64
Joined
Jan 18, 2005
Messages
27,198
I do rely on async strings both on dota & lod. so far (3 years) no desyncs whatsoever. Strings aren't agents, and only reason they are cached in some way is to improve WC3' perfomance. C doesn't really like to work with strings, so devs opted it via caching. Any given player could have totally different set of strings given. Just think about translations, customkeys, etc. Strings cannot cause desync whatsoever, unless proved wrong.
And yet dozens of OOS issues in the past have been caused by local strings...

WC3 caches strings for some unknown, but likely lazy, reason. Sure it allows fast string comparison but it makes string creation painfully slow. Additionally due to no reference counter system it is impossible for strings to be recycled so as the hashtables fill up the string creation performance falls even further.

This is why in StarCraft II strings are unique objects which are automatically garbage collected. This is also how Java programming language does it. StarCraft II also uses text for localized content so that strings are always in sync between clients.

The issue seems to be with unique string creation. As long as all clients have the same strings cached in the same order there does not seem to be a problem. In game localized text is likely separate from the string system.
 
Level 13
Joined
Oct 18, 2013
Messages
691
Any update on this? As a preventative measure, I'll probably just set the filepaths on init anyways, just curious as to whether this can desync or not.
 
Status
Not open for further replies.
Top