Skip to content

Conversation

@Caball009
Copy link

@Caball009 Caball009 commented Aug 1, 2025

Update: Scope of this PR has expanded from patch information to product information.

With this PR it'll become clear which clients are on a patched version with this feature and which are not:

  • the patched clients inform all other clients in the lobby and pre-match of their patch version.
  • the retail clients ignore the patch version data.
  • the patched clients show the player names of patched clients in a different color.
  • the patched clients show the player status of patched clients with a short Git SHA1 hash; is prefixed with ~ if there were uncommitted changes.

LAN Lobby:
image

Pre-match / Game Options:
image

Status in match:
image

TODO:

  • Add code comments.
  • Replicate in Generals.

@Caball009 Caball009 added Enhancement Is new feature or request GUI For graphical user interface Network Anything related to network, servers Gen Relates to Generals ZH Relates to Zero Hour labels Aug 1, 2025
@Caball009 Caball009 marked this pull request as ready for review August 10, 2025 19:34
@Caball009 Caball009 requested a review from a team August 11, 2025 15:24
Copy link

@xezon xezon left a comment

Choose a reason for hiding this comment

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

Good effort.

This work relates to #16

I think the packets need redesigning.

@L3-M
Copy link

L3-M commented Oct 23, 2025

What is the current status of this change? I think this would be a nice change for the first release.

@L3-M L3-M added this to the Important features milestone Oct 23, 2025
@Caball009
Copy link
Author

Caball009 commented Nov 1, 2025

What is the current status of this change? I think this would be a nice change for the first release.

The current implementation ought to be changed to make it more efficient / optimal, but that requires much more work. I did some of the work locally, but it didn't really work out iirc, so the PR is kind of stuck for now.

@Caball009 Caball009 force-pushed the show_clients_with_sh_patch branch from 9fb6a01 to c4e3f1d Compare November 6, 2025 13:52
@Caball009
Copy link
Author

I've revisited this PR and was able to move away from the broadcast implementation. It feels better now. I put networking related changes in one commit and the color / status stuff in another.

What sort of information do we want to exchange just to establish which clients are on a patched version? Maybe it's a good idea to send the commit hash as well.

@Caball009 Caball009 requested a review from a team November 6, 2025 14:04
@Caball009
Copy link
Author

Caball009 commented Nov 6, 2025

Short overview of the new implementation. Patch information is not broadcast and only sent when needed.

Interacting with players in the lobby:

  1. When a player detects a new player in the lobby, they send a patch information request to that player.
  2. If the other player responds with an acknowledgement, they are on a 'patched version'.

Interacting with game hosts in the lobby:

  1. When a player in the lobby detects a new game host, they send a patch information request to that host.
  2. If the game host responds with an acknowledgement, they are on a 'patched version'.

Interacting with players in the pre-match game:

  1. When a player joins a match, they send all players in that match a patch information request.
  2. If the other players respond with an acknowledgement, they are on a 'patched version'.
  3. The other players consider the patch information request from the joining player as acknowledgement.

Currently, players in the lobby do not have a way to know which players in a match are on a 'patched version' except the host. It doesn't seem necessary to me to have the host communicate this information, and it also breaks the current pattern where each client only sends data about itself.

Copy link

@xezon xezon left a comment

Choose a reason for hiding this comment

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

This change is going into the right direction but needs more polishing and wider scope.

Are the pictures of the first post still relevant?

The terminology of the network data needs changing from "Patch" to "Product", because "Patch" is a much more limited term than "Product" is.

The ProductInfo message needs to contain all relevant information to describe the Product that the remote player is using. A version number alone will not be enough to properly describe a Product. Think of 100 different products that the user could interact with in the lobby.

Renamed 'patch' to 'product' and added more information to the product information that's exchanged between clients.
@Caball009
Copy link
Author

Caball009 commented Nov 8, 2025

Are the pictures of the first post still relevant?

Yes, the colors are still like that; the status text will be slightly different. My current idea is that it shows the Git short hash string there (there isn't much room for additional text, unfortunately).

The terminology of the network data needs changing from "Patch" to "Product", because "Patch" is a much more limited term than "Product" is.

Fair enough. Everything should say 'product' instead of 'patch' now.

The ProductInfo message needs to contain all relevant information to describe the Product that the remote player is using. A version number alone will not be enough to properly describe a Product. Think of 100 different products that the user could interact with in the lobby.

I added a couple of stuff (e.g. exe and ini crc values), but I don't feel like this is final version yet.

@Caball009 Caball009 changed the title feat(gui): Distinguish patch players from retail players by a colored name and different status feat(network): Send product information to distinguish clients (with a colored name and different status) Nov 8, 2025
@Caball009
Copy link
Author

I could use some feedback on this PR.

Copy link

@xezon xezon left a comment

Choose a reason for hiding this comment

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

Current thoughts on this. No exhaustive review.

}
if(slot->isHuman())
{
if (myGame->getSlot(i)->getProductInfo().productVersion > 0)
Copy link

Choose a reason for hiding this comment

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

This is only useful for a destinction between Retail and any Community Product version. It does not work well as soon as there are 2 Community Products.

It perhaps would be better to show Tooltip with Product Information on Player Hover.

Other than that, you could implement an auto color coding that is generated from a Product Hash (and blend that new color with the default color to retain overall appearance (bright, dark)).

Copy link
Author

Choose a reason for hiding this comment

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

I currently have no grand designs for any color coding, other than to provide the option to see at a glance who's on retail and who's not.

UnicodeString gitShortHash;
gitShortHash.translate(slot->getProductInfo().gitShortHash);

text.format(L"%s [%s]", text.str(), gitShortHash.str());
Copy link

Choose a reason for hiding this comment

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

What if a product has no git hash? It was not created from a git repository. I think this needs to be more general. Git Hash is also user unfriendly/unreadable.

Maybe use first 3 letters of Product Title and last 5 letters of Product Version or similar. Or build a new hash from Product Title, Version, Author. That is needed anyway if you do the color coding.

&productInfo.productAuthor,
&productInfo.gitShortHash
};
getProductInfoStrings(msg->ProductInfo.data, strings);
Copy link
Author

Choose a reason for hiding this comment

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

@xezon The getProductInfoStrings and setProductInfoStrings logic, is this ok with you? It's basically a way to not waste data on separate arrays for 4 or more strings.

Copy link

Choose a reason for hiding this comment

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

The function interface is oddly specific expecting these array sizes. Perhaps use template instead, although VC6 might have some trouble with [Size]

* LAN message class
*/
#pragma pack(push, 1)
struct LANMessage
Copy link

Choose a reason for hiding this comment

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

You moved this whole struct up so you can use it further down below, which is fine. Can you make a separate Pull Request moving it, so that the diff of this change is cleaner?

const Color chatSystemColor = GameMakeColor(255,255,255,255);
const Color acceptTrueColor = GameMakeColor(0,255,0,255);
const Color acceptFalseColor = GameMakeColor(255,0,0,255);
const Color playerColor = GameMakeColor(255,255,255,255);
Copy link

Choose a reason for hiding this comment

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

This refactor can also be in separate change.

UnsignedInt flags;
UnsignedInt exeCRC;
UnsignedInt iniCRC;
WideChar data[201];
Copy link

Choose a reason for hiding this comment

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

What would be the absolute max possible length for this? I suspect MAX_PACKET_SIZE-12 ?

{
enum CPP_11(: UnsignedInt)
{
COMMUNITY_PATCH = 1 << 0
Copy link

Choose a reason for hiding this comment

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

What is the purpose of this flag? It seems oddly specific. Now every product that derives from this will deliver this flag. If all this is needed for is seeing if the remote player has any non retail patch, then simply check if productTitle (or exeCRC?) is set, because the retail game will not serve this information.

bool isRetailGame() const
{
  return productTitle.empty();
}

char options[m_lanMaxOptionsLength+1];
} GameOptions;

// ProductInfo is sent with REQUEST_PRODUCT_INFO and RESPONSE_PRODUCT_INFO
Copy link

Choose a reason for hiding this comment

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

Perhaps also explain how this is different from the original GameToJoin struct, which also contains exeCRC and iniCRC.

On that note, does ProductInfo also implicitly cover Product information for Game Rooms?

//DEBUG_ASSERTCRASH(false, ("setting host to %ls@%ls", m_currentGame->getLANSlot(0)->getUser()->getLogin().str(),
// m_currentGame->getLANSlot(0)->getUser()->getHost().str()));

// TheSuperHackers @feature Caball009 06/11/2025 Request players in the match to send product information.
Copy link

Choose a reason for hiding this comment

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

You added feature comments at many different places for the same feature. Prefer to document the feature at a single central place, for example before MSG_GAME_REQUEST_PRODUCT_INFO = 1000, or somewhere else suitable.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Enhancement Is new feature or request Gen Relates to Generals GUI For graphical user interface Network Anything related to network, servers ZH Relates to Zero Hour

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants