diff --git a/MinecraftClient/Protocol/Message/ChatParser.cs b/MinecraftClient/Protocol/Message/ChatParser.cs index 400ba785..5bfd2b66 100644 --- a/MinecraftClient/Protocol/Message/ChatParser.cs +++ b/MinecraftClient/Protocol/Message/ChatParser.cs @@ -34,11 +34,12 @@ namespace MinecraftClient.Protocol.Message public static void ReadChatType(Dictionary registryCodec) { Dictionary chatTypeDictionary = ChatId2Type ?? new(); - var chatTypeListNbt = (object[])(((Dictionary)registryCodec["minecraft:chat_type"])["value"]); + var chatTypeListNbt = + (object[])(((Dictionary)registryCodec["minecraft:chat_type"])["value"]); foreach (var (chatName, chatId) in from Dictionary chatTypeNbt in chatTypeListNbt - let chatName = (string)chatTypeNbt["name"] - let chatId = (int)chatTypeNbt["id"] - select (chatName, chatId)) + let chatName = (string)chatTypeNbt["name"] + let chatId = (int)chatTypeNbt["id"] + select (chatName, chatId)) { chatTypeDictionary[chatId] = chatName switch { @@ -52,6 +53,7 @@ namespace MinecraftClient.Protocol.Message _ => MessageType.CHAT, }; } + ChatId2Type = chatTypeDictionary; } @@ -147,6 +149,7 @@ namespace MinecraftClient.Protocol.Message default: goto case MessageType.CHAT; } + return text; } @@ -198,7 +201,14 @@ namespace MinecraftClient.Protocol.Message /// Initialize translation rules. /// Necessary for properly printing some chat messages. /// - public static void InitTranslations() { if (!RulesInitialized) { InitRules(); RulesInitialized = true; } } + public static void InitTranslations() + { + if (!RulesInitialized) + { + InitRules(); + RulesInitialized = true; + } + } /// /// Internal rule initialization method. Looks for local rule file or download it from Mojang asset servers. @@ -207,7 +217,9 @@ namespace MinecraftClient.Protocol.Message { if (Config.Main.Advanced.Language == "en_us") { - TranslationRules = JsonSerializer.Deserialize>((byte[])MinecraftAssets.ResourceManager.GetObject("en_us.json")!)!; + TranslationRules = + JsonSerializer.Deserialize>( + (byte[])MinecraftAssets.ResourceManager.GetObject("en_us.json")!)!; return; } @@ -222,13 +234,19 @@ namespace MinecraftClient.Protocol.Message { try { - TranslationRules = JsonSerializer.Deserialize>(File.OpenRead(languageFilePath))!; + TranslationRules = + JsonSerializer.Deserialize>(File.OpenRead(languageFilePath))!; + } + catch (IOException) + { + } + catch (JsonException) + { } - catch (IOException) { } - catch (JsonException) { } } - if (TranslationRules.TryGetValue("Version", out string? version) && version == Settings.TranslationsFile_Version) + if (TranslationRules.TryGetValue("Version", out string? version) && + version == Settings.TranslationsFile_Version) { if (Config.Logging.DebugMessages) ConsoleIO.WriteLineFormatted(Translations.chat_loaded, acceptnewlines: true); @@ -236,32 +254,39 @@ namespace MinecraftClient.Protocol.Message } // Try downloading language file from Mojang's servers? - ConsoleIO.WriteLineFormatted("§8" + string.Format(Translations.chat_download, Config.Main.Advanced.Language)); + ConsoleIO.WriteLineFormatted( + "§8" + string.Format(Translations.chat_download, Config.Main.Advanced.Language)); HttpClient httpClient = new(); try { Task fetch_index = httpClient.GetStringAsync(TranslationsFile_Website_Index); fetch_index.Wait(); - Match match = Regex.Match(fetch_index.Result, $"minecraft/lang/{Config.Main.Advanced.Language}.json" + @""":\s\{""hash"":\s""([\d\w]{40})"""); + Match match = Regex.Match(fetch_index.Result, + $"minecraft/lang/{Config.Main.Advanced.Language}.json" + @""":\s\{""hash"":\s""([\d\w]{40})"""); fetch_index.Dispose(); if (match.Success && match.Groups.Count == 2) { string hash = match.Groups[1].Value; string translation_file_location = TranslationsFile_Website_Download + '/' + hash[..2] + '/' + hash; if (Config.Logging.DebugMessages) - ConsoleIO.WriteLineFormatted(string.Format(Translations.chat_request, translation_file_location)); + ConsoleIO.WriteLineFormatted( + string.Format(Translations.chat_request, translation_file_location)); - Task?> fetckFileTask = httpClient.GetFromJsonAsync>(translation_file_location); + Task?> fetckFileTask = + httpClient.GetFromJsonAsync>(translation_file_location); fetckFileTask.Wait(); if (fetckFileTask.Result != null && fetckFileTask.Result.Count > 0) { TranslationRules = fetckFileTask.Result; TranslationRules["Version"] = TranslationsFile_Version; - File.WriteAllText(languageFilePath, JsonSerializer.Serialize(TranslationRules, typeof(Dictionary)), Encoding.UTF8); + File.WriteAllText(languageFilePath, + JsonSerializer.Serialize(TranslationRules, typeof(Dictionary)), + Encoding.UTF8); ConsoleIO.WriteLineFormatted("§8" + string.Format(Translations.chat_done, languageFilePath)); return; } + fetckFileTask.Dispose(); } else @@ -275,7 +300,8 @@ namespace MinecraftClient.Protocol.Message } catch (IOException) { - ConsoleIO.WriteLineFormatted("§8" + string.Format(Translations.chat_save_fail, languageFilePath), acceptnewlines: true); + ConsoleIO.WriteLineFormatted("§8" + string.Format(Translations.chat_save_fail, languageFilePath), + acceptnewlines: true); } catch (Exception e) { @@ -289,7 +315,9 @@ namespace MinecraftClient.Protocol.Message httpClient.Dispose(); } - TranslationRules = JsonSerializer.Deserialize>((byte[])MinecraftAssets.ResourceManager.GetObject("en_us.json")!)!; + TranslationRules = + JsonSerializer.Deserialize>( + (byte[])MinecraftAssets.ResourceManager.GetObject("en_us.json")!)!; ConsoleIO.WriteLine(Translations.chat_use_default); } @@ -310,7 +338,12 @@ namespace MinecraftClient.Protocol.Message /// Returns the formatted text according to the given data private static string TranslateString(string rulename, List using_data) { - if (!RulesInitialized) { InitRules(); RulesInitialized = true; } + if (!RulesInitialized) + { + InitRules(); + RulesInitialized = true; + } + if (TranslationRules.ContainsKey(rulename)) { int using_idx = 0; @@ -334,8 +367,8 @@ namespace MinecraftClient.Protocol.Message //Using specified string or int with %1$s, %2$s... else if (char.IsDigit(rule[i + 1]) - && i + 3 < rule.Length && rule[i + 2] == '$' - && (rule[i + 3] == 's' || rule[i + 3] == 'd')) + && i + 3 < rule.Length && rule[i + 2] == '$' + && (rule[i + 3] == 's' || rule[i + 3] == 'd')) { int specified_idx = rule[i + 1] - '1'; if (using_data.Count > specified_idx) @@ -347,8 +380,10 @@ namespace MinecraftClient.Protocol.Message } } } + result.Append(rule[i]); } + return result.ToString(); } else return "[" + rulename + "] " + string.Join(" ", using_data); @@ -371,6 +406,7 @@ namespace MinecraftClient.Protocol.Message { colorcode = Color2tag(JSONData2String(data.Properties["color"], "", links)); } + if (data.Properties.ContainsKey("clickEvent") && links != null) { Json.JSONData clickEvent = data.Properties["clickEvent"]; @@ -382,12 +418,14 @@ namespace MinecraftClient.Protocol.Message links.Add(clickEvent.Properties["value"].StringValue); } } + if (data.Properties.ContainsKey("extra")) { Json.JSONData[] extras = data.Properties["extra"].DataArray.ToArray(); foreach (Json.JSONData item in extras) extra_result = extra_result + JSONData2String(item, colorcode, links) + "§r"; } + if (data.Properties.ContainsKey("text")) { return colorcode + JSONData2String(data.Properties["text"], colorcode, links) + extra_result; @@ -405,7 +443,10 @@ namespace MinecraftClient.Protocol.Message using_data.Add(JSONData2String(array[i], colorcode, links)); } } - return colorcode + TranslateString(JSONData2String(data.Properties["translate"], "", links), using_data) + extra_result; + + return colorcode + + TranslateString(JSONData2String(data.Properties["translate"], "", links), using_data) + + extra_result; } else return extra_result; @@ -415,6 +456,7 @@ namespace MinecraftClient.Protocol.Message { result += JSONData2String(item, colorcode, links); } + return result; case Json.JSONData.DataType.String: @@ -443,90 +485,70 @@ namespace MinecraftClient.Protocol.Message switch (key) { case "text": - { - message = (string)value; - } + { + message = (string)value; + } break; case "extra": + { + object[] extras = (object[])value; + for (var i = 0; i < extras.Length; i++) { - object[] extras = (object[])value; - for (var i = 0; i < extras.Length; i++) + var extraDict = extras[i] switch { - try + int => new Dictionary { { "text", $"{extras[i]}" } }, + string => new Dictionary { - var extraDict = extras[i] switch - { - int => new Dictionary { { "text", $"{extras[i]}" } }, - string => new Dictionary - { - { "text", (string)extras[i] } - }, - _ => (Dictionary)extras[i] - }; + { "text", (string)extras[i] } + }, + _ => (Dictionary)extras[i] + }; - extraBuilder.Append(NbtToString(extraDict) + "§r"); - } - catch - { - ConsoleIO.WriteLine("[DEBUG] Full NBT object:" + JsonSerializer.Serialize(nbt)); - ConsoleIO.WriteLine("[DEBUG] Full extras object:" + JsonSerializer.Serialize(extras)); - ConsoleIO.WriteLine("[DEBUG] Value in question:" + JsonSerializer.Serialize(extras[i])); - ConsoleIO.WriteLine("[DEBUG] Full string builder so far:" + extraBuilder.ToString()); - throw; - } - } + extraBuilder.Append(NbtToString(extraDict) + "§r"); } + } break; case "translate": + { + if (nbt.TryGetValue("translate", out object translate)) { - if (nbt.TryGetValue("translate", out object translate)) + var translateKey = (string)translate; + List translateString = new(); + if (nbt.TryGetValue("with", out object withComponent)) { - var translateKey = (string)translate; - List translateString = new(); - if (nbt.TryGetValue("with", out object withComponent)) + var withs = (object[])withComponent; + for (var i = 0; i < withs.Length; i++) { - var withs = (object[])withComponent; - for (var i = 0; i < withs.Length; i++) + var withDict = withs[i] switch { - try + int => new Dictionary { { "text", $"{withs[i]}" } }, + string => new Dictionary { - var withDict = withs[i] switch - { - int => new Dictionary { { "text", $"{withs[i]}" } }, - string => new Dictionary - { - { "text", (string)withs[i] } - }, - _ => (Dictionary)withs[i] - }; + { "text", (string)withs[i] } + }, + _ => (Dictionary)withs[i] + }; - translateString.Add(NbtToString(withDict)); - } - catch - { - ConsoleIO.WriteLine("[DEBUG] Full NBT object:" + JsonSerializer.Serialize(nbt)); - ConsoleIO.WriteLine("[DEBUG] Full withs object:" + JsonSerializer.Serialize(withs)); - ConsoleIO.WriteLine("[DEBUG] Value in question:" + JsonSerializer.Serialize(withs[i])); - ConsoleIO.WriteLine("[DEBUG] Full string builder so far:" + extraBuilder.ToString()); - throw; - } - } + translateString.Add(NbtToString(withDict)); } - message = TranslateString(translateKey, translateString); } + + message = TranslateString(translateKey, translateString); } + } break; case "color": + { + if (nbt.TryGetValue("color", out object color)) { - if (nbt.TryGetValue("color", out object color)) - { - colorCode = Color2tag((string)color); - } + colorCode = Color2tag((string)color); } + } break; } } + return colorCode + message + extraBuilder.ToString(); } } -} +} \ No newline at end of file