I'll just raise this topic in the off-chance that you know anything, as well as just getting future advice out there for some of these issues that others may come to face as well.
Me and Damage have been suffering from desync issues within our map for quite a while now. We've identified some potential issues, and have definitely reduced the frequency of desyncs, but unfortunately the issue continues to plague the map and at this point getting a single desync to occur could take a handful of games. Frequent enough to make people not want to play the map, but infrequent enough to make testing whether a change helped an extremely tedious process, even when trying our best by doing a sort of binary-search style of enabling/disabling functionality.
It's worth noting that Damage's other large C# map, Assault the Throne, has not had any issues with desyncs, but as a C# programmer IRL, I bring some more advanced techniques and code to the table and have inadvertently brought problems along with me.
One of the things that we've at the very least noted as a guaranteed source of desyncs is sorting. Although this may be obvious to someone experienced in Lua, I personally expected that the sorting would be deterministic, as most sorting algorithms are. But Lua's is not, meaning that any instance of using OrderBy without being 100% sure that there is only ONE possible order is a risk. The simple solution here is to use a ThenBy to sort by something unique such as an ID to ensure the list has only one possible sort order.
More obvious ones are Dictionaries and HashSets, as these aren't stable in C# either. You need to properly sort them before enumerating any of their content, though of course just doing stuff like Contains or TryGetValue does not pose any risks.
Notable is that this extends to some aspects that may not be obvious. For example, the possible values of an enum are stored in a dictionary-like construct, which means that Enum.GetValues will return values in a non-stable order. A list of stuff that I know for sure:
- Enum.GetValues
- Enum.GetNames
- Type.GetMethods (only when you have metadata disabled?)
- Type.GetFields (only when you have metadata disabled?)
- Type.GetMembers (inherits from the 2 above ones)
It'd be good to address these non-obvious ones so that mapmakers don't have to concern themselves with these, really. I don't really know about the Reflection ones, but at least Enum does normally have a fixed order to them. If there is a fixed order in C# we can open tickets for CSharpLua itself, but otherwise I'd like to eventually see these things addressed on War3Net's fork.
Anyway, returning to the present, would you perhaps have any ideas on other desync possibilities or solutions? I know that the use of "pairs" is not recommended, while it is used in various places in the CSharpLua code. However, besides the ones listed above, I do not believe that other instances of it in CSharpLua are harmful, as the order should not impact the outcome. Going by Damage's map, we can at least assume that the fundamentals aren't inherently problematic, but there are definitely some hidden traps.