-
Notifications
You must be signed in to change notification settings - Fork 59
Desyncs
Stijn edited this page Sep 8, 2024
·
13 revisions
This is a list of things that can cause a desync in 1.32 and later. These are not caused by HiveWE, but having a list is handy.
- Code in
GetLocalPlayer()
blocks will cause desyncs if it makes changes that should have happened on both player clients at the same time. The following will cause a desync because the unit is deleted on only one client.
if (GetTriggeringPlayer() == GetLocalPlayer) then
KillUnit(GetTriggeringUnit())
endif
But the following will not because a UI frame being visible or not is not something that needs to be synchronised between players.
if (GetTriggeringPlayer() == GetLocalPlayer) then
HideFrame(SomeFrameID)
endif
- Using
GetLocationZ()
for things that need to be synced between clients (e.g. killing a unit) will cause desyncs as there are height differences between Classic and Reforged graphics. - The
CreepCampPathingCellDistance
gameplay constant will desync if players don't restart their game before playing your map. - Frames are cached between maps, so if you create a frame before loading your .toc it can create the frame for some people but not others.
-
BlzDestroyFrame()
will cause desyncs - (Unconfirmed) Using Player Slot/Controller comparisons on initialization can occasionally cause desyncs because at the time of the initialization you don't necessarily have the information on other players
- Creating objects outside of the main function in Lua is prone to desyncs. To lazily solve this I moved TSTL's module creation inside of the main function.
- Using
StartTimerBJ
andbj_lastStartedTimer
will cause desyncs. This also means that the GUICountdown Timer - Start Timer
will desync. UseTimerStart()
in a custom script block instead. - Looping table entries with
pairs
doesn't guarantee the order of entries is the same across multiple clients, therefore this can cause desyncs if you're handling sensitive game data/objects. To circumvent this, always make loopable tables with integer keys instead and useipairs
. Tables with non-integer keys are fine as long as you're not looping them. -
local unitID = GetHandleId(unit)
leads to desyncs. It's never needed though, as you can use the Unit object itself as the key of arrays or lists, meaning the handle ID has no purpose.
Not all functions are async safe and can be used inside of a GetLocalPlayer() block. Obvious ones are KillUnit()
but less obvious ones exist.
ForForce()
ForGroup()
GetRandomInt()
GetRandomReal()
math.random()
Select group for player GUI