tweak(gamemessage): Reduce number of MSG_DESTROY_SELECTED_GROUP messages#2668
tweak(gamemessage): Reduce number of MSG_DESTROY_SELECTED_GROUP messages#2668Caball009 wants to merge 7 commits into
Conversation
|
| Filename | Overview |
|---|---|
| GeneralsMD/Code/GameEngine/Source/GameClient/InGameUI.cpp | Core change: deselectAllDrawables now captures whether any drawables were selected before clearing them, and only posts MSG_DESTROY_SELECTED_GROUP when updateGameLogic=true AND objects were previously selected. Logic is correct; the snapshot precedes the deselection loop. |
| Core/GameEngine/Source/GameClient/MessageStream/SelectionXlat.cpp | Introduces m_pendingDeselection to defer the deselect message from RAW_MOUSE_LEFT_BUTTON_UP until after MOUSE_LEFT_CLICK resolves, preventing double MSG_DESTROY_SELECTED_GROUP on new-object selection. Removes the now-redundant deselectAll() static helper. Double-deselection bug in onMetaAddTeam is also fixed with a deselectedAllDrawables flag. |
| Core/GameEngine/Source/GameClient/MessageStream/CommandXlat.cpp | All deselectAllDrawables() call-sites that immediately precede MSG_CREATE_SELECTED_GROUP are updated to pass FALSE, suppressing the redundant MSG_DESTROY_SELECTED_GROUP in those paths. One change is inside a block comment and has no runtime effect. |
| GeneralsMD/Code/GameEngine/Include/GameClient/InGameUI.h | Parameter rename only: postMsg → updateGameLogic for better clarity. No functional change. |
| Core/GameEngine/Include/GameClient/SelectionXlat.h | Adds the m_pendingDeselection Bool member to SelectionTranslator. Straightforward declaration change. |
| GeneralsMD/Code/GameEngine/Source/GameClient/GUI/ControlBar/ControlBarCommandProcessing.cpp | Single call-site update: deselectAllDrawables(FALSE) before MSG_CREATE_SELECTED_GROUP, suppressing the redundant destroy message. |
| Core/GameEngine/Source/GameLogic/System/GameLogicDispatch.cpp | Single call-site update in replay observer path: deselectAllDrawables(FALSE) before reselecting objects for the replay camera, suppressing the destroy message during replay sync. |
Sequence Diagram
%%{init: {'theme': 'neutral'}}%%
sequenceDiagram
participant Mouse
participant SelectionXlat
participant InGameUI
participant MessageStream
Note over Mouse,MessageStream: Alternate mouse mode – click on empty space (deselect)
Mouse->>SelectionXlat: RAW_MOUSE_LEFT_BUTTON_UP
SelectionXlat->>SelectionXlat: "m_pendingDeselection = TRUE"
Mouse->>SelectionXlat: MOUSE_LEFT_CLICK
SelectionXlat->>SelectionXlat: onMouseLeftClick() – no object found
Note over SelectionXlat: m_pendingDeselection still TRUE
SelectionXlat->>InGameUI: "deselectAllDrawables(updateGameLogic=true)"
InGameUI-->>InGameUI: hadSelectedDrawables?
alt had selected drawables
InGameUI->>MessageStream: MSG_DESTROY_SELECTED_GROUP
end
Note over Mouse,MessageStream: Alternate mouse mode – click on new object
Mouse->>SelectionXlat: RAW_MOUSE_LEFT_BUTTON_UP
SelectionXlat->>SelectionXlat: "m_pendingDeselection = TRUE"
Mouse->>SelectionXlat: MOUSE_LEFT_CLICK
SelectionXlat->>SelectionXlat: onMouseLeftClick() – object found
SelectionXlat->>SelectionXlat: "m_pendingDeselection = FALSE"
SelectionXlat->>InGameUI: "deselectAllDrawables(updateGameLogic=false)"
Note over SelectionXlat: No MSG_DESTROY_SELECTED_GROUP (skipped)
SelectionXlat->>MessageStream: MSG_CREATE_SELECTED_GROUP
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
sequenceDiagram
participant Mouse
participant SelectionXlat
participant InGameUI
participant MessageStream
Note over Mouse,MessageStream: Alternate mouse mode – click on empty space (deselect)
Mouse->>SelectionXlat: RAW_MOUSE_LEFT_BUTTON_UP
SelectionXlat->>SelectionXlat: "m_pendingDeselection = TRUE"
Mouse->>SelectionXlat: MOUSE_LEFT_CLICK
SelectionXlat->>SelectionXlat: onMouseLeftClick() – no object found
Note over SelectionXlat: m_pendingDeselection still TRUE
SelectionXlat->>InGameUI: "deselectAllDrawables(updateGameLogic=true)"
InGameUI-->>InGameUI: hadSelectedDrawables?
alt had selected drawables
InGameUI->>MessageStream: MSG_DESTROY_SELECTED_GROUP
end
Note over Mouse,MessageStream: Alternate mouse mode – click on new object
Mouse->>SelectionXlat: RAW_MOUSE_LEFT_BUTTON_UP
SelectionXlat->>SelectionXlat: "m_pendingDeselection = TRUE"
Mouse->>SelectionXlat: MOUSE_LEFT_CLICK
SelectionXlat->>SelectionXlat: onMouseLeftClick() – object found
SelectionXlat->>SelectionXlat: "m_pendingDeselection = FALSE"
SelectionXlat->>InGameUI: "deselectAllDrawables(updateGameLogic=false)"
Note over SelectionXlat: No MSG_DESTROY_SELECTED_GROUP (skipped)
SelectionXlat->>MessageStream: MSG_CREATE_SELECTED_GROUP
Reviews (6): Last reviewed commit: "Misc fixes." | Re-trigger Greptile
2a1e6c7 to
fcb6ef1
Compare
xezon
left a comment
There was a problem hiding this comment.
How confident are we that this will cause no gameplay issues?
| if( !TheInGameUI->getPreventLeftClickDeselectionInAlternateMouseModeForOneClick() ) | ||
| { | ||
| deselectAll(); | ||
| m_pendingDeselection = TRUE; |
There was a problem hiding this comment.
Why is this necessary? Can't we just call deselectAllDrawables here? A second call to deselectAllDrawables will not send a second message then.
There was a problem hiding this comment.
(My comment assumes alternate mouse mode is enabled).
The selection of an object generates two messages, RAW_MOUSE_LEFT_BUTTON_DOWN and MOUSE_LEFT_CLICK. Originally, both would deselect everything, even in the case of a new group creation, which doesn't require prior deselection.
Why is this necessary? Can't we just call
deselectAllDrawableshere? A second call todeselectAllDrawableswill not send a second message then.
It would be ok to call deselectAllDrawables here, except it's extremely likely that the next message is MOUSE_LEFT_CLICK creating a new group in which case there's no Logic deselection required at all. If you can think of a cleaner way to do this, I'd like that.
There was a problem hiding this comment.
So MSG_MOUSE_LEFT_CLICK is synonymous for a single MSG_RAW_MOUSE_LEFT_BUTTON_UP.
If object deselect cannot be fully determined at RAW_MOUSE_LEFT_BUTTON_DOWN, then why not just determine it at only MSG_MOUSE_LEFT_CLICK?
There was a problem hiding this comment.
Perhaps for consistency with RAW_MOUSE_RIGHT_BUTTON_DOWN, and because MSG_MOUSE_LEFT_CLICK has 7 early breaks before it gets to the code that does the group creation.
65a34a7 to
74b9ff4
Compare
8baab11 to
219fa73
Compare
| DEBUG_ASSERTCRASH(selectThisObject->getContainedBy() == nullptr, ("InGameUI::selectNextIdleWorker Selected idle object should not be contained")); | ||
| deselectAllDrawables(); | ||
| deselectAllDrawables(FALSE); | ||
| GameMessage *teamMsg = TheMessageStream->appendMessage( GameMessage::MSG_CREATE_SELECTED_GROUP ); |
There was a problem hiding this comment.
MSG_CREATE_SELECTED_GROUP is guaranteed to deselect, yes? If it was not, then behavior would be changed.
There was a problem hiding this comment.
MSG_CREATE_SELECTED_GROUPis guaranteed to deselect, yes?
That depends on the first parameter. A new group means deselection.
//New group or add to group? Passed in value is true if we are creating a new group.
teamMsg->appendBooleanArgument( TRUE );
There was a problem hiding this comment.
I changed 12 of those (in commit 5), 11 are followed by the creation of a new group.
The other one is here: 1ba3f6e#diff-3d35bdf48c71852a399a66cf0cc15056aa294618b54e3c69b9258b3988979c5bR831 and only applies to playback mode in which object (de)selection shouldn't* impact the game logic anyway.
There was a problem hiding this comment.
Yes but in handler of MSG_CREATE_SELECTED_GROUP are a couple more conditions. I wonder if this is gucci.
There was a problem hiding this comment.
The only relevant one I see is if the ObjectID lookup leads to a nullptr. If that happens we have bigger problems, I think.
There was a problem hiding this comment.
The only way I can see how MSG_CREATE_SELECTED_GROUP + group creation parameter doesn't actually create a new AIGroup is if either all ObjectIDs are invalid or the player mask is invalid.
The behavior in those cases remains the same with or without this PR: no logical deselection / no new group creation and no logical selection.
The client considers primary mouse clicks in the game world as a deselection, and will also update the game logic. This means that
GameMessage::MSG_DESTROY_SELECTED_GROUPmessages are sent frequently, even if no objects are currently selected. There's actually an old EA comment on this issue. It's also unnecessary to send this message prior to the creation of a new group. This PR changes that by checking first if the local player has objects selected, which reduces the number of messages significantly.I've tested with two local clients in multiplayer (VS22 debug builds); one had this feature and one didn't, and everything worked fine.
See commits for cleaner diffs.
Results for Golden Replay 1:
MSG_NETWORK_MESSAGES: 56985MSG_LOGIC_CRC: 11601 (doesn't include 1785 for playback)MSG_DO_MOVETO: 6888MSG_AREA_SELECTION_DEPRECATED: 4476MSG_QUEUE_UNIT_CREATE: 2225MSG_DESTROY_SELECTED_GROUP: 17366MSG_CREATE_SELECTED_GROUP_NO_SOUND: 317, new group: 88MSG_CREATE_SELECTED_GROUP: 8299, new group: 8114MSG_DESTROY_SELECTED_GROUPbefore new group creation: 8901 (more than 8114 + 88, because sometimes this message is used twice).Just the
MSG_DESTROY_SELECTED_GROUPmessage before the creation of a new group accounts for 15% (8901 / 56985) of all network game messages in this replay. That doesn't even take into account how many times this message was used when no units were selected.TODO: