From 70d3b6175bb29e30cab5d15daaa70e3e2a1a96d0 Mon Sep 17 00:00:00 2001 From: ORelio Date: Sat, 27 Mar 2021 19:15:58 +0100 Subject: [PATCH] Process command prompt text on main thread (#1510) Fix possible threading issues when MCC commands interactively --- MinecraftClient/McClient.cs | 100 +++++++++++++++++++++--------------- 1 file changed, 60 insertions(+), 40 deletions(-) diff --git a/MinecraftClient/McClient.cs b/MinecraftClient/McClient.cs index 66525dcb..8259b031 100644 --- a/MinecraftClient/McClient.cs +++ b/MinecraftClient/McClient.cs @@ -26,7 +26,9 @@ namespace MinecraftClient private static readonly List cmd_names = new List(); private static readonly Dictionary cmds = new Dictionary(); private readonly Dictionary onlinePlayers = new Dictionary(); - private static bool CommandLoaded = false; + + private static bool commandsLoaded = false; + private Queue commandQueue = new Queue(); private Queue chatQueue = new Queue(); private static DateTime nextMessageSendTime = DateTime.MinValue; @@ -289,58 +291,68 @@ namespace MinecraftClient } /// - /// Allows the user to send chat messages, commands, and to leave the server. + /// Allows the user to send chat messages, commands, and leave the server. + /// Enqueue text typed in the command prompt for processing on the main thread. /// private void CommandPrompt() { try { - string text = ""; Thread.Sleep(500); - handler.SendRespawnPacket(); - while (client.Client.Connected) { - text = ConsoleIO.ReadLine(); - if (ConsoleIO.BasicIO && text.Length > 0 && text[0] == (char)0x00) + string text = ConsoleIO.ReadLine(); + lock (commandQueue) { - //Process a request from the GUI - string[] command = text.Substring(1).Split((char)0x00); - switch (command[0].ToLower()) - { - case "autocomplete": - if (command.Length > 1) { ConsoleIO.WriteLine((char)0x00 + "autocomplete" + (char)0x00 + handler.AutoComplete(command[1])); } - else Console.WriteLine((char)0x00 + "autocomplete" + (char)0x00); - break; - } + commandQueue.Enqueue(text); } - else - { - text = text.Trim(); - if (text.Length > 0) - { - if (Settings.internalCmdChar == ' ' || text[0] == Settings.internalCmdChar) - { - string response_msg = ""; - string command = Settings.internalCmdChar == ' ' ? text : text.Substring(1); - if (!PerformInternalCommand(Settings.ExpandVars(command), ref response_msg) && Settings.internalCmdChar == '/') - { - SendText(text); - } - else if (response_msg.Length > 0) - { - Log.Info(response_msg); - } - } - else SendText(text); - } - } - } + } } catch (IOException) { } catch (NullReferenceException) { } } + /// + /// Allows the user to send chat messages, commands, and leave the server. + /// Process text from the MCC command prompt on the main thread. + /// + private void HandleCommandPromptText(string text) + { + if (ConsoleIO.BasicIO && text.Length > 0 && text[0] == (char)0x00) + { + //Process a request from the GUI + string[] command = text.Substring(1).Split((char)0x00); + switch (command[0].ToLower()) + { + case "autocomplete": + if (command.Length > 1) { ConsoleIO.WriteLine((char)0x00 + "autocomplete" + (char)0x00 + handler.AutoComplete(command[1])); } + else Console.WriteLine((char)0x00 + "autocomplete" + (char)0x00); + break; + } + } + else + { + text = text.Trim(); + if (text.Length > 0) + { + if (Settings.internalCmdChar == ' ' || text[0] == Settings.internalCmdChar) + { + string response_msg = ""; + string command = Settings.internalCmdChar == ' ' ? text : text.Substring(1); + if (!PerformInternalCommand(Settings.ExpandVars(command), ref response_msg) && Settings.internalCmdChar == '/') + { + SendText(text); + } + else if (response_msg.Length > 0) + { + Log.Info(response_msg); + } + } + else SendText(text); + } + } + } + /// /// Periodically checks for server keepalives and consider that connection has been lost if the last received keepalive is too old. /// @@ -426,7 +438,7 @@ namespace MinecraftClient { /* Load commands from the 'Commands' namespace */ - if (!CommandLoaded) + if (!commandsLoaded) { Type[] cmds_classes = Program.GetTypesInNamespace("MinecraftClient.Commands"); foreach (Type type in cmds_classes) @@ -447,7 +459,7 @@ namespace MinecraftClient } } } - CommandLoaded = true; + commandsLoaded = true; } } @@ -560,6 +572,14 @@ namespace MinecraftClient } } + lock (commandQueue) + { + if (commandQueue.Count > 0) + { + HandleCommandPromptText(commandQueue.Dequeue()); + } + } + lock (chatQueue) { if (chatQueue.Count > 0 && nextMessageSendTime < DateTime.Now)