Пример #1
0
        public static float RollProportionalGamePoints(StoreIncidentVariables incident, float pointsWager, float gamePoints)
        {
            int cost          = incident.cost;
            int totalPossible = incident.maxWager - incident.minPointsToFire;

            float coinsPerThreatPoint = (totalPossible / 2) / gamePoints;
            float pointsPurchased     = pointsWager / coinsPerThreatPoint;

            float rollToCoinRatio = totalPossible / 8;
            int   totalRolls      = (int)Math.Round(pointsWager / rollToCoinRatio);

            int highestRoll = 65;

            for (int i = 0; i < totalRolls; i++)
            {
                int roll = Verse.Rand.Range(65, 125);
                if (roll > highestRoll)
                {
                    highestRoll = roll;
                }
            }

            float finalPoints = pointsPurchased * ((float)highestRoll / 100f);

            Helper.Log($"wager: {pointsWager} gamePoints: {gamePoints} pointsPurchased: {pointsPurchased} totalRolls: {totalRolls} highestRoll: {highestRoll} finalPoints: {finalPoints}");
            Store_Logger.LogString($"wager: {pointsWager} gamePoints: {gamePoints} pointsPurchased: {pointsPurchased} totalRolls: {totalRolls} highestRoll: {highestRoll} finalPoints: {finalPoints}");

            return(Math.Max(finalPoints, 35));
        }
Пример #2
0
        void OnPrivMsg(IRCMessage message)
        {
            Store_Logger.LogString(message.Message);
            Store_Logger.LogString($"connected: {Toolkit.client.client.Connected} - {DateTime.Now.ToShortTimeString()}");

            //if (activeChatWindow != null && !message.Message.StartsWith("!") && message.User != ToolkitSettings.Username)
            //{
            //    if ((_voteActive && !int.TryParse(message.Message[0].ToString(), out int result)) || !_voteActive)
            //    {
            //        activeChatWindow.AddMessage(
            //            message.Message,
            //            message.User,
            //            (message.Parameters.ContainsKey("color")) ? message.Parameters["color"].Remove(0, 1) : Viewer.GetViewerColorCode(message.User)
            //        );
            //    }

            //}

            Store_Logger.LogString("Checking command");

            if (Helper.ModActive)
            {
                Commands.CheckCommand(message);
            }

            Store_Logger.LogString("Checking if is vote");

            if (VoteHandler.voteActive && int.TryParse(message.Message[0].ToString(), out int voteKey))
            {
                VoteHandler.currentVote.RecordVote(Viewers.GetViewer(message.User).id, voteKey - 1);
            }
        }
Пример #3
0
        public void CalculateNewKarma(KarmaType karmaType, int price)
        {
            int old      = this.GetViewerKarma();
            int newKarma = Karma.CalculateNewKarma(old, karmaType, price);

            SetViewerKarma(newKarma);
            Store_Logger.LogKarmaChange(username, old, newKarma);
        }
Пример #4
0
        void ReadCallback(IAsyncResult asyncResult)
        {
            Store_Logger.LogString("Reading callback");
            var read = _sslStream.EndRead(asyncResult);

            _parser.Parse(_buffer, read, OnCommand);
            Read();
        }
Пример #5
0
 void Read()
 {
     try
     {
         Store_Logger.LogString("Reading buffer");
         _sslStream.BeginRead(_buffer, 0, _buffer.Length, new AsyncCallback(ReadCallback), null);
     }
     catch (Exception)
     {
         Connect();
     }
 }
Пример #6
0
        public override void RunCommand([NotNull] ITwitchMessage twitchMessage)
        {
            var worker = ArgWorker.CreateInstance(CommandFilter.Parse(twitchMessage.Message).Skip(1));

            if (!worker.TryGetNextAsViewer(out Viewer viewer) || !worker.TryGetNextAsInt(out int amount))
            {
                return;
            }

            viewer.GiveViewerCoins(amount);
            Store_Logger.LogGiveCoins(twitchMessage.Username, viewer.username, amount);
            twitchMessage.Reply("TKUtils.GiveCoins.Done".LocalizeKeyed(amount.ToString("N0"), viewer.username, viewer.GetViewerCoins().ToString("N0")));
        }
Пример #7
0
        private static bool ResolvePurchaseSimplePrefix(
            [NotNull] Viewer viewer,
            ITwitchMessage twitchMessage,
            [NotNull] StoreIncidentSimple incident,
            string formattedMessage
            )
        {
            if (!Purchase_Handler.CheckIfViewerHasEnoughCoins(viewer, incident.cost))
            {
                return(false);
            }

            if (Purchase_Handler.CheckIfKarmaTypeIsMaxed(incident, viewer.username))
            {
                return(false);
            }

            if (!TryMakeIncident(incident, viewer, formattedMessage, out IncidentHelper inc))
            {
                TkUtils.Logger.Warn(@$ "The incident " "{incident.defName}" " does not define an incident helper");

                return(false);
            }

            if (!inc.IsPossible())
            {
                MessageHelper.ReplyToUser(viewer.username, "TwitchToolkitEventNotPossible".Localize());

                return(false);
            }

            viewer.Charge(incident);

            Current.Game.GetComponent <Coordinator>()?.QueueIncident(new IncidentProxy {
                SimpleIncident = inc
            });
            Current.Game.GetComponent <Store_Component>()?.LogIncident(incident);

            Store_Logger.LogPurchase(viewer.username, twitchMessage.Message);

            if (!ToolkitSettings.PurchaseConfirmations)
            {
                return(false);
            }

            TwitchWrapper.SendChatMessage(
                Helper.ReplacePlaceholder("TwitchToolkitEventPurchaseConfirm".Localize(), viewer: viewer.username, first: incident.label.CapitalizeFirst())
                );

            return(false);
        }
Пример #8
0
        public override void RunCommand(IRCMessage message)
        {
            Viewer viewer = Viewers.GetViewer(message.User);

            string[] command = message.Message.Split(' ');

            if (command.Count() < 3)
            {
                Log.Message("command not long enough");
                return;
            }

            string target = command[1].Replace("@", "");

            bool isNumeric = int.TryParse(command[2], out int amount);

            if (isNumeric && amount > 0)
            {
                Viewer giftee = Viewers.GetViewer(target);

                if (ToolkitSettings.KarmaReqsForGifting)
                {
                    if (giftee.GetViewerKarma() < ToolkitSettings.MinimumKarmaToRecieveGifts || viewer.GetViewerKarma() < ToolkitSettings.MinimumKarmaToSendGifts)
                    {
                        return;
                    }
                }

                if (viewer.GetViewerCoins() >= amount)
                {
                    viewer.TakeViewerCoins(amount);
                    giftee.GiveViewerCoins(amount);
                    Toolkit.client.SendMessage($"@{giftee.username} " + Helper.ReplacePlaceholder("TwitchToolkitGiftCoins".Translate(), amount: amount.ToString(), from: viewer.username), CommandsHandler.SendToChatroom(message));
                    Store_Logger.LogGiftCoins(viewer.username, giftee.username, amount);
                }
            }
        }
Пример #9
0
        private static bool ResolvePurchaseVariablesPrefix(
            [NotNull] Viewer viewer,
            ITwitchMessage twitchMessage,
            [NotNull] StoreIncidentVariables incident,
            string formattedMessage
            )
        {
            if (!Purchase_Handler.CheckIfViewerHasEnoughCoins(viewer, incident.cost) || IsOnCooldown(incident, viewer))
            {
                return(false);
            }

            if (!TryMakeIncident(incident, viewer, formattedMessage, out IncidentHelperVariables inc))
            {
                TkUtils.Logger.Warn(@$ "The incident " "{incident.defName}" " does not define an incident helper");

                return(false);
            }

            Purchase_Handler.viewerNamesDoingVariableCommands.Add(viewer.username.ToLowerInvariant());

            if (!inc.IsPossible(formattedMessage, viewer))
            {
                Purchase_Handler.viewerNamesDoingVariableCommands.Remove(viewer.username.ToLowerInvariant());

                return(false);
            }

            Store_Logger.LogPurchase(viewer.username, twitchMessage.Message);
            Current.Game.GetComponent <Coordinator>()?.QueueIncident(new IncidentProxy {
                VariablesIncident = inc
            });
            Current.Game.GetComponent <Store_Component>()?.LogIncident(incident);

            return(false);
        }
Пример #10
0
        public override void RunCommand(TwitchIRCMessage message)
        {
            try
            {
                string[] command = message.Message.Split(' ');

                if (command.Length < 3)
                {
                    return;
                }

                string receiver = command[1].Replace("@", "");

                if (message.User.ToLower() != ToolkitSettings.Channel.ToLower() && receiver.ToLower() == message.User.ToLower())
                {
                    Toolkit.client.SendMessage($"@{message.User} " + "TwitchToolkitModCannotGiveCoins".Translate());
                    return;
                }

                int  amount;
                bool isNumeric = int.TryParse(command[2], out amount);
                if (isNumeric)
                {
                    Viewer giftee = ViewerModel.GetViewerByTypeAndUsername(receiver, message.Viewer.ViewerType);

                    Helper.Log($"Giving viewer {giftee.Username} {amount} coins");
                    giftee.GiveCoins(amount);
                    Toolkit.client.SendMessage($"@{message.User} " + Helper.ReplacePlaceholder("TwitchToolkitGivingCoins".Translate(), viewer: giftee.Username, amount: amount.ToString(), newbalance: giftee.Coins.ToString()), CommandsHandler.SendToChatroom(message));
                    Store_Logger.LogGiveCoins(message.User, giftee.Username, amount);
                }
            }
            catch (InvalidCastException e)
            {
                Helper.Log("Invalid Give Viewer Coins Command " + e.Message);
            }
        }
Пример #11
0
        public override void RunCommand(ITwitchMessage twitchMessage)
        {
            try
            {
                string[] command = twitchMessage.Message.Split(' ');

                if (command.Length < 3)
                {
                    return;
                }

                string receiver = command[1].Replace("@", "");

                if (twitchMessage.Username.ToLower() != ToolkitSettings.Channel.ToLower() && receiver.ToLower() == twitchMessage.Username.ToLower())
                {
                    TwitchWrapper.SendChatMessage($"@{twitchMessage.Username} " + "TwitchToolkitModCannotGiveCoins".Translate());
                    return;
                }

                int  amount;
                bool isNumeric = int.TryParse(command[2], out amount);
                if (isNumeric)
                {
                    Viewer giftee = Viewers.GetViewer(receiver);

                    Helper.Log($"Giving viewer {giftee.username} {amount} coins");
                    giftee.GiveViewerCoins(amount);
                    TwitchWrapper.SendChatMessage($"@{twitchMessage.Username} " + Helper.ReplacePlaceholder("TwitchToolkitGivingCoins".Translate(), viewer: giftee.username, amount: amount.ToString(), newbalance: giftee.coins.ToString()));
                    Store_Logger.LogGiveCoins(twitchMessage.Username, giftee.username, amount);
                }
            }
            catch (InvalidCastException e)
            {
                Helper.Log("Invalid Give Viewer Coins Command " + e.Message);
            }
        }
Пример #12
0
        public override void ParseCommand(IRCMessage msg)
        {
            Viewer viewer = Viewers.GetViewer(msg.User);

            foreach (KeyValuePair <string, string> pair in msg.Parameters)
            {
                //Log.Warning(pair.Key + " : " + pair.Value);
                switch (pair.Key)
                {
                case "color":
                    if (pair.Value == null)
                    {
                        break;
                    }
                    string colorCode = "";
                    if (pair.Value.Length > 6)
                    {
                        colorCode = pair.Value.Remove(0, 1);
                        ToolkitSettings.ViewerColorCodes[msg.User.ToLower()] = colorCode;
                    }
                    else
                    {
                        break;
                    }
                    GameComponentPawns component = Current.Game.GetComponent <GameComponentPawns>();

                    if (component.HasUserBeenNamed(msg.User))
                    {
                        Pawn pawn = component.PawnAssignedToUser(msg.User);

                        pawn.story.hairColor = GetColorFromHex(colorCode);
                    }

                    break;

                case "mod":
                    if (viewer.mod || pair.Value == null)
                    {
                        break;
                    }
                    bool modValue = int.TryParse(pair.Value, out int modStatus);
                    if (modValue && modStatus == 1)
                    {
                        viewer.mod = true;
                    }
                    break;

                case "subscriber":
                    if (pair.Value == null)
                    {
                        break;
                    }
                    bool subValue = int.TryParse(pair.Value, out int subStatus);
                    if (subValue && subStatus == 1)
                    {
                        viewer.subscriber = true;
                    }
                    break;

                case "badges":
                    if (pair.Value == null)
                    {
                        break;
                    }
                    IEnumerable <string> badges = pair.Value.Split(',');
                    foreach (string badge in badges)
                    {
                        if (badge == "vip/1")
                        {
                            viewer.vip = true;
                            break;
                        }
                    }
                    break;
                }
            }

            Store_Logger.LogString("Parsed command parameters");
        }
Пример #13
0
        public override void ParseCommand(IRCMessage msg)
        {
            Viewer viewer = Viewers.GetViewer(msg.User);

            GameComponentPawns component = Current.Game.GetComponent <GameComponentPawns>();

            if (msg.Message.StartsWith("!mypawnskills") && Commands.AllowCommand(msg))
            {
                if (!component.HasUserBeenNamed(viewer.username))
                {
                    Toolkit.client.SendMessage($"@{viewer.username} you are not in the colony.", Commands.SendToChatroom(msg));
                    return;
                }

                Pawn   pawn   = component.PawnAssignedToUser(viewer.username);
                string output = $"@{viewer.username} {pawn.Name.ToStringShort.CapitalizeFirst()}'s skill levels are ";

                List <SkillRecord> skills = pawn.skills.skills;

                for (int i = 0; i < skills.Count; i++)
                {
                    if (skills[i].TotallyDisabled)
                    {
                        output += $"{skills[i].def.LabelCap}: -";
                    }
                    else
                    {
                        output += $"{skills[i].def.LabelCap}: {skills[i].levelInt}";
                    }

                    if (skills[i].passion == Passion.Minor)
                    {
                        output += "+";
                    }
                    if (skills[i].passion == Passion.Major)
                    {
                        output += "++";
                    }

                    if (i != skills.Count - 1)
                    {
                        output += ", ";
                    }
                }

                Toolkit.client.SendMessage(output, Commands.SendToChatroom(msg));
            }

            if (msg.Message.StartsWith("!mypawnstory") && Commands.AllowCommand(msg))
            {
                if (!component.HasUserBeenNamed(viewer.username))
                {
                    Toolkit.client.SendMessage($"@{viewer.username} you are not in the colony.", Commands.SendToChatroom(msg));
                    return;
                }

                Pawn pawn = component.PawnAssignedToUser(viewer.username);

                string output = $"@{viewer.username} About {pawn.Name.ToStringShort.CapitalizeFirst()}: ";

                List <Backstory> backstories = pawn.story.AllBackstories.ToList();

                for (int i = 0; i < backstories.Count; i++)
                {
                    output += backstories[i].title;
                    if (i != backstories.Count - 1)
                    {
                        output += ", ";
                    }
                }

                output += " | " + pawn.gender;

                StringBuilder stringBuilder            = new StringBuilder();
                WorkTags      combinedDisabledWorkTags = pawn.story.CombinedDisabledWorkTags;
                if (combinedDisabledWorkTags == WorkTags.None)
                {
                    stringBuilder.Append("(" + "NoneLower".Translate() + "), ");
                }
                else
                {
                    List <WorkTags> list  = WorkTagsFrom(combinedDisabledWorkTags).ToList <WorkTags>();
                    bool            flag2 = true;
                    foreach (WorkTags tags in list)
                    {
                        if (flag2)
                        {
                            stringBuilder.Append(tags.LabelTranslated().CapitalizeFirst());
                        }
                        else
                        {
                            stringBuilder.Append(tags.LabelTranslated());
                        }
                        stringBuilder.Append(", ");
                        flag2 = false;
                    }
                }
                string text = stringBuilder.ToString();
                text = text.Substring(0, text.Length - 2);

                output += " | Incapable of: " + text;

                output += " | Traits: ";

                List <Trait> traits = pawn.story.traits.allTraits;
                for (int i = 0; i < traits.Count; i++)
                {
                    output += traits[i].LabelCap;

                    if (i != traits.Count - 1)
                    {
                        output += ", ";
                    }
                }

                Toolkit.client.SendMessage(output, Commands.SendToChatroom(msg));
            }

            if (msg.Message.StartsWith("!changepawnname") && Commands.AllowCommand(msg))
            {
                string[] command = msg.Message.Split(' ');

                if (command.Length < 2)
                {
                    return;
                }

                string newName = command[1];

                if (newName == null || newName == "" || newName.Length > 16)
                {
                    Toolkit.client.SendMessage($"@{viewer.username} your name can be up to 16 characters.", Commands.SendToChatroom(msg));
                    return;
                }

                if (!component.HasUserBeenNamed(viewer.username))
                {
                    Toolkit.client.SendMessage($"@{viewer.username} you are not in the colony.", Commands.SendToChatroom(msg));
                    return;
                }

                if (!Purchase_Handler.CheckIfViewerHasEnoughCoins(viewer, 500, true))
                {
                    return;
                }

                viewer.TakeViewerCoins(500);
                nameRequests.Add(viewer.username, newName);
                Toolkit.client.SendMessage($"@{ToolkitSettings.Channel} {viewer.username} has requested to be named {newName}, use !approvename @{viewer.username} or !declinename @{viewer.username}", false);
            }

            if (Viewer.IsModerator(viewer.username) || viewer.username == ToolkitSettings.Channel)
            {
                if (msg.Message.StartsWith("!unstickpeople"))
                {
                    Purchase_Handler.viewerNamesDoingVariableCommands = new List <string>();
                }

                if (msg.Message.StartsWith("!approvename"))
                {
                    string[] command = msg.Message.Split(' ');

                    if (command.Length < 2)
                    {
                        return;
                    }

                    string username = command[1].Replace("@", "");

                    if (username == null || username == "" || !nameRequests.ContainsKey(username))
                    {
                        Toolkit.client.SendMessage($"@{viewer.username} invalid username", Commands.SendToChatroom(msg));
                        return;
                    }

                    if (!component.HasUserBeenNamed(username))
                    {
                        return;
                    }

                    Pawn       pawn = component.PawnAssignedToUser(username);
                    NameTriple old  = pawn.Name as NameTriple;
                    pawn.Name = new NameTriple(old.First, nameRequests[username], old.Last);
                    Toolkit.client.SendMessage($"@{viewer.username} approved request for name change from {old} to {pawn.Name}");
                }

                if (msg.Message.StartsWith("!declinename"))
                {
                    string[] command = msg.Message.Split(' ');

                    if (command.Length < 2)
                    {
                        return;
                    }

                    string username = command[1].Replace("@", "");

                    if (username == null || username == "" || !nameRequests.ContainsKey(username))
                    {
                        Toolkit.client.SendMessage($"@{viewer.username} invalid username", Commands.SendToChatroom(msg));
                        return;
                    }

                    if (!component.HasUserBeenNamed(username))
                    {
                        return;
                    }

                    nameRequests.Remove(username);
                    Toolkit.client.SendMessage($"@{viewer.username} declined name change request from {username}");
                }
            }

            Store_Logger.LogString("Parsed pawn command");
        }
Пример #14
0
        public static void AwardViewersCoins(int setamount = 0)
        {
            List <string> usernames = ParseViewersFromJsonAndFindActiveViewers();

            if (usernames != null)
            {
                foreach (string username in usernames)
                {
                    Viewer viewer = GetViewer(username);

                    if (viewer.IsBanned)
                    {
                        continue;
                    }

                    if (setamount > 0)
                    {
                        viewer.GiveViewerCoins(setamount);
                    }
                    else
                    {
                        int   baseCoins      = ToolkitSettings.CoinAmount;
                        float baseMultiplier = (float)viewer.GetViewerKarma() / 100f;

                        if (viewer.IsSub)
                        {
                            baseCoins      += ToolkitSettings.SubscriberExtraCoins;
                            baseMultiplier *= ToolkitSettings.SubscriberCoinMultiplier;
                        }
                        else if (viewer.IsVIP)
                        {
                            baseCoins      += ToolkitSettings.VIPExtraCoins;
                            baseMultiplier *= ToolkitSettings.VIPCoinMultiplier;
                        }
                        else if (viewer.mod)
                        {
                            baseCoins      += ToolkitSettings.ModExtraCoins;
                            baseMultiplier *= ToolkitSettings.ModCoinMultiplier;
                        }

                        // check if viewer is active in chat
                        int minutesSinceViewerWasActive = TimeHelper.MinutesElapsed(viewer.last_seen);

                        if (ToolkitSettings.ChatReqsForCoins)
                        {
                            if (minutesSinceViewerWasActive > ToolkitSettings.TimeBeforeHalfCoins)
                            {
                                baseMultiplier *= 0.5f;
                            }

                            if (minutesSinceViewerWasActive > ToolkitSettings.TimeBeforeNoCoins)
                            {
                                baseMultiplier *= 0f;
                            }
                        }

                        double coinsToReward = (double)baseCoins * baseMultiplier;

                        Store_Logger.LogString($"{viewer.username} gets {baseCoins} * {baseMultiplier} coins, total {(int)Math.Ceiling(coinsToReward)}");

                        viewer.GiveViewerCoins((int)Math.Ceiling(coinsToReward));
                    }
                }
            }
        }
        public override void ParseCommand(IRCMessage msg)
        {
            foreach (KeyValuePair <string, string> pair in msg.Parameters)
            {
                //Log.Warning($"{pair.Key} : {pair.Value}");

                return;

                switch (pair.Key)
                {
                case "color":
                    if (pair.Value == null)
                    {
                        return;
                    }
                    string colorCode = "";
                    if (pair.Value.Length > 6)
                    {
                        colorCode = pair.Value.Remove(0, 1);
                        ToolkitSettings.ViewerColorCodes[msg.User.ToLower()] = colorCode;
                    }
                    else
                    {
                        break;
                    }
                    GameComponentPawns component = Current.Game.GetComponent <GameComponentPawns>();

                    if (component.HasUserBeenNamed(msg.User))
                    {
                        Pawn pawn = component.PawnAssignedToUser(msg.User);

                        pawn.story.hairColor = GetColorFromHex(colorCode);
                    }

                    break;

                case "mod":
                    if (pair.Value == null)
                    {
                        return;
                    }
                    bool modValue = int.TryParse(pair.Value, out int modStatus);
                    if (modValue && modStatus == 1)
                    {
                        Viewers.GetViewer(msg.User).mod = true;
                    }
                    break;

                case "subscriber":
                    if (pair.Value == null)
                    {
                        return;
                    }
                    bool subValue = int.TryParse(pair.Value, out int subStatus);
                    if (subValue && subStatus == 1)
                    {
                        Viewers.GetViewer(msg.User).subscriber = true;
                    }
                    break;
                }
            }

            Store_Logger.LogString("Parsed command parameters");
        }
Пример #16
0
        public void Parse(byte[] buffer, int length, OnMessage callback)
        {
            Store_Logger.LogString("parsing string");
            Decoder decoder = Helper.LanguageEncoding().GetDecoder();

            char[] chars;

            int charCount = decoder.GetCharCount(buffer, 0, buffer.Length);

            chars = new Char[charCount];
            int charLength = decoder.GetChars(buffer, 0, buffer.Length, chars, 0, true);

            _state = IRCParserState.Start;
            for (int i = 0; i < length; i++)
            {
                if (i > 8024)
                {
                    continue;
                }
                var b = chars[i];
                switch (_state)
                {
                case IRCParserState.Start:
                    //Helper.Log($"{_state} starts at {i} {b}");
                    string msg = "";
                    foreach (char c in chars)
                    {
                        msg += c;
                    }
                    _message = new IRCMessage();
                    _key     = "";
                    _value   = "";
                    switch (b)
                    {
                    case 'P':
                        _state = IRCParserState.P;
                        break;

                    case '@':
                        _state = IRCParserState.Key;
                        break;

                    case ':':
                        _state = IRCParserState.Host;
                        break;

                    default:
                        _state = IRCParserState.Unknown;
                        break;
                    }
                    break;

                case IRCParserState.P:
                    if (b == 'I')
                    {
                        _state = IRCParserState.Pi;
                    }
                    else if (b == 'O')
                    {
                        _state = IRCParserState.Po;
                    }
                    else
                    {
                        _state = IRCParserState.Unknown;
                    }
                    break;

                case IRCParserState.Pi:
                    if (b == 'N')
                    {
                        _state = IRCParserState.Pin;
                    }
                    else
                    {
                        _state = IRCParserState.Unknown;
                    }
                    break;

                case IRCParserState.Pin:
                    if (b == 'G')
                    {
                        _state = IRCParserState.Ping;
                    }
                    else
                    {
                        _state = IRCParserState.Unknown;
                    }
                    break;

                case IRCParserState.Ping:
                    if (b == '\n')
                    {
                        _message.Cmd = "PING";
                        callback(_message);
                        _state = IRCParserState.Start;
                    }
                    break;

                case IRCParserState.Po:
                    if (b == 'N')
                    {
                        _state = IRCParserState.Pon;
                    }
                    else
                    {
                        _state = IRCParserState.Unknown;
                    }
                    break;

                case IRCParserState.Pon:
                    if (b == 'G')
                    {
                        _state = IRCParserState.Pong;
                    }
                    else
                    {
                        _state = IRCParserState.Unknown;
                    }
                    break;

                case IRCParserState.Pong:
                    if (b == '\n')
                    {
                        _message.Cmd = "PONG";
                        callback(_message);
                        _state = IRCParserState.Start;
                    }
                    break;

                case IRCParserState.Host:
                    if (b == ' ')
                    {
                        _state = IRCParserState.Cmd;
                    }
                    else if (b == '@')
                    {
                        _state = IRCParserState.User;
                    }
                    else if (b != '\r')
                    {
                        _message.Host += b;
                    }
                    break;

                case IRCParserState.User:
                    if (b == '.')
                    {
                        _state = IRCParserState.Host;
                    }
                    else
                    {
                        _message.User += b;
                    }
                    break;

                case IRCParserState.Cmd:
                    if (b == '\n')
                    {
                        callback(_message);
                        _state = IRCParserState.Start;
                    }
                    else if (b == ' ')
                    {
                        _state = IRCParserState.Args;
                    }
                    else if (b != '\r')
                    {
                        _message.Cmd += b;
                    }
                    break;

                case IRCParserState.Args:
                    if (b == '\n')
                    {
                        if (Array.IndexOf(new string[] { "PRIVMSG", "WHISPER", "USERSTATE", "USERNOTICE", "NOTICE" }, _message.Cmd) != -1)
                        {
                            int state = 0;
                            for (int j = 0; j < _message.Args.Length; j++)
                            {
                                switch (state)
                                {
                                case 0:
                                    if (_message.Args[j] == ' ')
                                    {
                                        state = 1;
                                    }
                                    else
                                    {
                                        _message.Channel += _message.Args[j];
                                    }
                                    break;

                                case 1:
                                    if (_message.Args[j] == ':')
                                    {
                                        state = 2;
                                    }
                                    break;

                                default:
                                    _message.Message += _message.Args[j];
                                    break;
                                }
                            }
                        }
                        callback(_message);
                        _state = IRCParserState.Start;
                    }
                    else if (b != '\r')
                    {
                        _message.Args += b;
                    }
                    break;

                case IRCParserState.Unknown:
                    if (b == '\n')
                    {
                        _state = IRCParserState.Start;
                    }
                    break;

                case IRCParserState.Key:
                    if (b == '=')
                    {
                        _state = IRCParserState.Value;
                    }
                    else if (b == ' ')
                    {
                        _state = IRCParserState.Host;
                    }
                    else
                    {
                        _key += b;
                    }
                    break;

                case IRCParserState.Value:
                    if (b == ';' || b == ' ')
                    {
                        _message.Parameters.Add(_key, _value);
                        _key   = "";
                        _value = "";
                    }

                    if (b == ';')
                    {
                        _state = IRCParserState.Key;
                    }
                    else if (b == ' ')
                    {
                        _state = IRCParserState.Host;
                    }
                    else
                    {
                        _value += b;
                    }
                    break;

                default:
                    _state = IRCParserState.Start;
                    break;
                }
            }
        }