public BnetUsername getUsername(String username)
 {
     String decoding = username, color = null;
     char[] divider = { '|', 'C', 'F', 'F' };
     int step = 0;
     for(int i=0; i<decoding.Length; i++)
     {
         if (step < 4)
         {
             if (decoding[i] == divider[step])
             {
                 if(step < 3)
                 {
                     step++;
                 } else
                 {
                     step = i + 1;
                 }
             }
             else
             {
                 step = 0;
             }
         } else
         {
             decoding = username.Substring(step + 6);
             color = username.Substring(step, 6);
         }
     }
     BnetUsername bnetUsername = new BnetUsername();
     bnetUsername.name = decoding;
     bnetUsername.color = color;
     return bnetUsername;
 }
        private void AddListItem(BnetUsername data,  BnetChattingColor bnetChattingColor = BnetChattingColor.Plain, BnetChattingStatus bnetChattingStatus = BnetChattingStatus.Default)
        {
            String message = "";
            if (bnetChattingColor == BnetChattingColor.Info || bnetChattingColor == BnetChattingColor.Error)
            {
                if(bnetChattingStatus == BnetChattingStatus.Join)
                {
                    String currentChannel = bClient.getCurrentChannel();
                    if (currentChannel != "")
                    {
                        message = "님이 채널 [" + currentChannel + "]에 입장하셨습니다.";
                    }
                    else
                    {
                        message = "님이 입장하셨습니다.";
                    }
                }
                else if(bnetChattingStatus == BnetChattingStatus.Leave)
                {
                    String currentChannel = bClient.getCurrentChannel();
                    if (currentChannel != "")
                    {
                        message = "님이 채널 [" + currentChannel + "]에서 나가셨습니다.";
                    }
                    else
                    {
                        message = "님이 나가셨습니다.";
                    }
                }
            }

            this.AddListItem(data, message, bnetChattingColor);
        }
        public void OnReceiveCallback(IAsyncResult IAR)
        {
            try
            {
                receiveDone.Reset();
                Socket recvSock = (Socket)IAR.AsyncState;
                int receiveLen = recvSock.EndReceive(IAR);
                byte[] receiveBuffer = this.sockBuffer;
                receiveDone.Set();

                if (receiveLen > 0)
                {
                    if (receiveBuffer[0] == 0xFF)
                    {
                        int bnetResult;
                        BnetPacketStruct bnetPackSt = bnetProtocol.decapsulize(receiveBuffer);
                        switch (bnetPackSt.packet_id)
                        {
                            case BnetPacketModel.SID_OPTIONALWORK:
                            case BnetPacketModel.SID_EXTRAWORK:
                            case BnetPacketModel.SID_REQUIREDWORK:
                                this.getHandleMsg("미사용 패킷: " + bnetPackSt.packet_id.ToString("X"));
                                break;
                            case BnetPacketModel.SID_NULL:
                                bnetProtocol.send(recvSock, BnetPacketModel.SID_NULL);
                                break;
                            case BnetPacketModel.SID_PING:
                                bnetProtocol.setBnetByte(bnetPackSt.pack_data.ToArray());
                                bnetProtocol.send(recvSock, BnetPacketModel.SID_PING);
                                this.getHandleMsg(BnetCode.ConnectionPING);
                                break;
                            case BnetPacketModel.SID_AUTH_INFO:
                                bnetProtocol.nlsRevision = bnetPacketStream.readDword(bnetPackSt.pack_data.ToArray(), 0);
                                bnetProtocol.serverToken = bnetPacketStream.readDword(bnetPackSt.pack_data.ToArray(), 4);

                                bnetProtocol.setBnetByte(bnetProtocol.clientToken);
                                bnetProtocol.setBnetByte(0x00000000); // EXE Version
                                bnetProtocol.setBnetByte(0x00000000); // EXE Hash
                                bnetProtocol.setBnetByte(0x00000001); // Number of CD-Key
                                bnetProtocol.setBnetByte(0x00000000); // Spawn CD-Key
                                bnetProtocol.setBnetByte(0x00000000);
                                bnetProtocol.setBnetByte(0x00000000);
                                bnetProtocol.setBnetByte(0x00000000);
                                bnetProtocol.setBnetByte(0x00000000);
                                bnetProtocol.setBnetByte(0x00000000);
                                bnetProtocol.setBnetByte(0x00000000);
                                bnetProtocol.setBnetByte(0x00000000);
                                bnetProtocol.setBnetByte(0x00000000);
                                bnetProtocol.setBnetByte(0x00000000);
                                bnetProtocol.setBnetByte("war3.exe 03/18/11 20:03:55 471040", true);
                                bnetProtocol.setBnetByte("Chat", true);
                                bnetProtocol.send(recvSock, BnetPacketModel.SID_AUTH_CHECK);
                                this.getHandleMsg(BnetCode.ConnectionAUTH_INFO);
                                break;
                            case BnetPacketModel.SID_AUTH_CHECK:
                                bnetResult = BitConverter.ToInt32(bnetPackSt.pack_data.ToArray(), 0);
                                if (bnetResult != 0)
                                {
                                    switch (bnetResult)
                                    {
                                        case 0x201:
                                            this.getHandleMsg(BnetCode.ServerBen);
                                            break;
                                        default:
                                            this.getHandleMsg(BnetCode.UnkownError);
                                            break;
                                    }
                                }
                                else
                                {
                                    byte[] bnetPwHash = bnetProtocol.encriptDobuleHash(bnetUserPw);

                                    bnetProtocol.setBnetByte(bnetProtocol.clientToken);
                                    bnetProtocol.setBnetByte(bnetProtocol.serverToken);
                                    bnetProtocol.setBnetByte(BitConverter.ToUInt32(bnetPwHash, 0));
                                    bnetProtocol.setBnetByte(BitConverter.ToUInt32(bnetPwHash, 4));
                                    bnetProtocol.setBnetByte(BitConverter.ToUInt32(bnetPwHash, 8));
                                    bnetProtocol.setBnetByte(BitConverter.ToUInt32(bnetPwHash, 12));
                                    bnetProtocol.setBnetByte(BitConverter.ToUInt32(bnetPwHash, 16));
                                    bnetProtocol.setBnetByte(bnetUsrId, true);
                                    bnetProtocol.send(recvSock, BnetPacketModel.SID_LOGONRESPONSE2);
                                    this.getHandleMsg(BnetCode.ConnectionAUTH_CHECK);
                                }
                                break;
                            case BnetPacketModel.SID_LOGONRESPONSE2:
                                bnetResult = BitConverter.ToInt32(bnetPackSt.pack_data.ToArray(), 0);
                                switch (bnetResult)
                                {
                                    case 0x00:
                                        this.getHandleMsg(BnetCode.LOGONRESP_Success);
                                        bnetProtocol.setBnetByte(0x00);
                                        bnetProtocol.setBnetByte(0x00);
                                        bnetProtocol.send(recvSock, BnetPacketModel.SID_ENTERCHAT);
                                        break;
                                    case 0x01:
                                        this.getHandleMsg(BnetCode.LOGONRESP_FaildID);
                                        OnChatUserLoginFaild(BnetCode.LOGONRESP_FaildID);
                                        break;
                                    case 0x02:
                                        this.getHandleMsg(BnetCode.LOGONRESP_FaildPW);
                                        OnChatUserLoginFaild(BnetCode.LOGONRESP_FaildPW);
                                        break;
                                    case 0x06:
                                        this.getHandleMsg(BnetCode.LOGONRESP_LockedID);
                                        OnChatUserLoginFaild(BnetCode.LOGONRESP_LockedID);
                                        break;
                                    default:
                                        this.getHandleMsg(BnetCode.UnkownError);
                                        OnChatUserLoginFaild(BnetCode.UnkownError);
                                        break;
                                }
                                break;
                            case BnetPacketModel.SID_ENTERCHAT:
                                this.getHandleMsg(BnetCode.ENTERCHAT);
                                this.getHandleMsg(Encoding.UTF8.GetString(bnetPackSt.pack_data.ToArray()));
                                this.bnetUserUid = bnetPackSt.getUsername(bnetPackSt.getData(bnetPackSt.pack_data.ToArray()));
                                OnChatLogined(this.bnetUserUid);
                                bnetProtocol.setBnetByte(0x01);
                                bnetProtocol.setBnetByte(firstJoinChannel, true);
                                bnetProtocol.send(recvSock, BnetPacketModel.SID_JOINCHANNEL);
                                this.commandFriendsUpdate(this.bnetSock);
                                //Thread musicBotThread = new Thread(new ThreadStart(MusicBot));
                                //musicBotThread.Start();
                                break;
                            case BnetPacketModel.SID_CHATEVENT:
                                BnetPacketEvent bnetPacketEvent = (BnetPacketEvent)BitConverter.ToUInt32(bnetPackSt.pack_data.ToArray(), 0);
                                uint flags = BitConverter.ToUInt32(bnetPackSt.pack_data.ToArray(), 4);
                                uint ping = BitConverter.ToUInt32(bnetPackSt.pack_data.ToArray(), 8);
                                String message;
                                BnetUsername user = bnetPackSt.getUsername(bnetPackSt.getData(bnetPackSt.pack_data.ToArray(), 24));

                                switch (bnetPacketEvent)
                                {
                                    case BnetPacketEvent.EID_CHANNEL:
                                        String channel = bnetPackSt.getData(bnetPackSt.pack_data.ToArray());
                                        this.getHandleMsg("채널 유저 확인:" + user.name);
                                        bnetCurrentChannel = channel;
                                        OnChatInfo(this.bnetUserUid, "님이 " + channel + " 채널에 입장.");
                                        bnetUserList = new List<BnetUsername>();
                                        bnetUserList.Add(this.bnetUserUid);
                                        OnChatUserUpdate(bnetUserList.ToArray());
                                        OnChatUserChannelMove(this.bnetUserUid, channel);
                                        break;
                                    case BnetPacketEvent.EID_USERFLAGS:
                                        this.getHandleMsg("플래그 유저 확인:" + user.name);
                                        bnetUserList = bnetPacketStream.getUserFlags(bnetPackSt, receiveBuffer);
                                        bnetUserList = bnetUserList.Distinct().ToList();
                                        OnChatUserUpdate(bnetUserList.ToArray());

                                        foreach(var data in bnetUserList)
                                        {
                                            this.getHandleMsg("플래그 서브 유저:" + data.name);
                                        }
                                        break;
                                    case BnetPacketEvent.EID_SHOWUSER:
                                        this.getHandleMsg("SHOW 유저 확인:" + user.name);
                                        break;
                                    case BnetPacketEvent.EID_ERROR:
                                        message = bnetPackSt.getData(bnetPackSt.pack_data.ToArray());
                                        this.getHandleMsg(message);
                                        OnChatError(user, message);
                                        break;
                                    case BnetPacketEvent.EID_INFO:
                                    case BnetPacketEvent.EID_BROADCAST:
                                        message = bnetPackSt.getData(bnetPackSt.pack_data.ToArray());
                                        this.getHandleMsg(message);
                                        OnChatInfo(user, message);
                                        break;
                                    case BnetPacketEvent.EID_WHISPER:
                                    case BnetPacketEvent.EID_WHISPERSENT:
                                        message = bnetPackSt.getData(bnetPackSt.pack_data.ToArray());
                                        this.getHandleMsg(message);
                                        OnChatWhisper(user, message);
                                        break;
                                    case BnetPacketEvent.EID_TALK:
                                        message = bnetPackSt.getData(bnetPackSt.pack_data.ToArray());
                                        this.getHandleMsg(message);
                                        OnChatUser(user, message);
                                        break;
                                    case BnetPacketEvent.EID_JOIN:
                                        message = bnetPackSt.getData(bnetPackSt.pack_data.ToArray());
                                        this.getHandleMsg("Join: " + user + " : " + message);
                                        OnChatJoin(user);
                                        bnetUserList.Add(user);
                                        bnetUserList = bnetUserList.Distinct().ToList();
                                        OnChatUserUpdate(bnetUserList.ToArray());
                                        break;
                                    case BnetPacketEvent.EID_LEAVE:
                                        message = bnetPackSt.getData(bnetPackSt.pack_data.ToArray());
                                        this.getHandleMsg("Leave: " + user + " : " + message);
                                        OnChatLeave(user);
                                        bnetUserList.RemoveAll(x => x.name == user.name);
                                        OnChatUserUpdate(bnetUserList.ToArray());
                                        break;
                                    default:
                                        this.getHandleMsg("별도 타입 패킷 [EID]: " + bnetPacketEvent.ToString("X"));
                                        break;
                                }
                                break;
                            case BnetPacketModel.SID_FRIENDSLIST:
                                uint seek = 0;
                                byte cnt = bnetPackSt.pack_data[(int)seek++];
                                BnetFriends[] bnetFriends = new BnetFriends[(int)cnt];
                                this.getHandleMsg(BnetCode.Search_FriendList);
                                this.getHandleMsg("탐색 된 프랜즈 " + cnt.ToString() + " 명");
                                int player;
                                for (player = 0; player < cnt; player++)
                                {
                                    bnetFriends[player].name = bnetPackSt.getUsername(bnetPackSt.getData(bnetPackSt.pack_data.ToArray()));
                                    seek = bnetPackSt.getSeek();
                                    bnetFriends[player].status = bnetPackSt.pack_data[(int)seek++];
                                    bnetFriends[player].location = bnetPackSt.pack_data[(int)seek++];
                                    bnetFriends[player].product = BitConverter.ToUInt32(bnetPackSt.pack_data.ToArray(), (int)seek);
                                    bnetFriends[player].locationName = bnetPackSt.getData(bnetPackSt.pack_data.ToArray(), seek + 4);
                                }

                                try
                                {
                                    OnChatFriendsUpdate(bnetFriends);
                                }
                                catch (NullReferenceException e)
                                {
                                    this.getHandleMsg(e.StackTrace);
                                }
                                break;
                            default:
                                this.getHandleMsg("별도 타입 패킷: " + bnetPackSt.packet_id.ToString("X"));
                                break;
                        }
                    }
                    this.BindREceiveHandler(recvSock);
                }
                else
                {
                    recvSock.Close();
                }
            }
            catch (SocketException e)
            {
                this.getHandleMsg(e.StackTrace);
            }
        }
 private void OnChatUserUpdateHandler(BnetUsername[] bnetUsersname)
 {
     Dispatcher.Invoke(DispatcherPriority.Normal, new Action(delegate
     {
         UsersList.Items.Clear();
         BnetChattingColor bnetChattingColor = new BnetChattingColor();
         for (int i = 0; i < bnetUsersname.Length; i++)
         {
             if (bnetUsersname[i].name == bnetUsername.name)
             {
                 bnetChattingColor = BnetChattingColor.Me;
             }
             else
             {
                 bnetChattingColor = BnetChattingColor.Plain;
             }
             this.AddListUser(bnetUsersname[i], bnetChattingColor);
         }
     }));
 }
 private void OnChatUserChannelMoveHandler(BnetUsername user, String channel)
 {
     Dispatcher.Invoke(DispatcherPriority.Normal, new Action(delegate
     {
         this.MainChannel.Text = channel;
     }));
 }
 private void OnChatWhisperHandler(BnetUsername user, String message)
 {
     Dispatcher.Invoke(DispatcherPriority.Normal, new Action(delegate {
         this.AddListItem(user, message, BnetChattingColor.Whisper);
     }));
 }
 private void OnChatLeaveHandler(BnetUsername user)
 {
     Dispatcher.Invoke(DispatcherPriority.Normal, new Action(delegate {
         this.AddListItem(user, BnetChattingColor.Info, BnetChattingStatus.Leave);
     }));
 }
 private void OnChatLoginHandler(BnetUsername user)
 {
     Dispatcher.Invoke(DispatcherPriority.Normal, new Action(delegate
     {
         MainChatInput.IsEnabled = true;
         MainChatInput.Focus();
         this.AddListItem(user, BnetChattingColor.Info, BnetChattingStatus.Join);
         bnetUsername = bClient.getUsername();
         MainSpinner.IsActive = false;
     }));
 }
        private void AddListFriend(BnetUsername name, String clan, BnetChattingColor bnetChattingColor = BnetChattingColor.Plain)
        {
            ListBoxItem lb = new ListBoxItem();
            TextBlock tb = new TextBlock();
            tb.TextWrapping = TextWrapping.Wrap;
            tb.Text = name.name + ((clan != "") ? " [" + clan + "]" : "");
            lb.Content = tb;
            FriendsList.Items.Add(lb);
            FriendsList.SelectedIndex = FriendsList.Items.Count - 1;
            FriendsList.ScrollIntoView(FriendsList.Items[FriendsList.Items.Count - 1]);

            if (name.color != null)
            {
                tb.Foreground = (SolidColorBrush)(new BrushConverter().ConvertFrom("#" + name.color));
            }

            BnetChattingRGB colorSet = this.getListColor(bnetChattingColor);
            BnetChattingRGB borderSet = new BnetChattingRGB();

            borderSet.r = (byte)Math.Max(0, colorSet.r - 32);
            borderSet.g = (byte)Math.Max(0, colorSet.g - 32);
            borderSet.b = (byte)Math.Max(0, colorSet.b - 32);
            lb.Background = new SolidColorBrush(Color.FromRgb(colorSet.r, colorSet.g, colorSet.b));
            lb.BorderBrush = new SolidColorBrush(Color.FromRgb(borderSet.r, borderSet.g, borderSet.b));
            lb.BorderThickness = new Thickness(1, 1, 1, 1);
        }
        private void AddListItem(BnetUsername data, String message, BnetChattingColor bnetChattingColor = BnetChattingColor.Plain)
        {
            ListBoxItem lb = new ListBoxItem();
            DockPanel dp = new DockPanel();
            TextBlock user = new TextBlock();
            user.Text = data.name;
            if(data.color != null)
            {
                user.Foreground = (SolidColorBrush)(new BrushConverter().ConvertFrom("#" + data.color));
            }
            TextBlock tb = new TextBlock();
            tb.TextWrapping = TextWrapping.Wrap;
            tb.Text = message;
            if (bnetChattingColor == BnetChattingColor.Error || bnetChattingColor == BnetChattingColor.Info || bnetChattingColor == BnetChattingColor.Whisper)
            {
                TextBlock status = new TextBlock();
                Thickness statusMargin = status.Margin;
                statusMargin.Right = 6;
                status.Margin = statusMargin;
                if (bnetChattingColor == BnetChattingColor.Error)
                {
                    status.Text = "[에러]";
                }
                else if (bnetChattingColor == BnetChattingColor.Info)
                {
                    status.Text = "[정보]";
                }
                else if (bnetChattingColor == BnetChattingColor.Whisper)
                {
                    status.Text = "[귓속말]";
                    Thickness userMargin = user.Margin;
                    userMargin.Right = 6;
                    user.Margin = userMargin;
                    user.Text += ":";
                }
                dp.Children.Add(status);
            } else
            {
                Thickness userMargin = user.Margin;
                userMargin.Right = 6;
                user.Margin = userMargin;
                user.Text += ":";
            }
            dp.Children.Add(user);
            dp.Children.Add(tb);
            lb.Content = dp;
            MainChatList.Items.Add(lb);
            MainChatList.SelectedIndex = MainChatList.Items.Count - 1;
            MainChatList.ScrollIntoView(MainChatList.Items[MainChatList.Items.Count - 1]);

            BnetChattingRGB colorSet = this.getListColor(bnetChattingColor);
            BnetChattingRGB borderSet = new BnetChattingRGB();

            borderSet.r = (byte)Math.Max(0, colorSet.r - 32);
            borderSet.g = (byte)Math.Max(0, colorSet.g - 32);
            borderSet.b = (byte)Math.Max(0, colorSet.b - 32);
            lb.Background = new SolidColorBrush(Color.FromRgb(colorSet.r, colorSet.g, colorSet.b));
            lb.BorderBrush = new SolidColorBrush(Color.FromRgb(borderSet.r, borderSet.g, borderSet.b));
            lb.BorderThickness = new Thickness(1, 1, 1, 1);
        }