Conversation
1.6 introduces Statues, which causes problems. This fixes two issues with the new method InitFakePawn: 1. Pawn name sync issue: The pawn name was being synced because the getter was called before the pawn was fully initialized. At that point, the pawn was not set up correctly, which caused syncing errors due to the missing PawnKindDef. 2. Desyncs due to UniqueIdsPatch: This was the main reason I investigated the issue. Many desyncs occurred because UniqueIdsPatch generates negative thing IDs if certain values are set in a specific way. These values differ between client and host — specifically the Multiplayer.InInterface property. The method InitFakePawn is called inside an ExecuteWhenFinished event. On the host, this event runs as an async long event, while on the client it runs as a synced event. As a result, the LongEventHandler.currentEvent field is different on host and client, which makes InInterface differ as well. This causes the host to generate negative new thing IDs, while the clients generate positive ones. Since clients get ahead in nextThingIds, the next time a thing is generated a desync occurs.
To explain the highlighted part: The game expects a lot of objects in the game to have a unique ID, and desyncs will happen when they are out of sync between players. However, sometimes we don't want the IDs to be in syncs. Usually in situations when something happens only for one of the clients - for example, displaying a message when rejecting input. It would be pointless to display a message for every player when it's related to something one person did. Likewise, syncing a message saying "increment IDs by 1" every time such a message is generated would be wasteful - especially since those messages can get quite spammy. So a simple solution to that is to just use negative IDs. Anything with a negative ID is considered a local object that is not synced with all players (unless a bug such as this one occurs). The game never really uses negative values for ID (with exception of -1/-2/-3), meaning it's pretty safe to do so as well. And when we're syncing something using local IDs with other players - that's when such object gets assigned a positive ID. |
To expand a bit on this: We'll likely need to modify |
|
I believe that modifying However, if this is not the case, then we'd need to look into other solutions first. |
|
I have already written a comment and deleted it due me looking wrongly at the code and making a wrong suggestion. Looking into it tomorrow again - Thanks for the feedback :) |
This will still be a problem, I assume. My first solution for that was to change I also looked into the different execution orders between I’ll implement your proposal and make the change for problem 1 as written above :) |
Calling the Pawn.Name getter in CompStatue.InitFakePawn causes issues because the pawn has not been initialized correctly at this point.
Fix Problem 2 from rwmt#632 by adjusting the execution of the cleanup logic in UpdateCurrentAsynchronousEvent, as suggested by @SokyranTheDragon
|
I implemented the suggested changes for Problem 2 and updated the logic for Problem 1 by replacing I created two variations of your proposal:
You can see the implementation for Option B here. I kept the logs so you can review how I tested the functionality, since this is the first time I’ve done it this way. |
|
We migrated our playthrough to 9d235f4 and so far no issues |
Important: From what tool are those screenshots? 😮😮😮
Yep, I did test it
I thought you had this in mind. But I think then it should be the other way around. Meaning leaving the async version as it is and change the other two. But this would just fix the syncing error in the expose process. Multiplayer/Source/Client/Multiplayer.cs Lines 57 to 64 in f0221d0
Yeah that would work. I already had it implemented that way in the unchanged version of this PR. Happily change it back.
I think we don’t update the LongEvents through our tick system (I quickly double checked). The problem happens in the expose process of the statue. |
Honestly, I must have misremembered this code then. Oh well, my bad. Perhaps we should consider adding another condition that checks if we're inside
Using a prefix/finalizer would probably be safer in case of conflicts with other mods - other mods may use the code we're replacing as hooks, or something of the sorts. Although that's probably not the most likely scenario, I feel. Anyway, either way it's done should work. So yeah, I'm giving this PR a green light. Even either in current form, or using prefix/finalizer with |
|
I reverted the change and opened #654 so the additional |


Label: 1.6, High Priority, Fix
Tested:
This PR fixes two issues with the new method CompStatue.InitFakePawn:
Multiplayer/Source/Client/Patches/UniqueIds.cs
Lines 9 to 31 in f0221d0
Important:
I'm not entirely sure if the fix is the right approach. I haven’t looked into why we use two different events or why we rely on local IDs that are negative values. If the fix feels off to you, I can dig deeper into the problem.