diff --git a/MinecraftClient/ChatBots/Alerts.cs b/MinecraftClient/ChatBots/Alerts.cs index c5b1402a..c3f1f6a0 100644 --- a/MinecraftClient/ChatBots/Alerts.cs +++ b/MinecraftClient/ChatBots/Alerts.cs @@ -11,15 +11,21 @@ namespace MinecraftClient.ChatBots private string[] dictionary = Array.Empty(); private string[] excludelist = Array.Empty(); private bool logToFile = false; + float curRainLevel = 0; + float curThunderLevel = 0; + const float threshold = 0.2f; /// /// Intitialize the Alerts bot /// public override void Initialize() { - dictionary = LoadDistinctEntriesFromFile(Settings.Alerts_MatchesFile); - excludelist = LoadDistinctEntriesFromFile(Settings.Alerts_ExcludesFile); - logToFile = Settings.Alerts_File_Logging; + if (Settings.Alerts_Trigger_By_Words) + { + dictionary = LoadDistinctEntriesFromFile(Settings.Alerts_MatchesFile); + excludelist = LoadDistinctEntriesFromFile(Settings.Alerts_ExcludesFile); + logToFile = Settings.Alerts_File_Logging; + } } /// @@ -28,28 +34,87 @@ namespace MinecraftClient.ChatBots /// Received text public override void GetText(string text) { - //Remove color codes and convert to lowercase - text = GetVerbatim(text).ToLower(); - - //Proceed only if no exclusions are found in text - if (!excludelist.Any(exclusion => text.Contains(exclusion))) + if (Settings.Alerts_Trigger_By_Words) { - //Show an alert for each alert item found in text, if any - foreach (string alert in dictionary.Where(alert => text.Contains(alert))) + //Remove color codes and convert to lowercase + text = GetVerbatim(text).ToLower(); + + //Proceed only if no exclusions are found in text + if (!excludelist.Any(exclusion => text.Contains(exclusion))) { - if (Settings.Alerts_Beep_Enabled) - Console.Beep(); //Text found ! - - ConsoleIO.WriteLine(text.Replace(alert, "§c" + alert + "§r")); - - if (logToFile && Settings.Alerts_LogFile.Length > 0) + //Show an alert for each alert item found in text, if any + foreach (string alert in dictionary.Where(alert => text.Contains(alert))) { - DateTime now = DateTime.Now; - string TimeStamp = "[" + now.Year + '/' + now.Month + '/' + now.Day + ' ' + now.Hour + ':' + now.Minute + ']'; - System.IO.File.AppendAllText(Settings.Alerts_LogFile, TimeStamp + " " + GetVerbatim(text) + "\n"); + if (Settings.Alerts_Beep_Enabled) + Console.Beep(); //Text found ! + + ConsoleIO.WriteLine(text.Replace(alert, "§c" + alert + "§r")); + + if (logToFile && Settings.Alerts_LogFile.Length > 0) + { + DateTime now = DateTime.Now; + string TimeStamp = "[" + now.Year + '/' + now.Month + '/' + now.Day + ' ' + now.Hour + ':' + now.Minute + ']'; + System.IO.File.AppendAllText(Settings.Alerts_LogFile, TimeStamp + " " + GetVerbatim(text) + "\n"); + } } } } } + + public override void OnRainLevelChange(float level) + { + if (curRainLevel < threshold && level >= threshold) + { + if (Settings.Alerts_Trigger_By_Rain) + { + if (Settings.Alerts_Beep_Enabled) + { + Console.Beep(); + Console.Beep(); + } + LogToConsole(Translations.TryGet("bot.alerts.start_rain")); + } + } + else if (curRainLevel >= threshold && level < threshold) + { + if (Settings.Alerts_Trigger_By_Rain) + { + if (Settings.Alerts_Beep_Enabled) + { + Console.Beep(); + } + LogToConsole(Translations.TryGet("bot.alerts.end_rain")); + } + } + curRainLevel = level; + } + + public override void OnThunderLevelChange(float level) + { + if (curThunderLevel < threshold && level >= threshold) + { + if (Settings.Alerts_Trigger_By_Thunderstorm) + { + if (Settings.Alerts_Beep_Enabled) + { + Console.Beep(); + Console.Beep(); + } + LogToConsole(Translations.TryGet("bot.alerts.start_thunderstorm")); + } + } + else if (curThunderLevel >= threshold && level < threshold) + { + if (Settings.Alerts_Trigger_By_Thunderstorm) + { + if (Settings.Alerts_Beep_Enabled) + { + Console.Beep(); + } + LogToConsole(Translations.TryGet("bot.alerts.end_thunderstorm")); + } + } + curThunderLevel = level; + } } } diff --git a/MinecraftClient/McClient.cs b/MinecraftClient/McClient.cs index a8fed3b9..5584c62b 100644 --- a/MinecraftClient/McClient.cs +++ b/MinecraftClient/McClient.cs @@ -3294,6 +3294,26 @@ namespace MinecraftClient ////handler.SetUserUUID(UUID); } + + /// + /// Used for a wide variety of game events, from weather to bed use to gamemode to demo messages. + /// + /// Event type + /// Depends on Reason + public void OnGameEvent(byte reason, float value) + { + switch (reason) + { + case 7: + + DispatchBotEvent(bot => bot.OnRainLevelChange(value)); + break; + case 8: + DispatchBotEvent(bot => bot.OnThunderLevelChange(value)); + break; + } + } + #endregion } } diff --git a/MinecraftClient/Protocol/Handlers/Protocol18.cs b/MinecraftClient/Protocol/Handlers/Protocol18.cs index 0ec192b4..c267b429 100644 --- a/MinecraftClient/Protocol/Handlers/Protocol18.cs +++ b/MinecraftClient/Protocol/Handlers/Protocol18.cs @@ -1139,6 +1139,15 @@ namespace MinecraftClient.Protocol.Handlers handler.GetWorld()[chunkX, chunkZ] = null; } break; + case PacketTypesIn.ChangeGameState: + if (protocolVersion >= MC_1_15_2_Version) + { + byte reason = dataTypes.ReadNextByte(packetData); + float state = dataTypes.ReadNextFloat(packetData); + + handler.OnGameEvent(reason, state); + } + break; case PacketTypesIn.PlayerInfo: if (protocolVersion >= MC_1_8_Version) { diff --git a/MinecraftClient/Protocol/IMinecraftComHandler.cs b/MinecraftClient/Protocol/IMinecraftComHandler.cs index 11040bfa..724055d8 100644 --- a/MinecraftClient/Protocol/IMinecraftComHandler.cs +++ b/MinecraftClient/Protocol/IMinecraftComHandler.cs @@ -425,5 +425,12 @@ namespace MinecraftClient.Protocol /// The player's username received from the server /// Tuple public void OnLoginSuccess(Guid uuid, string userName, Tuple[]? playerProperty); + + /// + /// Used for a wide variety of game events, from weather to bed use to gamemode to demo messages. + /// + /// Event type + /// Depends on Reason + public void OnGameEvent(byte reason, float value); } } diff --git a/MinecraftClient/Resources/config/MinecraftClient.ini b/MinecraftClient/Resources/config/MinecraftClient.ini index a072d60a..0cb95813 100644 --- a/MinecraftClient/Resources/config/MinecraftClient.ini +++ b/MinecraftClient/Resources/config/MinecraftClient.ini @@ -131,6 +131,9 @@ skin_pants_right=false # Get alerted when specified words are detected in chat # Useful for moderating your server or detecting when someone is talking to you enabled=false +trigger_by_words=false # Triggers an alert after receiving a specified keyword. +trigger_by_rain=false # Trigger alerts when it rains and when it stops. +trigger_by_thunderstorm=false # Triggers alerts at the beginning and end of thunderstorms. alertsfile=alerts.txt # List of words/strings to alert you on, e.g. "Yourname" excludesfile=alerts-exclude.txt # List of words/strings to NOT alert you on, e.g. "" beeponalert=true # Play a beep sound when a word is detected in addition to highlighting diff --git a/MinecraftClient/Resources/lang/en.ini b/MinecraftClient/Resources/lang/en.ini index 1a89dc37..444f5b10 100644 --- a/MinecraftClient/Resources/lang/en.ini +++ b/MinecraftClient/Resources/lang/en.ini @@ -444,6 +444,12 @@ cmd.useitem.use=Used an item [bot] # ChatBots. Naming style: bot.. +# Alerts +bot.alerts.start_rain=§cWeather change: It's raining now.§r +bot.alerts.end_rain=§cWeather change: It's no longer raining.§r +bot.alerts.start_thunderstorm=§cWeather change: It's a thunderstorm.§r +bot.alerts.end_thunderstorm=§cWeather change: It's no longer a thunderstorm.§r + # Anti AFK bot.antiafk.not_using_terrain_handling=The terrain handling is not enabled in the settings of the client, enable it if you want to use it with this bot. Using alternative (command) method. bot.antiafk.invalid_range_partial=Invalid time range provided, using the first part of the range {0} as the time! diff --git a/MinecraftClient/Scripting/ChatBot.cs b/MinecraftClient/Scripting/ChatBot.cs index b5016d87..4007155d 100644 --- a/MinecraftClient/Scripting/ChatBot.cs +++ b/MinecraftClient/Scripting/ChatBot.cs @@ -413,6 +413,18 @@ namespace MinecraftClient /// The packet is received from server or sent by client public virtual void OnNetworkPacket(int packetID, List packetData, bool isLogin, bool isInbound) { } + /// + /// Called when the rain level have been changed + /// + /// + public virtual void OnRainLevelChange(float level) { } + + /// + /// Called when the thunder level have been changed + /// + /// + public virtual void OnThunderLevelChange(float level) { } + /* =================================================================== */ /* ToolBox - Methods below might be useful while creating your bot. */ /* You should not need to interact with other classes of the program. */ diff --git a/MinecraftClient/Settings.cs b/MinecraftClient/Settings.cs index c8cb6106..8fe4211e 100644 --- a/MinecraftClient/Settings.cs +++ b/MinecraftClient/Settings.cs @@ -152,6 +152,9 @@ namespace MinecraftClient //Alerts Settings public static bool Alerts_Enabled = false; + public static bool Alerts_Trigger_By_Words = false; + public static bool Alerts_Trigger_By_Rain = false; + public static bool Alerts_Trigger_By_Thunderstorm = false; public static bool Alerts_Beep_Enabled = true; public static bool Alerts_File_Logging = false; public static string Alerts_MatchesFile = "alerts.txt"; @@ -585,6 +588,9 @@ namespace MinecraftClient switch (ToLowerIfNeed(argName)) { case "enabled": Alerts_Enabled = str2bool(argValue); return true; + case "trigger_by_words": Alerts_Trigger_By_Words = str2bool(argValue); return true; + case "trigger_by_rain": Alerts_Trigger_By_Rain = str2bool(argValue); return true; + case "trigger_by_thunderstorm": Alerts_Trigger_By_Thunderstorm = str2bool(argValue); return true; case "alertsfile": Alerts_MatchesFile = argValue; return true; case "excludesfile": Alerts_ExcludesFile = argValue; return true; case "beeponalert": Alerts_Beep_Enabled = str2bool(argValue); return true;