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

Local multiplayer checking is bugged on Lua

Status
Not open for further replies.
Level 9
Joined
Jul 20, 2018
Messages
176
This was found by Bergi_Bear.

If you launch war3 in 2 windows offline and create local game using map on Lua, after some time handles will be different for each player.
Test map 1 desyncs after this happens.

But if all code in global do end block is eliminated, then no desync happens, although handles are still different.
Test map 2 has such behavior.

No problems if both maps are run in real multiplayer.

AFAIK, there were no such problems in 1.31 and was broken in some reforged patch.
 

Attachments

  • code1.w3x
    16.1 KB · Views: 36
  • code2.w3x
    15.6 KB · Views: 28
Last edited:
As you mentioned, in Lua handle IDs are not synchronized between clients but this has been known for quite some time. As long as you aren't using them in a way which produces different outcomes then you should be fine. For example, iterating a table using ipairs with handle IDs as the key and modifying game state would not be safe. So, in the context of this post I don't think it's really relevant.

The first map likely desyncs because of garbage collection. For whatever reason handles created in the global scope are more subject to being cleaned up.

Take the following code as an example.

Lua:
-- gets garbage collected
TimerStart(CreateTimer(), 1, true, function()
    Location(0,0)
end)

function main()
end

The timer will eventually stop running because the garbage collector will destroy the timer. However, if you stored a reference to the timer in a global it would not be garbage collected since the code is not deemed unreachable.
Lua:
-- does not get garbage collected
myTimer = CreateTimer()

TimerStart(myTimer, 1, true, function()
    Location(0,0)
end)

function main()
end

Another interesting thing is if you take the first piece of code and place it inside of main it does not get cleaned up.
Lua:
-- does not get garbage collected
function main()
    TimerStart(CreateTimer(), 1, true, function()
        Location(0,0)
    end)
end
I do not understand Lua's garbage collection enough to know if this is because handles created inside main are linked to the parent function, deeming them reachable / in use or if Blizzard's custom method of handling GC is not invoked until main is called. The former would make more sense because in your first map you have the periodic timer nested inside the callback of your non-periodic timer and the periodic timer does not get cleaned up, although I could see the later being the case because the GC seems to happen at different times for each player whereas Blizzard's implementation is synchronized. I suppose it could be both, but I haven't tested this in a long time.

I also don't think it's a LAN specific thing, although I could be wrong. I wouldn't be suprised if the first map desynced if you had tested with a full house in Battle.net.

AFAIK, there were no such problems in 1.31 and was broken in some reforged patch.

1.31 had it's own issues with garbage collection desyncs. You can read more about it from @Dr Super Good's post in this thread.
 
Level 9
Joined
Jul 20, 2018
Messages
176
I wouldn't be suprised if the first map desynced if you had tested with a full house in Battle.net.
According to Bergi, first map does not desync when players are on different machines, ex. are connected over Battle.net.

Another interesting thing is if you take the first piece of code and place it inside of main it does not get cleaned up.
This is what is done in 2nd map, periodic timer is created in trigger action with event "Game Time is 0".


As you mentioned, in Lua handle IDs are not synchronized between clients but this has been known for quite some time.
OK then, thank you for complete answer.
 
Status
Not open for further replies.
Top