Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Game listings fetched by IRC List #570

Closed
wants to merge 38 commits into from

Conversation

GrantBartlett
Copy link
Member

@GrantBartlett GrantBartlett commented Oct 9, 2024

image

Changes

  • Request LIST of game lobby, should return somewhat instantly the list of games
  • Parse the topic of the channel to give the CnCNet lobby game information (as opposed to using ctcp)
  • Updates topic if game options have changed

Copy link

github-actions bot commented Oct 9, 2024

Nightly build for this pull request:

@GrantBartlett GrantBartlett changed the title WIP: Game listings fetched by IRC List Game listings fetched by IRC List Oct 9, 2024
@GrantBartlett GrantBartlett marked this pull request as ready for review October 9, 2024 16:30
DrawTexture(hostedGame.Game.Texture,
new Rectangle(x, height,
hostedGame.Game.Texture.Width, hostedGame.Game.Texture.Height), Color.White);
var hostedGameTexture = hostedGame.HasSpecialGameMode == true && hostedGame.Game.TextureSpecialGameMode != null ?
Copy link
Member

Choose a reason for hiding this comment

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

remove == true since HasSpecialGameMode is bool

connectionManager.SetChannelTopic(channel, sb.ToString());
}

private StringBuilder BuildGameBroadcastingString()
Copy link
Member

Choose a reason for hiding this comment

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

return string since the caller does not need to append more strings

@@ -1925,11 +1964,19 @@ private void BroadcastGame()
sb.Append(";");
sb.Append(GameMode?.UntranslatedUIName ?? string.Empty);
sb.Append(";");
sb.Append(tunnelHandler.CurrentTunnel.Address + ":" + tunnelHandler.CurrentTunnel.Port);
sb.Append(tunnelHandler?.CurrentTunnel?.Address + ":" + tunnelHandler?.CurrentTunnel?.Port);
Copy link
Member

Choose a reason for hiding this comment

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

Have you test the case where tunnelHandler?.CurrentTunnel?.Address is null, which string will be append?

Personally I prefer if tunnderHandler?.CurrentTunnel is null, append string.Empty, otherwise append {address}:{port}.


broadcastChannel.SendCTCPMessage(sb.ToString(), QueuedMessageType.SYSTEM_MESSAGE, 20);
// Append additional game info (11 onwards)
sb.Append(hasSpecialGameMode ? "1" : "0");
Copy link
Member

@SadPencil SadPencil Oct 9, 2024

Choose a reason for hiding this comment

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

Something like sb.Append(Convert.ToInt32(isCustomPassword));


// Ensure the topic starts with "GAME " as expected
if (!e.Topic.StartsWith("GAME "))
{
Copy link
Member

Choose a reason for hiding this comment

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

In this project, it is preferred not using braces for a single line. Same below.

@@ -20,6 +20,9 @@ public abstract class GenericHostedGame: IEquatable<GenericHostedGame>
public string GameVersion { get; set; }
public string HostName { get; set; }
public string[] Players { get; set; }
public bool HasSpecialGameMode { get; set; }
public bool HasCrates { get; set; }
public bool HasSupers { get; set; }
Copy link
Member

Choose a reason for hiding this comment

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

I prefer HasSuperWeapons

lblCrates.Text = "Crates:".L10N("Client:Main:GameInfoCrates") + " " + Renderer.GetSafeString(game.HasCrates ? "Yes" : "No", lblCrates.FontIndex);
lblCrates.Visible = true;

lblSupers.Text = "Superweapons:".L10N("Client:Main:GameInfoSupers") + " " + Renderer.GetSafeString(game.HasSupers ? "Yes" : "No", lblSupers.FontIndex);
Copy link
Member

Choose a reason for hiding this comment

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

I prefer HasSuperWeapons

@@ -28,11 +28,13 @@ public class CnCNetManager : IConnectionManager
public delegate void UserListDelegate(string channelName, string[] userNames);

public event EventHandler<ServerMessageEventArgs> WelcomeMessageReceived;
public event EventHandler ChannelMOTDComplete;
Copy link
Member

@SadPencil SadPencil Oct 9, 2024

Choose a reason for hiding this comment

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

What is "MOTD" short for?

Copy link
Member Author

Choose a reason for hiding this comment

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

What is "MOTD" short for?

Message of the day

Copy link
Member

Choose a reason for hiding this comment

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

Use "MessageOfTheDay"/"MsgOfTheDay" to replace "MOTD" in the method name or at least leave comments on this abbreviation

@GrantBartlett
Copy link
Member Author

@SadPencil thanks for reviewing - have pushed up the changes

sb.Append(";");

// Append additional game info (11 onwards)
sb.Append(hasSpecialGameMode ? "1" : "0");
Copy link
Member

Choose a reason for hiding this comment

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

duplicated line 1973 and 1974?

Copy link
Member

@SadPencil SadPencil left a comment

Choose a reason for hiding this comment

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

Sorry, but I have another comment and it should be the last, which was not proposed in my initial review.


foreach (var nameTopic in channelList)
{
string channelName = nameTopic.Item1;
Copy link
Member

Choose a reason for hiding this comment

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

C# has builtin support to deconstruct a tuple, which gets rid of meaningless name like "Item1".

(string name1, string name2) = tuple;

https://learn.microsoft.com/en-us/dotnet/csharp/fundamentals/functional/deconstruct

Copy link
Member Author

Choose a reason for hiding this comment

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

Good to know cheers. Have updated

Copy link
Member

@SadPencil SadPencil left a comment

Choose a reason for hiding this comment

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

You may also deconstruct a tuple in foreach loop: foreach ((string name1, string name2) in someCollection)

LGTM

Copy link
Member

@Metadorius Metadorius left a comment

Choose a reason for hiding this comment

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

The idea is good apart from the hacked in special icon, good as a first iteration / PoC, but we would need a bit more work on that so it fits the standards. I've written the suggestions on how to improve further.

Also I would recommend to split the PR if possible/not hard to address and merge the parts individually, but that's up to you, it's kinda in the gray area of features being intertwined enough or not enough.


// Extract the game information from the topic string
string msg = e.Topic.Substring(5); // Cut out "GAME " part
string[] splitMessage = msg.Split(new char[] { ';' });
Copy link
Member

Choose a reason for hiding this comment

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

It would be great if you added a comment with an example valid topic for reference.

Comment on lines 718 to 723
if (UserINISettings.Instance.PlaySoundOnGameHosted &&
cncnetGame.InternalName == localGameID.ToLower() &&
!ProgramConstants.IsInGame && !game.Locked)
{
SoundPlayer.Play(sndGameCreated);
}
Copy link
Member

Choose a reason for hiding this comment

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

I am pretty sure the initial fetch with 100 games is gonna destroy your eardrums if the new game sound is on. Also since you're touching this code anyways - for the sake of better readability we now place operators at the beginning of a split line, not at the end.

string gameRoomChannelName = splitMessage[3];
string gameRoomDisplayName = splitMessage[4];
bool locked = Conversions.BooleanFromString(splitMessage[5].Substring(0, 1), true);
bool isCustomPassword = Conversions.BooleanFromString(splitMessage[5].Substring(1, 1), false);
bool isClosed = Conversions.BooleanFromString(splitMessage[5].Substring(2, 1), true);
Copy link
Member

@Metadorius Metadorius Oct 11, 2024

Choose a reason for hiding this comment

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

You're currently producing a ton of waste IRC traffic and only read 1% of that waste traffic. This won't do.

Either don't remove the game broadcast messages at all (then the routine of parsing the game info need to be split into a new function that would parse both CTCP and channel topics) or change what is broadcasted and how it is broadcasted. What one could do is to broadcast a message "hey, my options changed, please refetch the game info for channel #123456789" and make the client fetch that channel's topic, though it needs evaluation whether that is better than just broadcasting CTCPs.

@Rampastring wdyt?

private string BuildGameBroadcastingString()
{
// @TODO: Do we need a way to allow games/mods to specify their additional game options they want to broadcast
// For now hardcoded bits
Copy link
Member

Choose a reason for hiding this comment

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

Yeah this is a hack, I am quite negative about such hacks. We are trying to walk away from hardcoded per game hacks, this goes against that path.

The client already has options broadcasting for all players inside the lobby, it already builds the string for all the checkboxes, dropdowns etc., so you don't need to invent much, rather reuse. Could add a new INI tag for a game option that would indicate that it is broadcasted to the outside lobby and split options building from that function, and/or reorganize it's a bit since outside/inside options communication seems to be more and more similar with this kind of changes.

Comment on lines 146 to 150
lblCrates.Text = "Crates:".L10N("Client:Main:GameInfoCrates") + " " + Renderer.GetSafeString(game.HasCrates ? "Yes" : "No", lblCrates.FontIndex);
lblCrates.Visible = true;

lblSuperWeapons.Text = "Superweapons:".L10N("Client:Main:GameInfoSuperWeapons") + " " + Renderer.GetSafeString(game.HasSuperWeapons ? "Yes" : "No", lblSuperWeapons.FontIndex);
lblSuperWeapons.Visible = true;
Copy link
Member

Choose a reason for hiding this comment

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

Also no, those things are already defined in INI.

Comment on lines 44 to 45
public Texture2D TextureSpecialGameMode { get; set; }

Copy link
Member

Choose a reason for hiding this comment

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

Same, the solution is hacky, which in this case also goes against the design (this is a distribution/game/mod icon, it can't change depending on a game mode). We would need to come up with a proper way to achieve what you want.

An option I see is:
0. Use both RA2/YR icon as Texture for CnCNet YR,

  1. Make an option in ClientDefintions to hide the main game icon in game list,
  2. Make an option to add enabled/disabled icons to the game settings, something like EnabledIcon and DisabledIcon for INI defined game options, and Icon for dropdown items,
  3. When some option is broadcasted to the outside world - prepend an icon to the game name, same for all of the options.

This way you could define ra2mode as broadcasted to cncnet lobby in INI, define enabled / disabled texture for it and it would change the "icon" of the game.

Comment on lines 1901 to 1905
// @TODO: Sending ctcp for broadcasting may not be needed now, if its only informing cncnet lobby
broadcastChannel.SendCTCPMessage(gameBroadcastingString, QueuedMessageType.SYSTEM_MESSAGE, 20);

// @TODO: Perhaps we should only update the topic when something has changed?
connectionManager.SetChannelTopic(channel, gameBroadcastingString);
Copy link
Member

Choose a reason for hiding this comment

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

See the comment above about generating a ton of waste traffic. We would need to rethink when to send that too. TODOs are correct, they just need to be done. 😛

@GrantBartlett
Copy link
Member Author

I'm going to stop working on this. The benefits aren't enough. Thank you all for your reviews/comments.
I've learnt a lot about the networking of the client so its not been a full waste of time.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants