Defer UI operations until UI system runs frame update#50
Conversation
Component states should be authoritative and ordering should be irrelevant; anything that is co-dependent on another component should be handling that in its own state update by updating the UI. I think the only exception to this is co-dependent compstates but afaik that only affects joints. |
|
Also we need a content issue specifying technologydatabasecomponent should actually be handling the UI update in its own state handler. |
Yeah, I'm just concerned that there's a lot of hidden co-dependent states in there. The
Can look into this; what would be your ideal solution here? Would the Whatever we do to content here is (hopefully) obsoleted by this PR, but there might need to be a huge amount of changes for this; there's two patterns used in UI code- one is that an instance of a |
In the UI system, some updates are applied immediately, while some are deferred until the frame update. This changes all the operations to be deferred. This fixes a UI bug, but there's a more fundamental underlying bug here.
First, the bug;
forcemap PackedstartroundFor clarification:

Two important components here; the
TechnologyDatabaseComponentstores the information on unlocked and available technologies, and theUserInterfaceComponentprovides the UI (uh-huh). TheResearchConsoleBoundUserInterface.UpdateStatecalls an update on theResearchConsoleMenu, which in turn reads theTechnologyDatabaseComponentto populate the UI. When you press the "Research" button, a message is sent to the server which causes it toDirty()both of these components.For the broken computers, the
ClientGameStateManager.ApplyGameStateapplies the state to theUserInterfaceComponentbefore theTechnologyDatabaseComponent, but because theSharedUserInterfaceSystemhas aComponentHandleStatesubscription, it performs the work in that callback immediately so the UI ends up reading stale values. By deferring all the UI operations until the frame render, we know that any components the UI wants to read will have had their state applied.I didn't look into why one of the computers seems to work - suspect it's simply serialization and the order of components stored in that map.
There seems to be a more fundamental issue here; because the component state updates are unordered, any time you have a system which subscribes to
ComponentHandleStateand reads from a different component, you're in danger of getting stale data. I did a quick scan over all the subscriptions in content and most look pretty benign, though it's gonna be a bunch of work to untangle, especially with systems which raise further events in that subscription.SharedSolutionContainerSystemlooks suspicious, for example, whileFixtureSystem(in engine) seems to have a much clearer issue if the updates arrive out of order.