Exemple #1
0
        public override void ExecuteCommand(EvtChatCommandArgs e)
        {
            List <string> args = e.Command.ArgumentsAsList;

            if (args.Count < 1)
            {
                BotProgram.MsgHandler.QueueMessage("Usage: state #");
                return;
            }

            string stateNumStr = args[0];

            if (int.TryParse(stateNumStr, out int stateNum) == false)
            {
                BotProgram.MsgHandler.QueueMessage("Invalid state number.");
                return;
            }

            string saveStateStr = $"ss{stateNum}";

            if (InputGlobals.CurrentConsole.ButtonInputMap.ContainsKey(saveStateStr) == false)
            {
                BotProgram.MsgHandler.QueueMessage("Invalid state number.");
                return;
            }

            User user = BotProgram.GetOrAddUser(e.Command.ChatMessage.Username, false);

            //Check if the user can perform this input
            ParserPostProcess.InputValidation inputValidation = ParserPostProcess.CheckInputPermissions(user.Level, saveStateStr, BotProgram.BotData.InputAccess.InputAccessDict);

            //If the input isn't valid, exit
            if (inputValidation.IsValid == false)
            {
                if (string.IsNullOrEmpty(inputValidation.Message) == false)
                {
                    BotProgram.MsgHandler.QueueMessage(inputValidation.Message);
                }

                return;
            }

            //Savestates are always performed on the first controller
            IVirtualController joystick = InputGlobals.ControllerMngr.GetController(0);

            joystick.PressButton(InputGlobals.CurrentConsole.ButtonInputMap[saveStateStr]);
            joystick.UpdateController();

            //Track the time of the savestate
            DateTime curTime = DateTime.UtcNow;

            //Add a new savestate log
            GameLog newStateLog = new GameLog();

            newStateLog.User = e.Command.ChatMessage.Username;

            string date = curTime.ToShortDateString();
            string time = curTime.ToLongTimeString();

            newStateLog.DateTimeString = $"{date} at {time}";

            newStateLog.User       = e.Command.ChatMessage.Username;
            newStateLog.LogMessage = string.Empty;

            //Add the message if one was specified
            if (args.Count > 1)
            {
                string message = e.Command.ArgumentsAsString.Remove(0, stateNumStr.Length + 1);
                newStateLog.LogMessage = message;
            }

            //Add or replace the log and save the bot data
            BotProgram.BotData.SavestateLogs[stateNum] = newStateLog;
            BotProgram.SaveBotData();

            BotProgram.MsgHandler.QueueMessage($"Saved state {stateNum}!");

            //Wait a bit before releasing the input
            const float wait = 50f;
            Stopwatch   sw   = Stopwatch.StartNew();

            while (sw.ElapsedMilliseconds < wait)
            {
            }

            joystick.ReleaseButton(InputGlobals.CurrentConsole.ButtonInputMap[saveStateStr]);
            joystick.UpdateController();
        }
Exemple #2
0
        //NOTE: This would result in lots of code duplication if other streaming services were integrated
        //Is there a better way to do this?

        private void ProcessMsgAsInput(User userData, EvtUserMessageArgs e)
        {
            //Don't process for inputs if a meme
            string possibleMeme = e.UsrMessage.Message.ToLower();

            if (BotProgram.BotData.Memes.TryGetValue(possibleMeme, out string meme) == true)
            {
                return;
            }

            //Ignore commands as inputs
            if (possibleMeme.StartsWith(Globals.CommandIdentifier) == true)
            {
                return;
            }

            //If there are no valid inputs, don't attempt to parse
            if (InputGlobals.CurrentConsole.ValidInputs == null || InputGlobals.CurrentConsole.ValidInputs.Length == 0)
            {
                return;
            }

            //Parser.InputSequence inputSequence = default;
            //(bool, List<List<Parser.Input>>, bool, int) parsedVal = default;
            Parser.InputSequence inputSequence = default;

            try
            {
                string parse_message = Parser.Expandify(Parser.PopulateMacros(e.UsrMessage.Message));
                inputSequence = Parser.ParseInputs(parse_message, userData.Team, true, true);
                //parsedVal = Parser.Parse(parse_message);
                //Console.WriteLine(inputSequence.ToString());
                //Console.WriteLine("\nReverse Parsed: " + ReverseParser.ReverseParse(inputSequence));
                //Console.WriteLine("\nReverse Parsed Natural:\n" + ReverseParser.ReverseParseNatural(inputSequence));
            }
            catch (Exception exception)
            {
                string excMsg = exception.Message;

                //Kimimaru: Sanitize parsing exceptions
                //Most of these are currently caused by differences in how C# and Python handle slicing strings (Substring() vs string[:])
                //One example that throws this that shouldn't is "#mash(w234"
                //BotProgram.MsgHandler.QueueMessage($"ERROR: {excMsg}");
                inputSequence.InputValidationType = Parser.InputValidationTypes.Invalid;
                //parsedVal.Item1 = false;
            }

            //Check for non-valid messages
            if (inputSequence.InputValidationType != Parser.InputValidationTypes.Valid)
            {
                //Display error message for invalid inputs
                if (inputSequence.InputValidationType == Parser.InputValidationTypes.Invalid)
                {
                    BotProgram.MsgHandler.QueueMessage(inputSequence.Error);
                }

                return;
            }

            //It's a valid message, so process it

            //Ignore if user is silenced
            if (userData.Silenced == true)
            {
                return;
            }

            //Ignore based on user level and permissions
            if (userData.Level < BotProgram.BotData.InputPermissions)
            {
                BotProgram.MsgHandler.QueueMessage($"Inputs are restricted to levels {(AccessLevels.Levels)BotProgram.BotData.InputPermissions} and above");
                return;
            }

            #region Parser Post-Process Validation

            /* All this validation is very slow
             * Find a way to speed it up, ideally without integrating it directly into the parser
             */

            //Check if the user has permission to perform all the inputs they attempted
            //Also validate that the controller ports they're inputting for are valid
            ParserPostProcess.InputValidation inputValidation = ParserPostProcess.CheckInputPermissionsAndPorts(userData.Level, inputSequence.Inputs,
                                                                                                                BotProgram.BotData.InputAccess.InputAccessDict);

            //If the input isn't valid, exit
            if (inputValidation.IsValid == false)
            {
                if (string.IsNullOrEmpty(inputValidation.Message) == false)
                {
                    BotProgram.MsgHandler.QueueMessage(inputValidation.Message);
                }
                return;
            }

            //Lastly, check for invalid button combos given the current console
            if (BotProgram.BotData.InvalidBtnCombos.InvalidCombos.TryGetValue((int)InputGlobals.CurrentConsoleVal, out List <string> invalidCombos) == true)
            {
                bool buttonCombosValidated = ParserPostProcess.ValidateButtonCombos(inputSequence.Inputs, invalidCombos);

                if (buttonCombosValidated == false)
                {
                    string msg    = "Invalid input: buttons ({0}) are not allowed to be pressed at the same time.";
                    string combos = string.Empty;

                    for (int i = 0; i < invalidCombos.Count; i++)
                    {
                        combos += "\"" + invalidCombos[i] + "\"";

                        if (i < (invalidCombos.Count - 1))
                        {
                            combos += ", ";
                        }
                    }

                    msg = string.Format(msg, combos);
                    BotProgram.MsgHandler.QueueMessage(msg);

                    return;
                }
            }

            #endregion

            if (InputHandler.StopRunningInputs == false)
            {
                //Invoke input event
                UserMadeInputEvent?.Invoke(userData, e, inputSequence);
            }
            else
            {
                BotProgram.MsgHandler.QueueMessage("New inputs cannot be processed until all other inputs have stopped.");
            }
        }
        public override void ExecuteCommand(EvtChatCommandArgs e)
        {
            List <string> args = e.Command.ArgumentsAsList;

            if (args.Count != 1)
            {
                BotProgram.MsgHandler.QueueMessage("Usage: state #");
                return;
            }

            string stateNumStr = args[0];

            if (int.TryParse(stateNumStr, out int stateNum) == false)
            {
                BotProgram.MsgHandler.QueueMessage($"Invalid state number.");
                return;
            }

            string loadStateStr = $"ls{stateNum}";

            if (InputGlobals.CurrentConsole.ButtonInputMap.ContainsKey(loadStateStr) == false)
            {
                BotProgram.MsgHandler.QueueMessage($"Invalid state number.");
                return;
            }

            User user = BotProgram.GetOrAddUser(e.Command.ChatMessage.Username, false);

            //Check if the user can perform this input
            ParserPostProcess.InputValidation inputValidation = ParserPostProcess.CheckInputPermissions(user.Level, loadStateStr, BotProgram.BotData.InputAccess.InputAccessDict);

            //If the input isn't valid, exit
            if (inputValidation.IsValid == false)
            {
                if (string.IsNullOrEmpty(inputValidation.Message) == false)
                {
                    BotProgram.MsgHandler.QueueMessage(inputValidation.Message);
                }

                return;
            }

            //Load states are always performed on the first controller
            IVirtualController joystick = InputGlobals.ControllerMngr.GetController(0);

            joystick.PressButton(InputGlobals.CurrentConsole.ButtonInputMap[loadStateStr]);
            joystick.UpdateController();

            BotProgram.MsgHandler.QueueMessage($"Loaded state {stateNum}!");

            //Wait a bit before releasing the input
            const float wait = 50f;
            Stopwatch   sw   = Stopwatch.StartNew();

            while (sw.ElapsedMilliseconds < wait)
            {
            }

            joystick.ReleaseButton(InputGlobals.CurrentConsole.ButtonInputMap[loadStateStr]);
            joystick.UpdateController();
        }