From 42de4378e15ef4463d2f808c1d3e0c16bc83659f Mon Sep 17 00:00:00 2001 From: Milutinke Date: Mon, 29 Aug 2022 19:12:44 +0200 Subject: [PATCH 1/2] Added an option for custom timeout as requested in #1337. --- MinecraftClient/McClient.cs | 6 +++--- .../Resources/config/MinecraftClient.ini | 1 + MinecraftClient/Settings.cs | 15 ++++++++++----- 3 files changed, 14 insertions(+), 8 deletions(-) diff --git a/MinecraftClient/McClient.cs b/MinecraftClient/McClient.cs index abc001e8..e7d6647e 100644 --- a/MinecraftClient/McClient.cs +++ b/MinecraftClient/McClient.cs @@ -60,7 +60,7 @@ namespace MinecraftClient private float playerYaw; private float playerPitch; private double motionY; - public enum MovementType { Sneak, Walk, Sprint} + public enum MovementType { Sneak, Walk, Sprint } public int currentMovementSpeed = 4; private int sequenceId; // User for player block synchronization (Aka. digging, placing blocks, etc..) @@ -229,7 +229,7 @@ namespace MinecraftClient { client = ProxyHandler.newTcpClient(host, port); client.ReceiveBufferSize = 1024 * 1024; - client.ReceiveTimeout = 30000; // 30 seconds + client.ReceiveTimeout = Settings.Timeout * 1000; // Default: 30 seconds handler = Protocol.ProtocolHandler.GetProtocolHandler(client, protocolversion, forgeInfo, this); Log.Info(Translations.Get("mcc.version_supported")); @@ -414,7 +414,7 @@ namespace MinecraftClient lock (lastKeepAliveLock) { - if (lastKeepAlive.AddSeconds(30) < DateTime.Now) + if (lastKeepAlive.AddSeconds(Settings.Timeout) < DateTime.Now) { if (((CancellationToken)o!).IsCancellationRequested) return; diff --git a/MinecraftClient/Resources/config/MinecraftClient.ini b/MinecraftClient/Resources/config/MinecraftClient.ini index 2b93abf6..b77d8542 100644 --- a/MinecraftClient/Resources/config/MinecraftClient.ini +++ b/MinecraftClient/Resources/config/MinecraftClient.ini @@ -47,6 +47,7 @@ timestamps=false # Prepend timestamps to chat messages autorespawn=false # Toggle auto respawn if client player was dead (make sure your spawn point is safe) minecraftrealms=true # Enable support for joining Minecraft Realms worlds moveheadwhilewalking=true # Enable head movement while walking to avoid anti-cheat triggers +timeout=30 # Set a custom timeout in seconds (Default: 30). Use only if you know what you're doing. [Signature] # Chat settings (affects minecraft 1.19+) diff --git a/MinecraftClient/Settings.cs b/MinecraftClient/Settings.cs index 6f0f6654..9a668669 100644 --- a/MinecraftClient/Settings.cs +++ b/MinecraftClient/Settings.cs @@ -105,6 +105,7 @@ namespace MinecraftClient public static bool AutoRespawn = false; public static bool MinecraftRealmsEnabled = true; public static bool MoveHeadWhileWalking = true; + public static int Timeout = 30; // Signature public static bool LoginWithSecureProfile = true; @@ -206,7 +207,7 @@ namespace MinecraftClient //AutoCraft public static bool AutoCraft_Enabled = false; public static string AutoCraft_configFile = @"autocraft\config.ini"; - + //Mailer public static bool Mailer_Enabled = false; public static string Mailer_DatabaseFile = "MailerDatabase.ini"; @@ -355,10 +356,12 @@ namespace MinecraftClient { case "login": Login = argValue; return true; case "password": Password = argValue; return true; - case "type": AccountType = argValue == "mojang" + case "type": + AccountType = argValue == "mojang" ? ProtocolHandler.AccountType.Mojang : ProtocolHandler.AccountType.Microsoft; return true; - case "method": LoginMethod = argValue.ToLower() == "browser" + case "method": + LoginMethod = argValue.ToLower() == "browser" ? "browser" : "mcc"; return true; case "serverip": if (!SetServerIP(argValue)) ServerAliasTemp = argValue; return true; @@ -386,6 +389,7 @@ namespace MinecraftClient case "debugmessages": DebugMessages = str2bool(argValue); return true; case "minecraftrealms": MinecraftRealmsEnabled = str2bool(argValue); return true; case "moveheadwhilewalking": MoveHeadWhileWalking = str2bool(argValue); return true; + case "timeout": Timeout = str2int(argValue); return true; case "botowners": Bots_Owners.Clear(); @@ -821,7 +825,7 @@ namespace MinecraftClient public static void WriteDefaultSettings(string settingsfile) { // Load embedded default config and adjust line break for the current operating system - string settingsContents = String.Join(Environment.NewLine, + string settingsContents = String.Join(Environment.NewLine, DefaultConfigResource.MinecraftClient.Split(new[] { "\r\n", "\r", "\n" }, StringSplitOptions.None)); // Write configuration file with current version number @@ -843,7 +847,8 @@ namespace MinecraftClient { return Convert.ToInt32(str.Trim()); } - catch { + catch + { ConsoleIO.WriteLogLine(Translations.Get("error.setting.str2int", str)); return 0; } From dcf1442b4f5dcd1d45ee97608eaf204299acc55f Mon Sep 17 00:00:00 2001 From: Milutinke Date: Tue, 6 Sep 2022 16:08:51 +0200 Subject: [PATCH 2/2] Resolved a conflict --- MinecraftClient/Settings.cs | 150 +++++++++++++++++++++--------------- 1 file changed, 90 insertions(+), 60 deletions(-) diff --git a/MinecraftClient/Settings.cs b/MinecraftClient/Settings.cs index 9a668669..bb706672 100644 --- a/MinecraftClient/Settings.cs +++ b/MinecraftClient/Settings.cs @@ -7,6 +7,9 @@ using System.Text.RegularExpressions; using MinecraftClient.Protocol.Session; using MinecraftClient.Protocol; using MinecraftClient.Mapping; +using System.Threading.Tasks; +using System.Collections.Concurrent; +using System.Runtime.CompilerServices; namespace MinecraftClient { @@ -256,31 +259,27 @@ namespace MinecraftClient /// File to load public static void LoadFile(string file) { - ConsoleIO.WriteLogLine("[Settings] Loading Settings from " + Path.GetFullPath(file)); + Task.Factory.StartNew(() => ConsoleIO.WriteLogLine("[Settings] Loading Settings from " + Path.GetFullPath(file))); if (File.Exists(file)) { try { - string[] Lines = File.ReadAllLines(file); Section section = Section.Default; - foreach (string lineRAW in Lines) + foreach (var lineRAW in File.ReadLines(file)) { - string line = section == Section.Main && lineRAW.ToLower().Trim().StartsWith("password") - ? lineRAW.Trim() //Do not strip # in passwords - : lineRAW.Split('#')[0].Trim(); - - if (line.Length > 0) + string line = lineRAW.Split('#')[0].Trim(); + if (line.Length > 1) { - if (line[0] == '[' && line[line.Length - 1] == ']') - { - section = GetSection(line.Substring(1, line.Length - 2).ToLower()); - } + if (line.Length > 2 && line[0] == '[' && line[^1] == ']') + section = GetSection(line[1..^1]); else { string argName = line.Split('=')[0]; + if (section == Section.Main && argName == "password") + line = lineRAW.Trim(); //Do not strip # in passwords if (line.Length > (argName.Length + 1)) { - string argValue = line.Substring(argName.Length + 1); + string argValue = line[(argName.Length + 1)..]; LoadSingleSetting(section, argName, argValue); } } @@ -352,7 +351,7 @@ namespace MinecraftClient switch (section) { case Section.Main: - switch (argName.ToLower()) + switch (ToLowerIfNeed(argName)) { case "login": Login = argValue; return true; case "password": Password = argValue; return true; @@ -361,9 +360,8 @@ namespace MinecraftClient ? ProtocolHandler.AccountType.Mojang : ProtocolHandler.AccountType.Microsoft; return true; case "method": - LoginMethod = argValue.ToLower() == "browser" - ? "browser" - : "mcc"; return true; + argValue = ToLowerIfNeed(argValue); + LoginMethod = argValue == "browser" ? "browser" : "mcc"; return true; case "serverip": if (!SetServerIP(argValue)) ServerAliasTemp = argValue; return true; case "singlecommand": SingleCommand = argValue; return true; case "language": Language = argValue; return true; @@ -383,7 +381,7 @@ namespace MinecraftClient case "entityhandling": EntityHandling = str2bool(argValue); return true; case "enableentityhandling": EntityHandling = str2bool(argValue); return true; case "inventoryhandling": InventoryHandling = str2bool(argValue); return true; - case "privatemsgscmdname": PrivateMsgsCmdName = argValue.ToLower().Trim(); return true; + case "privatemsgscmdname": PrivateMsgsCmdName = ToLowerIfNeed(argValue).Trim(); return true; case "autorespawn": AutoRespawn = str2bool(argValue); return true; // Backward compatible so people can still enable debug with old config format case "debugmessages": DebugMessages = str2bool(argValue); return true; @@ -393,8 +391,9 @@ namespace MinecraftClient case "botowners": Bots_Owners.Clear(); - string[] names = argValue.ToLower().Split(','); - if (!argValue.Contains(",") && argValue.ToLower().EndsWith(".txt") && File.Exists(argValue)) + string lowerArgValue = ToLowerIfNeed(argValue); + string[] names = lowerArgValue.Split(','); + if (!argValue.Contains(",") && lowerArgValue.EndsWith(".txt") && File.Exists(argValue)) names = File.ReadAllLines(argValue); foreach (string name in names) if (!String.IsNullOrWhiteSpace(name)) @@ -402,7 +401,8 @@ namespace MinecraftClient return true; case "internalcmdchar": - switch (argValue.ToLower()) + argValue = ToLowerIfNeed(argValue); + switch (argValue) { case "none": internalCmdChar = ' '; break; case "slash": internalCmdChar = '/'; break; @@ -430,7 +430,7 @@ namespace MinecraftClient //Each line contains account data: 'Alias,Login,Password' string[] account_data = account_line.Split('#')[0].Trim().Split(','); if (account_data.Length == 3) - Accounts[account_data[0].ToLower()] + Accounts[ToLowerIfNeed(account_data[0])] = new KeyValuePair(account_data[1], account_data[2]); } @@ -450,7 +450,7 @@ namespace MinecraftClient { //Each line contains server data: 'Alias,Host:Port' string[] server_data = server_line.Split('#')[0].Trim().Split(','); - server_data[0] = server_data[0].ToLower(); + server_data[0] = ToLowerIfNeed(server_data[0]); if (server_data.Length == 2 && server_data[0] != "localhost" && !server_data[0].Contains('.') @@ -473,7 +473,7 @@ namespace MinecraftClient return true; case "brandinfo": - switch (argValue.Trim().ToLower()) + switch (ToLowerIfNeed(argValue.Trim())) { case "mcc": BrandInfo = MCCBrandInfo; break; case "vanilla": BrandInfo = "vanilla"; break; @@ -482,7 +482,7 @@ namespace MinecraftClient return true; case "resolvesrvrecords": - if (argValue.Trim().ToLower() == "fast") + if (ToLowerIfNeed(argValue.Trim()) == "fast") { ResolveSrvRecords = true; ResolveSrvRecordsShortTimeout = true; @@ -495,7 +495,7 @@ namespace MinecraftClient return true; case "mcforge": - if (argValue.ToLower() == "auto") + if (ToLowerIfNeed(argValue) == "auto") { ServerAutodetectForge = true; ServerForceForge = false; @@ -510,7 +510,7 @@ namespace MinecraftClient break; case Section.Signature: - switch (argName.ToLower()) + switch (ToLowerIfNeed(argName)) { case "login_with_secure_profile": LoginWithSecureProfile = str2bool(argValue); return true; case "sign_chat": SignChat = str2bool(argValue); return true; @@ -525,7 +525,7 @@ namespace MinecraftClient break; case Section.Logging: - switch (argName.ToLower()) + switch (ToLowerIfNeed(argName)) { case "debugmessages": DebugMessages = str2bool(argValue); return true; case "chatmessages": ChatMessages = str2bool(argValue); return true; @@ -535,7 +535,7 @@ namespace MinecraftClient case "chatfilter": ChatFilter = new Regex(argValue); return true; case "debugfilter": DebugFilter = new Regex(argValue); return true; case "filtermode": - if (argValue.ToLower().StartsWith("white")) + if (ToLowerIfNeed(argValue).StartsWith("white")) FilterMode = FilterModeEnum.Whitelist; else FilterMode = FilterModeEnum.Blacklist; @@ -548,7 +548,7 @@ namespace MinecraftClient break; case Section.Alerts: - switch (argName.ToLower()) + switch (ToLowerIfNeed(argName)) { case "enabled": Alerts_Enabled = str2bool(argValue); return true; case "alertsfile": Alerts_MatchesFile = argValue; return true; @@ -558,7 +558,7 @@ namespace MinecraftClient break; case Section.AntiAFK: - switch (argName.ToLower()) + switch (ToLowerIfNeed(argName)) { case "enabled": AntiAFK_Enabled = str2bool(argValue); return true; case "delay": AntiAFK_Delay = str2int(argValue); return true; @@ -567,7 +567,7 @@ namespace MinecraftClient break; case Section.AutoRelog: - switch (argName.ToLower()) + switch (ToLowerIfNeed(argName)) { case "enabled": AutoRelog_Enabled = str2bool(argValue); return true; case "retries": AutoRelog_Retries = str2int(argValue); return true; @@ -591,7 +591,7 @@ namespace MinecraftClient break; case Section.ChatLog: - switch (argName.ToLower()) + switch (ToLowerIfNeed(argName)) { case "enabled": ChatLog_Enabled = str2bool(argValue); return true; case "timestamps": ChatLog_DateTime = str2bool(argValue); return true; @@ -601,7 +601,7 @@ namespace MinecraftClient break; case Section.Hangman: - switch (argName.ToLower()) + switch (ToLowerIfNeed(argName)) { case "enabled": Hangman_Enabled = str2bool(argValue); return true; case "english": Hangman_English = str2bool(argValue); return true; @@ -611,7 +611,7 @@ namespace MinecraftClient break; case Section.ScriptScheduler: - switch (argName.ToLower()) + switch (ToLowerIfNeed(argName)) { case "enabled": ScriptScheduler_Enabled = str2bool(argValue); return true; case "tasksfile": ScriptScheduler_TasksFile = argValue; return true; @@ -619,7 +619,7 @@ namespace MinecraftClient break; case Section.RemoteControl: - switch (argName.ToLower()) + switch (ToLowerIfNeed(argName)) { case "enabled": RemoteCtrl_Enabled = str2bool(argValue); return true; case "autotpaccept": RemoteCtrl_AutoTpaccept = str2bool(argValue); return true; @@ -628,7 +628,7 @@ namespace MinecraftClient break; case Section.ChatFormat: - switch (argName.ToLower()) + switch (ToLowerIfNeed(argName)) { case "builtins": ChatFormat_Builtins = str2bool(argValue); return true; case "public": ChatFormat_Public = new Regex(argValue); return true; @@ -638,15 +638,15 @@ namespace MinecraftClient break; case Section.Proxy: - switch (argName.ToLower()) + switch (ToLowerIfNeed(argName)) { case "enabled": ProxyEnabledLogin = ProxyEnabledIngame = str2bool(argValue); - if (argValue.Trim().ToLower() == "login") + if (ToLowerIfNeed(argValue.Trim()) == "login") ProxyEnabledLogin = true; return true; case "type": - argValue = argValue.ToLower(); + argValue = ToLowerIfNeed(argValue); if (argValue == "http") { proxyType = Proxy.ProxyHandler.Type.HTTP; } else if (argValue == "socks4") { proxyType = Proxy.ProxyHandler.Type.SOCKS4; } else if (argValue == "socks4a") { proxyType = Proxy.ProxyHandler.Type.SOCKS4a; } @@ -675,7 +675,7 @@ namespace MinecraftClient return true; case Section.AutoRespond: - switch (argName.ToLower()) + switch (ToLowerIfNeed(argName)) { case "enabled": AutoRespond_Enabled = str2bool(argValue); return true; case "matchesfile": AutoRespond_Matches = argValue; return true; @@ -683,13 +683,13 @@ namespace MinecraftClient break; case Section.AutoAttack: - switch (argName.ToLower()) + switch (ToLowerIfNeed(argName)) { case "enabled": AutoAttack_Enabled = str2bool(argValue); return true; - case "mode": AutoAttack_Mode = argValue.ToLower(); return true; - case "priority": AutoAttack_Priority = argValue.ToLower(); return true; + case "mode": AutoAttack_Mode = ToLowerIfNeed(argValue); return true; + case "priority": AutoAttack_Priority = ToLowerIfNeed(argValue); return true; case "cooldownseconds": - if (argValue.ToLower() == "auto") + if (ToLowerIfNeed(argValue) == "auto") { AutoAttack_OverrideAttackSpeed = false; } @@ -705,7 +705,7 @@ namespace MinecraftClient break; case Section.AutoFishing: - switch (argName.ToLower()) + switch (ToLowerIfNeed(argName)) { case "enabled": AutoFishing_Enabled = str2bool(argValue); return true; case "antidespawn": AutoFishing_Antidespawn = str2bool(argValue); return true; @@ -713,7 +713,7 @@ namespace MinecraftClient break; case Section.AutoEat: - switch (argName.ToLower()) + switch (ToLowerIfNeed(argName)) { case "enabled": AutoEat_Enabled = str2bool(argValue); return true; case "threshold": AutoEat_hungerThreshold = str2int(argValue); return true; @@ -721,7 +721,7 @@ namespace MinecraftClient break; case Section.AutoCraft: - switch (argName.ToLower()) + switch (ToLowerIfNeed(argName)) { case "enabled": AutoCraft_Enabled = str2bool(argValue); return true; case "configfile": AutoCraft_configFile = argValue; return true; @@ -729,7 +729,7 @@ namespace MinecraftClient break; case Section.AutoDrop: - switch (argName.ToLower()) + switch (ToLowerIfNeed(argName)) { case "enabled": AutoDrop_Enabled = str2bool(argValue); return true; case "mode": AutoDrop_Mode = argValue; return true; @@ -738,12 +738,12 @@ namespace MinecraftClient break; case Section.MCSettings: - switch (argName.ToLower()) + switch (ToLowerIfNeed(argName)) { case "enabled": MCSettings_Enabled = str2bool(argValue); return true; case "locale": MCSettings_Locale = argValue; return true; case "difficulty": - switch (argValue.ToLower()) + switch (ToLowerIfNeed(argValue)) { case "peaceful": MCSettings_Difficulty = 0; break; case "easy": MCSettings_Difficulty = 1; break; @@ -759,7 +759,7 @@ namespace MinecraftClient } else { - switch (argValue.ToLower()) + switch (ToLowerIfNeed(argValue)) { case "tiny": MCSettings_RenderDistance = 2; break; case "short": MCSettings_RenderDistance = 4; break; @@ -769,7 +769,7 @@ namespace MinecraftClient } return true; case "chatmode": - switch (argValue.ToLower()) + switch (ToLowerIfNeed(argValue)) { case "enabled": MCSettings_ChatMode = 0; break; case "commands": MCSettings_ChatMode = 1; break; @@ -785,7 +785,7 @@ namespace MinecraftClient case "skin_pants_right": MCSettings_Skin_Pants_Right = str2bool(argValue); return true; case "skin_hat": MCSettings_Skin_Hat = str2bool(argValue); return true; case "main_hand": - switch (argValue.ToLower()) + switch (ToLowerIfNeed(argValue)) { case "left": MCSettings_MainHand = 0; break; case "right": MCSettings_MainHand = 1; break; @@ -795,7 +795,7 @@ namespace MinecraftClient break; case Section.Mailer: - switch (argName.ToLower()) + switch (ToLowerIfNeed(argName)) { case "enabled": Mailer_Enabled = str2bool(argValue); return true; case "database": Mailer_DatabaseFile = argValue; return true; @@ -808,7 +808,7 @@ namespace MinecraftClient break; case Section.ReplayMod: - switch (argName.ToLower()) + switch (ToLowerIfNeed(argName)) { case "enabled": ReplayMod_Enabled = str2bool(argValue); return true; case "backupinterval": ReplayMod_BackupInterval = str2int(argValue); return true; @@ -884,13 +884,43 @@ namespace MinecraftClient return str == "true" || str == "1"; } + [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] + public static string ToLowerIfNeed(string str) + { + const string lookupStringL = +"---------------------------------!-#$%&-()*+,-./0123456789:;<=>?@abcdefghijklmnopqrstuvwxyz[-]^_`abcdefghijklmnopqrstuvwxyz{|}~-"; + + bool needLower = false; + foreach (Char c in str) + { + if (Char.IsUpper(c)) + { + needLower = true; + break; + } + } + + if (needLower) + { + StringBuilder sb = new(str); + for (int i = 0; i < str.Length; ++i) + if (char.IsUpper(sb[i])) + sb[i] = lookupStringL[sb[i]]; + return sb.ToString(); + } + else + { + return str; + } + } + /// /// Load login/password using an account alias /// /// True if the account was found and loaded public static bool SetAccount(string accountAlias) { - accountAlias = accountAlias.ToLower(); + accountAlias = Settings.ToLowerIfNeed(accountAlias); if (Accounts.ContainsKey(accountAlias)) { Settings.Login = Accounts[accountAlias].Key; @@ -906,7 +936,7 @@ namespace MinecraftClient /// True if the server IP was valid and loaded, false otherwise public static bool SetServerIP(string server) { - server = server.ToLower(); + server = ToLowerIfNeed(server); string[] sip = server.Split(':'); string host = sip[0]; ushort port = 25565; @@ -951,7 +981,7 @@ namespace MinecraftClient { lock (AppVars) { - varName = new string(varName.TakeWhile(char.IsLetterOrDigit).ToArray()).ToLower(); + varName = Settings.ToLowerIfNeed(new string(varName.TakeWhile(char.IsLetterOrDigit).ToArray())); if (varName.Length > 0) { AppVars[varName] = varData; @@ -1003,7 +1033,7 @@ namespace MinecraftClient if (varname_ok) { string varname = var_name.ToString(); - string varname_lower = varname.ToLower(); + string varname_lower = Settings.ToLowerIfNeed(varname); i = i + varname.Length + 1; switch (varname_lower)