Пример #1
0
        ///// <summary>
        ///// Create a node and add it to the view-model.
        ///// </summary>
        //public NodeViewModel CreateNode(string name, Point nodeLocation, bool centerNode)
        //{
        //    var node = new NodeViewModel(name);
        //    node.X = nodeLocation.X;
        //    node.Y = nodeLocation.Y;

        //    node.InputConnectors.Add(new ConnectorViewModel("Input"));
        //    node.OutputConnectors.Add(new ConnectorViewModel("Button 1"));
        //    node.OutputConnectors.Add(new ConnectorViewModel("Button 2"));

        //    #region MyRegion
        //    //if (centerNode)
        //    //{
        //    //    //
        //    //    // We want to center the node.
        //    //    //
        //    //    // For this to happen we need to wait until the UI has determined the
        //    //    // size based on the node's data-template.
        //    //    //
        //    //    // So we define an anonymous method to handle the SizeChanged event for a node.
        //    //    //
        //    //    // Note: If you don't declare sizeChangedEventHandler before initializing it you will get
        //    //    //       an error when you try and unsubscribe the event from within the event handler.
        //    //    //
        //    //    EventHandler<EventArgs> sizeChangedEventHandler = null;
        //    //    sizeChangedEventHandler =
        //    //        delegate (object sender, EventArgs e)
        //    //        {
        //    //            //
        //    //            // This event handler will be called after the size of the node has been determined.
        //    //            // So we can now use the size of the node to modify its position.
        //    //            //
        //    //            node.X -= node.Size.Width / 2;
        //    //            node.Y -= node.Size.Height / 2;

        //    //            //
        //    //            // Don't forget to unhook the event, after the initial centering of the node
        //    //            // we don't need to be notified again of any size changes.
        //    //            //
        //    //            node.SizeChanged -= sizeChangedEventHandler;
        //    //        };

        //    //    //
        //    //    // Now we hook the SizeChanged event so the anonymous method is called later
        //    //    // when the size of the node has actually been determined.
        //    //    //
        //    //    node.SizeChanged += sizeChangedEventHandler;
        //    //}
        //    #endregion

        //    //
        //    // Add the node to the view-model.
        //    //
        //    this.Network.Nodes.Add(node);

        //    return node;
        //}
        #endregion
        public NodeViewModel CreateNode(ChatNode chatNode, Point nodeLocation)
        {
            var node = new NodeViewModel(chatNode, nodeLocation);

            this.Network.Nodes.Add(node);
            return(node);
        }
Пример #2
0
        private static void Main(string[] args)
        {
            ChatNode cn = new ChatNode(true);

            Console.WriteLine(cn.OutputAllFrames());
            Console.ReadKey();
        }
Пример #3
0
        /// <summary>
        /// Renders the specified chat node to the client.
        /// </summary>
        /// <param name="node">The node to append.</param>
        /// <remarks>
        /// <para>The return value of this function is a reference to the outermost <see cref="HtmlElement">HtmlElement</see> constructed
        /// by this function.  It may create additional inner elements as needed.</para>
        /// </remarks>
        /// <returns>
        /// Returns an object instance of <see cref="HtmlElement">HtmlElement</see> that can be appended to the HTML document.
        /// </returns>
        public override Inline Render(ChatNode node)
        {
            IIconProvider provider = ProfileResourceProvider.GetForClient(null).Icons;

            ImageChatNode icn = node as ImageChatNode;

            if (icn != null)
            {
                InlineUIContainer result = new InlineUIContainer();
                Image             img    = new Image();
                img.Source  = System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap((icn.Image as System.Drawing.Bitmap).GetHbitmap(), IntPtr.Zero, Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions());
                img.ToolTip = icn.Text;
                img.Width   = provider.IconSize.Width;
                img.Height  = provider.IconSize.Height;

                result.Child = img;

                if (icn.LinkUri != null)
                {
                    Hyperlink container = new Hyperlink(result);
                    container.NavigateUri = node.LinkUri;
                    container.ToolTip     = string.Format(CultureInfo.CurrentUICulture, "Link to {0}", node.LinkUri);

                    return(container);
                }

                return(result);
            }
            else
            {
                return(base.Render(node));
            }
        }
Пример #4
0
 public static string Identifer(this ChatNode node)
 {
     if (!string.IsNullOrWhiteSpace(node.Name))
     {
         return(node.Name + " - " + node.Id);
     }
     return(node.Id);
 }
Пример #5
0
 /**
  * Handles ChatNode changes
  */
 public void HandleChatNodeChange(ChatNode newChatNode)
 {
     if (isActive)
     {
         currentChatNode = newChatNode;
         dialogueManager.ChangeCurrentChatNode(currentChatNode);
     }
 }
Пример #6
0
 public static Content GetFor(this List <Content> contentCollection, ChatNode node)
 {
     if (string.IsNullOrWhiteSpace(node.Id))
     {
         return(null);
     }
     return(contentCollection.FirstOrDefault(x => !string.IsNullOrWhiteSpace(x.NodeId) && x.NodeId == node.Id));
 }
Пример #7
0
        public int GetContinuationIndex()
        {
            ChatNode currentChatNode = dialogueGraph.currentChatNode;
            int      firstValidConditionsListIndex =
                GetFirstListMeetingItsConditions(currentChatNode.continuationConditions);

            return(firstValidConditionsListIndex > -1
                ? firstValidConditionsListIndex
                : currentChatNode.continuationConditions.Count - 1);
        }
Пример #8
0
 public NodeViewModel(ChatNode chatNode, Point?location)
 {
     ChatNode = chatNode;
     InputConnectors.Add(new ConnectorViewModel(""));
     if (location != null)
     {
         X = location.Value.X;
         Y = location.Value.Y;
     }
 }
 public void ShowReceivedMessage(ChatMessageReceivedEvent e, ChatNode chatNode, [JoinAll] SelfUserNode selfUser)
 {
     if (e.SystemMessage)
     {
         base.NewEvent(new BattleChatSystemMessageReceivedEvent(e.Message)).Attach(chatNode).Schedule();
     }
     else if (!selfUser.blackList.BlockedUsers.Contains(e.UserId))
     {
         base.NewEvent(new BattleChatValidMessageReceivedEvent(e.Message, e.UserId)).Attach(chatNode).Schedule();
     }
 }
Пример #10
0
 public override void Init()
 {
     base.Init();
     FloatBallManager.Instance.Hide();
     PageManager.Instance.canvas.renderMode  = RenderMode.ScreenSpaceCamera;
     PageManager.Instance.canvas.worldCamera = Camera.main;
     NodeManager.OpenNode <ChatNode>(null, null, false);
     ChatNode.Close();
     animations = BundleManager.Instance.GetSprites(faceBundle);
     NodeManager.OpenNode <NoticeNode>(null, null, false, false).Inits(Vector3.up * 412.7f, NoticeNode.NoticeSize.Short);
 }
Пример #11
0
        public void CheckForInterruptions()
        {
            ChatNode currentChatNode = dialogueGraph.currentChatNode;
            int      firstValidConditionsListIndex =
                GetFirstListMeetingItsConditions(currentChatNode.interruptionConditions);

            if (firstValidConditionsListIndex > -1)
            {
                dialogueGraph.currentChatNode.PickInterruption(firstValidConditionsListIndex);
            }
        }
Пример #12
0
 private string ExtractNextNodeIdFromAPIResp(ChatNode node, JObject resp)
 {
     if (node.Buttons == null)
     {
         return(null);
     }
     return(node.Buttons.FirstOrDefault(btn =>
                                        !string.IsNullOrWhiteSpace(btn.APIResponseMatchKey) && //resp[btn.APIResponseMatchKey] != null &&
                                        resp.SelectToken(btn.APIResponseMatchKey) + "" == btn.APIResponseMatchValue + "")
            ?.NextNodeId);
 }
Пример #13
0
        internal void addChat(ArrayInstance chatNodes)
        {
            List <ChatNode> result = new List <ChatNode>();

            for (int i = 0; i < chatNodes.Length; i++)
            {
                ObjectInstance obj = chatNodes[i] as ObjectInstance;
                if (obj == null)
                {
                    continue;
                }

                string str  = obj.GetPropertyValue("text") as string;
                object oTxt = obj.GetPropertyValue("text");
                if (oTxt == null)
                {
                    continue;
                }
                str = oTxt.ToString();

                ColorInstance color    = obj.GetPropertyValue("color") as ColorInstance;
                string        cssClass = obj.GetPropertyValue("cssClass") as string;

                if (str == null)
                {
                    continue;
                }
                else if (color == null && cssClass == null)
                {
                    continue;
                }

                ChatNode node;
                if (color == null)
                {
                    node = new ChatNode(str, cssClass);
                }
                else
                {
                    node = new ChatNode(str, Color.FromArgb(255, color.R, color.G, color.B));
                }

                result.Add(node);
            }

            try
            {
                _client.MainWindow.AddChat(result);
            }
            catch (Exception ex)
            {
                throw new JavaScriptException(_engine, ex.GetType().Name, ex.Message);
            }
        }
Пример #14
0
    /// <summary>
    /// Vip时间更新
    /// </summary>
    public static void FinishVipDay(IsVipUserResp isVipUserResp)
    {
        ChatNode node = NodeManager.GetNode <ChatNode>();

        if (node)
        {
            BqPanel bq = node.bqPanel;
            UserInfoModel.userInfo.vipDay = isVipUserResp.TimeLeft;
            bq.vipTimerLb.text            = "剩余" + UserInfoModel.userInfo.vipDay;
        }
    }
Пример #15
0
        ///// <summary>
        ///// Create a node and add it to the view-model.
        ///// </summary>
        //public NodeViewModel CreateNode(string name, Point nodeLocation, bool centerNode)
        //{
        //    var node = new NodeViewModel(name);
        //    node.X = nodeLocation.X;
        //    node.Y = nodeLocation.Y;

        //    node.InputConnectors.Add(new ConnectorViewModel("Input"));
        //    node.OutputConnectors.Add(new ConnectorViewModel("Button 1"));
        //    node.OutputConnectors.Add(new ConnectorViewModel("Button 2"));

        //    #region MyRegion
        //    //if (centerNode)
        //    //{
        //    //    //
        //    //    // We want to center the node.
        //    //    //
        //    //    // For this to happen we need to wait until the UI has determined the
        //    //    // size based on the node's data-template.
        //    //    //
        //    //    // So we define an anonymous method to handle the SizeChanged event for a node.
        //    //    //
        //    //    // Note: If you don't declare sizeChangedEventHandler before initializing it you will get
        //    //    //       an error when you try and unsubscribe the event from within the event handler.
        //    //    //
        //    //    EventHandler<EventArgs> sizeChangedEventHandler = null;
        //    //    sizeChangedEventHandler =
        //    //        delegate (object sender, EventArgs e)
        //    //        {
        //    //            //
        //    //            // This event handler will be called after the size of the node has been determined.
        //    //            // So we can now use the size of the node to modify its position.
        //    //            //
        //    //            node.X -= node.Size.Width / 2;
        //    //            node.Y -= node.Size.Height / 2;

        //    //            //
        //    //            // Don't forget to unhook the event, after the initial centering of the node
        //    //            // we don't need to be notified again of any size changes.
        //    //            //
        //    //            node.SizeChanged -= sizeChangedEventHandler;
        //    //        };

        //    //    //
        //    //    // Now we hook the SizeChanged event so the anonymous method is called later
        //    //    // when the size of the node has actually been determined.
        //    //    //
        //    //    node.SizeChanged += sizeChangedEventHandler;
        //    //}
        //    #endregion

        //    //
        //    // Add the node to the view-model.
        //    //
        //    this.Network.Nodes.Add(node);

        //    return node;
        //}
        #endregion
        public NodeViewModel CreateNode(ChatNode chatNode, Point nodeLocation)
        {
            if (this.Network?.Nodes == null)
            {
                MessageBox.Show("Not connected to chat server or no project is loaded. If this is the first time, create a new project from file menu and get started. Please close the app and try again if the issue continues.");
                return(null);
            }
            var node = new NodeViewModel(chatNode, nodeLocation);

            this.Network.Nodes.Add(node);
            return(node);
        }
Пример #16
0
        /**
         * Sets the current ChatNode to another one, meaning a new dialogue line has to be displayed
         */
        public void ChangeCurrentChatNode(ChatNode newChatNode)
        {
            // Change the stored current ChatNode
            currentChatNode = newChatNode;

            // Start the text-typing coroutine
            string currentChatNodeContent = GetCurrentChatNodeContent();

            chatNodeCoroutinesManager.StartCoroutine(TypeText(currentChatNodeContent, currentChatNode.sentenceDurationInSeconds,
                                                              currentChatNode.totalDurationInSeconds));

            // Change the dialogue headshot
            dialogueHeadshotAnimator.runtimeAnimatorController = currentChatNode.character.animatorController;
        }
Пример #17
0
    public List <ChatNode> GetChatThread(int UserId, int CorrespondentId)
    {
        ChatNode Node = new ChatNode();

        List <ChatNode> ChatThread = new List <ChatNode>();

        using (var Con = new SqlConnection(GC.ConnectionString))
        {
            Con.Open();

            Query = "Select * from User_Chat where Sender_id='" + CorrespondentId + "' and Receiver_id='" + UserId + "' or Sender_id='" + UserId + "' and Receiver_id='" + CorrespondentId + "' order by TimeSpan asc";

            using (var Com = new SqlCommand(Query, Con))
            {
                Reader = Com.ExecuteReader();

                while (Reader.Read())
                {
                    Node = new ChatNode();

                    Node.Message = Reader["Message"].ToString();

                    Users User = new Users();

                    Node.Receiver = User.UserInfo(Convert.ToInt32(Reader["Receiver_id"].ToString()));
                    Node.Sender   = User.UserInfo(Convert.ToInt32(Reader["Sender_id"].ToString()));

                    if (Convert.ToInt32(Reader["Receiver_id"].ToString()) == UserId)
                    {
                        Node.Indicator = 0;
                    }
                    else
                    {
                        Node.Indicator = 1;
                    }



                    ChatThread.Add(Node);
                }
            }

            Con.Close();
        }

        return(ChatThread);
    }
        public void ShowReceivedTeamMessage(BattleChatSystemMessageReceivedEvent e, ChatNode chatNode, [JoinByScreen] BattleChatGUINode battleChatGUINode, [JoinByScreen] ChatContentGUINode chatContentGUINode)
        {
            ChatUIComponent        chatUI    = battleChatGUINode.chatUI;
            GameObject             obj2      = Object.Instantiate <GameObject>(chatContentGUINode.chatContentGUI.MessagePrefab);
            Entity                 entity    = obj2.GetComponent <EntityBehaviour>().Entity;
            ChatMessageUIComponent component = obj2.GetComponent <ChatMessageUIComponent>();

            component.FirstPartText       = string.Empty;
            component.SecondPartText      = e.Message;
            component.SecondPartTextColor = chatUI.SystemMessageColor;
            RectTransform parent = chatContentGUINode.chatContentGUI.gameObject.GetComponent <RectTransform>();

            obj2.transform.SetParent(parent, false);
            parent.offsetMin = Vector2.zero;
            base.ScheduleEvent <ResizeBattleChatScrollViewEvent>(entity);
            chatUI.SendMessage("RefreshCurve", SendMessageOptions.DontRequireReceiver);
        }
Пример #19
0
 public void ShowReceivedMessage(ChatMessageReceivedEvent e, ChatNode chatNode, [JoinAll] SelfUserNode selfNode)
 {
     if (e.SystemMessage || !selfNode.blackList.BlockedUsers.Contains(e.UserId))
     {
         ChatMessage message = new ChatMessage {
             Author   = !e.SystemMessage ? e.UserUid : LocalizationUtils.Localize(this.systemMessageAuthorKey),
             AvatarId = e.UserAvatarId,
             Message  = e.Message,
             Time     = DateTime.Now.ToString("HH:mm"),
             System   = e.SystemMessage,
             Self     = (e.UserId == selfNode.Entity.Id) && !e.SystemMessage,
             ChatType = chatNode.chatChannel.ChatType,
             ChatId   = chatNode.Entity.Id
         };
         chatNode.chatChannel.AddMessage(message);
         base.ScheduleEvent(new RecievedLobbyChatMessageEvent(message), chatNode);
     }
 }
Пример #20
0
        public NodeViewModel(ChatNode chatNode, Point?location)
        {
            ChatNode = chatNode;

            ChatNode.PropertyChanged -= ChatNode_PropertyChanged;
            ChatNode.PropertyChanged += ChatNode_PropertyChanged;

            ChatNode.Buttons.CollectionChanged -= Buttons_CollectionChanged;
            ChatNode.Buttons.CollectionChanged += Buttons_CollectionChanged;

            InputConnectors.Add(new ConnectorViewModel(""));
            InvalidateNode();
            if (location != null)
            {
                X = location.Value.X;
                Y = location.Value.Y;
            }
        }
Пример #21
0
        public static Models.ChatFlowSearchItem SearchNode(this ChatNode node, string searchKeywords)
        {
            if (node.ToString().IsMatch(searchKeywords) || node.Id.IsMatch(searchKeywords))
            {
                return(new Models.ChatFlowSearchItem
                {
                    NodeId = node.Id,
                    NodeText = node.ToString() ?? node.Alias
                });
            }

            foreach (var btn in node.Buttons)
            {
                if (btn.ToString().IsMatch(searchKeywords) || btn._id.IsMatch(searchKeywords))
                {
                    return(new Models.ChatFlowSearchItem
                    {
                        NodeId = node.Id,
                        NodeText = node.ToString() ?? node.Alias,
                        ButtonText = btn.ToString()
                    });
                }
            }

            foreach (var sec in node.Sections)
            {
                if (sec.ToString().IsMatch(searchKeywords) || sec._id.IsMatch(searchKeywords))
                {
                    return(new Models.ChatFlowSearchItem
                    {
                        NodeId = node.Id,
                        NodeText = node.ToString() ?? node.Alias,
                        SectionText = sec.ToString()
                    });
                }
            }

            return(null);
        }
Пример #22
0
 /// <summary>
 /// 发消息
 /// </summary>
 /// <param name="type"></param>
 public void SendMessage(ChatInfo info, bool isClose)
 {
     if (PageManager.Instance.CurrentPage is LandlordsPage)
     {//斗地主
         SocketClient.Instance.AddSendMessageQueue(new C2GMessage()
         {
             ddzChatReq = new DdzChatReq()
             {
                 type           = info.type,
                 ddzChatContent = new DdzChatContent()
                 {
                     text = info.text,
                 }
             },
             msgid = MessageId.C2G_DdzChatReq
         });
     }
     else
     {//麻将
         SocketClient.Instance.AddSendMessageQueue(new C2GMessage()
         {
             UserTalk = new UserTalk()
             {
                 msg  = info.text,
                 type = info.type
             },
             msgid = MessageId.C2G_UserTalk
         });
     }
     if (SetNode.chat == 0)
     {
         TipManager.Instance.OpenTip(TipType.SimpleTip, "您已关闭聊天功能,如要查看聊天信息请在设置里打开聊天功能");
     }
     if (isClose)
     {
         ChatNode.Close();
     }
 }
Пример #23
0
        public (bool, string) LoadChatFlowProject()
        {
            try
            {
                if (!string.IsNullOrWhiteSpace(ProjectFilePath))
                {
                    var rawProjectJson = File.ReadAllText(ProjectFilePath);
                    ChatFlow = BsonSerializer.Deserialize <ChatFlowPack>(rawProjectJson);
                }
                else
                {
                    var firstNode = new ChatNode {
                        Name = "New Node"
                    };
                    firstNode.Id = ObjectId.GenerateNewId().ToString();

                    ChatFlow = new ChatFlowPack
                    {
                        ChatNodes     = new List <ChatNode>(new[] { firstNode }),
                        ChatContent   = new List <Models.BaseContent>(),
                        NodeLocations = new Dictionary <string, Models.LayoutPoint> {
                            { firstNode.Id, new Models.LayoutPoint {
                                  X = 500, Y = 500
                              } }
                        }
                    };
                }
                LastChatFlowSavedHash = Utilities.GenerateHash(ChatFlow.ToJson());
                ChatFlowBuilder.Build(ChatFlow);
                return(true, "");
            }
            catch (Exception ex)
            {
                return(false, ex.Message);
            }
        }
Пример #24
0
        public static List <CarouselItem> ProcessCarousalItems(List <CarouselItem> items, ChatNode parsedNode)
        {
            var resultItems = new List <CarouselItem>();

            foreach (var item in items)
            {
                if (item.DoesRepeat)
                {
                    var repeatOn = ButtonActionHelper.GetSavedArray(item.RepeatOn);
                    var max      = item.MaxRepeats == 0 ? repeatOn.Count - 1 : item.MaxRepeats;
                    for (int i = item.StartPosition; i <= max; i++)
                    {
                        var it = item.DeepCopy();

                        ButtonActionHelper.ClearSavedValue(it.RepeatAs);
                        ButtonActionHelper.HandleSaveTextInput(it.RepeatAs, repeatOn[i] + "");
                        it.Title    = VerbProcessor.Process(it.Title);
                        it.Caption  = VerbProcessor.Process(it.Caption);
                        it.ImageUrl = VerbProcessor.Process(it.ImageUrl);
                        it.Buttons  = VerbProcessor.ProcessCarousalButtons(it.Buttons, parsedNode);
                        ButtonActionHelper.ClearSavedValue(it.RepeatAs);
                    }
                    resultItems.Add(item);
                }
                else
                {
                    item.Buttons = VerbProcessor.ProcessCarousalButtons(item.Buttons, parsedNode);
                    resultItems.Add(item);
                }
            }
            return(resultItems);
        }
Пример #25
0
 public void SendMessageOnEnterPressed(UpdateEvent e, InputFieldNode inputFieldNode, [JoinByScreen] ChatUINode chatUI, [JoinByScreen] ChatNode chat)
 {
     if (Input.GetKeyDown(KeyCode.Return) || Input.GetKeyDown(KeyCode.KeypadEnter))
     {
         this.SendMessage(chat.Entity, chatUI, inputFieldNode);
     }
 }
Пример #26
0
        public void SetMessageLength(InputFieldValueChangedEvent e, InputFieldNode input, [JoinByScreen] ChatNode chat)
        {
            string str = input.inputField.Input;
            int    maxMessageLength = chat.chatConfig.MaxMessageLength;

            if (str.Length > maxMessageLength)
            {
                input.inputField.Input = str.Remove(maxMessageLength);
            }
        }
Пример #27
0
 public NodeEditWindow(ChatNode chatNode)
 {
     InitializeComponent();
     ChatNode    = chatNode.DeepCopy();
     DataContext = this;
 }
Пример #28
0
        //public static string ProcessUnescaped(string input)
        //{
        //    if (string.IsNullOrWhiteSpace(input)) return "";
        //    var matches = Regex.Matches(input, VERB_REGEX);
        //    foreach (Match match in matches)
        //    {
        //        if (match.Groups.Count >= 2)
        //        {
        //            var varName = match.Groups[1].Value;
        //            var value = ButtonActionHelper.GetSavedValue(varName);
        //            if (!string.IsNullOrWhiteSpace(value + ""))
        //                input = input.Replace(match.Value, value + "");
        //        }
        //    }
        //    return input;
        //}

        public static List <CarouselButton> ProcessCarousalButtons(List <CarouselButton> sourceButtons, ChatNode parsedNode)
        {
            var resultBtns = new List <CarouselButton>();

            foreach (var btn in sourceButtons)
            {
                if (btn != null)
                {
                    if (btn.DoesRepeat)
                    {
                        var repeatOn = ButtonActionHelper.GetSavedArray(btn.RepeatOn);
                        var max      = btn.MaxRepeats == 0 ? repeatOn.Count - 1 : btn.MaxRepeats;
                        for (int i = btn.StartPosition; i <= max; i++)
                        {
                            var b = btn.DeepCopy();
                            ButtonActionHelper.ClearSavedValue(b.RepeatAs);
                            ButtonActionHelper.HandleSaveTextInput(b.RepeatAs, repeatOn[i] + "");
                            b.Text         = Process(b.Text);
                            b.Url          = Process(b.Url);
                            b.VariableName = parsedNode.VariableName;
                            b.NodeId       = parsedNode.Id;
                            ButtonActionHelper.ClearSavedValue(b.RepeatAs);
                            resultBtns.Add(b);
                        }
                    }
                    else
                    {
                        btn.VariableName = parsedNode.VariableName;
                        btn.NodeId       = parsedNode.Id;
                        resultBtns.Add(btn);
                    }
                }
            }
            return(resultBtns);
        }
Пример #29
0
 private void OnNextChatNode(ChatNode nodeData)
 {
 }
Пример #30
0
        private void AnnounceUser(UserEventArgs e)
        {
            ChatUser  user        = e.User;
            UserStats us          = e.User.Stats;
            string    imgID       = m_prp.Icons.GetImageIdFor(user.Flags, us);
            ChatNode  productNode = ChatNode.Empty;

            if (m_profile.IncludeIconsInChat)
            {
                Image img = m_prp.Icons.GetImageFor(user.Flags, us);
                productNode = new ImageChatNode(string.Concat(imgID, ".jpg"),
                                                img, imgID);
            }

            switch (us.Product.ProductCode)
            {
            case "DRTL":
            case "DSHR":
            case "SSHR":
            case "STAR":
            case "SEXP":
            case "JSTR":
            case "W2BN":
                StarcraftStats ss = us as StarcraftStats;
                if (ss == null)
                {
                    chat.AddChat(new ChatNode(user.Username, CssClasses.UsernameOther), productNode,
                                 new ChatNode(string.Format(" joined the channel with {0}.", us.Product.Name), CssClasses.JoinedChannel));
                }
                else
                {
                    chat.AddChat(new ChatNode(user.Username, CssClasses.UsernameOther), productNode, new ChatNode(string.Format(" joined the channel with {0} ({1} win{2}, ladder rating {3}, rank {4}).", ss.Product.Name, ss.Wins, ss.Wins != 1 ? "s" : string.Empty,
                                                                                                                                ss.LadderRating, ss.LadderRank), CssClasses.JoinedChannel));
                }
                break;

            case "D2DV":
            case "D2XP":
                Diablo2Stats ds = us as Diablo2Stats;
                if (ds == null)
                {
                    chat.AddChat(new ChatNode(user.Username, CssClasses.UsernameOther), productNode, new ChatNode(string.Format(" joined the channel with {0}.", us.Product.Name), CssClasses.JoinedChannel));
                }
                else
                {
                    StringBuilder sb = new StringBuilder();
                    sb.Append(" joined the channel with ");
                    sb.Append(ds.Product.Name);
                    if (ds.IsRealmCharacter)
                    {
                        sb.Append(" as ");
                        sb.Append(ds.CharacterName);
                        sb.AppendFormat(", a level {0}", ds.Level);
                        if (ds.IsHardcoreCharacter)
                        {
                            sb.Append(" hardcore");
                        }
                        if (ds.IsLadderCharacter)
                        {
                            sb.Append(" ladder");
                        }
                        if (ds.IsExpansionCharacter)
                        {
                            sb.Append(" Expansion ");
                        }
                        else
                        {
                            sb.Append(" Classic ");
                        }
                        sb.Append(ds.CharacterClass);
                        sb.Append(".");

                        chat.AddChat(new ChatNode(ds.UserName, CssClasses.UsernameOther), new ChatNode(sb.ToString(), CssClasses.JoinedChannel));
                    }
                    else
                    {
                        chat.AddChat(new ChatNode(user.Username, CssClasses.UsernameOther), productNode, new ChatNode(string.Format(" joined the channel with {0}.", us.Product.Name), CssClasses.JoinedChannel));
                    }
                }
                break;

            case "WAR3":
            case "W3XP":
                Warcraft3Stats ws = us as Warcraft3Stats;
                if (ws == null)
                {
                    chat.AddChat(new ChatNode(user.Username, CssClasses.UsernameOther), productNode, new ChatNode(string.Format(" joined the channel with {0}.", us.Product.Name), CssClasses.JoinedChannel));
                }
                else
                {
                    if (string.IsNullOrEmpty(ws.ClanTag))
                    {
                        chat.AddChat(new ChatNode(user.Username, CssClasses.UsernameOther), productNode, new ChatNode(string.Format(" joined the channel with {0}, {1} icon tier {2}, level {3}.", ws.Product.Name, ws.IconRace, ws.IconTier, ws.Level), CssClasses.JoinedChannel));
                    }
                    else
                    {
                        chat.AddChat(new ChatNode(user.Username, CssClasses.UsernameOther), productNode, new ChatNode(string.Format(" of clan {0} joined the channel with {1}, {2} icon tier {3}, level {4}.", ws.ClanTag, ws.Product.Name, ws.IconRace, ws.IconTier, ws.Level), CssClasses.JoinedChannel));
                    }
                }
                break;

            default:
                chat.AddChat(new ChatNode(user.Username, CssClasses.UsernameOther), productNode, new ChatNode(string.Format(" joined the channel with {0} ({1}).", us.Product.Name, us.LiteralText), CssClasses.JoinedChannel));
                break;
            }
            if (user.Flags != UserFlags.None)
            {
                chat.AddChat(new ChatNode(user.Username, CssClasses.UsernameOther), new ChatNode(string.Format(" had the following flags: {0}", user.Flags), CssClasses.JoinedChannel));
            }
        }