Пример #1
0
        private static void Run()
        {
            Connect();
            while (true)
            {
                if (GameBase.Time - lastPingTime > pingTimeout)
                {
                    Connect();
                    Thread.Sleep(20);
                    continue;
                }

                if (client != null && client.Connected)
                {
                    try
                    {
                        //Send any waiting requests.
                        if (Requests.Count > 0 && stream.CanWrite && Authenticated)
                        {
                            Requests.Dequeue().Send(stream);
                            sendSequence = (sendSequence + 1) % ushort.MaxValue;
                        }

                        while (Connected && stream != null && stream.DataAvailable)
                        {
                            lastPingTime = GameBase.Time;

                            readBytes += stream.Read(readByteArray, readBytes, readByteArray.Length - readBytes);

                            //Read header data
                            if (readBytes == readByteArray.Length && readingHeader)
                            {
                                readType    = (RequestType)BitConverter.ToUInt16(readByteArray, 0);
                                compression = readByteArray[2] == 1;
                                uint length = BitConverter.ToUInt32(readByteArray, 3);

                                Console.WriteLine("R" + length + ": " + readType);

                                ResetReadArray(false);
                                readByteArray = new byte[length];
                            }

                            //Read payload data
                            if (readBytes != readByteArray.Length)
                            {
                                continue;
                            }

                            switch (readType)
                            {
                            /* CONNECTION MANAGEMENT */

                            case RequestType.Bancho_LoginReply:
                                GameBase.User.Id = new bInt(readStream).number;
                                switch (GameBase.User.Id)
                                {
                                case -1:
                                    GameBase.ShowMessage(
                                        "Bancho authentication failed.  Please check your username/password by clicking the user pane on the main menu.",
                                        Color.Red, 4400);
                                    Authenticated = false;
                                    Disconnect(true);
                                    if (LoginResult != null)
                                    {
                                        LoginResult(false, null);
                                    }
                                    break;

                                case -2:
                                    GameBase.ShowMessage(
                                        "Bancho connection failed: Version mismatch",
                                        Color.Red, 4400);
                                    GameBase.CheckForUpdates();
                                    Authenticated = false;
                                    Disconnect(true);
                                    return;

                                default:
                                    Console.WriteLine("login success userid:" + GameBase.User.Id);

                                    ChatEngine.BanchoConnected();
                                    GameBase.ShowMessage("Welcome to osu!Bancho.", Color.SlateBlue, 4400);

                                    Status = bStatus.Idle;
                                    UpdateStatus();

                                    Authenticated = true;
                                    if (OnConnect != null)
                                    {
                                        OnConnect();
                                    }
                                    if (LoginResult != null)
                                    {
                                        LoginResult(true, null);
                                    }
                                    break;
                                }
                                break;

                            case RequestType.Bancho_Ping:
                                SendRequest(RequestType.Osu_Pong, null);
                                break;

                            case RequestType.Bancho_VersionUpdate:
                                GameBase.CheckForUpdates();
                                break;

                            /* CHAT and MESSAGING */

                            case RequestType.Bancho_SendIrcMessage:
                                ChatEngine.HandleMessage(new bMessage(readStream), false);
                                break;

                            case RequestType.Bancho_HandleIrcChangeUsername:
                                string message = new bString(readStream).text;
                                string oldname = message.Substring(0, message.IndexOf(">>>>"));
                                string newname = message.Remove(0, message.IndexOf(">>>>") + 4);
                                ChatEngine.HandleChangeUsername(oldname, newname);
                                break;

                            case RequestType.Bancho_HandleIrcQuit:
                                ChatEngine.HandleQuit("#osu", new bString(readStream).text);
                                break;

                            case RequestType.Bancho_HandleIrcJoin:
                                ChatEngine.HandleJoin("#osu", new bString(readStream).text);
                                break;

                            case RequestType.Bancho_HandleOsuQuit:
                                ChatEngine.HandleUserQuit(new bInt(readStream).number);
                                break;

                            /* STATISTICS */

                            case RequestType.Bancho_HandleOsuUpdate:
                                if (readStream == null)
                                {
                                    break;
                                }
                                bUserStats stats = new bUserStats(readStream);
                                ChatEngine.HandleUserUpdate(stats);
                                if (stats.userId == GameBase.User.Id)
                                {
                                    if (stats.username != null)
                                    {
                                        ConfigManager.sUsername = stats.username;
                                    }
                                    GameBase.User.bancho_StatsReceived(null, stats);
                                }
                                break;

                            /* SPECTATING */
                            case RequestType.Bancho_FellowSpectatorJoined:
                                lock (StreamingManager.Spectators)
                                {
                                    User u = GetUserById(new bInt(readStream).number);
                                    StreamingManager.HasSpectators = true;
                                    if (!StreamingManager.FellowSpectators.Contains(u))
                                    {
                                        StreamingManager.FellowSpectators.Add(u);
                                    }
                                    StreamingManager.FellowSpectators.Sort();
                                }
                                break;

                            case RequestType.Bancho_FellowSpectatorLeft:
                                lock (StreamingManager.Spectators)
                                {
                                    User u = GetUserById(new bInt(readStream).number);
                                    StreamingManager.FellowSpectators.Remove(u);
                                    if (StreamingManager.Spectators.Count == 0)
                                    {
                                        StreamingManager.HasSpectators = false;
                                    }
                                }
                                break;

                            case RequestType.Bancho_SpectatorJoined:
                                //Start sending spectator frames.
                                lock (StreamingManager.Spectators)
                                {
                                    User u = GetUserById(new bInt(readStream).number);
                                    u.CantSpectate = false;
                                    if (!StreamingManager.Spectators.Contains(u))
                                    {
                                        StreamingManager.Spectators.Add(u);
                                    }
                                    StreamingManager.HasSpectators = true;
                                    StreamingManager.Spectators.Sort();
                                }
                                break;

                            case RequestType.Bancho_SpectatorCantSpectate:
                                GetUserById(new bInt(readStream).number).CantSpectate = true;
                                break;

                            case RequestType.Bancho_SpectatorLeft:
                                //Stop sending spectator frames.
                                lock (StreamingManager.Spectators)
                                {
                                    User u = GetUserById(new bInt(readStream).number);
                                    u.CantSpectate = false;
                                    StreamingManager.Spectators.Remove(u);
                                    if (StreamingManager.Spectators.Count == 0)
                                    {
                                        StreamingManager.HasSpectators = false;
                                    }
                                }
                                break;

                            case RequestType.Bancho_SpectateFrames:
                                StreamingManager.HandleFrames(new bReplayFrameBundle(readStream));
                                //Received some spectator frames.
                                break;

                            case RequestType.Bancho_GetAttention:
                                ChatEngine.PendingShow = true;
                                break;

                            case RequestType.Bancho_Announce:
                                GameBase.ShowMessage(new bString(readStream).text.Replace("\\n", "\n"), Color.DarkMagenta, 10000);
                                break;

                            case RequestType.Bancho_MatchUpdate:
                            case RequestType.Bancho_MatchNew:
                                Lobby.IncomingMatch(new bMatch(readStream));
                                break;

                            case RequestType.Bancho_MatchStart:
                                MatchSetup.MatchStart(new bMatch(readStream));
                                break;

                            case RequestType.Bancho_MatchDisband:
                                Lobby.DisbandedMatch(new bInt(readStream).number);
                                break;

                            case RequestType.Bancho_LobbyJoin:
                            case RequestType.Bancho_LobbyPart:
                                User f = GetUserById(new bInt(readStream).number);
                                if (f != null)
                                {
                                    f.InLobby = readType == RequestType.Bancho_LobbyJoin;
                                }
                                Lobby.LobbyUpdatePending = true;
                                break;

                            case RequestType.Bancho_MatchJoinFail:
                                Lobby.OnJoinFail();
                                break;

                            case RequestType.Bancho_MatchJoinSuccess:
                                MatchSetup.Match = new bMatch(readStream);
                                Lobby.OnJoinSuccess();
                                break;

                            case RequestType.Bancho_MatchScoreUpdate:
                                if (GameBase.Mode == Modes.Play && Lobby.Status == LobbyStatus.Play)
                                {
                                    PlayerVs.MatchScoreUpdate(new bScoreFrame(readStream));
                                }
                                break;

                            case RequestType.Bancho_MatchTransferHost:
                                MatchSetup.MatchTransferHost();
                                break;

                            case RequestType.Bancho_MatchAllPlayersLoaded:
                                if (GameBase.Mode == Modes.Play && Lobby.Status == LobbyStatus.Play)
                                {
                                    PlayerVs.AllPlayersLoaded = true;
                                }
                                break;

                            case RequestType.Bancho_MatchPlayerFailed:
                                if (GameBase.Mode == Modes.Play && Lobby.Status == LobbyStatus.Play)
                                {
                                    PlayerVs.MatchPlayerFailed(new bInt(readStream).number);
                                }
                                break;

                            case RequestType.Bancho_MatchComplete:
                                if (GameBase.Mode == Modes.Play && Lobby.Status == LobbyStatus.Play)
                                {
                                    PlayerVs.MatchComplete();
                                }
                                break;

                            case RequestType.Bancho_MatchSkip:
                                if (GameBase.Mode == Modes.Play && Lobby.Status == LobbyStatus.Play)
                                {
                                    Player.QueueSkip();
                                }
                                break;

                            case RequestType.Bancho_Unauthorised:

                                break;

                            case RequestType.Bancho_ChannelJoinSuccess:
                                string  match   = new bString(readStream).text;
                                Channel channel = ChatEngine.channels.Find(ch => ch.name == match);
                                if (channel != null)
                                {
                                    channel.HandleJoinSuccess();
                                }
                                break;

                            case RequestType.Bancho_ChannelAvailable:
                                ChatEngine.AddChannel(new bString(readStream).text, false);
                                break;

                            case RequestType.Bancho_ChannelAvailableAutojoin:
                                ChatEngine.AddChannel(new bString(readStream).text, true);
                                break;

                            case RequestType.Bancho_ChannelRevoked:
                                ChatEngine.RemoveChannel(new bString(readStream).text);
                                break;

                            case RequestType.Bancho_BeatmapInfoReply:
                                BeatmapManager.IncomingBeatmapInfoReply(new bBeatmapInfoReply(readStream));
                                break;
                            }
                            ResetReadArray(true);
                        }
                    }
                    catch (Exception e)
                    {
                        if (firstError)
                        {
                            firstError = false;
                            if (Connected)
                            {
                                StringBuilder report = new StringBuilder();
                                report.AppendLine("----------------------BANCHO--------------------------------");
                                report.AppendLine("Bancho error from " + ConfigManager.sUsername + " at " +
                                                  DateTime.UtcNow.ToString(GameBase.nfi));
                                report.AppendLine();
                                report.AppendLine("Mode: " + GameBase.Mode);
                                report.AppendLine();
                                report.Append(e + "\n");
                                report.AppendLine();
                                report.AppendLine("------------------------------------------------------------");
                                try
                                {
                                    new RequestGeneric(RequestType.Osu_ErrorReport, new bString(report.ToString())).Send
                                        (stream);
                                }
                                catch (Exception)
                                {
                                }
                            }
                        }
                        FailConnection("An error occurred somewhere in bancho comms.  Reconnecting!", errorRetry);
                        errorRetry = (int)(errorRetry * 1.5);
                    }
                }

                if (Connected)
                {
                    CheckAfk();
                }

                Thread.Sleep(20);
            }
        }