/// <summary> /// Scrolls all the visible terminal windows to the bottom. /// </summary> public void ScrollAllToBottom() { OocCommunicationTerminal.ScrollToLastLine(); CommunicationTerminal.ScrollToLastLine(); GameTerminal.ScrollToLastLine(); }
/// <summary> /// The PreviewKeyDown event for the input text box used to setup special behavior from that box. /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void Editor_PreviewKeyDown(object sender, KeyEventArgs e) { // So they key's for macros aren't entered into the text box. foreach (var item in App.Settings.ProfileSettings.MacroList) { if ((int)e.Key == item.Key) { e.Handled = true; return; } } switch (e.Key) { case Key.Enter: e.Handled = true; // When a command is entered into the input box. // Make sure the newline didn't make it into the text input, then select all in the box so it can be cleared quickly. TextInput.Editor.Text = TextInput.Editor.Text.Replace("\r", "").Replace("\n", ""); TextInput.Editor.SelectAll(); Interp.Send(TextInput.Editor.Text); // If the user wants the input box to clear after a command, make it so. if (App.Settings.AvalonSettings.InputBoxClearAfterCommand) { TextInput.Editor.Text = ""; } // Set the history count to the end Interp.InputHistoryPosition = -1; break; case Key.Up: e.Handled = false; // If the drop down is open allow the up and down keys to work for it, not history. if (TextInput.IsDropDownOpen) { return; } // Go to the previous item in the history. TextInput.Editor.Text = Interp.InputHistoryNext(); TextInput.Editor.SelectionStart = (TextInput.Editor.Text.Length); TextInput.Editor.SelectionLength = 0; break; case Key.Down: e.Handled = false; // If the drop down is open allow the up and down keys to work for it, not history. if (TextInput.IsDropDownOpen) { return; } // Go to the next item in the history. TextInput.Editor.Text = Interp.InputHistoryPrevious(); TextInput.Editor.SelectionStart = (TextInput.Editor.Text.Length); TextInput.Editor.SelectionLength = 0; break; case Key.PageUp: e.Handled = true; // Back buffer is collapsed, show it, scroll to the bottom of it. if (GameBackBufferTerminal.Visibility == System.Windows.Visibility.Collapsed) { GameBackBufferTerminal.ScrollToLastLine(); GameBackBufferTerminal.Visibility = System.Windows.Visibility.Visible; // Since the height of this changed scroll it to the bottom. GameTerminal.ScrollToLastLine(); break; } // If it was already visible, then we PageUp() GameBackBufferTerminal.PageUp(); break; case Key.PageDown: e.Handled = true; // Back buffer is visible then execute a PageDown() if (GameBackBufferTerminal.Visibility == System.Windows.Visibility.Visible) { GameBackBufferTerminal.PageDown(); } // Now, if the last line in the back buffer is visible then we can just collapse the // back buffer because the main terminal shows everything at the end. if (GameBackBufferTerminal.IsLastLineVisible()) { GameBackBufferTerminal.Visibility = System.Windows.Visibility.Collapsed; TextInput.Editor.Focus(); } break; case Key.Oem5: case Key.OemBackslash: TextInput.Editor.SelectAll(); e.Handled = true; break; case Key.Escape: // Collapse the back buffer so it hides it and reclaims the space for the main terminal. GameBackBufferTerminal.Visibility = System.Windows.Visibility.Collapsed; // Setting to see if the comm windows should scroll to the bottom on escape. if (App.Settings.AvalonSettings.EscapeScrollsAllTerminalsToBottom) { OocCommunicationTerminal.ScrollToLastLine(); CommunicationTerminal.ScrollToLastLine(); GameTerminal.ScrollToLastLine(); } // Reset the input history to the default position and clear the text in the input box. Interp.InputHistoryPosition = -1; TextInput.Editor.Text = ""; break; } }
/// <summary> /// Checks a line to see if any Triggers should fire and if so executes those triggers. /// </summary> /// <param name="line"></param> public async void CheckTriggers(Line line) { // Don't process if the user has disabled triggers. if (!App.Settings.ProfileSettings.TriggersEnabled) { return; } // Don't process if the line is blank. if (string.IsNullOrWhiteSpace(line.Text)) { return; } // Go through the immutable system triggers, system triggers are silent in that // they won't echo to the terminal window, they also don't adhere to attributes like // character or enabled. These can and will have CLR implementations and can be loaded // from other DLL's as plugins. System triggers are also unique in that they are designed // to be loaded from a plugin and they don't save their state in the profile. foreach (var item in App.SystemTriggers) { // Skip it if it's not enabled. if (!item.Enabled) { continue; } if (item.IsMatch(line.Text)) { // Run any CLR that might exist. item.Execute(); if (!string.IsNullOrEmpty(item.Command) && item.IsLua == false) { // If it has text but it's not lua, send it to the interpreter. await Interp.Send(item.Command, item.IsSilent, false); } else if (!string.IsNullOrEmpty(item.Command) && item.IsLua == true) { // If it has text and it IS lua, send it to the LUA engine. await Interp.LuaCaller.ExecuteAsync(item.Command); } // Check if we're supposed to move this line somewhere else. if (item.MoveTo != TerminalTarget.None) { string timeStamp; switch (App.Settings.AvalonSettings.TimestampFormat) { case Common.Settings.AvalonSettings.TimestampFormats.HoursMinutes: timeStamp = DateTime.Now.ToString("hh:mm tt"); break; case Common.Settings.AvalonSettings.TimestampFormats.HoursMinutesSeconds: timeStamp = DateTime.Now.ToString("hh:mm:ss tt"); break; case Common.Settings.AvalonSettings.TimestampFormats.OSDefault: timeStamp = DateTime.Now.ToString("g"); break; case Common.Settings.AvalonSettings.TimestampFormats.TwentyFourHour: timeStamp = DateTime.Now.ToString("HH:mm:ss"); break; default: timeStamp = DateTime.Now.ToString("hh:mm:ss tt"); break; } // Create a brand new line (not a shared reference) where this can be shown in the communication window. var commLine = new Line { FormattedText = $"[{timeStamp}]: {line.FormattedText}\r\n" }; if (item.MoveTo == TerminalTarget.Communication) { CommunicationTerminal.Append(commLine); } else if (item.MoveTo == TerminalTarget.OutOfCharacterCommunication) { OocCommunicationTerminal.Append(commLine); } } } } // Go through the TriggerList which are user defined triggers foreach (var item in App.Settings.ProfileSettings.TriggerList) { // Skip it if it's not enabled. if (!item.Enabled) { continue; } // Skip it if it's not global or for this character. if (!string.IsNullOrWhiteSpace(item.Character) && item.Character != App.Conveyor.GetVariable("Character")) { continue; } // If there is no pattern skip it, we don't want to send thousands of commands on empty patterns. if (string.IsNullOrWhiteSpace(item.Pattern)) { continue; } if (item.IsMatch(line.Text)) { // Run any CLR that might exist. item.Execute(); // Increment the counter. item.Count++; // Line Highlighting if the trigger is supposed to. if (item.HighlightLine) { // TODO - Allow the highlighted color to be set for each trigger. int start = GameTerminal.Document.Text.LastIndexOf(line.Text, StringComparison.Ordinal); GameTerminal.Document.Replace(start, line.Text.Length, $"{AnsiColors.DarkCyan}{line.Text}"); } // Only send if it has something in it. Use the processed command. if (!string.IsNullOrEmpty(item.ProcessedCommand) && item.IsLua == false) { // If it has text but it's not lua, send it to the interpreter. await Interp.Send(item.ProcessedCommand, false, false); } else if (!string.IsNullOrEmpty(item.ProcessedCommand) && item.IsLua == true) { // If it has text and it IS lua, send it to the LUA engine. await Interp.LuaCaller.ExecuteAsync(item.ProcessedCommand); } // Check if we're supposed to move this line somewhere else. if (item.MoveTo != TerminalTarget.None) { string timeStamp; switch (App.Settings.AvalonSettings.TimestampFormat) { case Common.Settings.AvalonSettings.TimestampFormats.HoursMinutes: timeStamp = DateTime.Now.ToString("hh:mm tt"); break; case Common.Settings.AvalonSettings.TimestampFormats.HoursMinutesSeconds: timeStamp = DateTime.Now.ToString("hh:mm:ss tt"); break; case Common.Settings.AvalonSettings.TimestampFormats.OSDefault: timeStamp = DateTime.Now.ToString("g"); break; case Common.Settings.AvalonSettings.TimestampFormats.TwentyFourHour: timeStamp = DateTime.Now.ToString("HH:mm:ss"); break; default: timeStamp = DateTime.Now.ToString("hh:mm:ss tt"); break; } // Create a brand new line (not a shared reference) where this can be shown in the communication window. var commLine = new Line { FormattedText = $"[{timeStamp}]: {line.FormattedText}\r\n" }; if (item.MoveTo == TerminalTarget.Communication) { CommunicationTerminal.Append(commLine); } else if (item.MoveTo == TerminalTarget.OutOfCharacterCommunication) { OocCommunicationTerminal.Append(commLine); } } } } }
/// <summary> /// Shared preview key down logic between the game terminal and it's back buffer. If they have focus this /// will implement page up and page down so that the back buffer will show all of the paging, once it gets /// to the bottom it will disappear. The escape key will send the focus back to the input box hiding the /// back buffer. /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void GameTerminal_PreviewKeyDown(object sender, KeyEventArgs e) { switch (e.Key) { case Key.PageUp: e.Handled = true; // Back buffer is collapsed, show it, scroll to the bottom of it. if (GameBackBufferTerminal.Visibility == System.Windows.Visibility.Collapsed) { GameBackBufferTerminal.ScrollToLastLine(); GameBackBufferTerminal.Visibility = System.Windows.Visibility.Visible; // Since the height of this changed scroll it to the bottom. GameTerminal.ScrollToLastLine(); break; } // If it was already visible, then we PageUp() GameBackBufferTerminal.PageUp(); break; case Key.PageDown: e.Handled = true; // Back buffer is visible then execute a PageDown() if (GameBackBufferTerminal.Visibility == System.Windows.Visibility.Visible) { GameBackBufferTerminal.PageDown(); } // Now, if the last line in the back buffer is visible then we can just collapse the // back buffer because the main terminal shows everything at the end. Set the focus // back to the input box if it's not already there. if (GameBackBufferTerminal.IsLastLineVisible()) { GameBackBufferTerminal.Visibility = System.Windows.Visibility.Collapsed; TextInput.Editor.Focus(); } break; case Key.Escape: // Collapse the back buffer so it hides it and reclaims the space for the main terminal. GameBackBufferTerminal.Visibility = System.Windows.Visibility.Collapsed; // Setting to see if the comm windows should scroll to the bottom on escape. if (App.Settings.AvalonSettings.EscapeScrollsAllTerminalsToBottom) { GameTerminal.ScrollToLastLine(); OocCommunicationTerminal.ScrollToLastLine(); CommunicationTerminal.ScrollToLastLine(); } // Reset the input history to the default position and clear the text in the input box. Interp.InputHistoryPosition = -1; TextInput.Editor.Text = ""; TextInput.Editor.Focus(); break; } }
/// <summary> /// Checks a line to see if any Triggers should fire and if so executes those triggers. /// </summary> /// <param name="line"></param> public async void CheckTriggers(Line line) { // Don't process if the user has disabled triggers. if (!App.Settings.ProfileSettings.TriggersEnabled) { return; } // Don't process if the line is blank. if (string.IsNullOrWhiteSpace(line.Text)) { return; } // Go through the immutable system triggers, system triggers are silent in that // they won't echo to the terminal window, they also don't adhere to attributes like // character or enabled. These can and will have CLR implementations and can be loaded // from other DLL's as plugins. foreach (var item in App.SystemTriggers) { if (item.IsMatch(line.Text)) { // Run any CLR that might exist. item.Execute(); if (!string.IsNullOrEmpty(item.Command)) { await Interp.Send(item.Command, item.IsSilent, false); } // Check if we're supposed to move this line somewhere else. if (item.MoveTo != TerminalTarget.None) { // Create a brand new line (not a shared reference) where this can be shown in the communication window. var commLine = new Line { Text = line.Text, FormattedText = $"[{DateTime.Now.ToShortTimeString()}]: {line.FormattedText}\r\n" }; if (item.MoveTo == TerminalTarget.Communication) { CommunicationTerminal.Append(commLine); } else if (item.MoveTo == TerminalTarget.OutOfCharacterCommunication) { OocCommunicationTerminal.Append(commLine); } } } } // Go through the TriggerList which are user defined triggers foreach (var item in App.Settings.ProfileSettings.TriggerList) { // Skip it if it's not enabled. if (!item.Enabled) { continue; } // Skip it if it's not global or for this character. if (!string.IsNullOrWhiteSpace(item.Character) && item.Character != this.Conveyor.GetVariable("Character")) { continue; } // If there is no pattern skip it, we don't want to send thousands of commands on empty patterns. if (string.IsNullOrWhiteSpace(item.Pattern)) { continue; } if (item.IsMatch(line.Text)) { // Run any CLR that might exist. item.Execute(); // Increment the counter. item.Count++; // Line Highlighting if the trigger is supposed to. if (item.HighlightLine) { // TODO - Allow the highlighted color to be set for each trigger. int start = GameTerminal.Document.Text.LastIndexOf(line.Text, StringComparison.Ordinal); GameTerminal.Document.Replace(start, line.Text.Length, $"{AnsiColors.DarkCyan}{line.Text}"); } // Only send if it has something in it. Use the processed command. (in the future a target could be // a lua script, etc.). if (!string.IsNullOrWhiteSpace(item.ProcessedCommand)) { await Interp.Send(item.ProcessedCommand, false, false); } // Check if we're supposed to move this line somewhere else. if (item.MoveTo != TerminalTarget.None) { // Create a brand new line (not a shared reference) where this can be shown in the communication window. var commLine = new Line { Text = line.Text, FormattedText = $"[{DateTime.Now.ToShortTimeString()}]: {line.FormattedText}\r\n" }; if (item.MoveTo == TerminalTarget.Communication) { CommunicationTerminal.Append(commLine); } else if (item.MoveTo == TerminalTarget.OutOfCharacterCommunication) { OocCommunicationTerminal.Append(commLine); } } } } }