Skip to content

refactor(gamelogic): Split switch cases of GameLogic::logicMessageDispatcher into separate functions#2702

Open
xezon wants to merge 11 commits into
TheSuperHackers:mainfrom
xezon:xezon/refactor-gamelogicdispatch
Open

refactor(gamelogic): Split switch cases of GameLogic::logicMessageDispatcher into separate functions#2702
xezon wants to merge 11 commits into
TheSuperHackers:mainfrom
xezon:xezon/refactor-gamelogicdispatch

Conversation

@xezon
Copy link
Copy Markdown

@xezon xezon commented May 12, 2026

This change breaks all switch cases of GameLogic::logicMessageDispatcher into separate functions for ease of readability and maintainability.

The logic is unchanged.

TODO

  • Replicate in Generals

@xezon xezon added Minor Severity: Minor < Major < Critical < Blocker Gen Relates to Generals ZH Relates to Zero Hour Refactor Edits the code with insignificant behavior changes, is never user facing labels May 12, 2026
@greptile-apps
Copy link
Copy Markdown

greptile-apps Bot commented May 12, 2026

Greptile Summary

This PR extracts all ~50 switch cases from GameLogic::logicMessageDispatcher into individual bool on*() member functions for readability and maintainability, with a matching TODO replicated in the Generals target. No logic changes are intended.

  • The GameLogicDispatch.cpp dispatch body is collapsed to one-liner calls per case; all handler implementations are appended at the end of the file.
  • Both Generals/ and GeneralsMD/ GameLogic.h headers receive the full set of private method declarations and gain a #include \"GameLogic/AI.h\" (moved from the .cpp) to satisfy the AIGroupPtr reference parameters.

Confidence Score: 5/5

Pure refactor with no logic changes; all extraction is mechanically correct and matches the original switch behavior.

Every issue raised in prior review threads has been addressed: msgPlayer is now declared inside the #if !RETAIL_COMPATIBLE_CRC guards in the special-power handlers; the ALLOW_SURRENDER functions correctly receive AIGroupPtr & currentlySelectedGroup; both header files have the correct ALLOW_SURRENDER signatures; and onLogicCrc preserves the break that exits the slot-finding loop while using return false only in place of the switch-case break, so CRC validation is not silenced. No new functional differences were introduced.

No files require special attention.

Important Files Changed

Filename Overview
Core/GameEngine/Source/GameLogic/System/GameLogicDispatch.cpp Large refactor: switch cases replaced with on*() calls; all handler implementations appended at end of file. break→return false conversions and msgPlayer/currentlySelectedGroup parameter threading are all correct in this revision.
Generals/Code/GameEngine/Include/GameLogic/GameLogic.h Adds private on*() declarations and moves #include "GameLogic/AI.h" here to satisfy AIGroupPtr parameters. ALLOW_SURRENDER signatures correctly carry the AIGroupPtr & parameter.
GeneralsMD/Code/GameEngine/Include/GameLogic/GameLogic.h Mirror of the Generals header change — identical on*() declarations and AI.h include added.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[logicMessageDispatcher] --> B{switch msgType}
    B -->|MSG_NEW_GAME| C[onNewGame]
    B -->|MSG_CLEAR_GAME_DATA| D[onClearGameData]
    B -->|MSG_SET_RALLY_POINT| E[onSetRallyPoint]
    B -->|MSG_DO_SPECIAL_POWER*| F[onDoSpecialPower / onDoSpecialPowerAtLocation / onDoSpecialPowerAtObject / onDoSpecialPowerOverrideDestination]
    B -->|Movement msgs| G[onDoMoveto / onDoAttackmoveto / onAddWaypoint / ...]
    B -->|Production msgs| H[onQueueUnitCreate / onCancelUnitCreate / onDozerConstruct / ...]
    B -->|MSG_LOGIC_CRC| I[onLogicCrc]
    B -->|ALLOW_SURRENDER msgs| J[onDoSurrender / onPickUpPrisoner / onReturnToPrison]
    B -->|...more cases| K[30+ more on* functions]
    I -->|slotIndex found and connected| L[m_shouldValidateCRCs = TRUE / m_cachedCRCs update]
    I -->|slot not found or disconnected| M[return false]
    I -->|playback mode| N[TheRecorder handleCRCMessage]
Loading

Reviews (7): Last reviewed commit: "Add MAYBE_UNUSED to GameMessage args" | Re-trigger Greptile

@xezon
Copy link
Copy Markdown
Author

xezon commented May 12, 2026

Generals fails to compile until replicated.

Comment thread Core/GameEngine/Source/GameLogic/System/GameLogicDispatch.cpp
Comment thread Core/GameEngine/Source/GameLogic/System/GameLogicDispatch.cpp
Comment thread Core/GameEngine/Source/GameLogic/System/GameLogicDispatch.cpp
Comment thread Generals/Code/GameEngine/Include/GameLogic/GameLogic.h
@Caball009
Copy link
Copy Markdown

Do we need the braces per case? It makes the function a lot longer.

@xezon
Copy link
Copy Markdown
Author

xezon commented May 13, 2026

Do we need the braces per case? It makes the function a lot longer.

Is not strictly necessary. Braces are only needed if a variable needs declaration in the top switch case scope. Do you want it removed?

@xezon xezon force-pushed the xezon/refactor-gamelogicdispatch branch from 91c7c5d to 5d14b30 Compare May 13, 2026 19:41
@Caball009
Copy link
Copy Markdown

I don't have a strong opinion on it either way, but I lean toward removing them to make the function shorter.

@xezon
Copy link
Copy Markdown
Author

xezon commented May 22, 2026

Needs rebase.

@xezon xezon force-pushed the xezon/refactor-gamelogicdispatch branch from 5d14b30 to 883093b Compare May 22, 2026 19:19
@xezon
Copy link
Copy Markdown
Author

xezon commented May 22, 2026

Rebased without conflicts.

Comment thread Core/GameEngine/Source/GameLogic/System/GameLogicDispatch.cpp Outdated
Comment thread Core/GameEngine/Source/GameLogic/System/GameLogicDispatch.cpp
Comment thread Core/GameEngine/Source/GameLogic/System/GameLogicDispatch.cpp Outdated
Comment thread Core/GameEngine/Source/GameLogic/System/GameLogicDispatch.cpp Outdated
return true;
}

bool GameLogic::onInternetHack(GameMessage *msg, AIGroupPtr &currentlySelectedGroup)
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

GameMessage *msg is unused.

Copy link
Copy Markdown
Author

@xezon xezon May 25, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok but that is fine. We can keep msg anyway to keep it consistent with all the others. Plus there is a commented code line that uses msg.

Many times in this class.

return true;
}

bool GameLogic::onDoCheer(GameMessage *msg, AIGroupPtr &currentlySelectedGroup)
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

GameMessage *msg is unused.

return true;
}

bool GameLogic::onEvacuate(GameMessage *msg, AIGroupPtr &currentlySelectedGroup)
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

GameMessage *msg is unused.

return true;
}

bool GameLogic::onExecuteRailedTransport(GameMessage *msg, AIGroupPtr &currentlySelectedGroup)
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

GameMessage *msg is unused.

return true;
}

bool GameLogic::onToggleOvercharge(GameMessage *msg, AIGroupPtr &currentlySelectedGroup)
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

GameMessage *msg is unused.

return true;
}

bool GameLogic::onReturnToPrison(GameMessage *msg, AIGroupPtr &currentlySelectedGroup)
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

GameMessage *msg is unused.

Copy link
Copy Markdown

@Caball009 Caball009 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Incomplete review.

  1. There's a bunch of unused function parameters. Could remove or mark with MAYBE_UNUSED.
  2. Player *msgPlayer = getMessagePlayer(msg) can be made const in some functions.
  3. currentlySelectedGroup can be passed by pointer instead of pointer ref, I think.

Comment on lines 735 to 738
case GameMessage::MSG_SELECTED_GROUP_COMMAND:
{

break;

}
Copy link
Copy Markdown

@Caball009 Caball009 May 24, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This case could be removed technically.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I will keep it because the original had it too.

Comment thread Core/GameEngine/Source/GameLogic/System/GameLogicDispatch.cpp
@xezon
Copy link
Copy Markdown
Author

xezon commented May 25, 2026

  1. There's a bunch of unused function parameters. Could remove or mark with MAYBE_UNUSED.

I would like to keep passing all the message pointers because it is the common expectation that the message data is needed to properly act on a message - when it has message arguments.

  1. Player *msgPlayer = getMessagePlayer(msg) can be made const in some functions.

I checked and would like to keep it as is, because some functions do use it in const context but the constness is not consistently applied to all getter methods across the code base. I think that would need a polishing pass first.

  1. currentlySelectedGroup can be passed by pointer instead of pointer ref, I think.

I looked over it one more time and it strictly needs passing as reference only to onClearGameData. We could remove it from the others but that then would mean for the non retail compatible code it would Add_Ref and Release_Ref on function calls, because of RefCountPtr<AIGroup>. I think we can keep passing by reference here. It is ok.

@xezon xezon requested a review from Caball009 May 28, 2026 20:11
@Caball009
Copy link
Copy Markdown

Caball009 commented May 31, 2026

I would like to keep passing all the message pointers because it is the common expectation that the message data is needed to properly act on a message - when it has message arguments.

They ought to be marked as unused, though, otherwise this PR is going to add a bunch of new warnings for it.

@xezon
Copy link
Copy Markdown
Author

xezon commented Jun 1, 2026

They ought to be marked as unused, though, otherwise this PR is going to add a bunch of new warnings for it.

I think unused function arguments trigger no warning.

I did a recompile in VS2022 and there is no warning for this file.

43>GameLogicDispatch.cpp
43>RankInfo.cpp

@Caball009
Copy link
Copy Markdown

Caball009 commented Jun 1, 2026

Perhaps it only shows up when compiling with clang-cl and / or using clang-tidy.

Edit: -Wunused-variable / -Wunused-but-set-variable

@xezon
Copy link
Copy Markdown
Author

xezon commented Jun 3, 2026

Do we care for this? I don't mind unused function arguments. Just disable the warning for that particular aspect.

@Caball009
Copy link
Copy Markdown

Caball009 commented Jun 3, 2026

Disabling a warning should be the last resort.

@xezon
Copy link
Copy Markdown
Author

xezon commented Jun 3, 2026

Yes but what is this warning good for? What problem does it solve?

The problem with removing unused function argument names is that they will need to be added again when they are needed anyway.

void doStuff(float value, const char* name);
void doStuff(int value, const char*); // const char* unused

->
next we use const char*

void doStuff(float value, const char* name);
void doStuff(int value, const char* myNewCustomName); // Now argument name is
                  // added but different from the other because we did not pay attention when we added it

Why is not ok?

void doStuff(float value, const char* name);
void doStuff(int value, const char* name); // const char* unused

@Caball009
Copy link
Copy Markdown

Caball009 commented Jun 3, 2026

The problem with removing unused function argument names is that they will need to be added again when they are needed anyway.

I'm not arguing in favor of removing them. I can see the merit of having uniform arguments for all those functions. Unused variables are unexpected and could indicate an issue (typo or badly refactored code or whatever), though.

I'm arguing in favor marking them as ununsed with MAYBE_UNUSED. That signals that there's no issue and the compiler doesn't emit a warning for it.

@xezon
Copy link
Copy Markdown
Author

xezon commented Jun 3, 2026

Oh ok. I actually was not aware this is possible to set on function arguments. I will try.

@xezon xezon force-pushed the xezon/refactor-gamelogicdispatch branch from 3539719 to 19df18e Compare June 3, 2026 20:25
@xezon
Copy link
Copy Markdown
Author

xezon commented Jun 3, 2026

MAYBE_UNUSED added to function arguments.

@xezon xezon changed the title refactor(gamelogic): Break switch cases of GameLogic::logicMessageDispatcher into separate functions refactor(gamelogic): Split switch cases of GameLogic::logicMessageDispatcher into separate functions Jun 4, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Gen Relates to Generals Minor Severity: Minor < Major < Critical < Blocker Refactor Edits the code with insignificant behavior changes, is never user facing ZH Relates to Zero Hour

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants