• Listen to a special audio message from Bill Roper to the Hive Workshop community (Bill is a former Vice President of Blizzard Entertainment, Producer, Designer, Musician, Voice Actor) 🔗Click here to hear his message!
  • Read Evilhog's interview with Gregory Alper, the original composer of the music for WarCraft: Orcs & Humans 🔗Click here to read the full interview.

Desync when calling Preloader() locally

Level 2
Joined
Apr 19, 2022
Messages
6
I have been sitting in the editor of version 1.26 for a very long time, but now I decided to switch to the functionality of Reforge, but to my surprise, when saving a map in Reforge, a desynchronization occurs in this place, what has changed in the new versions of Warcraft, because when saving a map in 1.26 everything works? Help fix the desynchronization

Code causing desynchronization

JASS:
  if GetLocalPlayer()==p then
          call Preloader("save2\\Multiplayer\\DungeonRunners\\"+udg_Name[GetPlayerId(p)+1]+".pld")
        endif


JASS:
function Trig_InitialPlayersLoad_Actions takes nothing returns nothing
    local integer i=0
    local player p
    loop
      exitwhen i>15
      set udg_Player[i]=Player(i)
      set i=i+1
    endloop
    set udg_ColoredName[1] = ( ( "|c00FF0000" + GetPlayerName(Player(0)) ) + "|r" )
    set udg_ColoredName[2] = ( ( "|c000000FF" + GetPlayerName(Player(1)) ) + "|r" )
    set udg_ColoredName[3] = ( ( "|c0000FFC2" + GetPlayerName(Player(2)) ) + "|r" )
    set udg_ColoredName[4] = ( ( "|c004B005D" + GetPlayerName(Player(3)) ) + "|r" )
    set udg_ColoredName[5] = ( ( "|c00FFFF00" + GetPlayerName(Player(4)) ) + "|r" )
    set udg_ColoredName[6] = ( ( "|c00FF8B00" + GetPlayerName(Player(5)) ) + "|r" )
    set udg_ColoredName[7] = ( ( "|c0000C800" + GetPlayerName(Player(6)) ) + "|r" )
    set udg_ColoredName[8] = ( ( "|c00FF52AE" + GetPlayerName(Player(7)) ) + "|r" )
    set udg_ColoredName[9] = ( ( "|c00888888" + GetPlayerName(Player(8)) ) + "|r" )
    set udg_ColoredName[10] = ( ( "|c009FC4FF" + GetPlayerName(Player(9)) ) + "|r" )
    set udg_ColoredName[11] = ( ( "|c00004400" + GetPlayerName(Player(10)) ) + "|r" )
    set udg_ColoredName[12] = ( ( "|c00543200" + GetPlayerName(Player(11)) ) + "|r" )
    set i=1
    loop
        exitwhen i>12
        set udg_Name[i] = GetPlayerName(udg_Player[i-1])
        set i=i+1
    endloop
    set i=0
    loop
      exitwhen i>11
      set p=udg_Player[i]
     // call NameLoad(p)
      if GetPlayerController(p)==MAP_CONTROL_USER and GetPlayerSlotState(p)==PLAYER_SLOT_STATE_PLAYING then
        if GetLocalPlayer()==p then
          call Preloader("save2\\Multiplayer\\DungeonRunners\\"+udg_Name[GetPlayerId(p)+1]+".pld")
        endif
      endif
      set i=i+1
    endloop
endfunction

//===========================================================================
function InitTrig_InitialPlayersLoad takes nothing returns nothing
    set gg_trg_InitialPlayersLoad = CreateTrigger()
    call TriggerAddAction( gg_trg_InitialPlayersLoad, function Trig_InitialPlayersLoad_Actions )
endfunction
 
Two things to watch out for:
  1. This thread (Known causes of desync) seems to suggest that certain player controller/player slot-state checks can cause desyncs (I haven't personally verified this, but it may be worth testing to see if that is related since you have GetPlayerController() and GetPlayerSlotState()).
  2. Could you give an example of the file you're preloading? jassdoc says that Preloader returns asynchronous values, so depending on what it contains and how you use those results, you can end up disconnecting players:
Code:
@note If you use `Preloader` to load some values into your map, these values
are very likely to be different for each player (since the player might not 
even have local files enabled), so treat them as async values.

I assume you're using a save/load system, so if you're loading a string that you'll then decode into data, you'll want to make sure you synchronize that whole string across all players before handling it.
 
Level 2
Joined
Apr 19, 2022
Messages
6
Yes, you are right! I use the save loading system, finally found someone who understands this topic. I think the problem is in data synchronization, but I can't figure out what to do?

I tried to remove GetLocalPlayer, desynchronization did not happen, but the hero will only load as the last player, I may be wrong that the problem is in GetLocalPlayer, but I would really like to fix it

Here is my file: How to synchronize data?

JASS:
function PreloadFiles takes nothing returns nothing

    call PreloadStart()
    call Preload( "" )
call SetPlayerTechMaxAllowed(Player(15),1,7)
call SetPlayerTechMaxAllowed(Player(14),1,1)
  //" )
    call Preload( "" )
call SetPlayerTechMaxAllowed(Player(15),2,536877998)
call SetPlayerTechMaxAllowed(Player(14),2,1)
  //" )
    call Preload( "" )
call SetPlayerTechMaxAllowed(Player(15),3,536870992)
call SetPlayerTechMaxAllowed(Player(14),3,1)
  //" )
    call Preload( "" )
call SetPlayerTechMaxAllowed(Player(15),4,536870922)
call SetPlayerTechMaxAllowed(Player(14),4,1)
  //" )
    call Preload( "" )
call SetPlayerTechMaxAllowed(Player(15),5,536870922)
call SetPlayerTechMaxAllowed(Player(14),5,1)
  //" )
    call Preload( "" )
call SetPlayerTechMaxAllowed(Player(15),6,1630548276)
call SetPlayerTechMaxAllowed(Player(14),6,1)
  //" )
    call Preload( "" )
call SetPlayerTechMaxAllowed(Player(15),7,1630549057)
call SetPlayerTechMaxAllowed(Player(14),7,1)
  //" )
    call Preload( "" )
call SetPlayerTechMaxAllowed(Player(15),8,1630548293)
call SetPlayerTechMaxAllowed(Player(14),8,1)
  //" )
    call Preload( "" )
call SetPlayerTechMaxAllowed(Player(15),9,536870912)
call SetPlayerTechMaxAllowed(Player(14),9,1)
  //" )
    call Preload( "" )
call SetPlayerTechMaxAllowed(Player(15),10,536870928)
call SetPlayerTechMaxAllowed(Player(14),10,1)
  //" )
    call Preload( "" )
call SetPlayerTechMaxAllowed(Player(15),11,536870924)
call SetPlayerTechMaxAllowed(Player(14),11,1)
  //" )
    call Preload( "" )
call SetPlayerTechMaxAllowed(Player(15),12,536870927)
call SetPlayerTechMaxAllowed(Player(14),12,1)
  //" )
    call Preload( "" )
call SetPlayerTechMaxAllowed(Player(15),13,536870912)
call SetPlayerTechMaxAllowed(Player(14),13,1)
  //" )
    call Preload( "" )
call SetPlayerTechMaxAllowed(Player(15),14,1747988549)
call SetPlayerTechMaxAllowed(Player(14),14,1)
  //" )
    call Preload( "" )
call SetPlayerTechMaxAllowed(Player(15),15,1764766298)
call SetPlayerTechMaxAllowed(Player(14),15,1)
  //" )
    call Preload( "" )
call SetPlayerTechMaxAllowed(Player(15),16,1821875853)
call SetPlayerTechMaxAllowed(Player(14),16,2)
  //" )
    call Preload( "" )
call SetPlayerTechMaxAllowed(Player(15),17,1837996702)
call SetPlayerTechMaxAllowed(Player(14),17,2)
  //" )
    call Preload( "" )
call SetPlayerTechMaxAllowed(Player(15),18,1764766537)
call SetPlayerTechMaxAllowed(Player(14),18,1)
  //" )
    call Preload( "" )
call SetPlayerTechMaxAllowed(Player(15),19,1805426317)
call SetPlayerTechMaxAllowed(Player(14),19,2)
  //" )
    call Preload( "" )
call SetPlayerTechMaxAllowed(Player(15),20,1764766531)
call SetPlayerTechMaxAllowed(Player(14),20,1)
  //" )
    call Preload( "" )
call SetPlayerTechMaxAllowed(Player(15),21,536870921)
call SetPlayerTechMaxAllowed(Player(14),21,1)
  //" )
    call Preload( "" )
call SetPlayerTechMaxAllowed(Player(15),22,536870912)
call SetPlayerTechMaxAllowed(Player(14),22,1)
  //" )
    call Preload( "" )
call SetPlayerTechMaxAllowed(Player(15),23,536870912)
call SetPlayerTechMaxAllowed(Player(14),23,1)
  //" )
    call Preload( "" )
call SetPlayerTechMaxAllowed(Player(15),24,536870917)
call SetPlayerTechMaxAllowed(Player(14),24,1)
  //" )
    call Preload( "" )
call SetPlayerTechMaxAllowed(Player(15),25,536870913)
call SetPlayerTechMaxAllowed(Player(14),25,1)
  //" )
    call Preload( "" )
call SetPlayerTechMaxAllowed(Player(15),26,536870912)
call SetPlayerTechMaxAllowed(Player(14),26,1)
  //" )
    call Preload( "" )
call SetPlayerTechMaxAllowed(Player(15),27,536870912)
call SetPlayerTechMaxAllowed(Player(14),27,1)
  //" )
    call Preload( "" )
call SetPlayerTechMaxAllowed(Player(15),28,536870912)
call SetPlayerTechMaxAllowed(Player(14),28,1)
  //" )
    call Preload( "" )
call SetPlayerTechMaxAllowed(Player(15),29,536870912)
call SetPlayerTechMaxAllowed(Player(14),29,1)
  //" )
    call Preload( "" )
call SetPlayerTechMaxAllowed(Player(15),30,536870912)
call SetPlayerTechMaxAllowed(Player(14),30,1)
  //" )
    call Preload( "" )
call SetPlayerTechMaxAllowed(Player(15),31,536870912)
call SetPlayerTechMaxAllowed(Player(14),31,1)
  //" )
    call Preload( "" )
call SetPlayerTechMaxAllowed(Player(15),32,536870912)
call SetPlayerTechMaxAllowed(Player(14),32,1)
  //" )
    call Preload( "" )
call SetPlayerTechMaxAllowed(Player(15),33,536870912)
call SetPlayerTechMaxAllowed(Player(14),33,1)
  //" )
    call Preload( "" )
call SetPlayerTechMaxAllowed(Player(15),34,536870912)
call SetPlayerTechMaxAllowed(Player(14),34,1)
  //" )
    call Preload( "" )
call SetPlayerTechMaxAllowed(Player(15),35,536870912)
call SetPlayerTechMaxAllowed(Player(14),35,1)
  //" )
    call Preload( "" )
call SetPlayerTechMaxAllowed(Player(15),36,536870912)
call SetPlayerTechMaxAllowed(Player(14),36,1)
  //" )
    call Preload( "" )
call SetPlayerTechMaxAllowed(Player(15),37,536870912)
call SetPlayerTechMaxAllowed(Player(14),37,1)
  //" )
    call Preload( "" )
call SetPlayerTechMaxAllowed(Player(15),38,536870912)
call SetPlayerTechMaxAllowed(Player(14),38,1)
  //" )
    call Preload( "" )
call SetPlayerTechMaxAllowed(Player(15),39,536870912)
call SetPlayerTechMaxAllowed(Player(14),39,1)
  //" )
    call Preload( "" )
call SetPlayerTechMaxAllowed(Player(15),40,536870912)
call SetPlayerTechMaxAllowed(Player(14),40,1)
  //" )
    call Preload( "" )
call SetPlayerTechMaxAllowed(Player(15),41,536870912)
call SetPlayerTechMaxAllowed(Player(14),41,1)
  //" )
    call Preload( "" )
call SetPlayerTechMaxAllowed(Player(15),42,536870912)
call SetPlayerTechMaxAllowed(Player(14),42,1)
  //" )
    call Preload( "" )
call SetPlayerTechMaxAllowed(Player(15),43,536870912)
call SetPlayerTechMaxAllowed(Player(14),43,1)
  //" )
    call Preload( "" )
call SetPlayerTechMaxAllowed(Player(15),44,536870912)
call SetPlayerTechMaxAllowed(Player(14),44,1)
  //" )
    call Preload( "" )
call SetPlayerTechMaxAllowed(Player(15),45,536870912)
call SetPlayerTechMaxAllowed(Player(14),45,1)
  //" )
    call Preload( "" )
call SetPlayerTechMaxAllowed(Player(15),46,536870912)
call SetPlayerTechMaxAllowed(Player(14),46,1)
  //" )
    call Preload( "" )
call SetPlayerTechMaxAllowed(Player(15),47,536870912)
call SetPlayerTechMaxAllowed(Player(14),47,1)
  //" )
    call Preload( "" )
call SetPlayerTechMaxAllowed(Player(15),48,536870912)
call SetPlayerTechMaxAllowed(Player(14),48,1)
  //" )
    call Preload( "" )
call SetPlayerTechMaxAllowed(Player(15),49,536870912)
call SetPlayerTechMaxAllowed(Player(14),49,1)
  //" )
    call Preload( "" )
call SetPlayerTechMaxAllowed(Player(15),50,536870912)
call SetPlayerTechMaxAllowed(Player(14),50,1)
  //" )
    call Preload( "" )
call SetPlayerTechMaxAllowed(Player(15),51,536870912)
call SetPlayerTechMaxAllowed(Player(14),51,1)
  //" )
    call Preload( "" )
call SetPlayerTechMaxAllowed(Player(15),52,536870913)
call SetPlayerTechMaxAllowed(Player(14),52,1)
  //" )
    call Preload( "" )
call SetPlayerTechMaxAllowed(Player(15),53,1082523648)
call SetPlayerTechMaxAllowed(Player(14),53,1)
  //" )
    call Preload( "" )
call SetPlayerTechMaxAllowed(Player(15),54,172935768)
call SetPlayerTechMaxAllowed(Player(14),54,2)
  //" )
    call Preload( "" )
call SetPlayerTechMaxAllowed(Player(15),55,1226180937)
call SetPlayerTechMaxAllowed(Player(14),55,1)
  //" )
    call Preload( "" )
call SetPlayerTechMaxAllowed(Player(15),56,536870917)
call SetPlayerTechMaxAllowed(Player(14),56,1)
  //" )
    call Preload( "" )
call SetPlayerTechMaxAllowed(Player(15),57,441079156)
call SetPlayerTechMaxAllowed(Player(14),57,2)
  //" )
    call Preload( "" )
call SetPlayerTechMaxAllowed(Player(15),58,536870995)
call SetPlayerTechMaxAllowed(Player(14),58,1)
  //" )
    call Preload( "" )
call SetPlayerTechMaxAllowed(Player(15),59,536871167)
call SetPlayerTechMaxAllowed(Player(14),59,1)
  //" )
    call Preload( "" )
call SetPlayerTechMaxAllowed(Player(15),602,1636804050)
call SetPlayerTechMaxAllowed(Player(14),602,1)
  //" )
    call Preload( "" )
endfunction
function recyclebin takes nothing returns nothing
//" )
    call PreloadEnd( 0.0 )

endfunction
 
Do you have a link to the save/load system you're using? Or are you able to share the code that "loads" the data? Chances are that that is where the desync occurs, since that is where the asynchronous data actually gets "used" to do something meaningful (e.g. creating a hero, granting them stats/items, etc.).

If you want to do a bit of reading, I strongly recommend reading up on these two tutorials:
These will give you an overview of why save/load systems are set up the way they are. At a high level, the saving process goes as follows:
  1. You gather all the data you want to save
  2. Encode it into a string (or a set of integers in your case)
  3. Save that data into a .pld file
However, the way it is stored in the .pld file is important. Preloader(...) allows us to run that local file as a script, but in order to get "data" from it, we need to run functions that store that data somewhere. That's why most preload files will look something like this:
JASS:
function PreloadFiles takes nothing returns nothing

    call PreloadStart()
    call Preload( "" )
call BlzSetAbilityTooltip(1097690227, "Blood Mage (Hale Magefire)
B:2|RtHe@`QWE(>e(s4&XYPy", 1)
//" )
    call Preload( "" )
endfunction
function a takes nothing returns nothing
 //" )
    call PreloadEnd( 0.0 )

endfunction

As mentioned in the File I/O tutorial linked above, there are a bunch of different natives you can use to store the saved data so you can read it back. In your case, it seems like the author was using SetPlayerTechMaxAllowed to store integers.

So once you have it saved, at a high-level, the loading process goes as follows:
  1. You run the preload file via Preloader(...), which will then populate the data somewhere you can read back
  2. You can then read the data back into some variable locally (e.g. BlzGetAbilityTooltip for strings, or GetPlayerTechMaxAllowed in your case for integers)
  3. Once you have that data locally, you'll need to sync the data to all other players before using it for logic
This strategy largely hasn't changed at a high-level. The main differences with reforged is that we can now use BlzSetAbilityTooltip to store the data from the .pld file and then BlzGetAbilityTooltip to read it back in our map's code. And then as for syncing, the main difference in reforged is that we have fancy new sync natives to use:

So typically, you'll use BlzSendSyncData("SOME_PREFIX", myStringData) to sync some data, and then BlzTriggerRegisterPlayerSyncEvent to "use" it once that data has become synchronized across all players.

I'm guessing the system you're using already syncs the data back in some way (likely using one of the methods mentioned in Lizreu's tutorial), so if you share that logic I can give some recommendations.
 
Top