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

What causes players to desync?

Status
Not open for further replies.
Level 7
Joined
Jul 1, 2008
Messages
1,025
Hi there, we have a desync issue with a map we are working on, we are having a look at the triggers but we cant see what is causing it. I have to admit I had no idea that players could desync due to trigger bugs but clearly something is going wrong.

There are a number of triggers that play sounds for specific players using costum scripts, could this be what is causing it?
 
Level 10
Joined
Dec 15, 2012
Messages
650
I don't think play sound for specific player will cause that.
As far as I know, create quest (it won't cause that if u use Enable/Disable), pause game for a specific player will cause desync.You can find these in Tutorial, GetLocalPlayer
 
Last edited:
Level 7
Joined
Nov 15, 2009
Messages
225
Mostly the command If GetLocalPlayer() == Player(whatever) then causes desyncs, when used wrong.
But it depents what you change in those local blocks.

You are just allowed to insert non-game changing stuff here.
For example:
JASS:
local sound s
if GetLocalPlayer() == GetTriggerPlayer() then
     set s = Your sound path...
     call PlaySound(s)
endif
This could cause desyncs.
The wrong part in this script is set s = ...
 
Level 19
Joined
Aug 8, 2007
Messages
2,765
Mostly the command If GetLocalPlayer() == Player(whatever) then causes desyncs, when used wrong.
But it depents what you change in those local blocks.

You are just allowed to insert non-game changing stuff here.
For example:
JASS:
local sound s
if GetLocalPlayer() == GetTriggerPlayer() then
     set s = Your sound path...
     call PlaySound(s)
endif
This could cause desyncs.
The wrong part in this script is set s = ...

no, the wrong part is where you dont set s outside of the block than play the sound inside the block :p
 
Level 7
Joined
Jul 1, 2008
Messages
1,025
I placed a "Display message to all players" action just after get local player in order to display the message to just one single player, could that be which is causing the desync? Is this not to be used in a get local player fuction?


no, the wrong part is where you dont set s outside of the block than play the sound inside the block :p

I don't know what that means but Goblinkingsp do you understand that?
 
Level 19
Joined
Aug 8, 2007
Messages
2,765
Im not a JASS pro, but I think Arhowk meant that the actual script should be:
JASS:
local sound s
set sound s =  Your sound path
if GetLocalPlayer () == GetTriggerPlayer() then
        call PlaySound(s)
endif

Or Im wrong, Im learning too.

no
JASS:
local sound s = null
if GetLocalPlayer () == GetTriggerPlayer() then
        set s = your sound
endif
call PlaySound(s)

not that good with sounds but i think itd be safer to set the volume to 0% rather than setting the sound to null
 
Level 19
Joined
Feb 25, 2009
Messages
2,004
call StartSoundForPlayerBJ (<Player>, <Sound>)
If you don't want to bother with GetLocalPlayer()

call DisplayTimedTextToPlayer (<Player>, X, Y, Time, "<Message>")
To show a text to one player only.

Desync may be caused also by loading too many triggers at one time or a single trigger running too many actions really quick.
 
Level 19
Joined
Aug 8, 2007
Messages
2,765
call StartSoundForPlayerBJ (<Player>, <Sound>)
If you don't want to bother with GetLocalPlayer()

call DisplayTimedTextToPlayer (<Player>, X, Y, Time, "<Message>")
To show a text to one player only.

Desync may be caused also by loading too many triggers at one time or a single trigger running too many actions really quick.

Oh i guess blizzard allows that... oh well. My way is correct for everything else -_-

JASS:
function StartSoundForPlayerBJ takes player whichPlayer, sound soundHandle returns nothing
    if (whichPlayer == GetLocalPlayer()) then
        call StartSound(soundHandle)
    endif
endfunction
 
Level 26
Joined
Aug 18, 2009
Messages
4,097
JASS:
local sound s
if GetLocalPlayer() == GetTriggerPlayer() then
     set s = Your sound path...
     call PlaySound(s)
endif
This could cause desyncs.
The wrong part in this script is set s = ...

By itself, no.

not that good with sounds but i think itd be safer to set the volume to 0% rather than setting the sound to null

While setting it to null for playing does not make a difference, there are functions like GetSoundIsPlaying that would of course provide different results when starting the sound locally.

Desync may be caused also by loading too many triggers at one time or a single trigger running too many actions really quick.

Never had. But of course you could locally hit the op limit, which should be avoided either way.

Special effects don't cause desyncs.

False. Effects belong to the shared object id pool that should be in sync. Create them with an async model instead ("").
 
Level 21
Joined
Mar 27, 2012
Messages
3,232
Nope. And the string table desync is a myth to me or only appears in special cases. Same with the long-rumored sync of global variables.

I think it's about initialization.

Theory:
The first time a variable is initialized it is marked as "existant". (Probably by the existance of a value)
If you try to reference an unexistant variable, then it does something differently that affects the game. Thus, a desync.
There's a similar problem with trying to use i = i + 1 if i has not been initialized to a number. Simply put - variables reference to values. If they don't have a referenced value, then they are considered "nonexistant".
 

Dr Super Good

Spell Reviewer
Level 64
Joined
Jan 18, 2005
Messages
27,198
Anything that causes the internal synchronous game state to become different between two or more clients.

A very easy example is the use of terrain deformations from standard Blizzard spells (Shockwave, War Stomp) causing different terrain node heights depending on client platform and settings. The most common result is a split between Mac and Windows users.
 
Level 26
Joined
Aug 18, 2009
Messages
4,097
You should not read an unset variable. That's for sure. The trigger execution would halt. Nor should you call functions with invalid parameters.

I do not see the connection to what you quoted. The single variables do not have to be kept in sync let alone create extra traffic.

A very easy example is the use of terrain deformations from standard Blizzard spells (Shockwave, War Stomp) causing different terrain node heights depending on client platform and settings. The most common result is a split between Mac and Windows users.

Only if you use the GetLocationZ function, which may be async even with equal os and graphic options. Wc3 itself nowhere relies on the z dimension gameplay-wise.
 
Level 21
Joined
Mar 27, 2012
Messages
3,232
You should not read an unset variable. That's for sure. The trigger execution would halt. Nor should you call functions with invalid parameters.

I do not see the connection to what you quoted. The single variables do not have to be kept in sync let alone create extra traffic.

What I mean is that the engine obviously has its own automated ways of sharing variables based on some criteria. However, an array doesn't immediately take the space it would take if it was filled with nulls.
Thus I assume that the variables are actually created on first initialization.
How should it relate? Well if a client tries to reference variables that don't exist for all parties, then it will desync. Seems quite obvious.
So the problem isn't about reading unset variables, but trying to manipulate nonexistant variables. After all, reading unset variables already has some error handling(returning 0 if something is wrong).
 
Level 26
Joined
Aug 18, 2009
Messages
4,097
Well if a client tries to reference variables that don't exist for all parties, then it will desync. Seems quite obvious.
So the problem isn't about reading unset variables, but trying to manipulate nonexistant variables.

No, the other parties do not need to know your variables and this would be overkill. There are even object types you can instantiate on single clients, those that are handled locally. If you avoid all possible false signals, you can even do more like starting different triggers on different clients.

However, as for variables, you should pay attention to the reference-counting of agent object types. A unit does not release its id before all pointers to it are gone. Since you should not desync the shared id pool, you have to refrain from resetting the last pointer in an async pattern. Maybe that is why global variables are said to be checked because the concept of nullifying variables in order to avoid memory leaks is mostly taught targeting local ones only since globals are recycled in usage/not dynamic.
 
Level 7
Joined
Jul 1, 2008
Messages
1,025
Hey guys, well after messing about alot with my map it turns out players are STILL desyncing, in my latest test players desynced within a few seconds of map startup, I have looked at my triggers and I can't understand whats causing this.

If I gave one of you an unprotected version of my map would you be able to look at it and fix the triggers?

Its my LORDAERON: The Aftermath map (see link in sig).

If someone could fix this I would be eternally grateful as this is really holding up development of this map! It is an azeroth wars style map so pretty big though! Please can anyone help?
 
Status
Not open for further replies.
Top