Startup Optimization

This commit is contained in:
BruceChen 2022-08-30 22:50:05 +08:00
parent 3d13eb51e6
commit c90ea0e92b
6 changed files with 104 additions and 70 deletions

View file

@ -70,7 +70,7 @@ namespace MinecraftClient.ChatBots
public static MessageFilter str2filter(string filtername) public static MessageFilter str2filter(string filtername)
{ {
switch (filtername.ToLower()) switch (Settings.ToLowerIfNeed(filtername))
{ {
case "all": return MessageFilter.AllText; case "all": return MessageFilter.AllText;
case "messages": return MessageFilter.AllMessages; case "messages": return MessageFilter.AllMessages;

View file

@ -52,7 +52,7 @@ namespace MinecraftClient
/// </summary> /// </summary>
static void Main(string[] args) static void Main(string[] args)
{ {
Task.Factory.StartNew(() => new Thread(() =>
{ {
//Take advantage of Windows 10 / Mac / Linux UTF-8 console //Take advantage of Windows 10 / Mac / Linux UTF-8 console
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
@ -69,7 +69,10 @@ namespace MinecraftClient
// Fix issue #2119 // Fix issue #2119
Encoding.RegisterProvider(CodePagesEncodingProvider.Instance); Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
});
// "ToLower" require "CultureInfo" to be initialized on first run, which can take a lot of time.
// _ = "a".ToLower();
}).Start();
//Setup ConsoleIO //Setup ConsoleIO
ConsoleIO.LogPrefix = "§8[MCC] "; ConsoleIO.LogPrefix = "§8[MCC] ";
@ -102,7 +105,7 @@ namespace MinecraftClient
} }
//Process ini configuration file //Process ini configuration file
if (args.Length >= 1 && System.IO.File.Exists(args[0]) && System.IO.Path.GetExtension(args[0]).ToLower() == ".ini") if (args.Length >= 1 && System.IO.File.Exists(args[0]) && Settings.ToLowerIfNeed(Path.GetExtension(args[0])) == ".ini")
{ {
Settings.LoadFile(args[0]); Settings.LoadFile(args[0]);
@ -163,7 +166,7 @@ namespace MinecraftClient
} }
} }
if (string.IsNullOrEmpty(dataGenerator) || !(dataGenerator.ToLower().Equals("entity") || dataGenerator.ToLower().Equals("item") || dataGenerator.ToLower().Equals("block"))) if (string.IsNullOrEmpty(dataGenerator) || !(Settings.ToLowerIfNeed(dataGenerator).Equals("entity") || Settings.ToLowerIfNeed(dataGenerator).Equals("item") || Settings.ToLowerIfNeed(dataGenerator).Equals("block")))
{ {
Console.WriteLine(Translations.Get("error.generator.invalid")); Console.WriteLine(Translations.Get("error.generator.invalid"));
Console.WriteLine(Translations.Get("error.usage") + " MinecraftClient.exe --data-generator=<entity|item|block> --data-path=\"<path to resources.json>\""); Console.WriteLine(Translations.Get("error.usage") + " MinecraftClient.exe --data-generator=<entity|item|block> --data-path=\"<path to resources.json>\"");
@ -250,7 +253,7 @@ namespace MinecraftClient
Settings.Login = ConsoleIO.ReadLine(); Settings.Login = ConsoleIO.ReadLine();
} }
if (Settings.Password == "" if (Settings.Password == ""
&& (Settings.SessionCaching == CacheType.None || !SessionCache.Contains(Settings.Login.ToLower())) && (Settings.SessionCaching == CacheType.None || !SessionCache.Contains(Settings.ToLowerIfNeed(Settings.Login)))
&& !useBrowser) && !useBrowser)
{ {
RequestPassword(); RequestPassword();
@ -291,6 +294,7 @@ namespace MinecraftClient
ProtocolHandler.LoginResult result = ProtocolHandler.LoginResult.LoginRequired; ProtocolHandler.LoginResult result = ProtocolHandler.LoginResult.LoginRequired;
string loginLower = Settings.ToLowerIfNeed(Settings.Login);
if (Settings.Password == "-") if (Settings.Password == "-")
{ {
Translations.WriteLineFormatted("mcc.offline"); Translations.WriteLineFormatted("mcc.offline");
@ -301,9 +305,9 @@ namespace MinecraftClient
else else
{ {
// Validate cached session or login new session. // Validate cached session or login new session.
if (Settings.SessionCaching != CacheType.None && SessionCache.Contains(Settings.Login.ToLower())) if (Settings.SessionCaching != CacheType.None && SessionCache.Contains(loginLower))
{ {
session = SessionCache.Get(Settings.Login.ToLower()); session = SessionCache.Get(loginLower);
result = ProtocolHandler.GetTokenValidation(session); result = ProtocolHandler.GetTokenValidation(session);
if (result != ProtocolHandler.LoginResult.Success) if (result != ProtocolHandler.LoginResult.Success)
{ {
@ -338,7 +342,7 @@ namespace MinecraftClient
} }
if (result == ProtocolHandler.LoginResult.Success && Settings.SessionCaching != CacheType.None) if (result == ProtocolHandler.LoginResult.Success && Settings.SessionCaching != CacheType.None)
SessionCache.Store(Settings.Login.ToLower(), session); SessionCache.Store(loginLower, session);
if (result == ProtocolHandler.LoginResult.Success) if (result == ProtocolHandler.LoginResult.Success)
session.SessionPreCheckTask = Task.Factory.StartNew(() => session.SessionPreCheck()); session.SessionPreCheckTask = Task.Factory.StartNew(() => session.SessionPreCheck());
@ -355,9 +359,9 @@ namespace MinecraftClient
Translations.WriteLineFormatted(cacheKeyLoaded ? "debug.keys_cache_ok" : "debug.keys_cache_fail"); Translations.WriteLineFormatted(cacheKeyLoaded ? "debug.keys_cache_ok" : "debug.keys_cache_fail");
} }
if (Settings.ProfileKeyCaching != CacheType.None && KeysCache.Contains(Settings.Login.ToLower())) if (Settings.ProfileKeyCaching != CacheType.None && KeysCache.Contains(loginLower))
{ {
playerKeyPair = KeysCache.Get(Settings.Login.ToLower()); playerKeyPair = KeysCache.Get(loginLower);
if (playerKeyPair.NeedRefresh()) if (playerKeyPair.NeedRefresh())
Translations.WriteLineFormatted("mcc.profile_key_invalid"); Translations.WriteLineFormatted("mcc.profile_key_invalid");
else else
@ -370,7 +374,7 @@ namespace MinecraftClient
playerKeyPair = KeyUtils.GetNewProfileKeys(session.ID); playerKeyPair = KeyUtils.GetNewProfileKeys(session.ID);
if (Settings.ProfileKeyCaching != CacheType.None && playerKeyPair != null) if (Settings.ProfileKeyCaching != CacheType.None && playerKeyPair != null)
{ {
KeysCache.Store(Settings.Login.ToLower(), playerKeyPair); KeysCache.Store(loginLower, playerKeyPair);
} }
} }
} }
@ -442,7 +446,7 @@ namespace MinecraftClient
int protocolversion = 0; int protocolversion = 0;
ForgeInfo? forgeInfo = null; ForgeInfo? forgeInfo = null;
if (Settings.ServerVersion != "" && Settings.ServerVersion.ToLower() != "auto") if (Settings.ServerVersion != "" && Settings.ToLowerIfNeed(Settings.ServerVersion) != "auto")
{ {
protocolversion = Protocol.ProtocolHandler.MCVer2ProtocolVersion(Settings.ServerVersion); protocolversion = Protocol.ProtocolHandler.MCVer2ProtocolVersion(Settings.ServerVersion);

View file

@ -217,8 +217,7 @@ namespace MinecraftClient.Protocol
//Load the external dictionnary of translation rules or display an error message //Load the external dictionnary of translation rules or display an error message
if (System.IO.File.Exists(Language_File)) if (System.IO.File.Exists(Language_File))
{ {
string[] translations = System.IO.File.ReadAllLines(Language_File); foreach (var line in File.ReadLines(Language_File))
foreach (string line in translations)
{ {
if (line.Length > 0) if (line.Length > 0)
{ {

View file

@ -20,8 +20,8 @@ namespace MinecraftClient.Protocol.Keys
{ {
PublicKey = keyPublic; PublicKey = keyPublic;
PrivateKey = keyPrivate; PrivateKey = keyPrivate;
ExpiresAt = DateTime.Parse(expiresAt).ToUniversalTime(); ExpiresAt = DateTime.ParseExact(expiresAt, "yyyy-MM-ddTHH:mm:ss.fffffffZ", System.Globalization.CultureInfo.InvariantCulture).ToUniversalTime();
RefreshedAfter = DateTime.Parse(refreshedAfter).ToUniversalTime(); RefreshedAfter = DateTime.ParseExact(refreshedAfter, "yyyy-MM-ddTHH:mm:ss.fffffffZ", System.Globalization.CultureInfo.InvariantCulture).ToUniversalTime();
} }
public bool NeedRefresh() public bool NeedRefresh()

View file

@ -148,7 +148,7 @@ namespace MinecraftClient.Protocol.Session
&& sessionItem.ContainsKey("username") && sessionItem.ContainsKey("username")
&& sessionItem.ContainsKey("uuid")) && sessionItem.ContainsKey("uuid"))
{ {
string login = sessionItem["username"].StringValue.ToLower(); string login = Settings.ToLowerIfNeed(sessionItem["username"].StringValue);
try try
{ {
SessionToken session = SessionToken.FromString(String.Join(",", SessionToken session = SessionToken.FromString(String.Join(",",
@ -214,7 +214,7 @@ namespace MinecraftClient.Protocol.Session
{ {
try try
{ {
string login = keyValue[0].ToLower(); string login = Settings.ToLowerIfNeed(keyValue[0]);
SessionToken session = SessionToken.FromString(keyValue[1]); SessionToken session = SessionToken.FromString(keyValue[1]);
if (Settings.DebugMessages) if (Settings.DebugMessages)
ConsoleIO.WriteLineFormatted(Translations.Get("cache.loaded", login, session.ID)); ConsoleIO.WriteLineFormatted(Translations.Get("cache.loaded", login, session.ID));

View file

@ -9,6 +9,7 @@ using MinecraftClient.Protocol;
using MinecraftClient.Mapping; using MinecraftClient.Mapping;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Collections.Concurrent; using System.Collections.Concurrent;
using System.Runtime.CompilerServices;
namespace MinecraftClient namespace MinecraftClient
{ {
@ -257,17 +258,15 @@ namespace MinecraftClient
/// <param name="file">File to load</param> /// <param name="file">File to load</param>
public static void LoadFile(string file) 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)) if (File.Exists(file))
{ {
try try
{ {
string[] Lines = File.ReadAllLines(file);
Section section = Section.Default; Section section = Section.Default;
foreach (string lineRAW in Lines) foreach (var lineRAW in File.ReadLines(file))
{ {
string line = lineRAW.Split('#')[0].Trim(); string line = lineRAW.Split('#')[0].Trim();
if (line.Length > 1) if (line.Length > 1)
{ {
if (line.Length > 2 && line[0] == '[' && line[^1] == ']') if (line.Length > 2 && line[0] == '[' && line[^1] == ']')
@ -351,16 +350,16 @@ namespace MinecraftClient
switch (section) switch (section)
{ {
case Section.Main: case Section.Main:
switch (argName.ToLower()) switch (ToLowerIfNeed(argName))
{ {
case "login": Login = argValue; return true; case "login": Login = argValue; return true;
case "password": Password = argValue; return true; case "password": Password = argValue; return true;
case "type": AccountType = argValue == "mojang" case "type": AccountType = argValue == "mojang"
? ProtocolHandler.AccountType.Mojang ? ProtocolHandler.AccountType.Mojang
: ProtocolHandler.AccountType.Microsoft; return true; : ProtocolHandler.AccountType.Microsoft; return true;
case "method": LoginMethod = argValue.ToLower() == "browser" case "method":
? "browser" argValue = ToLowerIfNeed(argValue);
: "mcc"; return true; LoginMethod = argValue == "browser" ? "browser" : "mcc"; return true;
case "serverip": if (!SetServerIP(argValue)) ServerAliasTemp = argValue; return true; case "serverip": if (!SetServerIP(argValue)) ServerAliasTemp = argValue; return true;
case "singlecommand": SingleCommand = argValue; return true; case "singlecommand": SingleCommand = argValue; return true;
case "language": Language = argValue; return true; case "language": Language = argValue; return true;
@ -380,7 +379,7 @@ namespace MinecraftClient
case "entityhandling": EntityHandling = str2bool(argValue); return true; case "entityhandling": EntityHandling = str2bool(argValue); return true;
case "enableentityhandling": EntityHandling = str2bool(argValue); return true; case "enableentityhandling": EntityHandling = str2bool(argValue); return true;
case "inventoryhandling": InventoryHandling = 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; case "autorespawn": AutoRespawn = str2bool(argValue); return true;
// Backward compatible so people can still enable debug with old config format // Backward compatible so people can still enable debug with old config format
case "debugmessages": DebugMessages = str2bool(argValue); return true; case "debugmessages": DebugMessages = str2bool(argValue); return true;
@ -389,8 +388,9 @@ namespace MinecraftClient
case "botowners": case "botowners":
Bots_Owners.Clear(); Bots_Owners.Clear();
string[] names = argValue.ToLower().Split(','); string lowerArgValue = ToLowerIfNeed(argValue);
if (!argValue.Contains(",") && argValue.ToLower().EndsWith(".txt") && File.Exists(argValue)) string[] names = lowerArgValue.Split(',');
if (!argValue.Contains(",") && lowerArgValue.EndsWith(".txt") && File.Exists(argValue))
names = File.ReadAllLines(argValue); names = File.ReadAllLines(argValue);
foreach (string name in names) foreach (string name in names)
if (!String.IsNullOrWhiteSpace(name)) if (!String.IsNullOrWhiteSpace(name))
@ -398,7 +398,8 @@ namespace MinecraftClient
return true; return true;
case "internalcmdchar": case "internalcmdchar":
switch (argValue.ToLower()) argValue = ToLowerIfNeed(argValue);
switch (argValue)
{ {
case "none": internalCmdChar = ' '; break; case "none": internalCmdChar = ' '; break;
case "slash": internalCmdChar = '/'; break; case "slash": internalCmdChar = '/'; break;
@ -426,7 +427,7 @@ namespace MinecraftClient
//Each line contains account data: 'Alias,Login,Password' //Each line contains account data: 'Alias,Login,Password'
string[] account_data = account_line.Split('#')[0].Trim().Split(','); string[] account_data = account_line.Split('#')[0].Trim().Split(',');
if (account_data.Length == 3) if (account_data.Length == 3)
Accounts[account_data[0].ToLower()] Accounts[ToLowerIfNeed(account_data[0])]
= new KeyValuePair<string, string>(account_data[1], account_data[2]); = new KeyValuePair<string, string>(account_data[1], account_data[2]);
} }
@ -446,7 +447,7 @@ namespace MinecraftClient
{ {
//Each line contains server data: 'Alias,Host:Port' //Each line contains server data: 'Alias,Host:Port'
string[] server_data = server_line.Split('#')[0].Trim().Split(','); 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 if (server_data.Length == 2
&& server_data[0] != "localhost" && server_data[0] != "localhost"
&& !server_data[0].Contains('.') && !server_data[0].Contains('.')
@ -469,7 +470,7 @@ namespace MinecraftClient
return true; return true;
case "brandinfo": case "brandinfo":
switch (argValue.Trim().ToLower()) switch (ToLowerIfNeed(argValue.Trim()))
{ {
case "mcc": BrandInfo = MCCBrandInfo; break; case "mcc": BrandInfo = MCCBrandInfo; break;
case "vanilla": BrandInfo = "vanilla"; break; case "vanilla": BrandInfo = "vanilla"; break;
@ -478,7 +479,7 @@ namespace MinecraftClient
return true; return true;
case "resolvesrvrecords": case "resolvesrvrecords":
if (argValue.Trim().ToLower() == "fast") if (ToLowerIfNeed(argValue.Trim()) == "fast")
{ {
ResolveSrvRecords = true; ResolveSrvRecords = true;
ResolveSrvRecordsShortTimeout = true; ResolveSrvRecordsShortTimeout = true;
@ -491,7 +492,7 @@ namespace MinecraftClient
return true; return true;
case "mcforge": case "mcforge":
if (argValue.ToLower() == "auto") if (ToLowerIfNeed(argValue) == "auto")
{ {
ServerAutodetectForge = true; ServerAutodetectForge = true;
ServerForceForge = false; ServerForceForge = false;
@ -506,7 +507,7 @@ namespace MinecraftClient
break; break;
case Section.Signature: case Section.Signature:
switch (argName.ToLower()) switch (ToLowerIfNeed(argName))
{ {
case "login_with_secure_profile": LoginWithSecureProfile = str2bool(argValue); return true; case "login_with_secure_profile": LoginWithSecureProfile = str2bool(argValue); return true;
case "sign_chat": SignChat = str2bool(argValue); return true; case "sign_chat": SignChat = str2bool(argValue); return true;
@ -521,7 +522,7 @@ namespace MinecraftClient
break; break;
case Section.Logging: case Section.Logging:
switch (argName.ToLower()) switch (ToLowerIfNeed(argName))
{ {
case "debugmessages": DebugMessages = str2bool(argValue); return true; case "debugmessages": DebugMessages = str2bool(argValue); return true;
case "chatmessages": ChatMessages = str2bool(argValue); return true; case "chatmessages": ChatMessages = str2bool(argValue); return true;
@ -531,7 +532,7 @@ namespace MinecraftClient
case "chatfilter": ChatFilter = new Regex(argValue); return true; case "chatfilter": ChatFilter = new Regex(argValue); return true;
case "debugfilter": DebugFilter = new Regex(argValue); return true; case "debugfilter": DebugFilter = new Regex(argValue); return true;
case "filtermode": case "filtermode":
if (argValue.ToLower().StartsWith("white")) if (ToLowerIfNeed(argValue).StartsWith("white"))
FilterMode = FilterModeEnum.Whitelist; FilterMode = FilterModeEnum.Whitelist;
else else
FilterMode = FilterModeEnum.Blacklist; FilterMode = FilterModeEnum.Blacklist;
@ -544,7 +545,7 @@ namespace MinecraftClient
break; break;
case Section.Alerts: case Section.Alerts:
switch (argName.ToLower()) switch (ToLowerIfNeed(argName))
{ {
case "enabled": Alerts_Enabled = str2bool(argValue); return true; case "enabled": Alerts_Enabled = str2bool(argValue); return true;
case "alertsfile": Alerts_MatchesFile = argValue; return true; case "alertsfile": Alerts_MatchesFile = argValue; return true;
@ -554,7 +555,7 @@ namespace MinecraftClient
break; break;
case Section.AntiAFK: case Section.AntiAFK:
switch (argName.ToLower()) switch (ToLowerIfNeed(argName))
{ {
case "enabled": AntiAFK_Enabled = str2bool(argValue); return true; case "enabled": AntiAFK_Enabled = str2bool(argValue); return true;
case "delay": AntiAFK_Delay = str2int(argValue); return true; case "delay": AntiAFK_Delay = str2int(argValue); return true;
@ -563,7 +564,7 @@ namespace MinecraftClient
break; break;
case Section.AutoRelog: case Section.AutoRelog:
switch (argName.ToLower()) switch (ToLowerIfNeed(argName))
{ {
case "enabled": AutoRelog_Enabled = str2bool(argValue); return true; case "enabled": AutoRelog_Enabled = str2bool(argValue); return true;
case "retries": AutoRelog_Retries = str2int(argValue); return true; case "retries": AutoRelog_Retries = str2int(argValue); return true;
@ -587,7 +588,7 @@ namespace MinecraftClient
break; break;
case Section.ChatLog: case Section.ChatLog:
switch (argName.ToLower()) switch (ToLowerIfNeed(argName))
{ {
case "enabled": ChatLog_Enabled = str2bool(argValue); return true; case "enabled": ChatLog_Enabled = str2bool(argValue); return true;
case "timestamps": ChatLog_DateTime = str2bool(argValue); return true; case "timestamps": ChatLog_DateTime = str2bool(argValue); return true;
@ -597,7 +598,7 @@ namespace MinecraftClient
break; break;
case Section.Hangman: case Section.Hangman:
switch (argName.ToLower()) switch (ToLowerIfNeed(argName))
{ {
case "enabled": Hangman_Enabled = str2bool(argValue); return true; case "enabled": Hangman_Enabled = str2bool(argValue); return true;
case "english": Hangman_English = str2bool(argValue); return true; case "english": Hangman_English = str2bool(argValue); return true;
@ -607,7 +608,7 @@ namespace MinecraftClient
break; break;
case Section.ScriptScheduler: case Section.ScriptScheduler:
switch (argName.ToLower()) switch (ToLowerIfNeed(argName))
{ {
case "enabled": ScriptScheduler_Enabled = str2bool(argValue); return true; case "enabled": ScriptScheduler_Enabled = str2bool(argValue); return true;
case "tasksfile": ScriptScheduler_TasksFile = argValue; return true; case "tasksfile": ScriptScheduler_TasksFile = argValue; return true;
@ -615,7 +616,7 @@ namespace MinecraftClient
break; break;
case Section.RemoteControl: case Section.RemoteControl:
switch (argName.ToLower()) switch (ToLowerIfNeed(argName))
{ {
case "enabled": RemoteCtrl_Enabled = str2bool(argValue); return true; case "enabled": RemoteCtrl_Enabled = str2bool(argValue); return true;
case "autotpaccept": RemoteCtrl_AutoTpaccept = str2bool(argValue); return true; case "autotpaccept": RemoteCtrl_AutoTpaccept = str2bool(argValue); return true;
@ -624,7 +625,7 @@ namespace MinecraftClient
break; break;
case Section.ChatFormat: case Section.ChatFormat:
switch (argName.ToLower()) switch (ToLowerIfNeed(argName))
{ {
case "builtins": ChatFormat_Builtins = str2bool(argValue); return true; case "builtins": ChatFormat_Builtins = str2bool(argValue); return true;
case "public": ChatFormat_Public = new Regex(argValue); return true; case "public": ChatFormat_Public = new Regex(argValue); return true;
@ -634,15 +635,15 @@ namespace MinecraftClient
break; break;
case Section.Proxy: case Section.Proxy:
switch (argName.ToLower()) switch (ToLowerIfNeed(argName))
{ {
case "enabled": case "enabled":
ProxyEnabledLogin = ProxyEnabledIngame = str2bool(argValue); ProxyEnabledLogin = ProxyEnabledIngame = str2bool(argValue);
if (argValue.Trim().ToLower() == "login") if (ToLowerIfNeed(argValue.Trim()) == "login")
ProxyEnabledLogin = true; ProxyEnabledLogin = true;
return true; return true;
case "type": case "type":
argValue = argValue.ToLower(); argValue = ToLowerIfNeed(argValue);
if (argValue == "http") { proxyType = Proxy.ProxyHandler.Type.HTTP; } if (argValue == "http") { proxyType = Proxy.ProxyHandler.Type.HTTP; }
else if (argValue == "socks4") { proxyType = Proxy.ProxyHandler.Type.SOCKS4; } else if (argValue == "socks4") { proxyType = Proxy.ProxyHandler.Type.SOCKS4; }
else if (argValue == "socks4a") { proxyType = Proxy.ProxyHandler.Type.SOCKS4a; } else if (argValue == "socks4a") { proxyType = Proxy.ProxyHandler.Type.SOCKS4a; }
@ -671,7 +672,7 @@ namespace MinecraftClient
return true; return true;
case Section.AutoRespond: case Section.AutoRespond:
switch (argName.ToLower()) switch (ToLowerIfNeed(argName))
{ {
case "enabled": AutoRespond_Enabled = str2bool(argValue); return true; case "enabled": AutoRespond_Enabled = str2bool(argValue); return true;
case "matchesfile": AutoRespond_Matches = argValue; return true; case "matchesfile": AutoRespond_Matches = argValue; return true;
@ -679,13 +680,13 @@ namespace MinecraftClient
break; break;
case Section.AutoAttack: case Section.AutoAttack:
switch (argName.ToLower()) switch (ToLowerIfNeed(argName))
{ {
case "enabled": AutoAttack_Enabled = str2bool(argValue); return true; case "enabled": AutoAttack_Enabled = str2bool(argValue); return true;
case "mode": AutoAttack_Mode = argValue.ToLower(); return true; case "mode": AutoAttack_Mode = ToLowerIfNeed(argValue); return true;
case "priority": AutoAttack_Priority = argValue.ToLower(); return true; case "priority": AutoAttack_Priority = ToLowerIfNeed(argValue); return true;
case "cooldownseconds": case "cooldownseconds":
if (argValue.ToLower() == "auto") if (ToLowerIfNeed(argValue) == "auto")
{ {
AutoAttack_OverrideAttackSpeed = false; AutoAttack_OverrideAttackSpeed = false;
} }
@ -701,7 +702,7 @@ namespace MinecraftClient
break; break;
case Section.AutoFishing: case Section.AutoFishing:
switch (argName.ToLower()) switch (ToLowerIfNeed(argName))
{ {
case "enabled": AutoFishing_Enabled = str2bool(argValue); return true; case "enabled": AutoFishing_Enabled = str2bool(argValue); return true;
case "antidespawn": AutoFishing_Antidespawn = str2bool(argValue); return true; case "antidespawn": AutoFishing_Antidespawn = str2bool(argValue); return true;
@ -709,7 +710,7 @@ namespace MinecraftClient
break; break;
case Section.AutoEat: case Section.AutoEat:
switch (argName.ToLower()) switch (ToLowerIfNeed(argName))
{ {
case "enabled": AutoEat_Enabled = str2bool(argValue); return true; case "enabled": AutoEat_Enabled = str2bool(argValue); return true;
case "threshold": AutoEat_hungerThreshold = str2int(argValue); return true; case "threshold": AutoEat_hungerThreshold = str2int(argValue); return true;
@ -717,7 +718,7 @@ namespace MinecraftClient
break; break;
case Section.AutoCraft: case Section.AutoCraft:
switch (argName.ToLower()) switch (ToLowerIfNeed(argName))
{ {
case "enabled": AutoCraft_Enabled = str2bool(argValue); return true; case "enabled": AutoCraft_Enabled = str2bool(argValue); return true;
case "configfile": AutoCraft_configFile = argValue; return true; case "configfile": AutoCraft_configFile = argValue; return true;
@ -725,7 +726,7 @@ namespace MinecraftClient
break; break;
case Section.AutoDrop: case Section.AutoDrop:
switch (argName.ToLower()) switch (ToLowerIfNeed(argName))
{ {
case "enabled": AutoDrop_Enabled = str2bool(argValue); return true; case "enabled": AutoDrop_Enabled = str2bool(argValue); return true;
case "mode": AutoDrop_Mode = argValue; return true; case "mode": AutoDrop_Mode = argValue; return true;
@ -734,12 +735,12 @@ namespace MinecraftClient
break; break;
case Section.MCSettings: case Section.MCSettings:
switch (argName.ToLower()) switch (ToLowerIfNeed(argName))
{ {
case "enabled": MCSettings_Enabled = str2bool(argValue); return true; case "enabled": MCSettings_Enabled = str2bool(argValue); return true;
case "locale": MCSettings_Locale = argValue; return true; case "locale": MCSettings_Locale = argValue; return true;
case "difficulty": case "difficulty":
switch (argValue.ToLower()) switch (ToLowerIfNeed(argValue))
{ {
case "peaceful": MCSettings_Difficulty = 0; break; case "peaceful": MCSettings_Difficulty = 0; break;
case "easy": MCSettings_Difficulty = 1; break; case "easy": MCSettings_Difficulty = 1; break;
@ -755,7 +756,7 @@ namespace MinecraftClient
} }
else else
{ {
switch (argValue.ToLower()) switch (ToLowerIfNeed(argValue))
{ {
case "tiny": MCSettings_RenderDistance = 2; break; case "tiny": MCSettings_RenderDistance = 2; break;
case "short": MCSettings_RenderDistance = 4; break; case "short": MCSettings_RenderDistance = 4; break;
@ -765,7 +766,7 @@ namespace MinecraftClient
} }
return true; return true;
case "chatmode": case "chatmode":
switch (argValue.ToLower()) switch (ToLowerIfNeed(argValue))
{ {
case "enabled": MCSettings_ChatMode = 0; break; case "enabled": MCSettings_ChatMode = 0; break;
case "commands": MCSettings_ChatMode = 1; break; case "commands": MCSettings_ChatMode = 1; break;
@ -781,7 +782,7 @@ namespace MinecraftClient
case "skin_pants_right": MCSettings_Skin_Pants_Right = str2bool(argValue); return true; case "skin_pants_right": MCSettings_Skin_Pants_Right = str2bool(argValue); return true;
case "skin_hat": MCSettings_Skin_Hat = str2bool(argValue); return true; case "skin_hat": MCSettings_Skin_Hat = str2bool(argValue); return true;
case "main_hand": case "main_hand":
switch (argValue.ToLower()) switch (ToLowerIfNeed(argValue))
{ {
case "left": MCSettings_MainHand = 0; break; case "left": MCSettings_MainHand = 0; break;
case "right": MCSettings_MainHand = 1; break; case "right": MCSettings_MainHand = 1; break;
@ -791,7 +792,7 @@ namespace MinecraftClient
break; break;
case Section.Mailer: case Section.Mailer:
switch (argName.ToLower()) switch (ToLowerIfNeed(argName))
{ {
case "enabled": Mailer_Enabled = str2bool(argValue); return true; case "enabled": Mailer_Enabled = str2bool(argValue); return true;
case "database": Mailer_DatabaseFile = argValue; return true; case "database": Mailer_DatabaseFile = argValue; return true;
@ -804,7 +805,7 @@ namespace MinecraftClient
break; break;
case Section.ReplayMod: case Section.ReplayMod:
switch (argName.ToLower()) switch (ToLowerIfNeed(argName))
{ {
case "enabled": ReplayMod_Enabled = str2bool(argValue); return true; case "enabled": ReplayMod_Enabled = str2bool(argValue); return true;
case "backupinterval": ReplayMod_BackupInterval = str2int(argValue); return true; case "backupinterval": ReplayMod_BackupInterval = str2int(argValue); return true;
@ -879,13 +880,43 @@ namespace MinecraftClient
return str == "true" || str == "1"; 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;
}
}
/// <summary> /// <summary>
/// Load login/password using an account alias /// Load login/password using an account alias
/// </summary> /// </summary>
/// <returns>True if the account was found and loaded</returns> /// <returns>True if the account was found and loaded</returns>
public static bool SetAccount(string accountAlias) public static bool SetAccount(string accountAlias)
{ {
accountAlias = accountAlias.ToLower(); accountAlias = Settings.ToLowerIfNeed(accountAlias);
if (Accounts.ContainsKey(accountAlias)) if (Accounts.ContainsKey(accountAlias))
{ {
Settings.Login = Accounts[accountAlias].Key; Settings.Login = Accounts[accountAlias].Key;
@ -901,7 +932,7 @@ namespace MinecraftClient
/// <returns>True if the server IP was valid and loaded, false otherwise</returns> /// <returns>True if the server IP was valid and loaded, false otherwise</returns>
public static bool SetServerIP(string server) public static bool SetServerIP(string server)
{ {
server = server.ToLower(); server = ToLowerIfNeed(server);
string[] sip = server.Split(':'); string[] sip = server.Split(':');
string host = sip[0]; string host = sip[0];
ushort port = 25565; ushort port = 25565;
@ -946,7 +977,7 @@ namespace MinecraftClient
{ {
lock (AppVars) 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) if (varName.Length > 0)
{ {
AppVars[varName] = varData; AppVars[varName] = varData;
@ -998,7 +1029,7 @@ namespace MinecraftClient
if (varname_ok) if (varname_ok)
{ {
string varname = var_name.ToString(); string varname = var_name.ToString();
string varname_lower = varname.ToLower(); string varname_lower = Settings.ToLowerIfNeed(varname);
i = i + varname.Length + 1; i = i + varname.Length + 1;
switch (varname_lower) switch (varname_lower)