From 916903689346f4878c5409e8c2ee1b183638fb52 Mon Sep 17 00:00:00 2001 From: ORelio Date: Sat, 24 Oct 2020 17:41:35 +0200 Subject: [PATCH] Implement global chat message cooldown (#661) Merge 'splitmessagedelay' and 'botmessagedelay' settings into a single 'messagecooldown' entry, implement global cooldown to fix autorespond, scripts and commands not being delayed properly. --- MinecraftClient/CSharpRunner.cs | 6 +-- MinecraftClient/ChatBot.cs | 45 ++-------------- MinecraftClient/McClient.cs | 52 ++++++++++++------- .../Resources/config/MinecraftClient.ini | 3 +- MinecraftClient/Settings.cs | 6 +-- 5 files changed, 42 insertions(+), 70 deletions(-) diff --git a/MinecraftClient/CSharpRunner.cs b/MinecraftClient/CSharpRunner.cs index 9f3475d9..98555dee 100644 --- a/MinecraftClient/CSharpRunner.cs +++ b/MinecraftClient/CSharpRunner.cs @@ -233,13 +233,13 @@ namespace MinecraftClient /// Send text to the server. Can be anything such as chat messages or commands /// /// Text to send to the server - /// True if the text was sent with no error + /// TRUE if successfully sent (Deprectated, always returns TRUE for compatibility purposes with existing scripts) public bool SendText(object text) { - bool result = base.SendText(text is string ? (string)text : text.ToString()); + base.SendText(text is string ? (string)text : text.ToString()); tickHandler.WaitOne(); Thread.Sleep(1000); - return result; + return true; } /// diff --git a/MinecraftClient/ChatBot.cs b/MinecraftClient/ChatBot.cs index 4fcc23db..2091b862 100644 --- a/MinecraftClient/ChatBot.cs +++ b/MinecraftClient/ChatBot.cs @@ -16,7 +16,7 @@ namespace MinecraftClient /// Inherit from this class while adding your bot class to the "ChatBots" folder. /// Override the methods you want for handling events: Initialize, Update, GetText. /// - /// For testing your bot you can add it in McTcpClient.cs (see comment at line ~119). + /// For testing your bot you can add it in McClient.cs (see comment at line ~199). /// Your bot will be loaded everytime MCC is started so that you can test/debug. /// /// Once your bot is fully written and tested, you can export it a standalone script. @@ -40,8 +40,6 @@ namespace MinecraftClient private McClient _handler = null; private ChatBot master = null; private List registeredPluginChannels = new List(); - private Queue chatQueue = new Queue(); - private DateTime lastMessageSentTime = DateTime.MinValue; private McClient Handler { get @@ -53,30 +51,6 @@ namespace MinecraftClient throw new InvalidOperationException(Translations.Get("exception.chatbot.init")); } } - private bool MessageCooldownEnded - { - get - { - return DateTime.Now > lastMessageSentTime + Settings.botMessageDelay; - } - } - - /// - /// Processes the current chat message queue, displaying a message after enough time passes. - /// - internal void ProcessQueuedText() - { - if (chatQueue.Count > 0) - { - if (MessageCooldownEnded) - { - string text = chatQueue.Dequeue(); - LogToConsole("Sending '" + text + "'"); - lastMessageSentTime = DateTime.Now; - Handler.SendText(text); - } - } - } /* ================================================== */ /* Main methods to override for creating your bot */ @@ -375,23 +349,12 @@ namespace MinecraftClient /// /// Text to send to the server /// Whether the message should be sent immediately rather than being queued to avoid chat spam - /// True if the text was sent with no error + /// TRUE if successfully sent (Deprectated, always returns TRUE for compatibility purposes with existing scripts) protected bool SendText(string text, bool sendImmediately = false) { - if (Settings.botMessageDelay.TotalSeconds > 0 && !sendImmediately) - { - if (!MessageCooldownEnded) - { - chatQueue.Enqueue(text); - // TODO: We don't know whether there was an error at this point, so we assume there isn't. - // Might not be the best idea. - return true; - } - } - LogToConsole("Sending '" + text + "'"); - lastMessageSentTime = DateTime.Now; - return Handler.SendText(text); + Handler.SendText(text); + return true; } /// diff --git a/MinecraftClient/McClient.cs b/MinecraftClient/McClient.cs index ec35f08c..15a1a780 100644 --- a/MinecraftClient/McClient.cs +++ b/MinecraftClient/McClient.cs @@ -27,6 +27,9 @@ namespace MinecraftClient private readonly Dictionary onlinePlayers = new Dictionary(); private static bool CommandLoaded = false; + private Queue chatQueue = new Queue(); + private static DateTime nextMessageSendTime = DateTime.MinValue; + private readonly List bots = new List(); private static readonly List botsOnHold = new List(); private static Dictionary inventories = new Dictionary(); @@ -530,7 +533,6 @@ namespace MinecraftClient try { bot.Update(); - bot.ProcessQueuedText(); } catch (Exception e) { @@ -542,6 +544,16 @@ namespace MinecraftClient } } + lock (chatQueue) + { + if (chatQueue.Count > 0 && nextMessageSendTime < DateTime.Now) + { + string text = chatQueue.Dequeue(); + handler.SendChatMessage(text); + nextMessageSendTime = DateTime.Now + Settings.messageCooldown; + } + } + if (terrainAndMovementsEnabled && locationReceived) { lock (locationLock) @@ -886,32 +898,32 @@ namespace MinecraftClient /// Send a chat message or command to the server /// /// Text to send to the server - /// True if the text was sent with no error - public bool SendText(string text) + public void SendText(string text) { - int maxLength = handler.GetMaxChatMessageLength(); - if (text.Length > maxLength) //Message is too long? + lock (chatQueue) { - if (text[0] == '/') + int maxLength = handler.GetMaxChatMessageLength(); + if (text.Length > maxLength) //Message is too long? { - //Send the first 100/256 chars of the command - text = text.Substring(0, maxLength); - return handler.SendChatMessage(text); - } - else - { - //Send the message splitted into several messages - while (text.Length > maxLength) + if (text[0] == '/') { - handler.SendChatMessage(text.Substring(0, maxLength)); - text = text.Substring(maxLength, text.Length - maxLength); - if (Settings.splitMessageDelay.TotalSeconds > 0) - Thread.Sleep(Settings.splitMessageDelay); + //Send the first 100/256 chars of the command + text = text.Substring(0, maxLength); + chatQueue.Enqueue(text); + } + else + { + //Split the message into several messages + while (text.Length > maxLength) + { + chatQueue.Enqueue(text.Substring(0, maxLength)); + text = text.Substring(maxLength, text.Length - maxLength); + } + chatQueue.Enqueue(text); } - return handler.SendChatMessage(text); } + else chatQueue.Enqueue(text); } - else return handler.SendChatMessage(text); } /// diff --git a/MinecraftClient/Resources/config/MinecraftClient.ini b/MinecraftClient/Resources/config/MinecraftClient.ini index 65578ca6..5f682886 100644 --- a/MinecraftClient/Resources/config/MinecraftClient.ini +++ b/MinecraftClient/Resources/config/MinecraftClient.ini @@ -15,9 +15,8 @@ serverip= language=en_GB consoletitle=%username%@%serverip% - Minecraft Console Client internalcmdchar=slash # Use 'none', 'slash' or 'backslash' -splitmessagedelay=2 # Seconds between each part of a long message +messagecooldown=1 # Minimum delay in seconds between messages to avoid being kicked for spam. botowners=Player1,Player2,Player3 # Name list or myfile.txt, one name per line. !Server admins can impersonate owners! -botmessagedelay=2 # Seconds to delay between message a bot makes to avoid accidental spam mcversion=auto # Use 'auto' or '1.X.X' values. Allows to skip server info retrieval. mcforge=auto # Use 'auto', 'false' or 'true'. Force-enabling only works for MC 1.13+. brandinfo=mcc # Use 'mcc', 'vanilla', or 'none'. This is how MCC identifies itself to the server. diff --git a/MinecraftClient/Settings.cs b/MinecraftClient/Settings.cs index a7bbe86f..73a949d9 100644 --- a/MinecraftClient/Settings.cs +++ b/MinecraftClient/Settings.cs @@ -77,9 +77,8 @@ namespace MinecraftClient public static string TranslationsFile_FromMCDir = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + @"\.minecraft\assets\objects\eb\ebf762c137bd91ab2496397f2504e250f3c5d1ba"; //MC 1.16 en_GB.lang public static string TranslationsFile_Website_Index = "https://launchermeta.mojang.com/v1/packages/bdb68de96a44ec1e9ed6d9cfcd2ee973be618c3a/1.16.json"; public static string TranslationsFile_Website_Download = "http://resources.download.minecraft.net"; - public static TimeSpan splitMessageDelay = TimeSpan.FromSeconds(2); + public static TimeSpan messageCooldown = TimeSpan.FromSeconds(2); public static List Bots_Owners = new List(); - public static TimeSpan botMessageDelay = TimeSpan.FromSeconds(2); public static string Language = "en_GB"; public static bool interactiveMode = true; public static char internalCmdChar = '/'; @@ -271,7 +270,7 @@ namespace MinecraftClient case "playerheadicon": playerHeadAsIcon = str2bool(argValue); break; case "chatbotlogfile": chatbotLogFile = argValue; break; case "mcversion": ServerVersion = argValue; break; - case "splitmessagedelay": splitMessageDelay = TimeSpan.FromSeconds(str2int(argValue)); break; + case "messagecooldown": messageCooldown = TimeSpan.FromSeconds(str2int(argValue)); break; case "scriptcache": CacheScripts = str2bool(argValue); break; case "showsystemmessages": DisplaySystemMessages = str2bool(argValue); break; case "showxpbarmessages": DisplayXPBarMessages = str2bool(argValue); break; @@ -281,7 +280,6 @@ namespace MinecraftClient case "enableentityhandling": EntityHandling = str2bool(argValue); break; case "inventoryhandling": InventoryHandling = str2bool(argValue); break; case "privatemsgscmdname": PrivateMsgsCmdName = argValue.ToLower().Trim(); break; - case "botmessagedelay": botMessageDelay = TimeSpan.FromSeconds(str2int(argValue)); break; case "debugmessages": DebugMessages = str2bool(argValue); break; case "autorespawn": AutoRespawn = str2bool(argValue); break;