What exactly desyncs?

Korolen

New User (Why do I keep getting those red bars?)
Reaction score
69
I finally got map map to "beta stage", and have started to host it on Battle.net... and have experienced many hurtles of the players getting disconnected from desyncs.

I need some help on a few aspects as to what is causing the desyncs and what I can do to fix them.


At first, everyone got disconnected the instant the game started... I fixed this one by changing
Code:
Custom script:   if GetLocalPlayer() != GetOwningPlayer(GetEnumUnit()) then
Unit - Hide (Picked unit)
Custom script:   endif
to
Code:
Custom script:   if GetLocalPlayer() != GetOwningPlayer(GetEnumUnit()) then
Animation - Change (Picked unit)'s vertex coloring to (100.00%, 100.00%, 100.00%) with 100.00% transparency
Animation - Change (Picked unit)'s size to (0.00%, 0.00%, 0.00%) of its original size
Custom script:   endif


Next, people got disconnected whenever this "floating error" script was run:
Code:
function create_floating_error takes player p, string text, location l returns texttag
    local texttag tag
    if GetLocalPlayer() == p then
        set tag = CreateTextTag()
        call SetTextTagPos(tag, GetLocationX(l), GetLocationY(l), 30)
        call SetTextTagTextBJ(tag, text, 8)
        call SetTextTagPermanent(tag, false)
        call SetTextTagFadepoint(tag, 0.5)
        call SetTextTagLifespan(tag, 1.3) 
    endif
    return tag
endfunction
I fixed it by initializing "tag" to null.

Now, for the unsolved "hurdle". I added a tutorial to the beginning of the map... however, when a player skips it, it disconnects them. I found that the Blizzard cinematic code set the gamespeed, so I copied the "local" code except fo r that from the BJ function into the end_cinematic function, but the players still get disconnected. I'm guessing that there is a problem with fade filters, but I'm not sure. Here is all the relevant code.

The tutorial trigger:
Code:
Tutorial
    Events
    Conditions
    Actions
        Custom script:   local string s
        Cinematic - Turn cinematic mode On for (All players)
        Cinematic - Fade out over 0.00 seconds using texture Black Mask and color (0.00%, 0.00%, 0.00%) with 0.00% transparency
        Player Group - Pick every player in Players and do (Actions)
            Loop - Actions
                Set Playing_Cinematic[((Player number of (Picked player)) - 1)] = True
        Custom script:   call cinematic_message(7, "Welcome to Beast Bloodshed. This is a quick tutorial to introduce you to the game. If you have already played Beast Bloodshed and would like to load your code, press [\\[^ESC^\\]]|r at any time.")
        Custom script:   if udg_Playing_Cinematic[GetPlayerId(GetLocalPlayer())] == false then
        Skip remaining actions
        Custom script:   endif
        Environment - Set fog to style Linear, z-start 1000000.00, z-end 10000000.00, density 0.00 and color (100.00%, 100.00%, 100.00%)
        Player Group - Pick every player in Players and do (Camera - Apply Main Area <gen> for (Picked player) over 0.00 seconds)
        Cinematic - Fade in over 1.00 seconds using texture White Mask and color (0.00%, 0.00%, 0.00%) with 0.00% transparency
        Custom script:   call cinematic_message(8.5, "The goal of the Beast Bloodshed is to breed the prefect champion to conquer the other players in competitions.|n|nThis is the main area. Everyone's beasts that are not currently competing are located here.")
        Custom script:   if udg_Playing_Cinematic[GetPlayerId(GetLocalPlayer())] == false then
        Skip remaining actions
        Custom script:   endif
        Player Group - Pick every player in Players and do (Actions)
            Loop - Actions
                Camera - Pan camera for (Picked player) to ((Picked player) start location) over 1.00 seconds
                Camera - Set (Picked player)'s camera Angle of attack to -35.00 over 1.00 seconds
                Camera - Set (Picked player)'s camera Rotation to (Angle from ((Picked player) start location) to (Center of Main Area <gen>)) over 1.00 seconds
                Camera - Set (Picked player)'s camera Distance to target to 1800.00 over 1.00 seconds
        Custom script:   call cinematic_message(6.5, "This is your main base. Purchase new beasts here. New beasts will not appear until the start of the next Main Phase, or directly after the competition.")
        Custom script:   if udg_Playing_Cinematic[GetPlayerId(GetLocalPlayer())] == false then
        Skip remaining actions
        Custom script:   endif
        Custom script:   set s = "These are the crafters and the Bet Collector. The Potion Brewer can concoct powerful potions that will help your beasts outside of battle, and the Armor Crafter can forge sturdy armor to protect your beasts in battle. "
        Custom script:   set s = s + "The Bet Collector will allow you to enter your beasts into the competition and to place bets on who will win."
        Custom script:   call cinematic_message(-1, s)
        Player Group - Pick every player in Players and do (Actions)
            Loop - Actions
                Camera - Pan camera for (Picked player) to (Center of Shops <gen>) over 1.00 seconds
        Wait 1.00 seconds
        Custom script:   if udg_Playing_Cinematic[GetPlayerId(GetLocalPlayer())] == false then
        Skip remaining actions
        Custom script:   endif
        Player Group - Pick every player in Players and do (Actions)
            Loop - Actions
                Camera - Rotate camera (360.00 - (Angle from ((Picked player) start location) to (Center of Shops <gen>))) degrees around (Center of Shops <gen>) for (Picked player) over 9.00 seconds
        Custom script:   call cinematic_message(-1, s)
        Wait 9.00 seconds
        Custom script:   if udg_Playing_Cinematic[GetPlayerId(GetLocalPlayer())] == false then
        Skip remaining actions
        Custom script:   endif
        Custom script:   set s = "Comptetitions such as racing, sumos, deathmatches, and endurance games will happen periodically."
        Custom script:   call cinematic_message(-1, s)
        Player Group - Pick every player in Players and do (Actions)
            Loop - Actions
                Camera - Pan camera for (Picked player) to (Center of Long Race Start <gen>) over 1.50 seconds
                Camera - Set (Picked player)'s camera Rotation to 0.00 over 1.50 seconds
                Camera - Set (Picked player)'s camera Distance to target to 500.00 over 1.50 seconds
        Wait 1.50 seconds
        Custom script:   if udg_Playing_Cinematic[GetPlayerId(GetLocalPlayer())] == false then
        Skip remaining actions
        Custom script:   endif
        Player Group - Pick every player in Players and do (Actions)
            Loop - Actions
                Camera - Pan camera for (Picked player) to (Center of Long Race Finish <gen>) over 1.00 seconds
        Wait 0.80 seconds
        Custom script:   if udg_Playing_Cinematic[GetPlayerId(GetLocalPlayer())] == false then
        Skip remaining actions
        Custom script:   endif
        Player Group - Pick every player in Players and do (Actions)
            Loop - Actions
                Camera - Pan camera for (Picked player) to (Center of Figure Eight <gen>) over 1.80 seconds
                Camera - Set (Picked player)'s camera Distance to target to 3500.00 over 1.80 seconds
                Camera - Set (Picked player)'s camera Angle of attack to 304.00 over 1.80 seconds
        Wait 1.80 seconds
        Custom script:   if udg_Playing_Cinematic[GetPlayerId(GetLocalPlayer())] == false then
        Skip remaining actions
        Custom script:   endif
        Player Group - Pick every player in Players and do (Actions)
            Loop - Actions
                Camera - Pan camera for (Picked player) to (Center of Arena <gen>) over 0.50 seconds
        Wait 0.50 seconds
        Custom script:   if udg_Playing_Cinematic[GetPlayerId(GetLocalPlayer())] == false then
        Skip remaining actions
        Custom script:   endif
        Player Group - Pick every player in Players and do (Actions)
            Loop - Actions
                Camera - Rotate camera 90.00 degrees around (Center of Arena <gen>) for (Picked player) over 1.50 seconds
        Wait 1.50 seconds
        Custom script:   if udg_Playing_Cinematic[GetPlayerId(GetLocalPlayer())] == false then
        Skip remaining actions
        Custom script:   endif
        Player Group - Pick every player in Players and do (Actions)
            Loop - Actions
                Camera - Pan camera for (Picked player) to (Center of Sumo <gen>) over 0.50 seconds
        Wait 0.50 seconds
        Custom script:   if udg_Playing_Cinematic[GetPlayerId(GetLocalPlayer())] == false then
        Skip remaining actions
        Custom script:   endif
        Player Group - Pick every player in Players and do (Actions)
            Loop - Actions
                Camera - Set (Picked player)'s camera Distance to target to 0.00 over 1.00 seconds
        Cinematic - Fade out over 0.80 seconds using texture White Mask and color (0.00%, 0.00%, 0.00%) with 0.00% transparency
        Wait 1.20 seconds
        Custom script:   call end_cinematic(GetLocalPlayer())
The "skip" code:
Code:
Skip Cinematic
    Events
        Player - Player 1 (Red) skips a cinematic sequence
        Player - Player 2 (Blue) skips a cinematic sequence
        Player - Player 3 (Teal) skips a cinematic sequence
        Player - Player 4 (Purple) skips a cinematic sequence
        Player - Player 5 (Yellow) skips a cinematic sequence
        Player - Player 6 (Orange) skips a cinematic sequence
        Player - Player 7 (Green) skips a cinematic sequence
        Player - Player 8 (Pink) skips a cinematic sequence
    Conditions
        Playing_Cinematic[((Player number of (Triggering player)) - 1)] Equal to True
    Actions
        Custom script:   call end_cinematic(GetTriggerPlayer())
And the "end_cinematic" function:
Code:
function end_cinematic takes player p returns nothing
    set udg_Playing_Cinematic[GetPlayerId(p)] = false
    if GetLocalPlayer() == p then
        call ResetTerrainFog()
        call ResetToGameCamera(0)
        call PanCameraToTimed(GetPlayerStartLocationX(p), GetPlayerStartLocationY(p), 0)
        call CinematicFadeBJ(bj_CINEFADETYPE_FADEIN, 0.40, "ReplaceableTextures\\CameraMasks\\White_mask.blp", 0, 0, 0, 0)
        call ShowInterface(true, .4)
        call EnableUserControl(true)
        call EnableOcclusion(true)
        call VolumeGroupReset()
        call EndThematicMusic()
        call CameraResetSmoothingFactorBJ()
    endif
endfunction



Now I'm also wondering, if the fade filters are the problem, why Elil's local cinematic be so complex if you could do this... Only the latter looks just like the normal function but with the GetLocalPlayer()==target player comparison in the function instead of outside it. I don't get why the latter would work at all, and if it does, why would it work any better then moving the GetLocalPlayer() comparison outside the function? I'd really like to know exactly what is safe and what is not... I've done a bit of research and have found different opinions.

EDIT: I have also experienced random desyncing when playing my map on bnet; I'll post relevant code as I narrow down what is causing it.
 

Chocobo

White-Flower
Reaction score
409
For filter :

call ResetTerrainFog() : doesn't desync
call ResetToGameCamera() : doesn't desync
call PanCameraToTimed() : doesn't desync

call CinematicFadeBJ() : maybe desync
no idea if GetLocalPlayer() desyncs with strings and timers

call ShowInterface() : doesn't desync
call EnableUserControl() : doesn't desync
call EnableOcclusion() : doesn't desync
call VolumeGroupReset() : doesn't desync
call EndThematicMusic() : no idea of the theme desyncs
call CameraResetSmoothingFactorBJ() : doesn't desync

You should test CinematicFadeBJ() functions, strings and timers can be the problem (also it sets bj_ variables to an another value, so it may return differant values for other computers if it is set to a new value in globality)
 

Andrewgosu

The Silent Pandaren Helper
Reaction score
716
To conclude, everything You create for a local player, tends to de-sync, almost always (Like you did with the texttag).

Hiding units, showing fade filters and playing sounds for a local player is safe, however.
 

Chocobo

White-Flower
Reaction score
409
To conclude, everything You create for a local player, tends to de-sync, almost always (Like you did with the texttag).

Hiding units, showing fade filters and playing sounds for a local player is safe, however.

For texttags : there is a function to hide texttags and compatible for multiplaying, no one seems to like to use it and create local texttags instead of hiding one for each player

For fade filters : desyncs if people uses the normal fade filter, the advanced one never desyncs.

For sound : no desync, but no idea for music (=! sound)
 

SFilip

Gone but not forgotten
Reaction score
633
Here's a 100% safe version of your texttag
Code:
function create_floating_error takes player p, string text, location l returns texttag
    local texttag tag = CreateTextTag()
    local string tttext = ""
    if GetLocalPlayer() == p then
        set tttext = text
    endif
    call SetTextTagPos(tag, GetLocationX(l), GetLocationY(l), 30)
    call SetTextTagTextBJ(tag, tttext, 8)
    call SetTextTagPermanent(tag, false)
    call SetTextTagFadepoint(tag, 0.5)
    call SetTextTagLifespan(tag, 1.3) 
    return tag
endfunction
So as you can see it creates the same text for every player, but makes the text "" unless that player is p.
In general any function that creates something for only one player can and will desync. Always find a way to hide it somehow instead in order to avoid this.
 

Korolen

New User (Why do I keep getting those red bars?)
Reaction score
69
Here's a 100% safe version of your texttag
Code:
function create_floating_error takes player p, string text, location l returns texttag
    local texttag tag = CreateTextTag()
    local string tttext = ""
    if GetLocalPlayer() == p then
        set tttext = text
    endif
    call SetTextTagPos(tag, GetLocationX(l), GetLocationY(l), 30)
    call SetTextTagTextBJ(tag, tttext, 8)
    call SetTextTagPermanent(tag, false)
    call SetTextTagFadepoint(tag, 0.5)
    call SetTextTagLifespan(tag, 1.3) 
    return tag
endfunction
So as you can see it creates the same text for every player, but makes the text "" unless that player is p.
In general any function that creates something for only one player can and will desync. Always find a way to hide it somehow instead in order to avoid this.
Well, setting the local tag variable to null first seemed to fix the problem. I don't think that the creation of the tag was what caused the desync, as tags are passive. I'm pretty sure that the problem was after I called that function, I stopped the unit, and that function crashed on one computer and not on another. Again, I'm not sure, but I think that the crash was caused by returning a uninitialized handle – why else would initializing it to null help?

For fade filters : desyncs if people uses the normal fade filter, the advanced one never desyncs.
Why?!?! If fadetype == bj_CINEFADETYPE_FADEOUT, the normal fade filter does exactly the same thing as the advanced one. Maybe it's when you pass bj_CINEFADETYPE_FADEIN, which starts a timer, that it desyncs?

Oh well, I'll try replacing my code with advanced fades instead of normal fades and see if it helps :p.


BTW, the latter half of the end_cinematic function was simply the local code in CinematicModeExBJ. Calling the function "normally" also ran "global code" which caused desyncs, I'm sure.
 

Chocobo

White-Flower
Reaction score
409
Why?!?! If fadetype == bj_CINEFADETYPE_FADEOUT, the normal fade filter does exactly the same thing as the advanced one. Maybe it's when you pass bj_CINEFADETYPE_FADEIN, which starts a timer, that it desyncs?

Oh well, I'll try replacing my code with advanced fades instead of normal fades and see if it helps :p.


BTW, the latter half of the end_cinematic function was simply the local code in CinematicModeExBJ. Calling the function "normally" also ran "global code" which caused desyncs, I'm sure.

CinematicModeExBJ already uses GetLocalPlayer() inside it's script, lol.


For filters :

Code:
function CinematicFilterGenericBJ takes real duration,blendmode bmode,string tex,real red0,real green0,real blue0,real trans0,real red1,real green1,real blue1,real trans1 returns nothing
    call AbortCinematicFadeBJ()
    call SetCineFilterTexture(tex)
    call SetCineFilterBlendMode(bmode)
    call SetCineFilterTexMapFlags(TEXMAP_FLAG_NONE)
    call SetCineFilterStartUV(0, 0, 1, 1)
    call SetCineFilterEndUV(0, 0, 1, 1)
    call SetCineFilterStartColor(PercentTo255(red0), PercentTo255(green0), PercentTo255(blue0), PercentTo255(100-trans0))
    call SetCineFilterEndColor(PercentTo255(red1), PercentTo255(green1), PercentTo255(blue1), PercentTo255(100-trans1))
    call SetCineFilterDuration(duration)
    call DisplayCineFilter(true)
endfunction

This desyncs. (I think it's the AbortCinematicFadeBJ, because it destroys a timer)


No idea for the advanced filter (I'm 100% sure it doesn't desync), because I don't remember it's func name.
 

Korolen

New User (Why do I keep getting those red bars?)
Reaction score
69
CinematicModeExBJ already uses GetLocalPlayer() inside it's script, lol.
It also has code that's run for every player, not just the local player. I don't want that code going for every player when just one player skips the cinematic, but that code can't be run localy, so I just copied the code from CinematicModeExBJ that was IN the local block into end_cinematic.
For filters :

Code:
function CinematicFilterGenericBJ takes real duration,blendmode bmode,string tex,real red0,real green0,real blue0,real trans0,real red1,real green1,real blue1,real trans1 returns nothing
    call AbortCinematicFadeBJ()
    call SetCineFilterTexture(tex)
    call SetCineFilterBlendMode(bmode)
    call SetCineFilterTexMapFlags(TEXMAP_FLAG_NONE)
    call SetCineFilterStartUV(0, 0, 1, 1)
    call SetCineFilterEndUV(0, 0, 1, 1)
    call SetCineFilterStartColor(PercentTo255(red0), PercentTo255(green0), PercentTo255(blue0), PercentTo255(100-trans0))
    call SetCineFilterEndColor(PercentTo255(red1), PercentTo255(green1), PercentTo255(blue1), PercentTo255(100-trans1))
    call SetCineFilterDuration(duration)
    call DisplayCineFilter(true)
endfunction

This desyncs. (I think it's the AbortCinematicFadeBJ, because it destroys a timer)


No idea for the advanced filter (I'm 100% sure it doesn't desync), because I don't remember it's func name.
Advanced filter in GUI turns into CinematicFilterGenericBJ
 

Korolen

New User (Why do I keep getting those red bars?)
Reaction score
69
bump

I tried disabling everything in the Tutorial trigger, and it seems to desync the instant the trigger does something – even just a wait – on one computer and not on the other. I'm going to try to wrapping all the actions in the Tutorial trigger except for waits instead of just killing the trigger, so it's still running just not doing anything.
 
General chit-chat
Help Users
  • No one is chatting at the moment.

      The Helper Discord

      Members online

      No members online now.

      Affiliates

      Hive Workshop NUON Dome World Editor Tutorials

      Network Sponsors

      Apex Steel Pipe - Buys and sells Steel Pipe.
      Top