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

Overhaul IRC in preparation for the global chat UI #9586

Merged
merged 3 commits into from Oct 18, 2015

Conversation

pchote
Copy link
Member

@pchote pchote commented Oct 10, 2015

The existing code didn't scale to multiple panels, so I have reorganized and simplified it in preparation for the lobby and ingame integration.

This mainly focuses on the backend code, but there are a few visible changes:

  • Polished topic and op/voice status indicators.
  • Correctly handles kicks and errors.
  • Distinguishes between chat and notifications.

@pchote pchote added this to the Next release milestone Oct 10, 2015
@pchote
Copy link
Member Author

pchote commented Oct 10, 2015

The dispose commit will need to be redone. It currently disposes even when a window is temporarily hidden, which then breaks the chat when it is added to the game lobby (doesn't affect testing in the server brwoser, though).

{
Log.Write("debug", "Failed to load server browser IRC chrome layout");
}
Game.LoadWidget(null, "GLOBALCHAT_PANEL", panel.Get("GLOBALCHAT_ROOT"), new WidgetArgs());
Copy link
Member

Choose a reason for hiding this comment

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

This will make the IRC feature mandatory for every mod. Attention @phrohdoh this will break your RA2 branch.

Copy link
Member

Choose a reason for hiding this comment

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

I don't think we should be making any widget mandatory, and we shouldn't force (our!) IRC on thirdparty mods.

Copy link
Member Author

Choose a reason for hiding this comment

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

Mods that don't want this can define a dummy GLOBALCHAT_PANEL widget to disable it. The try/catch makes it impossible to debug any errors in the IRC logic, and leaves a bogus widget state when it does die.

@pchote
Copy link
Member Author

pchote commented Oct 10, 2015

Fixed the disposing logic.

var font = Game.Renderer.Fonts[widget.Font];

var color = message.Type == ChatMessageType.Notification ?
Color.LightGray : Color.White;
Copy link
Member

Choose a reason for hiding this comment

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

I like the subtle color differentiation, but I guess this wants to live in metrics.yaml instead.

@pchote
Copy link
Member Author

pchote commented Oct 11, 2015

This can crash if the IRC thread adds a message to the History or Users collections while the UI thread is enumerating them. I'll need to ensure that all dictionary accesses are done on the main thread - running just the widget updates in a RunAfterTick is not enough.

}
}

public sealed class ChatUserComparer : IComparer<string>
Copy link
Member

Choose a reason for hiding this comment

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

Use one of the static members on System.StringComparer and save yourself this class.

@pchote pchote force-pushed the irc-common branch 3 times, most recently from 9c96722 to 189033c Compare October 12, 2015 18:55
@pchote
Copy link
Member Author

pchote commented Oct 12, 2015

Fixed all above comments.


public class GlobalChat : IDisposable
{
volatile IrcClient client;
Copy link
Member

Choose a reason for hiding this comment

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

volatile is pointless here.

Copy link
Member Author

Choose a reason for hiding this comment

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

This was carried over from the earlier code, where I believe you asked for it yourself :P.
But you're right - this is only ever accessed from the worker thread now.

{
// Set a random default nick
if (Game.Settings.Chat.Nickname == new ChatSettings().Nickname)
Game.Settings.Chat.Nickname += Game.CosmeticRandom.Next(100, 999);
Copy link
Member

Choose a reason for hiding this comment

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

Modifying globals from a random static constructor is just asking for trouble with initialization order. You should move this somewhere more deterministic.

@pchote
Copy link
Member Author

pchote commented Oct 12, 2015

Updated.

connectionStatus = ChatConnectionStatus.Connected;

// Guard against settings.yaml modification
Game.Settings.Chat.Nickname = SanitizedName(Game.Settings.Chat.Nickname);
Copy link
Member

Choose a reason for hiding this comment

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

This write isn't thread-safe (since we usually only muck with globals on the UI thread).

@pchote pchote force-pushed the irc-common branch 5 times, most recently from d6cf33f to 0464afa Compare October 12, 2015 21:19
@pchote
Copy link
Member Author

pchote commented Oct 12, 2015

Fixed some more. Also fixed an inherited jank when first connecting to the IRC sever.

Game.RunAfterTick(() => Log.Write("irc", e.ToString()));
}

client.Listen();
Copy link
Member

Choose a reason for hiding this comment

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

If the connect fails, do we still want to listen?

@abcdefg30
Copy link
Member

Chat still works. ✅ / 👍

* Simplified UI plumbing.
* Improves handling of errors and kicks.
* Persists chat history between session.
* Fixes leaks of the old widget tree when exiting.
* A few small UI polish improvements.
@pchote
Copy link
Member Author

pchote commented Oct 17, 2015

Updated.

foreach (DictionaryEntry user in channel.Users)
{
var u = (ChannelUser)user.Value;
Game.RunAfterTick(() => Users.Add(u.Nick, new ChatUser(u.Nick, u.IsOp, u.IsVoice)));
Copy link
Contributor

Choose a reason for hiding this comment

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

I guess this is supposed to sync the server's and client's state, right? If so, wouldn't you need to use Users.Clear() before repopulating the list? Or does this only happen once when joining?

Copy link
Member Author

Choose a reason for hiding this comment

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

I haven't read the docs on this callback, but @Mailaender set it up as if it were used exclusively on first join to the channel. If it may be called multiple times, it would indeed be necessary to clear the dict.

Copy link
Contributor

Choose a reason for hiding this comment

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

Looks like it only happens that once. At least it doesn't happen when users join or leave. Could be that it's run once every hour or so, but I didn't test that long.

@obrakmann
Copy link
Contributor

Looks and works fine. 👍

obrakmann added a commit that referenced this pull request Oct 18, 2015
Overhaul IRC in preparation for the global chat UI
@obrakmann obrakmann merged commit c1dda97 into OpenRA:bleed Oct 18, 2015
@obrakmann
Copy link
Contributor

Changelog

@pchote pchote deleted the irc-common branch October 21, 2015 20:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

6 participants