From 16c1d1fd77d0d4c5ba79a7fcd2d4ee3805017385 Mon Sep 17 00:00:00 2001 From: BruceChen Date: Wed, 5 Oct 2022 15:02:30 +0800 Subject: [PATCH 01/14] Refactoring Settings.cs --- MinecraftClient/ChatBots/Alerts.cs | 110 +- MinecraftClient/ChatBots/AntiAFK.cs | 138 +- MinecraftClient/ChatBots/AutoAttack.cs | 161 +- MinecraftClient/ChatBots/AutoCraft.cs | 36 +- MinecraftClient/ChatBots/AutoDrop.cs | 92 +- MinecraftClient/ChatBots/AutoEat.cs | 35 +- MinecraftClient/ChatBots/AutoFishing.cs | 206 +- MinecraftClient/ChatBots/AutoRelog.cs | 88 +- MinecraftClient/ChatBots/AutoRespond.cs | 63 +- MinecraftClient/ChatBots/ChatLog.cs | 91 +- MinecraftClient/ChatBots/FollowPlayer.cs | 39 +- MinecraftClient/ChatBots/HangmanGame.cs | 68 +- MinecraftClient/ChatBots/Mailer.cs | 134 +- MinecraftClient/ChatBots/Map.cs | 60 +- MinecraftClient/ChatBots/PlayerListLogger.cs | 37 +- MinecraftClient/ChatBots/RemoteControl.cs | 24 +- MinecraftClient/ChatBots/ReplayCapture.cs | 34 +- MinecraftClient/ChatBots/Script.cs | 4 +- MinecraftClient/ChatBots/ScriptScheduler.cs | 54 +- MinecraftClient/Commands/Chunk.cs | 2 +- MinecraftClient/Commands/Connect.cs | 4 +- MinecraftClient/Commands/Debug.cs | 9 +- MinecraftClient/Commands/ExecIf.cs | 2 +- MinecraftClient/Commands/Inventory.cs | 2 +- MinecraftClient/Commands/Move.cs | 4 +- MinecraftClient/Commands/Reco.cs | 2 +- MinecraftClient/Commands/Set.cs | 13 +- MinecraftClient/Commands/SetRnd.cs | 8 +- .../DefaultConfigResource.Designer.cs | 332 ++- MinecraftClient/DefaultConfigResource.resx | 17 +- MinecraftClient/FileMonitor.cs | 4 +- MinecraftClient/Logger/FileLogLogger.cs | 2 +- MinecraftClient/Logger/FilteredLogger.cs | 19 +- MinecraftClient/Mapping/Movement.cs | 2 +- MinecraftClient/McClient.cs | 167 +- MinecraftClient/MinecraftClient.csproj | 10 +- MinecraftClient/Program.cs | 236 +- .../PacketPalettes/PacketTypePalette.cs | 4 +- .../Protocol/Handlers/Protocol16.cs | 9 +- .../Protocol/Handlers/Protocol18.cs | 19 +- .../Protocol/Handlers/Protocol18Forge.cs | 28 +- .../Protocol/Message/ChatParser.cs | 24 +- .../Protocol/MicrosoftAuthentication.cs | 16 +- .../Protocol/ProfileKey/KeyUtils.cs | 4 +- .../Protocol/ProfileKey/KeysCache.cs | 20 +- MinecraftClient/Protocol/ProtocolHandler.cs | 40 +- MinecraftClient/Protocol/ProxiedWebRequest.cs | 2 +- MinecraftClient/Protocol/ReplayHandler.cs | 2 +- MinecraftClient/Protocol/Session/CacheType.cs | 20 - .../Protocol/Session/SessionCache.cs | 24 +- MinecraftClient/Proxy/ProxyHandler.cs | 67 +- MinecraftClient/Resources/lang/en.ini | 217 +- .../lang/{zh-CHS.ini => zh-Hans.ini} | 22 +- MinecraftClient/Scripting/CSharpRunner.cs | 15 +- MinecraftClient/Scripting/ChatBot.cs | 46 +- MinecraftClient/Settings.cs | 2111 ++++++++--------- MinecraftClient/Translations.cs | 588 ++++- MinecraftClient/WinAPI/ConsoleIcon.cs | 10 + MinecraftClient/WinAPI/ExitCleanUp.cs | 8 +- 59 files changed, 3425 insertions(+), 2180 deletions(-) delete mode 100644 MinecraftClient/Protocol/Session/CacheType.cs rename MinecraftClient/Resources/lang/{zh-CHS.ini => zh-Hans.ini} (94%) diff --git a/MinecraftClient/ChatBots/Alerts.cs b/MinecraftClient/ChatBots/Alerts.cs index c3f1f6a0..51a82a18 100644 --- a/MinecraftClient/ChatBots/Alerts.cs +++ b/MinecraftClient/ChatBots/Alerts.cs @@ -1,5 +1,6 @@ using System; using System.Linq; +using Tomlet.Attributes; namespace MinecraftClient.ChatBots { @@ -8,9 +9,85 @@ namespace MinecraftClient.ChatBots /// public class Alerts : ChatBot { + public static Configs Config = new(); + + [TomlDoNotInlineObject] + public class Configs + { + [NonSerialized] + private const string BotName = "Alerts"; + + public bool Enabled = false; + + [TomlInlineComment("$config.ChatBot.Alerts.Beep_Enabled$")] + public bool Beep_Enabled = true; + + [TomlInlineComment("$config.ChatBot.Alerts.Trigger_By_Words$")] + public bool Trigger_By_Words = false; + + [TomlInlineComment("$config.ChatBot.Alerts.Trigger_By_Rain$")] + public bool Trigger_By_Rain = false; + + [TomlInlineComment("$config.ChatBot.Alerts.Trigger_By_Thunderstorm$")] + public bool Trigger_By_Thunderstorm = false; + + [TomlInlineComment("$config.ChatBot.Alerts.Matches_File$")] + public string Matches_File = @"alerts.txt"; + + [TomlInlineComment("$config.ChatBot.Alerts.Excludes_File$")] + public string Excludes_File = @"alerts-exclude.txt"; + + [TomlInlineComment("$config.ChatBot.Alerts.Log_To_File$")] + public bool Log_To_File = false; + + [TomlInlineComment("$config.ChatBot.Alerts.Log_File$")] + public string Log_File = @"alerts-log.txt"; + + public void OnSettingUpdate() + { + if (!Enabled) return; + + bool checkSuccessed = true; + + if (Trigger_By_Words) + { + if (!System.IO.File.Exists(Matches_File)) + { + checkSuccessed = false; + LogToConsole(BotName, "File not found: " + System.IO.Path.GetFullPath(Matches_File)); + } + + if (!System.IO.File.Exists(Excludes_File)) + { + checkSuccessed = false; + LogToConsole(BotName, "File not found: " + System.IO.Path.GetFullPath(Excludes_File)); + } + + if (Log_To_File) + { + try + { + System.IO.File.AppendAllText(Log_File, string.Empty); + } + catch + { + checkSuccessed = false; + LogToConsole(BotName, "Can't write logs to " + System.IO.Path.GetFullPath(Excludes_File)); + } + } + } + + if (!checkSuccessed) + { + LogToConsole(BotName, Translations.TryGet("general.bot_unload")); + Enabled = false; + } + } + } + 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; @@ -20,11 +97,10 @@ namespace MinecraftClient.ChatBots /// public override void Initialize() { - if (Settings.Alerts_Trigger_By_Words) + if (Config.Trigger_By_Words) { - dictionary = LoadDistinctEntriesFromFile(Settings.Alerts_MatchesFile); - excludelist = LoadDistinctEntriesFromFile(Settings.Alerts_ExcludesFile); - logToFile = Settings.Alerts_File_Logging; + dictionary = LoadDistinctEntriesFromFile(Config.Matches_File); + excludelist = LoadDistinctEntriesFromFile(Config.Excludes_File); } } @@ -34,7 +110,7 @@ namespace MinecraftClient.ChatBots /// Received text public override void GetText(string text) { - if (Settings.Alerts_Trigger_By_Words) + if (Config.Trigger_By_Words) { //Remove color codes and convert to lowercase text = GetVerbatim(text).ToLower(); @@ -45,16 +121,16 @@ namespace MinecraftClient.ChatBots //Show an alert for each alert item found in text, if any foreach (string alert in dictionary.Where(alert => text.Contains(alert))) { - if (Settings.Alerts_Beep_Enabled) + if (Config.Beep_Enabled) Console.Beep(); //Text found ! ConsoleIO.WriteLine(text.Replace(alert, "§c" + alert + "§r")); - if (logToFile && Settings.Alerts_LogFile.Length > 0) + if (Config.Log_To_File && Config.Log_File.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"); + System.IO.File.AppendAllText(Config.Log_File, TimeStamp + " " + GetVerbatim(text) + "\n"); } } } @@ -65,9 +141,9 @@ namespace MinecraftClient.ChatBots { if (curRainLevel < threshold && level >= threshold) { - if (Settings.Alerts_Trigger_By_Rain) + if (Config.Trigger_By_Rain) { - if (Settings.Alerts_Beep_Enabled) + if (Config.Beep_Enabled) { Console.Beep(); Console.Beep(); @@ -77,9 +153,9 @@ namespace MinecraftClient.ChatBots } else if (curRainLevel >= threshold && level < threshold) { - if (Settings.Alerts_Trigger_By_Rain) + if (Config.Trigger_By_Rain) { - if (Settings.Alerts_Beep_Enabled) + if (Config.Beep_Enabled) { Console.Beep(); } @@ -93,9 +169,9 @@ namespace MinecraftClient.ChatBots { if (curThunderLevel < threshold && level >= threshold) { - if (Settings.Alerts_Trigger_By_Thunderstorm) + if (Config.Trigger_By_Thunderstorm) { - if (Settings.Alerts_Beep_Enabled) + if (Config.Beep_Enabled) { Console.Beep(); Console.Beep(); @@ -105,9 +181,9 @@ namespace MinecraftClient.ChatBots } else if (curThunderLevel >= threshold && level < threshold) { - if (Settings.Alerts_Trigger_By_Thunderstorm) + if (Config.Trigger_By_Thunderstorm) { - if (Settings.Alerts_Beep_Enabled) + if (Config.Beep_Enabled) { Console.Beep(); } diff --git a/MinecraftClient/ChatBots/AntiAFK.cs b/MinecraftClient/ChatBots/AntiAFK.cs index c216d807..9408cd5e 100644 --- a/MinecraftClient/ChatBots/AntiAFK.cs +++ b/MinecraftClient/ChatBots/AntiAFK.cs @@ -1,6 +1,6 @@ using System; -using System.Globalization; using MinecraftClient.Mapping; +using Tomlet.Attributes; namespace MinecraftClient.ChatBots { @@ -10,94 +10,94 @@ namespace MinecraftClient.ChatBots public class AntiAFK : ChatBot { + public static Configs Config = new(); + + [TomlDoNotInlineObject] + public class Configs + { + [NonSerialized] + private const string BotName = "AntiAFK"; + + public bool Enabled = false; + + [TomlInlineComment("$config.ChatBot.AntiAfk.Delay$")] + public Range Delay = new(600); + + [TomlInlineComment("$config.ChatBot.AntiAfk.Command$")] + public string Command = "/ping"; + + [TomlInlineComment("$config.ChatBot.AntiAfk.Use_Terrain_Handling$")] + public bool Use_Terrain_Handling = false; + + [TomlInlineComment("$config.ChatBot.AntiAfk.Walk_Range$")] + public int Walk_Range = 5; + + [TomlInlineComment("$config.ChatBot.AntiAfk.Walk_Retries$")] + public int Walk_Retries = 20; + + public void OnSettingUpdate() + { + if (Walk_Range <= 0) + { + Walk_Range = 5; + LogToConsole(BotName, Translations.TryGet("bot.antiafk.invalid_walk_range")); + } + + if (Delay.min > Delay.max) + { + (Delay.min, Delay.max) = (Delay.max, Delay.min); + LogToConsole(BotName, Translations.TryGet("bot.antiafk.swapping")); + } + } + + public struct Range + { + public int min, max; + + public Range(int value) + { + value = Math.Max(value, 10); + min = max = value; + } + + public Range(int min, int max) + { + min = Math.Max(min, 10); + max = Math.Max(max, 10); + this.min = min; + this.max = max; + } + } + } + private int count; - private readonly string pingparam; - private int timeping = 600; - private int timepingMax = -1; - private bool useTerrainHandling = false; private bool previousSneakState = false; - private int walkRange = 5; - private readonly int walkRetries = 10; private readonly Random random = new(); /// /// This bot sends a /ping command every X seconds in order to stay non-afk. /// - /// Time amount between each ping (10 = 1s, 600 = 1 minute, etc.) Can be a range of numbers eg. 10-600 - - public AntiAFK(string pingparam, bool useTerrainHandling, int walkRange, int walkRetries) + public AntiAFK() { count = 0; - this.pingparam = pingparam; - this.useTerrainHandling = useTerrainHandling; - this.walkRange = walkRange; - this.walkRetries = walkRetries; } public override void Initialize() { - if (useTerrainHandling) + if (Config.Use_Terrain_Handling) { if (!GetTerrainEnabled()) { - useTerrainHandling = false; LogToConsole(Translations.TryGet("bot.antiafk.not_using_terrain_handling")); } - else - { - if (walkRange <= 0) - { - walkRange = 5; - LogToConsole(Translations.TryGet("bot.antiafk.invalid_walk_range")); - } - } } - - if (string.IsNullOrEmpty(pingparam)) - LogToConsole(Translations.TryGet("bot.antiafk.invalid_time")); - else - { - // Handle the random range - if (pingparam.Contains('-')) - { - string[] parts = pingparam.Split("-"); - - if (parts.Length == 2) - { - if (int.TryParse(parts[0].Trim(), NumberStyles.Any, CultureInfo.CurrentCulture, out int firstTime)) - { - timeping = firstTime; - - if (int.TryParse(parts[1].Trim(), NumberStyles.Any, CultureInfo.CurrentCulture, out int secondTime)) - timepingMax = secondTime; - else LogToConsole(Translations.TryGet("bot.antiafk.invalid_range_partial", timeping)); - } - else LogToConsole(Translations.TryGet("bot.antiafk.invalid_range")); - } - else LogToConsole(Translations.TryGet("bot.antiafk.invalid_range")); - } - else - { - if (int.TryParse(pingparam.Trim(), NumberStyles.Any, CultureInfo.CurrentCulture, out int value)) - timeping = value; - else LogToConsole(Translations.TryGet("bot.antiafk.invalid_value")); - } - } - - if (timepingMax != -1 && timeping > timepingMax) - { - (timeping, timepingMax) = (timepingMax, timeping); - LogToConsole(Translations.TryGet("bot.antiafk.swapping")); - } - - if (timeping < 10) { timeping = 10; } //To avoid flooding } public override void Update() { count++; - if ((timepingMax != -1 && count == random.Next(timeping, timepingMax)) || count == timeping) + if (count == random.Next(Config.Delay.min, Config.Delay.max)) { DoAntiAfkStuff(); count = 0; @@ -107,7 +107,7 @@ namespace MinecraftClient.ChatBots private void DoAntiAfkStuff() { - if (useTerrainHandling) + if (Config.Use_Terrain_Handling && GetTerrainEnabled()) { Location currentLocation = GetCurrentLocation(); Location goal; @@ -118,19 +118,19 @@ namespace MinecraftClient.ChatBots while (!moved) { - if (triesCounter++ >= walkRetries) + if (triesCounter++ >= Config.Walk_Retries) { useAlternativeMethod = true; break; } - goal = GetRandomLocationWithinRangeXZ(currentLocation, walkRange); + goal = GetRandomLocationWithinRangeXZ(currentLocation, Config.Walk_Range); // Prevent getting the same location while ((currentLocation.X == goal.X) && (currentLocation.Y == goal.Y) && (currentLocation.Z == goal.Z)) { LogToConsole("Same location!, generating new one"); - goal = GetRandomLocationWithinRangeXZ(currentLocation, walkRange); + goal = GetRandomLocationWithinRangeXZ(currentLocation, Config.Walk_Range); } if (!Movement.CheckChunkLoading(GetWorld(), currentLocation, goal)) @@ -151,7 +151,7 @@ namespace MinecraftClient.ChatBots } } - SendText(Settings.AntiAFK_Command); + SendText(Config.Command); Sneak(previousSneakState); previousSneakState = !previousSneakState; count = 0; diff --git a/MinecraftClient/ChatBots/AutoAttack.cs b/MinecraftClient/ChatBots/AutoAttack.cs index f9c6e820..522a8202 100644 --- a/MinecraftClient/ChatBots/AutoAttack.cs +++ b/MinecraftClient/ChatBots/AutoAttack.cs @@ -2,14 +2,89 @@ using System.Collections.Generic; using System.IO; using MinecraftClient.Mapping; +using Tomlet.Attributes; namespace MinecraftClient.ChatBots { /// /// The AutoAttack bot will automatically attack any hostile mob close to the player /// - class AutoAttack : ChatBot + public class AutoAttack : ChatBot { + public static Configs Config = new(); + + [TomlDoNotInlineObject] + public class Configs + { + [NonSerialized] + private const string BotName = "AutoAttack"; + + public bool Enabled = false; + + [TomlInlineComment("$config.ChatBot.AutoAttack.Mode$")] + public AttackMode Mode = AttackMode.single; + + [TomlInlineComment("$config.ChatBot.AutoAttack.Priority$")] + public PriorityType Priority = PriorityType.distance; + + [TomlInlineComment("$config.ChatBot.AutoAttack.Cooldown_Time$")] + public CooldownConfig Cooldown_Time = new(false, 1.0); + + [TomlInlineComment("$config.ChatBot.AutoAttack.Interaction$")] + public InteractType Interaction = InteractType.Attack; + + [TomlInlineComment("$config.ChatBot.AutoAttack.Attack_Hostile$")] + public bool Attack_Hostile = true; + + [TomlInlineComment("$config.ChatBot.AutoAttack.Attack_Passive$")] + public bool Attack_Passive = false; + + [TomlInlineComment("$config.ChatBot.AutoAttack.List_Mode$")] + public ListType List_Mode = ListType.blacklist; + + [TomlInlineComment("$config.ChatBot.AutoAttack.Entites_List$")] + public List Entites_List = new() { EntityType.Zombie, EntityType.Cow }; + + public void OnSettingUpdate() + { + if (Cooldown_Time.Custom && Cooldown_Time.value <= 0) + { + LogToConsole(BotName, Translations.TryGet("bot.autoAttack.invalidcooldown")); + Cooldown_Time.value = 1.0; + } + } + + public enum AttackMode { single, multi }; + + public enum PriorityType { distance, health }; + + public enum ListType { blacklist, whitelist }; + + public struct CooldownConfig + { + public bool Custom; + public double value; + + public CooldownConfig() + { + Custom = false; + value = 0; + } + + public CooldownConfig(double value) + { + Custom = true; + this.value = value; + } + + public CooldownConfig(bool Override, double value) + { + this.Custom = Override; + this.value = value; + } + } + } + private readonly Dictionary entitiesToAttack = new(); // mobs within attack range private int attackCooldown = 6; private int attackCooldownCounter = 6; @@ -19,73 +94,20 @@ namespace MinecraftClient.ChatBots private readonly int attackRange = 4; private Double serverTPS; private float health = 100; - private readonly bool singleMode = true; - private readonly bool priorityDistance = true; - private readonly InteractType interactMode; private readonly bool attackHostile = true; private readonly bool attackPassive = false; - private readonly string listMode = "blacklist"; - private readonly List listedEntites = new(); - public AutoAttack( - string mode, string priority, bool overrideAttackSpeed = false, double cooldownSeconds = 1, InteractType interaction = InteractType.Attack) + public AutoAttack() { - if (mode == "single") - singleMode = true; - else if (mode == "multi") - singleMode = false; - else LogToConsoleTranslated("bot.autoAttack.mode", mode); - - if (priority == "distance") - priorityDistance = true; - else if (priority == "health") - priorityDistance = false; - else LogToConsoleTranslated("bot.autoAttack.priority", priority); - - interactMode = interaction; - - if (overrideAttackSpeed) + overrideAttackSpeed = Config.Cooldown_Time.Custom; + if (Config.Cooldown_Time.Custom) { - if (cooldownSeconds <= 0) - { - LogToConsoleTranslated("bot.autoAttack.invalidcooldown"); - } - else - { - this.overrideAttackSpeed = overrideAttackSpeed; - attackCooldownSeconds = cooldownSeconds; - attackCooldown = Convert.ToInt32(Math.Truncate(attackCooldownSeconds / 0.1) + 1); - } + attackCooldownSeconds = Config.Cooldown_Time.value; + attackCooldown = Convert.ToInt32(Math.Truncate(attackCooldownSeconds / 0.1) + 1); } - attackHostile = Settings.AutoAttack_Attack_Hostile; - attackPassive = Settings.AutoAttack_Attack_Passive; - - if (Settings.AutoAttack_ListMode.Length > 0) - { - listMode = Settings.AutoAttack_ListMode.ToLower(); - - if (!(listMode.Equals("whitelist", StringComparison.OrdinalIgnoreCase) || listMode.Equals("blacklist", StringComparison.OrdinalIgnoreCase))) - { - LogToConsole(Translations.TryGet("bot.autoAttack.invalidlist")); - listMode = "blacklist"; - } - } - else LogToConsole(Translations.TryGet("bot.autoAttack.invalidlist")); - - if (File.Exists(Settings.AutoAttack_ListFile)) - { - string[] entityList = LoadDistinctEntriesFromFile(Settings.AutoAttack_ListFile); - - if (entityList.Length > 0) - { - foreach (var item in entityList) - { - if (Enum.TryParse(item, true, out EntityType resultingType)) - listedEntites.Add(resultingType); - } - } - } + attackHostile = Config.Attack_Hostile; + attackPassive = Config.Attack_Passive; } public override void Initialize() @@ -108,10 +130,10 @@ namespace MinecraftClient.ChatBots attackCooldownCounter = attackCooldown; if (entitiesToAttack.Count > 0) { - if (singleMode) + if (Config.Mode == Configs.AttackMode.single) { int priorityEntity = 0; - if (priorityDistance) // closest distance priority + if (Config.Priority == Configs.PriorityType.distance) // closest distance priority { double distance = 5; foreach (var entity in entitiesToAttack) @@ -142,7 +164,7 @@ namespace MinecraftClient.ChatBots // check entity distance and health again if (ShouldAttackEntity(entitiesToAttack[priorityEntity])) { - InteractEntity(priorityEntity, interactMode); // hit the entity! + InteractEntity(priorityEntity, Config.Interaction); // hit the entity! SendAnimation(Inventory.Hand.MainHand); // Arm animation } } @@ -154,7 +176,7 @@ namespace MinecraftClient.ChatBots // check that we are in range once again. if (ShouldAttackEntity(entity.Value)) { - InteractEntity(entity.Key, interactMode); // hit the entity! + InteractEntity(entity.Key, Config.Interaction); // hit the entity! } } SendAnimation(Inventory.Hand.MainHand); // Arm animation @@ -206,10 +228,13 @@ namespace MinecraftClient.ChatBots if (attackPassive && entity.Type.IsPassive()) result = true; - if (listedEntites.Count > 0) + if (Config.Entites_List.Count > 0) { - bool inList = listedEntites.Contains(entity.Type); - result = listMode.Equals("blacklist") ? (!inList && result) : (inList); + bool inList = Config.Entites_List.Contains(entity.Type); + if (Config.List_Mode == Configs.ListType.blacklist) + result = !inList && result; + else + result = inList; } return result; diff --git a/MinecraftClient/ChatBots/AutoCraft.cs b/MinecraftClient/ChatBots/AutoCraft.cs index a07bdf33..74876699 100644 --- a/MinecraftClient/ChatBots/AutoCraft.cs +++ b/MinecraftClient/ChatBots/AutoCraft.cs @@ -4,11 +4,27 @@ using System.IO; using System.Linq; using MinecraftClient.Inventory; using MinecraftClient.Mapping; +using Tomlet.Attributes; namespace MinecraftClient.ChatBots { - class AutoCraft : ChatBot + public class AutoCraft : ChatBot { + public static Configs Config = new(); + + [TomlDoNotInlineObject] + public class Configs + { + [NonSerialized] + private const string BotName = "AutoCraft"; + + public bool Enabled = false; + + public string configFile = @"autocraft\config.ini"; + + public void OnSettingUpdate() { } + } + private bool waitingForMaterials = false; private bool waitingForUpdate = false; private bool waitingForTable = false; @@ -26,7 +42,6 @@ namespace MinecraftClient.ChatBots private int updateTimeout = 0; private string timeoutAction = "unspecified"; - private readonly string configPath = @"autocraft\config.ini"; private string lastRecipe = ""; // Used in parsing recipe config private readonly Dictionary recipes = new(); @@ -158,11 +173,6 @@ namespace MinecraftClient.ChatBots } } - public AutoCraft(string configPath = @"autocraft\config.ini") - { - this.configPath = configPath; - } - public override void Initialize() { if (!GetInventoryEnabled()) @@ -247,9 +257,9 @@ namespace MinecraftClient.ChatBots public void LoadConfig() { - if (!File.Exists(configPath)) + if (!File.Exists(Config.configFile)) { - if (!Directory.Exists(configPath)) + if (!Directory.Exists(Config.configFile)) { Directory.CreateDirectory(@"autocraft"); } @@ -289,19 +299,19 @@ namespace MinecraftClient.ChatBots "# For the naming of the items, please see", "# https://github.com/MCCTeam/Minecraft-Console-Client/blob/master/MinecraftClient/Inventory/ItemType.cs" }; - File.WriteAllLines(configPath, content); + File.WriteAllLines(Config.configFile, content); } private void ParseConfig() { - string[] content = File.ReadAllLines(configPath); + string[] content = File.ReadAllLines(Config.configFile); if (content.Length <= 0) { - throw new Exception(Translations.Get("bot.autoCraft.exception.empty", configPath)); + throw new Exception(Translations.Get("bot.autoCraft.exception.empty", Config.configFile)); } if (content[0].ToLower() != "[autocraft]") { - throw new Exception(Translations.Get("bot.autoCraft.exception.invalid", configPath)); + throw new Exception(Translations.Get("bot.autoCraft.exception.invalid", Config.configFile)); } // local variable for use in parsing config diff --git a/MinecraftClient/ChatBots/AutoDrop.cs b/MinecraftClient/ChatBots/AutoDrop.cs index e101da54..c962cfaf 100644 --- a/MinecraftClient/ChatBots/AutoDrop.cs +++ b/MinecraftClient/ChatBots/AutoDrop.cs @@ -2,51 +2,43 @@ using System.Collections.Generic; using System.Linq; using MinecraftClient.Inventory; +using Tomlet.Attributes; +using static MinecraftClient.ChatBots.AutoDrop.Configs; namespace MinecraftClient.ChatBots { - class AutoDrop : ChatBot + public class AutoDrop : ChatBot { - private enum Mode + public static Configs Config = new(); + + [TomlDoNotInlineObject] + public class Configs { - Include, // Items in list will be dropped - Exclude, // Items in list will be kept - Everything // Everything will be dropped + [NonSerialized] + private const string BotName = "AutoDrop"; + + public bool Enabled = false; + + [TomlInlineComment("$config.ChatBot.AutoDrop.Mode$")] + public DropMode Mode = DropMode.include; + + [TomlInlineComment("$config.ChatBot.AutoDrop.Items$")] + public List Items = new() { ItemType.Cobblestone, ItemType.Dirt }; + + public void OnSettingUpdate() { } + + public enum DropMode + { + include, // Items in list will be dropped + exclude, // Items in list will be kept + everything // Everything will be dropped + } } - private Mode dropMode = Mode.Include; - private bool enable = true; private int updateDebounce = 0; private readonly int updateDebounceValue = 2; private int inventoryUpdated = -1; - private readonly List itemList = new(); - - public AutoDrop(string mode, string itemList) - { - if (!Enum.TryParse(mode, true, out dropMode)) - { - LogToConsoleTranslated("bot.autoDrop.no_mode"); - } - if (dropMode != Mode.Everything) - this.itemList = ItemListParser(itemList).ToList(); - } - - /// - /// Convert an item type string to item type array - /// - /// String to convert - /// Item type array - private ItemType[] ItemListParser(string itemList) - { - string trimed = new(itemList.Where(c => !char.IsWhiteSpace(c)).ToArray()); - List result = new(); - foreach (string t in trimed.Split(',')) - if (Enum.TryParse(t, true, out ItemType item)) - result.Add(item); - return result.ToArray(); - } - public string CommandHandler(string cmd, string[] args) { if (args.Length > 0) @@ -54,19 +46,19 @@ namespace MinecraftClient.ChatBots switch (args[0].ToLower()) { case "on": - enable = true; + Config.Enabled = true; inventoryUpdated = 0; OnUpdateFinish(); return Translations.Get("bot.autoDrop.on"); case "off": - enable = false; + Config.Enabled = false; return Translations.Get("bot.autoDrop.off"); case "add": if (args.Length >= 2) { if (Enum.TryParse(args[1], true, out ItemType item)) { - itemList.Add(item); + Config.Items.Add(item); return Translations.Get("bot.autoDrop.added", item.ToString()); } else @@ -83,9 +75,9 @@ namespace MinecraftClient.ChatBots { if (Enum.TryParse(args[1], true, out ItemType item)) { - if (itemList.Contains(item)) + if (Config.Items.Contains(item)) { - itemList.Remove(item); + Config.Items.Remove(item); return Translations.Get("bot.autoDrop.removed", item.ToString()); } else @@ -103,9 +95,9 @@ namespace MinecraftClient.ChatBots return Translations.Get("cmd.inventory.help.usage") + ": remove "; } case "list": - if (itemList.Count > 0) + if (Config.Items.Count > 0) { - return Translations.Get("bot.autoDrop.list", itemList.Count, string.Join("\n", itemList)); + return Translations.Get("bot.autoDrop.list", Config.Items.Count, string.Join("\n", Config.Items)); } else { @@ -117,20 +109,20 @@ namespace MinecraftClient.ChatBots switch (args[1].ToLower()) { case "include": - dropMode = Mode.Include; + Config.Mode = DropMode.include; break; case "exclude": - dropMode = Mode.Exclude; + Config.Mode = DropMode.exclude; break; case "everything": - dropMode = Mode.Everything; + Config.Mode = DropMode.everything; break; default: return Translations.Get("bot.autoDrop.unknown_mode"); // Unknwon mode. Available modes: Include, Exclude, Everything } inventoryUpdated = 0; OnUpdateFinish(); - return Translations.Get("bot.autoDrop.switched", dropMode.ToString()); // Switched to {0} mode. + return Translations.Get("bot.autoDrop.switched", Config.Mode.ToString()); // Switched to {0} mode. } else { @@ -178,7 +170,7 @@ namespace MinecraftClient.ChatBots public override void OnInventoryUpdate(int inventoryId) { - if (enable) + if (Config.Enabled) { updateDebounce = updateDebounceValue; // Always interact container if available (larger ID) because they included player inventory (ID 0) @@ -199,28 +191,28 @@ namespace MinecraftClient.ChatBots } var inventory = GetInventories()[inventoryUpdated]; var items = inventory.Items.ToDictionary(entry => entry.Key, entry => entry.Value); - if (dropMode == Mode.Include) + if (Config.Mode == DropMode.include) { foreach (var item in items) { // Ingore crafting result slot if (item.Key == 0) continue; - if (itemList.Contains(item.Value.Type)) + if (Config.Items.Contains(item.Value.Type)) { // Drop it !! WindowAction(inventoryUpdated, item.Key, WindowActionType.DropItemStack); } } } - else if (dropMode == Mode.Exclude) + else if (Config.Mode == DropMode.exclude) { foreach (var item in items) { // Ingore crafting result slot if (item.Key == 0) continue; - if (!itemList.Contains(item.Value.Type)) + if (!Config.Items.Contains(item.Value.Type)) { // Drop it !! WindowAction(inventoryUpdated, item.Key, WindowActionType.DropItemStack); diff --git a/MinecraftClient/ChatBots/AutoEat.cs b/MinecraftClient/ChatBots/AutoEat.cs index 2866fe4a..eb9c3762 100644 --- a/MinecraftClient/ChatBots/AutoEat.cs +++ b/MinecraftClient/ChatBots/AutoEat.cs @@ -1,19 +1,36 @@ -using MinecraftClient.Inventory; +using System; +using MinecraftClient.Inventory; +using Tomlet.Attributes; namespace MinecraftClient.ChatBots { - class AutoEat : ChatBot + public class AutoEat : ChatBot { + public static Configs Config = new(); + + [TomlDoNotInlineObject] + public class Configs + { + [NonSerialized] + private const string BotName = "AutoEat"; + + public bool Enabled = false; + + public int Threshold = 6; + + public void OnSettingUpdate() + { + if (Threshold > 20) + Threshold = 20; + else if (Threshold < 0) + Threshold = 0; + } + } + byte LastSlot = 0; public static bool Eating = false; - private readonly int HungerThreshold = 6; private int DelayCounter = 0; - public AutoEat(int Threshold) - { - HungerThreshold = Threshold; - } - public override void Update() { if (DelayCounter > 0) @@ -31,7 +48,7 @@ namespace MinecraftClient.ChatBots public override void OnHealthUpdate(float health, int food) { if (health <= 0) return; // player dead - if (((food <= HungerThreshold) || (food < 20 && health < 20)) && !Eating) + if (((food <= Config.Threshold) || (food < 20 && health < 20)) && !Eating) { Eating = FindFoodAndEat(); if (!Eating) diff --git a/MinecraftClient/ChatBots/AutoFishing.cs b/MinecraftClient/ChatBots/AutoFishing.cs index 4e11eada..6ff0d303 100644 --- a/MinecraftClient/ChatBots/AutoFishing.cs +++ b/MinecraftClient/ChatBots/AutoFishing.cs @@ -1,6 +1,9 @@ using System; using MinecraftClient.Inventory; using MinecraftClient.Mapping; +using Tomlet.Attributes; +using static MinecraftClient.ChatBots.AutoFishing.Configs; +using static MinecraftClient.ChatBots.AutoFishing.Configs.LocationConfig; namespace MinecraftClient.ChatBots { @@ -8,8 +11,122 @@ namespace MinecraftClient.ChatBots /// The AutoFishing bot semi-automates fishing. /// The player needs to have a fishing rod in hand, then manually send it using the UseItem command. /// - class AutoFishing : ChatBot + public class AutoFishing : ChatBot { + public static Configs Config = new(); + + [TomlDoNotInlineObject] + public class Configs + { + [NonSerialized] + private const string BotName = "AutoFishing"; + + public bool Enabled = false; + + [TomlInlineComment("$config.ChatBot.AutoFishing.Antidespawn$")] + public bool Antidespawn = false; + + [TomlInlineComment("$config.ChatBot.AutoFishing.Mainhand$")] + public bool Mainhand = true; + + [TomlInlineComment("$config.ChatBot.AutoFishing.Auto_Start$")] + public bool Auto_Start = true; + + [TomlInlineComment("$config.ChatBot.AutoFishing.Cast_Delay$")] + public double Cast_Delay = 0.4; + + [TomlInlineComment("$config.ChatBot.AutoFishing.Fishing_Delay$")] + public double Fishing_Delay = 3.0; + + [TomlInlineComment("$config.ChatBot.AutoFishing.Fishing_Timeout$")] + public double Fishing_Timeout = 300.0; + + [TomlInlineComment("$config.ChatBot.AutoFishing.Durability_Limit$")] + public double Durability_Limit = 2; + + [TomlInlineComment("$config.ChatBot.AutoFishing.Auto_Rod_Switch$")] + public bool Auto_Rod_Switch = true; + + [TomlInlineComment("$config.ChatBot.AutoFishing.Stationary_Threshold$")] + public double Stationary_Threshold = 0.001; + + [TomlInlineComment("$config.ChatBot.AutoFishing.Hook_Threshold$")] + public double Hook_Threshold = 0.2; + + [TomlInlineComment("$config.ChatBot.AutoFishing.Log_Fish_Bobber$")] + public bool Log_Fish_Bobber = false; + + [TomlInlineComment("$config.ChatBot.AutoFishing.Movements$")] + public LocationConfig[] Movements = Array.Empty(); + + public void OnSettingUpdate() + { + if (Cast_Delay < 0) + Cast_Delay = 0; + + if (Fishing_Delay < 0) + Fishing_Delay = 0; + + if (Fishing_Timeout < 0) + Fishing_Timeout = 0; + + if (Durability_Limit < 0) + Durability_Limit = 0; + else if (Durability_Limit > 64) + Durability_Limit = 64; + + if (Stationary_Threshold < 0) + Stationary_Threshold = -Stationary_Threshold; + + if (Hook_Threshold < 0) + Hook_Threshold = -Hook_Threshold; + } + + public struct LocationConfig + { + public Coordination? XYZ; + public Facing? facing; + + public LocationConfig(float yaw, float pitch) + { + this.XYZ = null; + this.facing = new(yaw, pitch); + } + + public LocationConfig(double x, double y, double z) + { + this.XYZ = new(x, y, z); + this.facing = null; + } + + public LocationConfig(double x, double y, double z, float yaw, float pitch) + { + this.XYZ = new(x, y, z); + this.facing = new(yaw, pitch); + } + + public struct Coordination + { + public double x, y, z; + + public Coordination(double x, double y, double z) + { + this.x = x; this.y = y; this.z = z; + } + } + + public struct Facing + { + public float yaw, pitch; + + public Facing(float yaw, float pitch) + { + this.yaw = yaw; this.pitch = pitch; + } + } + } + } + private int fishCount = 0; private bool inventoryEnabled; private int castTimeout = 12; @@ -54,9 +171,9 @@ namespace MinecraftClient.ChatBots private void StartFishing() { isFishing = false; - if (Settings.AutoFishing_AutoStart) + if (Config.Auto_Start) { - double delay = Settings.AutoFishing_FishingDelay; + double delay = Config.Fishing_Delay; LogToConsole(Translations.Get("bot.autoFish.start", delay)); lock (stateLock) { @@ -84,7 +201,7 @@ namespace MinecraftClient.ChatBots private void UseFishRod() { - if (Settings.AutoFishing_Mainhand) + if (Config.Mainhand) UseItemInHand(); else UseItemInLeftHand(); @@ -100,7 +217,7 @@ namespace MinecraftClient.ChatBots break; case FishingState.WaitingToCast: if (AutoEat.Eating) - counter = (int)(Settings.AutoFishing_CastDelay * 10); + counter = (int)(Config.Cast_Delay * 10); else if (--counter < 0) state = FishingState.CastingRod; break; @@ -116,28 +233,27 @@ namespace MinecraftClient.ChatBots castTimeout *= 2; // Exponential backoff LogToConsole(GetTimestamp() + ": " + Translations.Get("bot.autoFish.cast_timeout", castTimeout / 10.0)); - counter = (int)(Settings.AutoFishing_CastDelay * 10); + counter = (int)(Config.Cast_Delay * 10); state = FishingState.WaitingToCast; } break; case FishingState.WaitingFishToBite: - if (++counter > (int)(Settings.AutoFishing_FishingTimeout * 10)) + if (++counter > (int)(Config.Fishing_Timeout * 10)) { LogToConsole(GetTimestamp() + ": " + Translations.Get("bot.autoFish.fishing_timeout")); - counter = (int)(Settings.AutoFishing_CastDelay * 10); + counter = (int)(Config.Cast_Delay * 10); state = FishingState.WaitingToCast; } break; case FishingState.StartMove: if (--counter < 0) { - double[,]? locationList = Settings.AutoFishing_Location; - if (locationList != null) + if (Config.Movements.Length > 0) { if (GetTerrainEnabled()) { - UpdateLocation(locationList); + UpdateLocation(Config.Movements); state = FishingState.WaitingMovement; } else @@ -148,7 +264,7 @@ namespace MinecraftClient.ChatBots } else { - counter = (int)(Settings.AutoFishing_CastDelay * 10); + counter = (int)(Config.Cast_Delay * 10); state = FishingState.DurabilityCheck; goto case FishingState.DurabilityCheck; } @@ -167,7 +283,7 @@ namespace MinecraftClient.ChatBots case FishingState.DurabilityCheck: if (DurabilityCheck()) { - counter = (int)(Settings.AutoFishing_CastDelay * 10); + counter = (int)(Config.Cast_Delay * 10); state = FishingState.WaitingToCast; } break; @@ -181,7 +297,7 @@ namespace MinecraftClient.ChatBots { if (entity.Type == EntityType.FishingBobber && entity.ObjectData == GetPlayerEntityID()) { - if (Settings.AutoFishing_LogFishingBobber) + if (Config.Log_Fish_Bobber) LogToConsole(string.Format("FishingBobber spawn at {0}, distance = {1:0.00}", entity.Location, GetCurrentLocation().Distance(entity.Location))); LogToConsole(GetTimestamp() + ": " + Translations.Get("bot.autoFish.throw")); @@ -202,20 +318,20 @@ namespace MinecraftClient.ChatBots { if (entity != null && entity.Type == EntityType.FishingBobber && entity.ID == fishingBobber!.ID) { - if (Settings.AutoFishing_LogFishingBobber) + if (Config.Log_Fish_Bobber) LogToConsole(string.Format("FishingBobber despawn at {0}", entity.Location)); if (isFishing) { isFishing = false; - if (Settings.AutoFishing_Antidespawn) + if (Config.Antidespawn) { LogToConsoleTranslated("bot.autoFish.despawn"); lock (stateLock) { - counter = (int)(Settings.AutoFishing_CastDelay * 10); + counter = (int)(Config.Cast_Delay * 10); state = FishingState.WaitingToCast; } } @@ -233,12 +349,12 @@ namespace MinecraftClient.ChatBots double Dz = LastPos.Z - Pos.Z; LastPos = Pos; - if (Settings.AutoFishing_LogFishingBobber) + if (Config.Log_Fish_Bobber) LogToConsole(string.Format("FishingBobber {0} Dx={1:0.000000} Dy={2:0.000000} Dz={3:0.000000}", Pos, Dx, Math.Abs(Dy), Dz)); - if (Math.Abs(Dx) < Math.Abs(Settings.AutoFishing_StationaryThreshold) && - Math.Abs(Dz) < Math.Abs(Settings.AutoFishing_StationaryThreshold) && - Math.Abs(Dy) > Math.Abs(Settings.AutoFishing_HookThreshold)) + if (Math.Abs(Dx) < Math.Abs(Config.Stationary_Threshold) && + Math.Abs(Dz) < Math.Abs(Config.Stationary_Threshold) && + Math.Abs(Dy) > Math.Abs(Config.Hook_Threshold)) { // prevent triggering multiple time if ((DateTime.Now - CaughtTime).TotalSeconds > 1) @@ -283,7 +399,7 @@ namespace MinecraftClient.ChatBots public void OnCaughtFish() { ++fishCount; - if (Settings.AutoFishing_Location != null) + if (Config.Movements.Length > 0) LogToConsole(GetTimestamp() + ": " + Translations.Get("bot.autoFish.caught_at", fishingBobber!.Location.X, fishingBobber!.Location.Y, fishingBobber!.Location.Z, fishCount)); else @@ -298,47 +414,36 @@ namespace MinecraftClient.ChatBots } } - private void UpdateLocation(double[,] locationList) + private void UpdateLocation(LocationConfig[] locationList) { - if (curLocationIdx >= locationList.GetLength(0)) + if (curLocationIdx >= locationList.Length) { - curLocationIdx = Math.Max(0, locationList.GetLength(0) - 2); + curLocationIdx = Math.Max(0, locationList.Length - 2); moveDir = -1; } else if (curLocationIdx < 0) { - curLocationIdx = Math.Min(locationList.GetLength(0) - 1, 1); + curLocationIdx = Math.Min(locationList.Length - 1, 1); moveDir = 1; } - int locationType = locationList.GetLength(1); + LocationConfig curConfig = locationList[curLocationIdx]; - if (locationType == 2) - { - nextYaw = (float)locationList[curLocationIdx, 0]; - nextPitch = (float)locationList[curLocationIdx, 1]; - } - else if (locationType == 3) - { - nextYaw = GetYaw(); - nextPitch = GetPitch(); - } - else if (locationType == 5) - { - nextYaw = (float)locationList[curLocationIdx, 3]; - nextPitch = (float)locationList[curLocationIdx, 4]; - } + if (curConfig.facing != null) + (nextYaw, nextPitch) = (curConfig.facing.Value.yaw, curConfig.facing.Value.pitch); + else + (nextYaw, nextPitch) = (GetYaw(), GetPitch()); - if (locationType == 3 || locationType == 5) + if (curConfig.XYZ != null) { Location current = GetCurrentLocation(); - Location goal = new(locationList[curLocationIdx, 0], locationList[curLocationIdx, 1], locationList[curLocationIdx, 2]); + Location goal = new(curConfig.XYZ.Value.x, curConfig.XYZ.Value.y, curConfig.XYZ.Value.z); bool isMoveSuccessed; if (!Movement.CheckChunkLoading(GetWorld(), current, goal)) { - LogToConsole(Translations.Get("cmd.move.chunk_not_loaded", goal.X, goal.Y, goal.Z)); isMoveSuccessed = false; + LogToConsole(Translations.Get("cmd.move.chunk_not_loaded", goal.X, goal.Y, goal.Z)); } else { @@ -347,8 +452,7 @@ namespace MinecraftClient.ChatBots if (!isMoveSuccessed) { - nextYaw = GetYaw(); - nextPitch = GetPitch(); + (nextYaw, nextPitch) = (GetYaw(), GetPitch()); LogToConsole(Translations.Get("cmd.move.fail", goal)); } else @@ -365,13 +469,13 @@ namespace MinecraftClient.ChatBots if (!inventoryEnabled) return true; - bool useMainHand = Settings.AutoFishing_Mainhand; + bool useMainHand = Config.Mainhand; Container container = GetPlayerInventory(); int itemSolt = useMainHand ? GetCurrentSlot() + 36 : 45; if (container.Items.TryGetValue(itemSolt, out Item? handItem) && - handItem.Type == ItemType.FishingRod && (64 - handItem.Damage) >= Settings.AutoFishing_DurabilityLimit) + handItem.Type == ItemType.FishingRod && (64 - handItem.Damage) >= Config.Durability_Limit) { isWaitingRod = false; return true; @@ -381,11 +485,11 @@ namespace MinecraftClient.ChatBots if (!isWaitingRod) LogToConsole(GetTimestamp() + ": " + Translations.Get("bot.autoFish.no_rod")); - if (Settings.AutoFishing_AutoRodSwitch) + if (Config.Auto_Rod_Switch) { foreach ((int slot, Item item) in container.Items) { - if (item.Type == ItemType.FishingRod && (64 - item.Damage) >= Settings.AutoFishing_DurabilityLimit) + if (item.Type == ItemType.FishingRod && (64 - item.Damage) >= Config.Durability_Limit) { WindowAction(0, slot, WindowActionType.LeftClick); WindowAction(0, itemSolt, WindowActionType.LeftClick); diff --git a/MinecraftClient/ChatBots/AutoRelog.cs b/MinecraftClient/ChatBots/AutoRelog.cs index b6f5a6e6..40b9c169 100644 --- a/MinecraftClient/ChatBots/AutoRelog.cs +++ b/MinecraftClient/ChatBots/AutoRelog.cs @@ -1,5 +1,6 @@ using System; using System.Text; +using Tomlet.Attributes; namespace MinecraftClient.ChatBots { @@ -8,11 +9,59 @@ namespace MinecraftClient.ChatBots /// public class AutoRelog : ChatBot { + public static Configs Config = new(); + + [TomlDoNotInlineObject] + public class Configs + { + [NonSerialized] + private const string BotName = "AutoRelog"; + + public bool Enabled = false; + + [TomlInlineComment("$config.ChatBot.AutoRelog.Delay$")] + public Range Delay = new(10); + + [TomlInlineComment("$config.ChatBot.AutoRelog.Retries$")] + public int Retries = 3; + + [TomlInlineComment("$config.ChatBot.AutoRelog.Ignore_Kick_Message$")] + public bool Ignore_Kick_Message = false; + + [TomlInlineComment("$config.ChatBot.AutoRelog.Kick_Messages_File$")] + public string Kick_Messages_File = @"kickmessages.txt"; + + public void OnSettingUpdate() + { + if (Delay.min > Delay.max) + (Delay.min, Delay.max) = (Delay.max, Delay.min); + + if (Retries == -1) + Retries = int.MaxValue; + } + + public struct Range + { + public int min, max; + + public Range(int value) + { + value = Math.Max(value, 1); + min = max = value; + } + + public Range(int min, int max) + { + min = Math.Max(min, 1); + max = Math.Max(max, 1); + this.min = min; + this.max = max; + } + } + } + private static readonly Random random = new(); private string[] dictionary = Array.Empty(); - private readonly int attempts; - private readonly int delayMin; - private readonly int delayMax; /// /// This bot automatically re-join the server if kick message contains predefined string @@ -20,34 +69,25 @@ namespace MinecraftClient.ChatBots /// Minimum delay before re-joining the server (in seconds) /// Maximum delay before re-joining the server (in seconds) /// Number of retries if connection fails (-1 = infinite) - public AutoRelog(int DelayBeforeRelogMin, int DelayBeforeRelogMax, int retries) + public AutoRelog() { - attempts = retries; - if (attempts == -1) { attempts = int.MaxValue; } - McClient.ReconnectionAttemptsLeft = attempts; - delayMin = DelayBeforeRelogMin; - delayMax = DelayBeforeRelogMax; - if (delayMin < 1) - delayMin = 1; - if (delayMax < delayMin) - delayMax = delayMin; - LogDebugToConsoleTranslated("bot.autoRelog.launch", attempts); + LogDebugToConsoleTranslated("bot.autoRelog.launch", Config.Retries); } public override void Initialize() { - McClient.ReconnectionAttemptsLeft = attempts; - if (Settings.AutoRelog_IgnoreKickMessage) + McClient.ReconnectionAttemptsLeft = Config.Retries; + if (Config.Ignore_Kick_Message) { LogDebugToConsoleTranslated("bot.autoRelog.no_kick_msg"); } else { - if (System.IO.File.Exists(Settings.AutoRelog_KickMessagesFile)) + if (System.IO.File.Exists(Config.Kick_Messages_File)) { - LogDebugToConsoleTranslated("bot.autoRelog.loading", System.IO.Path.GetFullPath(Settings.AutoRelog_KickMessagesFile)); + LogDebugToConsoleTranslated("bot.autoRelog.loading", System.IO.Path.GetFullPath(Config.Kick_Messages_File)); - dictionary = System.IO.File.ReadAllLines(Settings.AutoRelog_KickMessagesFile, Encoding.UTF8); + dictionary = System.IO.File.ReadAllLines(Config.Kick_Messages_File, Encoding.UTF8); for (int i = 0; i < dictionary.Length; i++) { @@ -57,7 +97,7 @@ namespace MinecraftClient.ChatBots } else { - LogToConsoleTranslated("bot.autoRelog.not_found", System.IO.Path.GetFullPath(Settings.AutoRelog_KickMessagesFile)); + LogToConsoleTranslated("bot.autoRelog.not_found", System.IO.Path.GetFullPath(Config.Kick_Messages_File)); LogDebugToConsoleTranslated("bot.autoRelog.curr_dir", System.IO.Directory.GetCurrentDirectory()); } @@ -77,7 +117,7 @@ namespace MinecraftClient.ChatBots LogDebugToConsoleTranslated("bot.autoRelog.disconnect_msg", message); - if (Settings.AutoRelog_IgnoreKickMessage) + if (Config.Ignore_Kick_Message) { LaunchDelayedReconnection(null); return true; @@ -100,7 +140,7 @@ namespace MinecraftClient.ChatBots private void LaunchDelayedReconnection(string? msg) { - int delay = random.Next(delayMin, delayMax); + int delay = random.Next(Config.Delay.min, Config.Delay.max); LogDebugToConsoleTranslated(String.IsNullOrEmpty(msg) ? "bot.autoRelog.reconnect_always" : "bot.autoRelog.reconnect", msg); LogToConsoleTranslated("bot.autoRelog.wait", delay); System.Threading.Thread.Sleep(delay * 1000); @@ -109,9 +149,9 @@ namespace MinecraftClient.ChatBots public static bool OnDisconnectStatic(DisconnectReason reason, string message) { - if (Settings.AutoRelog_Enabled) + if (Config.Enabled) { - AutoRelog bot = new(Settings.AutoRelog_Delay_Min, Settings.AutoRelog_Delay_Max, Settings.AutoRelog_Retries); + AutoRelog bot = new(); bot.Initialize(); return bot.OnDisconnect(reason, message); } diff --git a/MinecraftClient/ChatBots/AutoRespond.cs b/MinecraftClient/ChatBots/AutoRespond.cs index 2b0738b5..d05ba350 100644 --- a/MinecraftClient/ChatBots/AutoRespond.cs +++ b/MinecraftClient/ChatBots/AutoRespond.cs @@ -1,31 +1,50 @@ using System; using System.Collections.Generic; +using System.Globalization; using System.IO; using System.Text; using System.Text.RegularExpressions; +using Tomlet.Attributes; +using static MinecraftClient.Settings; namespace MinecraftClient.ChatBots { /// /// This bot automatically runs actions when a user sends a message matching a specified rule /// - class AutoRespond : ChatBot + public class AutoRespond : ChatBot { - private readonly string matchesFile; - private readonly bool matchColors; + public static Configs Config = new(); + + [TomlDoNotInlineObject] + public class Configs + { + [NonSerialized] + private const string BotName = "AutoRespond"; + + public bool Enabled = false; + + public string Matches_File = @"matches.ini"; + + [TomlInlineComment("$config.ChatBot.AutoRespond.Match_Colors$")] + public bool Match_Colors = false; + + public void OnSettingUpdate() + { + if (!Enabled) return; + + if (!File.Exists(Matches_File)) + { + LogToConsole(BotName, Translations.TryGet("bot.autoRespond.file_not_found", Path.GetFullPath(Matches_File))); + LogToConsole(BotName, Translations.TryGet("general.bot_unload")); + Enabled = false; + } + } + } + private List? respondRules; private enum MessageType { Public, Private, Other }; - /// - /// Create a new AutoRespond bot - /// - /// INI File to load matches from - public AutoRespond(string matchesFile, bool matchColors) - { - this.matchesFile = matchesFile; - this.matchColors = matchColors; - } - /// /// Describe a respond rule based on a simple match or a regex /// @@ -96,7 +115,7 @@ namespace MinecraftClient.ChatBots string? toSend = null; - if (ownersOnly && (String.IsNullOrEmpty(username) || !Settings.Bots_Owners.Contains(username.ToLower()))) + if (ownersOnly && (String.IsNullOrEmpty(username) || !Settings.Config.Main.Advanced.BotOwners.Contains(username.ToLower()))) return null; switch (msgType) @@ -164,7 +183,7 @@ namespace MinecraftClient.ChatBots /// public override void Initialize() { - if (File.Exists(matchesFile)) + if (File.Exists(Config.Matches_File)) { Regex? matchRegex = null; string? matchString = null; @@ -175,9 +194,9 @@ namespace MinecraftClient.ChatBots TimeSpan cooldown = TimeSpan.Zero; respondRules = new List(); - LogDebugToConsoleTranslated("bot.autoRespond.loading", System.IO.Path.GetFullPath(matchesFile)); + LogDebugToConsoleTranslated("bot.autoRespond.loading", System.IO.Path.GetFullPath(Config.Matches_File)); - foreach (string lineRAW in File.ReadAllLines(matchesFile, Encoding.UTF8)) + foreach (string lineRAW in File.ReadAllLines(Config.Matches_File, Encoding.UTF8)) { string line = lineRAW.Split('#')[0].Trim(); if (line.Length > 0) @@ -211,8 +230,8 @@ namespace MinecraftClient.ChatBots case "action": matchAction = argValue; break; case "actionprivate": matchActionPrivate = argValue; break; case "actionother": matchActionOther = argValue; break; - case "ownersonly": ownersOnly = Settings.str2bool(argValue); break; - case "cooldown": cooldown = TimeSpan.FromSeconds(Settings.str2int(argValue)); break; + case "ownersonly": ownersOnly = bool.Parse(argValue); break; + case "cooldown": cooldown = TimeSpan.FromSeconds(int.Parse(argValue, NumberStyles.Any, CultureInfo.CurrentCulture)); break; } } } @@ -222,7 +241,7 @@ namespace MinecraftClient.ChatBots } else { - LogToConsoleTranslated("bot.autoRespond.file_not_found", System.IO.Path.GetFullPath(matchesFile)); + LogToConsoleTranslated("bot.autoRespond.file_not_found", System.IO.Path.GetFullPath(Config.Matches_File)); UnloadBot(); //No need to keep the bot active } } @@ -264,7 +283,7 @@ namespace MinecraftClient.ChatBots public override void GetText(string text) { //Remove colour codes - if (!matchColors) + if (!Config.Match_Colors) text = GetVerbatim(text); //Get Message type @@ -277,7 +296,7 @@ namespace MinecraftClient.ChatBots else message = text; //Do not process messages sent by the bot itself - if (msgType == MessageType.Other || sender != Settings.Username) + if (msgType == MessageType.Other || sender != InternalConfig.Username) { foreach (RespondRule rule in respondRules!) { diff --git a/MinecraftClient/ChatBots/ChatLog.cs b/MinecraftClient/ChatBots/ChatLog.cs index cc2e81b5..7da2f887 100644 --- a/MinecraftClient/ChatBots/ChatLog.cs +++ b/MinecraftClient/ChatBots/ChatLog.cs @@ -1,5 +1,7 @@ using System; using System.IO; +using Tomlet.Attributes; +using static System.Net.WebRequestMethods; namespace MinecraftClient.ChatBots { @@ -9,13 +11,42 @@ namespace MinecraftClient.ChatBots public class ChatLog : ChatBot { - public enum MessageFilter { AllText, AllMessages, OnlyChat, OnlyWhispers, OnlyInternalCommands }; - private readonly bool dateandtime; - private readonly bool saveOther = true; - private readonly bool saveChat = true; - private readonly bool savePrivate = true; - private readonly bool saveInternal = true; - private readonly string logfile; + public static Configs Config = new(); + + [TomlDoNotInlineObject] + public class Configs + { + [NonSerialized] + private const string BotName = "ChatLog"; + + public bool Enabled = false; + + public bool Add_DateTime = true; + + public string Log_File = @"chatlog-%username%-%serverip%.txt"; + + public MessageFilter Filter = MessageFilter.messages; + + public void OnSettingUpdate() + { + if (!Enabled) return; + + string Log_File_Full = Settings.Config.AppVar.ExpandVars(Log_File); + if (String.IsNullOrEmpty(Log_File_Full) || Log_File_Full.IndexOfAny(Path.GetInvalidPathChars()) >= 0) + { + LogToConsole(BotName, Translations.TryGet("bot.chatLog.invalid_file", Log_File_Full)); + LogToConsole(BotName, Translations.TryGet("general.bot_unload")); + Enabled = false; + } + } + + public enum MessageFilter { all, messages, chat, private_chat, internal_msg }; + } + + private bool saveOther = true; + private bool saveChat = true; + private bool savePrivate = true; + private bool saveInternal = true; private readonly object logfileLock = new(); /// @@ -25,59 +56,42 @@ namespace MinecraftClient.ChatBots /// The kind of messages to save /// Add a date and time before each message - public ChatLog(string file, MessageFilter filter, bool AddDateAndTime) + public ChatLog() + { + UpdateFilter(Config.Filter); + } + + public void UpdateFilter(Configs.MessageFilter filter) { - dateandtime = AddDateAndTime; - logfile = file; switch (filter) { - case MessageFilter.AllText: + case Configs.MessageFilter.all: saveOther = true; savePrivate = true; saveChat = true; break; - case MessageFilter.AllMessages: + case Configs.MessageFilter.messages: saveOther = false; savePrivate = true; saveChat = true; break; - case MessageFilter.OnlyChat: + case Configs.MessageFilter.chat: saveOther = false; savePrivate = false; saveChat = true; break; - case MessageFilter.OnlyWhispers: + case Configs.MessageFilter.private_chat: saveOther = false; savePrivate = true; saveChat = false; break; - case MessageFilter.OnlyInternalCommands: + case Configs.MessageFilter.internal_msg: saveOther = false; savePrivate = false; saveChat = false; saveInternal = true; break; } - if (String.IsNullOrEmpty(file) || file.IndexOfAny(Path.GetInvalidPathChars()) >= 0) - { - LogToConsoleTranslated("bot.chatLog.invalid_file", file); - UnloadBot(); - } - } - - public static MessageFilter str2filter(string filtername) - { - return Settings.ToLowerIfNeed(filtername) switch - { -#pragma warning disable format // @formatter:off - "all" => MessageFilter.AllText, - "messages" => MessageFilter.AllMessages, - "chat" => MessageFilter.OnlyChat, - "private" => MessageFilter.OnlyWhispers, - "internal" => MessageFilter.OnlyInternalCommands, - _ => MessageFilter.AllText, -#pragma warning restore format // @formatter:on - }; } public override void GetText(string text) @@ -110,14 +124,15 @@ namespace MinecraftClient.ChatBots private void Save(string tosave) { - if (dateandtime) + if (Config.Add_DateTime) tosave = GetTimestamp() + ' ' + tosave; + string Log_File_Full = Settings.Config.AppVar.ExpandVars(Config.Log_File); lock (logfileLock) { - string? directory = Path.GetDirectoryName(logfile); + string? directory = Path.GetDirectoryName(Log_File_Full); if (!String.IsNullOrEmpty(directory) && !Directory.Exists(directory)) Directory.CreateDirectory(directory); - FileStream stream = new(logfile, FileMode.OpenOrCreate); + FileStream stream = new(Log_File_Full, FileMode.OpenOrCreate); StreamWriter writer = new(stream); stream.Seek(0, SeekOrigin.End); writer.WriteLine(tosave); diff --git a/MinecraftClient/ChatBots/FollowPlayer.cs b/MinecraftClient/ChatBots/FollowPlayer.cs index e03eb253..37fbe221 100644 --- a/MinecraftClient/ChatBots/FollowPlayer.cs +++ b/MinecraftClient/ChatBots/FollowPlayer.cs @@ -1,23 +1,42 @@ using System; using System.Linq; using MinecraftClient.Mapping; +using Tomlet.Attributes; namespace MinecraftClient.ChatBots { public class FollowPlayer : ChatBot { + public static Configs Config = new(); + + [TomlDoNotInlineObject] + public class Configs + { + [NonSerialized] + private const string BotName = "FollowPlayer"; + + public bool Enabled = false; + + [TomlInlineComment("$config.ChatBot.FollowPlayer.Update_Limit$")] + public int Update_Limit = 10; + + [TomlInlineComment("$config.ChatBot.FollowPlayer.Stop_At_Distance$")] + public double Stop_At_Distance = 3.0; + + public void OnSettingUpdate() + { + if (Update_Limit < 0) + Update_Limit = 0; + + if (Stop_At_Distance < 0) + Stop_At_Distance = 0; + } + } + private string? _playerToFollow = null; private int _updateCounter = 0; - private readonly int _updateLimit; - private readonly int _stopAtDistance; private bool _unsafeEnabled = false; - public FollowPlayer(int updateLimit = 15, int stopAtDistance = 3) - { - _updateLimit = updateLimit; - _stopAtDistance = stopAtDistance; - } - public override void Initialize() { if (!GetEntityHandlingEnabled()) @@ -94,7 +113,7 @@ namespace MinecraftClient.ChatBots public override void OnEntityMove(Entity entity) { - if (_updateCounter < _updateLimit) + if (_updateCounter < Config.Update_Limit) return; _updateCounter = 0; @@ -114,7 +133,7 @@ namespace MinecraftClient.ChatBots // Stop at specified distance from plater (prevents pushing player around) double distance = entity.Location.Distance(GetCurrentLocation()); - if (distance < _stopAtDistance) + if (distance < Config.Stop_At_Distance) return; MoveToLocation(entity.Location, _unsafeEnabled); diff --git a/MinecraftClient/ChatBots/HangmanGame.cs b/MinecraftClient/ChatBots/HangmanGame.cs index c41324af..281ed68e 100644 --- a/MinecraftClient/ChatBots/HangmanGame.cs +++ b/MinecraftClient/ChatBots/HangmanGame.cs @@ -1,5 +1,6 @@ using System; using System.Text; +using Tomlet.Attributes; namespace MinecraftClient.ChatBots { @@ -9,26 +10,33 @@ namespace MinecraftClient.ChatBots public class HangmanGame : ChatBot { + public static Configs Config = new(); + + [TomlDoNotInlineObject] + public class Configs + { + [NonSerialized] + private const string BotName = "HangmanGame"; + + public bool Enabled = false; + + public bool English = true; + + public string FileWords_EN = "hangman-en.txt"; + + public string FileWords_FR = "hangman-fr.txt"; + + public void OnSettingUpdate() { } + } + private int vie = 0; private readonly int vie_param = 10; private int compteur = 0; private readonly int compteur_param = 3000; //5 minutes private bool running = false; - private bool[] discovered; + private bool[] discovered = Array.Empty(); private string word = ""; private string letters = ""; - private readonly bool English; - - /// - /// Le jeu du Pendu / Hangman Game - /// - /// if true, the game will be in english. If false, the game will be in french. - - public HangmanGame(bool english) - { - English = english; - discovered = Array.Empty(); - } public override void Update() { @@ -40,8 +48,8 @@ namespace MinecraftClient.ChatBots } else { - SendText(English ? "You took too long to try a letter." : "Temps imparti écoulé !"); - SendText(English ? "Game canceled." : "Partie annulée."); + SendText(Config.English ? "You took too long to try a letter." : "Temps imparti écoulé !"); + SendText(Config.English ? "Game canceled." : "Partie annulée."); running = false; } } @@ -55,7 +63,7 @@ namespace MinecraftClient.ChatBots if (IsPrivateMessage(text, ref message, ref username)) { - if (Settings.Bots_Owners.Contains(username.ToLower())) + if (Settings.Config.Main.Advanced.BotOwners.Contains(username.ToLower())) { switch (message) { @@ -81,7 +89,7 @@ namespace MinecraftClient.ChatBots { if (letters.Contains(letter)) { - SendText(English ? ("Letter " + letter + " has already been tried.") : ("Le " + letter + " a déjà été proposé.")); + SendText(Config.English ? ("Letter " + letter + " has already been tried.") : ("Le " + letter + " a déjà été proposé.")); } else { @@ -91,29 +99,29 @@ namespace MinecraftClient.ChatBots if (word.Contains(letter)) { for (int i = 0; i < word.Length; i++) { if (word[i] == letter) { discovered[i] = true; } } - SendText(English ? ("Yes, the word contains a " + letter + '!') : ("Le " + letter + " figurait bien dans le mot :)")); + SendText(Config.English ? ("Yes, the word contains a " + letter + '!') : ("Le " + letter + " figurait bien dans le mot :)")); } else { vie--; if (vie == 0) { - SendText(English ? "Game Over! :]" : "Perdu ! Partie terminée :]"); - SendText(English ? ("The word was: " + word) : ("Le mot était : " + word)); + SendText(Config.English ? "Game Over! :]" : "Perdu ! Partie terminée :]"); + SendText(Config.English ? ("The word was: " + word) : ("Le mot était : " + word)); running = false; } - else SendText(English ? ("The " + letter + "? No.") : ("Le " + letter + " ? Non.")); + else SendText(Config.English ? ("The " + letter + "? No.") : ("Le " + letter + " ? Non.")); } if (running) { - SendText(English ? ("Mysterious word: " + WordCached + " (lives : " + vie + ")") + SendText(Config.English ? ("Mysterious word: " + WordCached + " (lives : " + vie + ")") : ("Mot mystère : " + WordCached + " (vie : " + vie + ")")); } if (Winner) { - SendText(English ? ("Congrats, " + username + '!') : ("Félicitations, " + username + " !")); + SendText(Config.English ? ("Congrats, " + username + '!') : ("Félicitations, " + username + " !")); running = false; } } @@ -132,23 +140,23 @@ namespace MinecraftClient.ChatBots compteur = compteur_param; discovered = new bool[word.Length]; - SendText(English ? "Hangman v1.0 - By ORelio" : "Pendu v1.0 - Par ORelio"); - SendText(English ? ("Mysterious word: " + WordCached + " (lives : " + vie + ")") + SendText(Config.English ? "Hangman v1.0 - By ORelio" : "Pendu v1.0 - Par ORelio"); + SendText(Config.English ? ("Mysterious word: " + WordCached + " (lives : " + vie + ")") : ("Mot mystère : " + WordCached + " (vie : " + vie + ")")); - SendText(English ? ("Try some letters ... :)") : ("Proposez une lettre ... :)")); + SendText(Config.English ? ("Try some letters ... :)") : ("Proposez une lettre ... :)")); } private string Chooseword() { - if (System.IO.File.Exists(English ? Settings.Hangman_FileWords_EN : Settings.Hangman_FileWords_FR)) + if (System.IO.File.Exists(Config.English ? Config.FileWords_EN : Config.FileWords_FR)) { - string[] dico = System.IO.File.ReadAllLines(English ? Settings.Hangman_FileWords_EN : Settings.Hangman_FileWords_FR, Encoding.UTF8); + string[] dico = System.IO.File.ReadAllLines(Config.English ? Config.FileWords_EN : Config.FileWords_FR, Encoding.UTF8); return dico[new Random().Next(dico.Length)]; } else { - LogToConsole(English ? "File not found: " + Settings.Hangman_FileWords_EN : "Fichier introuvable : " + Settings.Hangman_FileWords_FR); - return English ? "WORDSAREMISSING" : "DICOMANQUANT"; + LogToConsole(Config.English ? "File not found: " + Config.FileWords_EN : "Fichier introuvable : " + Config.FileWords_FR); + return Config.English ? "WORDSAREMISSING" : "DICOMANQUANT"; } } diff --git a/MinecraftClient/ChatBots/Mailer.cs b/MinecraftClient/ChatBots/Mailer.cs index 8752d1fd..a596b9f4 100644 --- a/MinecraftClient/ChatBots/Mailer.cs +++ b/MinecraftClient/ChatBots/Mailer.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Data; using System.IO; using System.Linq; +using Tomlet.Attributes; namespace MinecraftClient.ChatBots { @@ -11,6 +12,60 @@ namespace MinecraftClient.ChatBots /// public class Mailer : ChatBot { + public static Configs Config = new(); + + [TomlDoNotInlineObject] + public class Configs + { + [NonSerialized] + private const string BotName = "Mailer"; + + public bool Enabled = false; + + public string DatabaseFile = "MailerDatabase.ini"; + + public string IgnoreListFile = "MailerIgnoreList.ini"; + + public bool PublicInteractions = false; + + public int MaxMailsPerPlayer = 10; + + public int MaxDatabaseSize = 10000; + + public int MailRetentionDays = 30; + + public void OnSettingUpdate() + { + if (!Enabled) return; + + bool checkSuccessed = true; + + if (Config.MaxDatabaseSize <= 0) + { + LogToConsole(BotName, Translations.TryGet("bot.mailer.init_fail.db_size")); + checkSuccessed = false; + } + + if (Config.MaxMailsPerPlayer <= 0) + { + LogToConsole(BotName, Translations.TryGet("bot.mailer.init_fail.max_mails")); + checkSuccessed = false; + } + + if (Config.MailRetentionDays <= 0) + { + LogToConsole(BotName, Translations.TryGet("bot.mailer.init_fail.mail_retention")); + checkSuccessed = false; + } + + if (!checkSuccessed) + { + LogToConsole(BotName, Translations.TryGet("general.bot_unload")); + Enabled = false; + } + } + } + /// /// Holds the list of ignored players /// @@ -161,58 +216,37 @@ namespace MinecraftClient.ChatBots public override void Initialize() { LogDebugToConsoleTranslated("bot.mailer.init"); - LogDebugToConsoleTranslated("bot.mailer.init.db" + Settings.Mailer_DatabaseFile); - LogDebugToConsoleTranslated("bot.mailer.init.ignore" + Settings.Mailer_IgnoreListFile); - LogDebugToConsoleTranslated("bot.mailer.init.public" + Settings.Mailer_PublicInteractions); - LogDebugToConsoleTranslated("bot.mailer.init.max_mails" + Settings.Mailer_MaxMailsPerPlayer); - LogDebugToConsoleTranslated("bot.mailer.init.db_size" + Settings.Mailer_MaxDatabaseSize); - LogDebugToConsoleTranslated("bot.mailer.init.mail_retention" + Settings.Mailer_MailRetentionDays + " days"); + LogDebugToConsoleTranslated("bot.mailer.init.db" + Config.DatabaseFile); + LogDebugToConsoleTranslated("bot.mailer.init.ignore" + Config.IgnoreListFile); + LogDebugToConsoleTranslated("bot.mailer.init.public" + Config.PublicInteractions); + LogDebugToConsoleTranslated("bot.mailer.init.max_mails" + Config.MaxMailsPerPlayer); + LogDebugToConsoleTranslated("bot.mailer.init.db_size" + Config.MaxDatabaseSize); + LogDebugToConsoleTranslated("bot.mailer.init.mail_retention" + Config.MailRetentionDays + " days"); - if (Settings.Mailer_MaxDatabaseSize <= 0) + if (!File.Exists(Config.DatabaseFile)) { - LogToConsoleTranslated("bot.mailer.init_fail.db_size"); - UnloadBot(); - return; + LogToConsoleTranslated("bot.mailer.create.db", Path.GetFullPath(Config.DatabaseFile)); + new MailDatabase().SaveToFile(Config.DatabaseFile); } - if (Settings.Mailer_MaxMailsPerPlayer <= 0) + if (!File.Exists(Config.IgnoreListFile)) { - LogToConsoleTranslated("bot.mailer.init_fail.max_mails"); - UnloadBot(); - return; - } - - if (Settings.Mailer_MailRetentionDays <= 0) - { - LogToConsoleTranslated("bot.mailer.init_fail.mail_retention"); - UnloadBot(); - return; - } - - if (!File.Exists(Settings.Mailer_DatabaseFile)) - { - LogToConsoleTranslated("bot.mailer.create.db", Path.GetFullPath(Settings.Mailer_DatabaseFile)); - new MailDatabase().SaveToFile(Settings.Mailer_DatabaseFile); - } - - if (!File.Exists(Settings.Mailer_IgnoreListFile)) - { - LogToConsoleTranslated("bot.mailer.create.ignore", Path.GetFullPath(Settings.Mailer_IgnoreListFile)); - new IgnoreList().SaveToFile(Settings.Mailer_IgnoreListFile); + LogToConsoleTranslated("bot.mailer.create.ignore", Path.GetFullPath(Config.IgnoreListFile)); + new IgnoreList().SaveToFile(Config.IgnoreListFile); } lock (readWriteLock) { - LogDebugToConsoleTranslated("bot.mailer.load.db", Path.GetFullPath(Settings.Mailer_DatabaseFile)); - mailDatabase = MailDatabase.FromFile(Settings.Mailer_DatabaseFile); + LogDebugToConsoleTranslated("bot.mailer.load.db", Path.GetFullPath(Config.DatabaseFile)); + mailDatabase = MailDatabase.FromFile(Config.DatabaseFile); - LogDebugToConsoleTranslated("bot.mailer.load.ignore", Path.GetFullPath(Settings.Mailer_IgnoreListFile)); - ignoreList = IgnoreList.FromFile(Settings.Mailer_IgnoreListFile); + LogDebugToConsoleTranslated("bot.mailer.load.ignore", Path.GetFullPath(Config.IgnoreListFile)); + ignoreList = IgnoreList.FromFile(Config.IgnoreListFile); } //Initialize file monitors. In case the bot needs to unload for some reason in the future, do not forget to .Dispose() them - mailDbFileMonitor = new FileMonitor(Path.GetDirectoryName(Settings.Mailer_DatabaseFile)!, Path.GetFileName(Settings.Mailer_DatabaseFile), FileMonitorCallback); - ignoreListFileMonitor = new FileMonitor(Path.GetDirectoryName(Settings.Mailer_IgnoreListFile)!, Path.GetFileName(Settings.Mailer_IgnoreListFile), FileMonitorCallback); + mailDbFileMonitor = new FileMonitor(Path.GetDirectoryName(Config.DatabaseFile)!, Path.GetFileName(Config.DatabaseFile), FileMonitorCallback); + ignoreListFileMonitor = new FileMonitor(Path.GetDirectoryName(Config.IgnoreListFile)!, Path.GetFileName(Config.IgnoreListFile), FileMonitorCallback); RegisterChatBotCommand("mailer", Translations.Get("bot.mailer.cmd"), "mailer ", ProcessInternalCommand); } @@ -224,7 +258,7 @@ namespace MinecraftClient.ChatBots { maxMessageLength = GetMaxChatMessageLength() - 44 // Deduct length of "/ 16CharPlayerName 16CharPlayerName mailed: " - - Settings.PrivateMsgsCmdName.Length; // Deduct length of "tell" command + - Settings.Config.Main.Advanced.PrivateMsgsCmdName.Length; // Deduct length of "tell" command } /// @@ -236,7 +270,7 @@ namespace MinecraftClient.ChatBots string username = ""; text = GetVerbatim(text); - if (IsPrivateMessage(text, ref message, ref username) || (Settings.Mailer_PublicInteractions && IsChatMessage(text, ref message, ref username))) + if (IsPrivateMessage(text, ref message, ref username) || (Config.PublicInteractions && IsChatMessage(text, ref message, ref username))) { string usernameLower = username.ToLower(); if (!ignoreList.Contains(usernameLower)) @@ -247,8 +281,8 @@ namespace MinecraftClient.ChatBots case "mail": case "tellonym": if (usernameLower != GetUsername().ToLower() - && mailDatabase.Count < Settings.Mailer_MaxDatabaseSize - && mailDatabase.Where(mail => mail.SenderLowercase == usernameLower).Count() < Settings.Mailer_MaxMailsPerPlayer) + && mailDatabase.Count < Config.MaxDatabaseSize + && mailDatabase.Where(mail => mail.SenderLowercase == usernameLower).Count() < Config.MaxMailsPerPlayer) { Queue args = new(Command.GetArgs(message)); if (args.Count >= 2) @@ -266,7 +300,7 @@ namespace MinecraftClient.ChatBots lock (readWriteLock) { mailDatabase.Add(mail); - mailDatabase.SaveToFile(Settings.Mailer_DatabaseFile); + mailDatabase.SaveToFile(Config.DatabaseFile); } SendPrivateMessage(username, "Message saved!"); } @@ -307,8 +341,8 @@ namespace MinecraftClient.ChatBots lock (readWriteLock) { mailDatabase.RemoveAll(mail => mail.Delivered); - mailDatabase.RemoveAll(mail => mail.DateSent.AddDays(Settings.Mailer_MailRetentionDays) < DateTime.Now); - mailDatabase.SaveToFile(Settings.Mailer_DatabaseFile); + mailDatabase.RemoveAll(mail => mail.DateSent.AddDays(Config.MailRetentionDays) < DateTime.Now); + mailDatabase.SaveToFile(Config.DatabaseFile); } nextMailSend = dateNow.AddSeconds(10); @@ -324,8 +358,8 @@ namespace MinecraftClient.ChatBots { lock (readWriteLock) { - mailDatabase = MailDatabase.FromFile(Settings.Mailer_DatabaseFile); - ignoreList = IgnoreList.FromFile(Settings.Mailer_IgnoreListFile); + mailDatabase = MailDatabase.FromFile(Config.DatabaseFile); + ignoreList = IgnoreList.FromFile(Config.IgnoreListFile); } } @@ -357,7 +391,7 @@ namespace MinecraftClient.ChatBots if (!ignoreList.Contains(username)) { ignoreList.Add(username); - ignoreList.SaveToFile(Settings.Mailer_IgnoreListFile); + ignoreList.SaveToFile(Config.IgnoreListFile); } } return Translations.Get("bot.mailer.cmd.ignore.added", args[1]); @@ -369,7 +403,7 @@ namespace MinecraftClient.ChatBots if (ignoreList.Contains(username)) { ignoreList.Remove(username); - ignoreList.SaveToFile(Settings.Mailer_IgnoreListFile); + ignoreList.SaveToFile(Config.IgnoreListFile); } } return Translations.Get("bot.mailer.cmd.ignore.removed", args[1]); diff --git a/MinecraftClient/ChatBots/Map.cs b/MinecraftClient/ChatBots/Map.cs index a03b3a72..83fc3dc1 100644 --- a/MinecraftClient/ChatBots/Map.cs +++ b/MinecraftClient/ChatBots/Map.cs @@ -5,41 +5,59 @@ using System.Globalization; using System.IO; using MinecraftClient.Mapping; using MinecraftClient.Protocol.Handlers; +using Tomlet.Attributes; namespace MinecraftClient.ChatBots { - class Map : ChatBot + public class Map : ChatBot { + public static Configs Config = new(); + + [TomlDoNotInlineObject] + public class Configs + { + [NonSerialized] + private const string BotName = "Map"; + + public bool Enabled = false; + + [TomlInlineComment("$config.ChatBot.Map.Should_Resize$")] + public bool Should_Resize = false; + + [TomlInlineComment("$config.ChatBot.Map.Resize_To$")] + public int Resize_To = 256; + + [TomlInlineComment("$config.ChatBot.Map.Auto_Render_On_Update$")] + public bool Auto_Render_On_Update = false; + + [TomlInlineComment("$config.ChatBot.Map.Delete_All_On_Unload$")] + public bool Delete_All_On_Unload = true; + + [TomlInlineComment("$config.ChatBot.Map.Notify_On_First_Update$")] + public bool Notify_On_First_Update = true; + + public void OnSettingUpdate() + { + if (Resize_To < 128) + Resize_To = 128; + } + } + private readonly string baseDirectory = @"Rendered_Maps"; private readonly Dictionary cachedMaps = new(); - private bool shouldResize = true; - private int resizeTo = 256; - private bool autoRenderOnUpdate = true; - private bool deleteAllOnExit = true; - private bool notifyOnFirstUpdate = true; public override void Initialize() { if (!Directory.Exists(baseDirectory)) Directory.CreateDirectory(baseDirectory); - shouldResize = Settings.Map_Should_Resize; - resizeTo = Settings.Map_Resize_To; - - if (resizeTo < 128) - resizeTo = 128; - - autoRenderOnUpdate = Settings.Map_Auto_Render_On_Update; - deleteAllOnExit = Settings.Map_Delete_All_On_Unload; - notifyOnFirstUpdate = Settings.Map_Notify_On_First_Update; - RegisterChatBotCommand("maps", "bot.map.cmd.desc", "maps list|render or maps l|r ", OnMapCommand); } public override void OnUnload() { - if (deleteAllOnExit) + if (Config.Delete_All_On_Unload) { DirectoryInfo di = new(baseDirectory); FileInfo[] files = di.GetFiles(); @@ -124,7 +142,7 @@ namespace MinecraftClient.ChatBots { cachedMaps.Add(mapid, map); - if (notifyOnFirstUpdate) + if (Config.Notify_On_First_Update) LogToConsoleTranslated("bot.map.received_map", map.MapId); } else @@ -133,7 +151,7 @@ namespace MinecraftClient.ChatBots cachedMaps.Add(mapid, map); } - if (autoRenderOnUpdate) + if (Config.Auto_Render_On_Update) GenerateMapImage(map); } @@ -165,8 +183,8 @@ namespace MinecraftClient.ChatBots // Resize, double the image - if (shouldResize) - image = ResizeBitmap(image, resizeTo, resizeTo); + if (Config.Should_Resize) + image = ResizeBitmap(image, Config.Resize_To, Config.Resize_To); image.Save(fileName); LogToConsole(Translations.TryGet("bot.map.rendered", map.MapId, fileName)); diff --git a/MinecraftClient/ChatBots/PlayerListLogger.cs b/MinecraftClient/ChatBots/PlayerListLogger.cs index b15d5f92..a8c6e333 100644 --- a/MinecraftClient/ChatBots/PlayerListLogger.cs +++ b/MinecraftClient/ChatBots/PlayerListLogger.cs @@ -1,6 +1,7 @@ using System; using System.Linq; using System.Text; +using Tomlet.Attributes; namespace MinecraftClient.ChatBots { @@ -10,28 +11,34 @@ namespace MinecraftClient.ChatBots public class PlayerListLogger : ChatBot { - private int count; - private readonly int timeping; - private readonly string file; + public static Configs Config = new(); - /// - /// This bot sends a /list command every X seconds and save the result. - /// - /// Time amount between each list ping (10 = 1s, 600 = 1 minute, etc.) - - public PlayerListLogger(int pingparam, string filetosavein) + [TomlDoNotInlineObject] + public class Configs { - count = 0; - file = filetosavein; - timeping = pingparam; - if (timeping < 10) { timeping = 10; } //To avoid flooding + [NonSerialized] + private const string BotName = "PlayerListLogger"; + public bool Enabled = false; + + public string File = "playerlog.txt"; + + [TomlInlineComment("$config.ChatBot.PlayerListLogger.Delay$")] + public int Delay = 600; + + public void OnSettingUpdate() + { + if (Delay < 10) + Delay = 10; + } } + private int count = 0; + public override void Update() { count++; - if (count == timeping) + if (count == Config.Delay) { DateTime now = DateTime.Now; @@ -40,7 +47,7 @@ namespace MinecraftClient.ChatBots StringBuilder sb = new(); sb.AppendLine(string.Format("[{0}/{1}/{2} {3}:{4}]", now.Year, now.Month, now.Day, now.Hour, now.Minute)); sb.AppendLine(string.Join(", ", GetOnlinePlayers())).AppendLine(); - System.IO.File.AppendAllText(file, sb.ToString()); + System.IO.File.AppendAllText(Settings.Config.AppVar.ExpandVars(Config.File), sb.ToString()); count = 0; } diff --git a/MinecraftClient/ChatBots/RemoteControl.cs b/MinecraftClient/ChatBots/RemoteControl.cs index 3baae1a1..ac1d544e 100644 --- a/MinecraftClient/ChatBots/RemoteControl.cs +++ b/MinecraftClient/ChatBots/RemoteControl.cs @@ -1,4 +1,5 @@ using System; +using Tomlet.Attributes; namespace MinecraftClient.ChatBots { @@ -8,11 +9,28 @@ namespace MinecraftClient.ChatBots public class RemoteControl : ChatBot { + public static Configs Config = new(); + + [TomlDoNotInlineObject] + public class Configs + { + [NonSerialized] + private const string BotName = "RemoteControl"; + + public bool Enabled = false; + + public bool AutoTpaccept = true; + + public bool AutoTpaccept_Everyone = false; + + public void OnSettingUpdate() { } + } + public override void GetText(string text) { text = GetVerbatim(text).Trim(); string command = "", sender = ""; - if (IsPrivateMessage(text, ref command, ref sender) && Settings.Bots_Owners.Contains(sender.ToLower().Trim())) + if (IsPrivateMessage(text, ref command, ref sender) && Settings.Config.Main.Advanced.BotOwners.Contains(sender.ToLower().Trim())) { string? response = ""; PerformInternalCommand(command, ref response); @@ -26,9 +44,9 @@ namespace MinecraftClient.ChatBots SendPrivateMessage(sender, response); } } - else if (Settings.RemoteCtrl_AutoTpaccept + else if (Config.AutoTpaccept && IsTeleportRequest(text, ref sender) - && (Settings.RemoteCtrl_AutoTpaccept_Everyone || Settings.Bots_Owners.Contains(sender.ToLower().Trim()))) + && (Config.AutoTpaccept_Everyone || Settings.Config.Main.Advanced.BotOwners.Contains(sender.ToLower().Trim()))) { SendText("/tpaccept"); } diff --git a/MinecraftClient/ChatBots/ReplayCapture.cs b/MinecraftClient/ChatBots/ReplayCapture.cs index 25ea1557..4232e8a0 100644 --- a/MinecraftClient/ChatBots/ReplayCapture.cs +++ b/MinecraftClient/ChatBots/ReplayCapture.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using MinecraftClient.Protocol; +using Tomlet.Attributes; namespace MinecraftClient.ChatBots { @@ -9,24 +10,35 @@ namespace MinecraftClient.ChatBots /// public class ReplayCapture : ChatBot { - private ReplayHandler? replay; - private readonly int backupInterval = 3000; // Unit: second * 10 - private int backupCounter = -1; + public static Configs Config = new(); - public ReplayCapture(int backupInterval) + [TomlDoNotInlineObject] + public class Configs { - if (backupInterval != -1) - this.backupInterval = backupInterval * 10; - else - this.backupInterval = -1; + [NonSerialized] + private const string BotName = "ReplayCapture"; + + public bool Enabled = false; + + [TomlInlineComment("$config.ChatBot.ReplayCapture.Backup_Interval$")] + public int Backup_Interval = 3000; + + public void OnSettingUpdate() + { + if (Backup_Interval < -1) + Backup_Interval = -1; + } } + private ReplayHandler? replay; + private int backupCounter = -1; + public override void Initialize() { SetNetworkPacketEventEnabled(true); replay = new ReplayHandler(GetProtocolVersion()); replay.MetaData.serverName = GetServerHost() + GetServerPort(); - backupCounter = backupInterval; + backupCounter = Config.Backup_Interval * 10; RegisterChatBotCommand("replay", Translations.Get("bot.replayCapture.cmd"), "replay ", Command); } @@ -38,12 +50,12 @@ namespace MinecraftClient.ChatBots public override void Update() { - if (backupInterval > 0 && replay!.RecordRunning) + if (Config.Backup_Interval > 0 && replay!.RecordRunning) { if (backupCounter <= 0) { replay.CreateBackupReplay(@"recording_cache\REPLAY_BACKUP.mcpr"); - backupCounter = backupInterval; + backupCounter = Config.Backup_Interval * 10; } else backupCounter--; } diff --git a/MinecraftClient/ChatBots/Script.cs b/MinecraftClient/ChatBots/Script.cs index 84ee6483..3fc1acaf 100644 --- a/MinecraftClient/ChatBots/Script.cs +++ b/MinecraftClient/ChatBots/Script.cs @@ -107,7 +107,7 @@ namespace MinecraftClient.ChatBots } } - if (Settings.DebugMessages) + if (Settings.Config.Logging.DebugMessages) { string caller = "Script"; try @@ -195,7 +195,7 @@ namespace MinecraftClient.ChatBots { if (instruction_line[0] != '#' && instruction_line[0] != '/' && instruction_line[1] != '/') { - instruction_line = Settings.ExpandVars(instruction_line, localVars); + instruction_line = Settings.Config.AppVar.ExpandVars(instruction_line, localVars); string instruction_name = instruction_line.Split(' ')[0]; switch (instruction_name.ToLower()) { diff --git a/MinecraftClient/ChatBots/ScriptScheduler.cs b/MinecraftClient/ChatBots/ScriptScheduler.cs index 8fe8af82..bd5296ad 100644 --- a/MinecraftClient/ChatBots/ScriptScheduler.cs +++ b/MinecraftClient/ChatBots/ScriptScheduler.cs @@ -1,7 +1,9 @@ using System; using System.Collections.Generic; using System.Globalization; +using System.IO; using System.Text; +using Tomlet.Attributes; namespace MinecraftClient.ChatBots { @@ -11,6 +13,32 @@ namespace MinecraftClient.ChatBots public class ScriptScheduler : ChatBot { + public static Configs Config = new(); + + [TomlDoNotInlineObject] + public class Configs + { + [NonSerialized] + private const string BotName = "ScriptScheduler"; + + public bool Enabled = false; + + public string Tasks_File = @"tasks.ini"; + + public void OnSettingUpdate() + { + if (!Enabled) return; + + string Tasks_File_Full = Settings.Config.AppVar.ExpandVars(Tasks_File); + if (!File.Exists(Tasks_File_Full)) + { + LogToConsole(BotName, Translations.TryGet("bot.scriptScheduler.not_found", Path.GetFullPath(Tasks_File_Full))); + LogToConsole(BotName, Translations.TryGet("general.bot_unload")); + Enabled = false; + } + } + } + private class TaskDesc { public string? action = null; @@ -27,26 +55,20 @@ namespace MinecraftClient.ChatBots private static bool firstlogin_done = false; - private readonly string tasksfile; - private bool serverlogin_done; + private bool serverlogin_done = false; private readonly List tasks = new(); private int verifytasks_timeleft = 10; private readonly int verifytasks_delay = 10; - public ScriptScheduler(string tasksfile) - { - this.tasksfile = tasksfile; - serverlogin_done = false; - } - public override void Initialize() { //Load the given file from the startup parameters - if (System.IO.File.Exists(tasksfile)) + string Tasks_File_Full = Settings.Config.AppVar.ExpandVars(Config.Tasks_File); + if (File.Exists(Tasks_File_Full)) { - LogDebugToConsoleTranslated("bot.scriptScheduler.loading", System.IO.Path.GetFullPath(tasksfile)); + LogDebugToConsoleTranslated("bot.scriptScheduler.loading", System.IO.Path.GetFullPath(Tasks_File_Full)); TaskDesc? current_task = null; - string[] lines = System.IO.File.ReadAllLines(tasksfile, Encoding.UTF8); + string[] lines = System.IO.File.ReadAllLines(Tasks_File_Full, Encoding.UTF8); foreach (string lineRAW in lines) { string line = lineRAW.Split('#')[0].Trim(); @@ -70,10 +92,10 @@ namespace MinecraftClient.ChatBots string argValue = line[(argName.Length + 1)..]; switch (argName.ToLower()) { - case "triggeronfirstlogin": current_task.triggerOnFirstLogin = Settings.str2bool(argValue); break; - case "triggeronlogin": current_task.triggerOnLogin = Settings.str2bool(argValue); break; - case "triggerontime": current_task.triggerOnTime = Settings.str2bool(argValue); break; - case "triggeroninterval": current_task.triggerOnInterval = Settings.str2bool(argValue); break; + case "triggeronfirstlogin": current_task.triggerOnFirstLogin = bool.Parse(argValue); break; + case "triggeronlogin": current_task.triggerOnLogin = bool.Parse(argValue); break; + case "triggerontime": current_task.triggerOnTime = bool.Parse(argValue); break; + case "triggeroninterval": current_task.triggerOnInterval = bool.Parse(argValue); break; case "timevalue": try { current_task.triggerOnTime_Times.Add(DateTime.ParseExact(argValue, "HH:mm", CultureInfo.InvariantCulture)); } catch { } break; case "timeinterval": int interval; @@ -112,7 +134,7 @@ namespace MinecraftClient.ChatBots } else { - LogToConsoleTranslated("bot.scriptScheduler.not_found", System.IO.Path.GetFullPath(tasksfile)); + LogToConsoleTranslated("bot.scriptScheduler.not_found", Path.GetFullPath(Tasks_File_Full)); UnloadBot(); //No need to keep the bot active } } diff --git a/MinecraftClient/Commands/Chunk.cs b/MinecraftClient/Commands/Chunk.cs index ee1b8c7b..5e793152 100644 --- a/MinecraftClient/Commands/Chunk.cs +++ b/MinecraftClient/Commands/Chunk.cs @@ -138,7 +138,7 @@ namespace MinecraftClient.Commands // \ud83d\udd33: 🔳, \ud83d\udfe8: 🟨, \ud83d\udfe9: 🟩, \u25A1: □, \u25A3: ▣, \u25A0: ■ - string[] chunkStatusStr = Settings.EnableEmoji ? + string[] chunkStatusStr = Settings.Config.Main.Advanced.EnableEmoji ? new string[] { "\ud83d\udd33", "\ud83d\udfe8", "\ud83d\udfe9" } : new string[] { "\u25A1", "\u25A3", "\u25A0" }; // Output diff --git a/MinecraftClient/Commands/Connect.cs b/MinecraftClient/Commands/Connect.cs index ca95c81a..12c94a3f 100644 --- a/MinecraftClient/Commands/Connect.cs +++ b/MinecraftClient/Commands/Connect.cs @@ -15,13 +15,13 @@ namespace MinecraftClient.Commands string[] args = GetArgs(command); if (args.Length > 1) { - if (!Settings.SetAccount(args[1])) + if (!Settings.Config.Main.Advanced.SetAccount(args[1])) { return Translations.Get("cmd.connect.unknown", args[1]); } } - if (Settings.SetServerIP(args[0])) + if (Settings.Config.Main.SetServerIP(new Settings.MainConfigHealper.MainConfig.ServerInfoConfig(args[0]), true)) { Program.Restart(); return ""; diff --git a/MinecraftClient/Commands/Debug.cs b/MinecraftClient/Commands/Debug.cs index c08404e0..c2bbda8a 100644 --- a/MinecraftClient/Commands/Debug.cs +++ b/MinecraftClient/Commands/Debug.cs @@ -11,11 +11,10 @@ namespace MinecraftClient.Commands public override string Run(McClient handler, string command, Dictionary? localVars) { if (HasArg(command)) - { - Settings.DebugMessages = (GetArg(command).ToLower() == "on"); - } - else Settings.DebugMessages = !Settings.DebugMessages; - return Translations.Get(Settings.DebugMessages ? "cmd.debug.state_on" : "cmd.debug.state_off"); + Settings.Config.Logging.DebugMessages = (GetArg(command).ToLower() == "on"); + else + Settings.Config.Logging.DebugMessages = !Settings.Config.Logging.DebugMessages; + return Translations.Get(Settings.Config.Logging.DebugMessages ? "cmd.debug.state_on" : "cmd.debug.state_off"); } } } diff --git a/MinecraftClient/Commands/ExecIf.cs b/MinecraftClient/Commands/ExecIf.cs index 474c1c50..06b8619f 100644 --- a/MinecraftClient/Commands/ExecIf.cs +++ b/MinecraftClient/Commands/ExecIf.cs @@ -36,7 +36,7 @@ namespace MinecraftClient.Commands var interpreter = new Interpreter(); interpreter.SetVariable("MCC", handler); - foreach (KeyValuePair entry in Settings.GetVariables()) + foreach (KeyValuePair entry in Settings.Config.AppVar.GetVariables()) interpreter.SetVariable(entry.Key, entry.Value); var result = interpreter.Eval(expressionText); diff --git a/MinecraftClient/Commands/Inventory.cs b/MinecraftClient/Commands/Inventory.cs index c01e9964..11c214bf 100644 --- a/MinecraftClient/Commands/Inventory.cs +++ b/MinecraftClient/Commands/Inventory.cs @@ -185,7 +185,7 @@ namespace MinecraftClient.Commands response.AppendLine(String.Format(" #{0} - {1}§8", inventoryId, inventory.Title)); string? asciiArt = inventory.Type.GetAsciiArt(); - if (asciiArt != null && Settings.DisplayInventoryLayout) + if (asciiArt != null && Settings.Config.Main.Advanced.ShowInventoryLayout) response.AppendLine(asciiArt); int selectedHotbar = handler.GetCurrentSlot() + 1; diff --git a/MinecraftClient/Commands/Move.cs b/MinecraftClient/Commands/Move.cs index 6bc6e1fb..bbebcded 100644 --- a/MinecraftClient/Commands/Move.cs +++ b/MinecraftClient/Commands/Move.cs @@ -45,8 +45,8 @@ namespace MinecraftClient.Commands else if (args[0] == "gravity") { if (args.Count >= 2) - Settings.GravityEnabled = (args[1] == "on"); - if (Settings.GravityEnabled) + Settings.InternalConfig.GravityEnabled = (args[1] == "on"); + if (Settings.InternalConfig.GravityEnabled) return Translations.Get("cmd.move.gravity.enabled"); else return Translations.Get("cmd.move.gravity.disabled"); } diff --git a/MinecraftClient/Commands/Reco.cs b/MinecraftClient/Commands/Reco.cs index 46beebbb..5b5b0e0f 100644 --- a/MinecraftClient/Commands/Reco.cs +++ b/MinecraftClient/Commands/Reco.cs @@ -13,7 +13,7 @@ namespace MinecraftClient.Commands string[] args = GetArgs(command); if (args.Length > 0) { - if (!Settings.SetAccount(args[0])) + if (!Settings.Config.Main.Advanced.SetAccount(args[0])) { return Translations.Get("cmd.connect.unknown", args[0]); } diff --git a/MinecraftClient/Commands/Set.cs b/MinecraftClient/Commands/Set.cs index 9f6ccd78..9f8cfe5d 100644 --- a/MinecraftClient/Commands/Set.cs +++ b/MinecraftClient/Commands/Set.cs @@ -15,15 +15,16 @@ namespace MinecraftClient.Commands string[] temp = GetArg(command).Split('='); if (temp.Length > 1) { - if (Settings.SetVar(temp[0], GetArg(command).Substring(temp[0].Length + 1))) - { + if (Settings.Config.AppVar.SetVar(temp[0], GetArg(command).Substring(temp[0].Length + 1))) return ""; //Success - } - else return Translations.Get("cmd.set.format"); + else + return Translations.Get("cmd.set.format"); } - else return GetCmdDescTranslated(); + else + return GetCmdDescTranslated(); } - else return GetCmdDescTranslated(); + else + return GetCmdDescTranslated(); } } } diff --git a/MinecraftClient/Commands/SetRnd.cs b/MinecraftClient/Commands/SetRnd.cs index 6ee7bfb8..6e0d00b2 100644 --- a/MinecraftClient/Commands/SetRnd.cs +++ b/MinecraftClient/Commands/SetRnd.cs @@ -40,9 +40,9 @@ namespace MinecraftClient.Commands (num2, num1) = (num1, num2); // create a variable or set it to num1 <= varlue < num2 - if (Settings.SetVar(args[0], rand.Next(num1, num2))) + if (Settings.Config.AppVar.SetVar(args[0], rand.Next(num1, num2))) { - return string.Format("Set %{0}% to {1}.", args[0], Settings.GetVar(args[0])); //Success + return string.Format("Set %{0}% to {1}.", args[0], Settings.Config.AppVar.GetVar(args[0])); //Success } else return Translations.Get("cmd.setrndnum.format"); } @@ -55,9 +55,9 @@ namespace MinecraftClient.Commands List values = ParseCommandLine(argString); // create a variable or set it to one of the values - if (values.Count > 0 && Settings.SetVar(args[0], values[rand.Next(0, values.Count)])) + if (values.Count > 0 && Settings.Config.AppVar.SetVar(args[0], values[rand.Next(0, values.Count)])) { - return string.Format("Set %{0}% to {1}.", args[0], Settings.GetVar(args[0])); //Success + return string.Format("Set %{0}% to {1}.", args[0], Settings.Config.AppVar.GetVar(args[0])); //Success } else return Translations.Get("cmd.setrndstr.format"); } diff --git a/MinecraftClient/DefaultConfigResource.Designer.cs b/MinecraftClient/DefaultConfigResource.Designer.cs index d3dfe630..6fa58c16 100644 --- a/MinecraftClient/DefaultConfigResource.Designer.cs +++ b/MinecraftClient/DefaultConfigResource.Designer.cs @@ -8,11 +8,10 @@ // //------------------------------------------------------------------------------ -namespace MinecraftClient -{ +namespace MinecraftClient { using System; - - + + /// /// A strongly-typed resource class, for looking up localized strings, etc. /// @@ -20,55 +19,47 @@ namespace MinecraftClient // class via a tool like ResGen or Visual Studio. // To add or remove a member, edit your .ResX file then rerun ResGen // with the /str option, or rebuild your VS project. - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")] [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - public class DefaultConfigResource - { - + public class DefaultConfigResource { + private static global::System.Resources.ResourceManager resourceMan; - + private static global::System.Globalization.CultureInfo resourceCulture; - + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - internal DefaultConfigResource() - { + internal DefaultConfigResource() { } - + /// /// Returns the cached ResourceManager instance used by this class. /// [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] - public static global::System.Resources.ResourceManager ResourceManager - { - get - { - if (object.ReferenceEquals(resourceMan, null)) - { + public static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("MinecraftClient.DefaultConfigResource", typeof(DefaultConfigResource).Assembly); resourceMan = temp; } return resourceMan; } } - + /// /// Overrides the current thread's CurrentUICulture property for all /// resource lookups using this strongly typed resource class. /// [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] - public static global::System.Globalization.CultureInfo Culture - { - get - { + public static global::System.Globalization.CultureInfo Culture { + get { return resourceCulture; } - set - { + set { resourceCulture = value; } } - + /// /// Looks up a localized string similar to ╔═════════════════════════════════════╗ ///║ Brewing Stand ║ @@ -82,16 +73,14 @@ namespace MinecraftClient ///║ Inventory ╚═══╝ ║ ///║╔═══╦═══╦═══╦═══╦═══╦═══╦═══╦═══╦═══╗║ ///║║ 5 ║ 6 ║ 7 ║ 8 ║ 9 ║10 ║11 ║12 ║13 ║║ - ///║╠═══╬═══╬═══╬═══╬═══╬═══╬═══╬══ [rest of string was truncated]";. + ///║╠═══╬═══╬═══╬═══╬══ [rest of string was truncated]";. /// - public static string ContainerType_BrewingStand - { - get - { + public static string ContainerType_BrewingStand { + get { return ResourceManager.GetString("ContainerType_BrewingStand", resourceCulture); } } - + /// /// Looks up a localized string similar to ╔═════════════════════════════════════╗ ///║ Crafting ║ @@ -105,24 +94,35 @@ namespace MinecraftClient ///║ Inventory ║ ///║╔═══╦═══╦═══╦═══╦═══╦═══╦═══╦═══╦═══╗║ ///║║10 ║11 ║12 ║13 ║14 ║15 ║16 ║17 ║18 ║║ - ///║╠═══╬═══╬═══╬═══╬═══╬═══╬═══╬══ [rest of string was truncated]";. + ///║╠═══╬═══╬═══╬═══╬══ [rest of string was truncated]";. /// - public static string ContainerType_Crafting - { - get - { + public static string ContainerType_Crafting { + get { return ResourceManager.GetString("ContainerType_Crafting", resourceCulture); } } - - public static string ContainerType_Furnace - { - get - { + + /// + /// Looks up a localized string similar to ╔═════════════════════════════════════╗ + ///║ Container ║ + ///║ ╔═══╗ ║ + ///║ ║ 0 ║ ║ + ///║ ╚═══╝ ╔═══╗ ║ + ///║ ⠂⡠⢂ ━━▶ ║ 2 ║ ║ + ///║ ⠂⡠⢂ ╚═══╝ ║ + ///║ ╔═══╗ ║ + ///║ ║ 1 ║ ║ + ///║ ╚═══╝ ║ + ///║ Inventory ║ + ///║╔═══╦═══╦═══╦═══╦═══╦═══╦═══╦═══╦═══╗║ + ///║║ 3 ║ 4 ║ 5 ║ 6 ║ 7 [rest of string was truncated]";. + /// + public static string ContainerType_Furnace { + get { return ResourceManager.GetString("ContainerType_Furnace", resourceCulture); } } - + /// /// Looks up a localized string similar to ╔═════════════════════════════════════╗ ///║ Container ║ @@ -136,19 +136,17 @@ namespace MinecraftClient ///║ Inventory ║ ///║╔═══╦═══╦═══╦═══╦═══╦═══╦═══╦═══╦═══╗║ ///║║ 9 ║10 ║11 ║12 ║13 ║14 ║15 ║16 ║17 ║║ - ///║╠═══╬═══╬═══╬═══╬═══╬═══╬═══╬══ [rest of string was truncated]";. + ///║╠═══╬═══╬═══╬═══╬══ [rest of string was truncated]";. /// - public static string ContainerType_Generic_3x3 - { - get - { + public static string ContainerType_Generic_3x3 { + get { return ResourceManager.GetString("ContainerType_Generic_3x3", resourceCulture); } } - + /// /// Looks up a localized string similar to ╔═════════════════════════════════════╗ - ///║ Chest ║ + ///║ Container ║ ///║╔═══╦═══╦═══╦═══╦═══╦═══╦═══╦═══╦═══╗║ ///║║ 0 ║ 1 ║ 2 ║ 3 ║ 4 ║ 5 ║ 6 ║ 7 ║ 8 ║║ ///║╠═══╬═══╬═══╬═══╬═══╬═══╬═══╬═══╬═══╣║ @@ -159,19 +157,17 @@ namespace MinecraftClient ///║ Inventory ║ ///║╔═══╦═══╦═══╦═══╦═══╦═══╦═══╦═══╦═══╗║ ///║║27 ║28 ║29 ║30 ║31 ║32 ║33 ║34 ║35 ║║ - ///║╠═══╬═══╬═══╬═══╬═══╬═══╬═══╬══ [rest of string was truncated]";. + ///║╠═══╬═══╬═══╬═══╬══ [rest of string was truncated]";. /// - public static string ContainerType_Generic_9x3 - { - get - { + public static string ContainerType_Generic_9x3 { + get { return ResourceManager.GetString("ContainerType_Generic_9x3", resourceCulture); } } - + /// /// Looks up a localized string similar to ╔═════════════════════════════════════╗ - ///║ Large Container ║ + ///║ Container ║ ///║╔═══╦═══╦═══╦═══╦═══╦═══╦═══╦═══╦═══╗║ ///║║ 0 ║ 1 ║ 2 ║ 3 ║ 4 ║ 5 ║ 6 ║ 7 ║ 8 ║║ ///║╠═══╬═══╬═══╬═══╬═══╬═══╬═══╬═══╬═══╣║ @@ -182,32 +178,56 @@ namespace MinecraftClient ///║║27 ║28 ║29 ║30 ║31 ║32 ║33 ║34 ║35 ║║ ///║╠═══╬═══╬═══╬═══╬═══╬═══╬═══╬═══╬═══╣║ ///║║36 ║37 ║38 ║39 ║40 ║41 ║42 ║43 ║44 ║║ - ///║╠═══╬═══╬═══╬═══╬═══╬═══╬═══╬══ [rest of string was truncated]";. + ///║╠═══╬═══╬═══╬═══╬══ [rest of string was truncated]";. /// - public static string ContainerType_Generic_9x6 - { - get - { + public static string ContainerType_Generic_9x6 { + get { return ResourceManager.GetString("ContainerType_Generic_9x6", resourceCulture); } } - - public static string ContainerType_Grindstone - { - get - { + + /// + /// Looks up a localized string similar to ╔═════════════════════════════════════╗ + ///║ Repair & Disenchant ║ + ///║ ╔═════════╗ ║ + ///║ ║ ╔═══╗ ║ ║ + ///║ ╔══║ ║ 0 ║ ║══╗ ║ + ///║ ║ ║ ╚═══╝ ║ ║ ║ + ///║ ║ ║ ╔═══╗ ║ ║ ╔═══╗ ║ + ///║ ║ ║ ║ 1 ║ ║ ║ ━━▶ ║ 2 ║ ║ + ///║ ║ ║ ╚═══╝ ║ ║ ╚═══╝ ║ + ///║ ║ ╠═════════╣ ║ ║ + ///║ ║ ║ ║ ║ ║ + ///║ ╚══╝ ╚══╝ ║ + ///║ [rest of string was truncated]";. + /// + public static string ContainerType_Grindstone { + get { return ResourceManager.GetString("ContainerType_Grindstone", resourceCulture); } } - - public static string ContainerType_Hopper - { - get - { + + /// + /// Looks up a localized string similar to ╔═════════════════════════════════════╗ + ///║ Container ║ + ///║ ╔═══╦═══╦═══╦═══╦═══╗ ║ + ///║ ║ 0 ║ 1 ║ 2 ║ 3 ║ 4 ║ ║ + ///║ ╚═══╩═══╩═══╩═══╩═══╝ ║ + ///║ Inventory ║ + ///║╔═══╦═══╦═══╦═══╦═══╦═══╦═══╦═══╦═══╗║ + ///║║ 5 ║ 6 ║ 7 ║ 8 ║ 9 ║10 ║11 ║12 ║13 ║║ + ///║╠═══╬═══╬═══╬═══╬═══╬═══╬═══╬═══╬═══╣║ + ///║║14 ║15 ║16 ║17 ║18 ║19 ║20 ║21 ║22 ║║ + ///║╠═══╬═══╬═══╬═══╬═══╬═══╬═══╬═══╬═══╣║ + ///║║23 ║24 ║25 ║26 ║27 ║28 ║29 ║30 ║31 ║║ + ///║╚═══╩═══╩═══╩═══╩══ [rest of string was truncated]";. + /// + public static string ContainerType_Hopper { + get { return ResourceManager.GetString("ContainerType_Hopper", resourceCulture); } } - + /// /// Looks up a localized string similar to ╔═════════════════════════════════════╗ ///║╔═══╦═══════════╗ ║ @@ -221,66 +241,156 @@ namespace MinecraftClient ///║╚═══╩═══════════╩═══╝ ║ ///║╔═══╦═══╦═══╦═══╦═══╦═══╦═══╦═══╦═══╗║ ///║║ 9 ║10 ║11 ║12 ║13 ║14 ║15 ║16 ║17 ║║ - ///║╠═══╬═══╬═══╬═══╬═══╬═══╬═══╬══ [rest of string was truncated]";. + ///║╠═══╬═══╬═══╬═══╬══ [rest of string was truncated]";. /// - public static string ContainerType_PlayerInventory - { - get - { + public static string ContainerType_PlayerInventory { + get { return ResourceManager.GetString("ContainerType_PlayerInventory", resourceCulture); } } - + /// /// Looks up a localized string similar to # Startup Config File /// - ///[Main] + ///# New to Minecraft Console Client? See README and sample configuration files here: + ///# https://github.com/MCCTeam/Minecraft-Console-Client/tree/master/MinecraftClient/config /// + ///# Want to upgrade to a newer version? See https://github.com/MCCTeam/Minecraft-Console-Client/#download + ///# Some settings missing here after an upgrade? Try to delete this file and relaunch MCC to generate a new one + /// + ///[Main] ///# General settings ///# Leave blank to prompt user on startup - ///# Use "-" as password for offline mode - /// - ///login= - ///password= - ///serverip= - ///type=mojang # Account type. mojang or microsoft - ///method=mcc # Microsoft Account sign-in method. mcc OR browser - /// - ///# Advanced settings - /// - ///language=en_GB - ///consoletitle=%username%@%serverip% - Minecraft Console Client - ///internalcmdchar=slash # Use 'none', 'slash' or 'backslash' - ///messagec [rest of string was truncated]";. + ///# Use "-" as password fo [rest of string was truncated]";. /// - public static string MinecraftClient - { - get - { + public static string MinecraftClient { + get { return ResourceManager.GetString("MinecraftClient", resourceCulture); } } - + /// /// Looks up a localized string similar to [mcc] ///# Messages from MCC itself ///mcc.login=Login : + ///mcc.login_basic_io=Bitte gib einen Nutzernamen oder eine E-Mail deiner Wahl ein. + ///mcc.password=Passwort : + ///mcc.password_basic_io=Bitte gib das Passwort für {0} ein. + ///mcc.password_hidden=Passwort : {0} + ///mcc.offline=§8Das Programm läuft im Offline-Modus. + ///mcc.session_invalid=§8Gespeicherte Session ungültig oder abgelaufen. + ///mcc.session_valid=§8Gespeicherte Session gültig für {0}. + ///mcc.connecting=Verbinde zu {0}... + ///mcc.ip=Server-IP : + ///mcc.use_version=§8B [rest of string was truncated]";. + /// + public static string Translation_de { + get { + return ResourceManager.GetString("Translation_de", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to [mcc] + ///# Messages from MCC itself + ///mcc.help_us_translate=Help us translate MCC: https://mccteam.github.io/guide/translation.html + ///mcc.run_with_default_settings=\nMCC is running with default settings. + ///mcc.settings_generated=§cSettings file MinecraftClient.ini has been generated. + ///mcc.login=Login : ///mcc.login_basic_io=Please type the username or email of your choice. ///mcc.password=Password : ///mcc.password_basic_io=Please type the password for {0}. ///mcc.password_hidden=Password : {0} - ///mcc.offline=§8You chose to run in offline mode. - ///mcc.session_invalid=§8Cached session is invalid or expired. - ///mcc.session_valid=§8Cached session is still valid for {0}. - ///mcc.connecting=Connecting to {0}... - ///mcc.ip=Server IP : - ///mcc.use_version=§8Using Minecraft version [rest of string was truncated]";. + ///mcc.offline=§8You chose [rest of string was truncated]";. /// - public static string TranslationEnglish - { - get - { - return ResourceManager.GetString("TranslationEnglish", resourceCulture); + public static string Translation_en { + get { + return ResourceManager.GetString("Translation_en", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to [mcc] + ///# Messages from MCC itself + ///mcc.login=Connexion : + ///mcc.login_basic_io=Veuillez saisir un nom d'utilisateur ou une adresse email. + ///mcc.password=Mot de passe : + ///mcc.password_basic_io=Saisissez le mot de passe pour {0}. + ///mcc.password_hidden=Mot de passe : {0} + ///mcc.offline=§8Vous avez choisi d'utiliser le mode hors ligne. + ///mcc.session_invalid=§8Le cache de la session est invalide ou a expiré. + ///mcc.session_valid=§8Le cache de la session est encore valable pendant {0}. + ///mcc.connecting=Connexion à {0}... + /// [rest of string was truncated]";. + /// + public static string Translation_fr { + get { + return ResourceManager.GetString("Translation_fr", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to [mcc] + ///# Messages from MCC itself + ///mcc.login=Логин : + ///mcc.login_basic_io=Пожалуйста, введите имя пользователя или email по вашему выбору. + ///mcc.password=Пароль: + ///mcc.password_basic_io=Пожалуйста, введите пароль для {0}. + ///mcc.password_hidden=Пароль: {0} + ///mcc.offline=§8Вы выбрали запуск в автономном режиме. + ///mcc.session_invalid=§8Кэшированная сессия недействительна или истекла. + ///mcc.session_valid=§8Кэшированная сессия все еще действительна для {0}. + ///mcc.connecting=Подключение к {0}... + ///mcc.ip=IP сервера: + ///mc [rest of string was truncated]";. + /// + public static string Translation_ru { + get { + return ResourceManager.GetString("Translation_ru", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to [mcc] + ///# Messages from MCC itself + ///mcc.login=Đăng nhập: + ///mcc.login_basic_io=Hãy nhập địa chỉ email hoặc tên tài khoản của bạn: + ///mcc.password=Mật khẩu: + ///mcc.password_basic_io=Hãy nhập mật khẩu cho {0}. + ///mcc.password_hidden=Password : {0} + ///mcc.offline=§8Bạn chọn sử dụng chế độ ngoại tuyến. + ///mcc.session_invalid=§8Phiên không hợp lệ hoặc đã hết hạn. + ///mcc.session_valid=§8Phiên vẫn còn hợp lệ cho {0}. + ///mcc.connecting=Đang kết nối tới {0}... + ///mcc.ip=Địa chỉ máy chủ: + ///mcc.use_version=§8Sử dụng Minecraft phiên bản [rest of string was truncated]";. + /// + public static string Translation_vi { + get { + return ResourceManager.GetString("Translation_vi", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to [mcc] + ///# Messages from MCC itself + ///mcc.help_us_translate=帮助我们翻译MCC:https://mccteam.github.io/guide/translation.html + ///mcc.run_with_default_settings=\nMCC正在使用默认配置运行。 + ///mcc.settings_generated=§c配置文件 MinecraftClient.ini 已经生成。 + ///mcc.login=登录: + ///mcc.login_basic_io=请输入用户名或邮箱。 + ///mcc.password=密码: + ///mcc.password_basic_io=请输入{0}的密码。 + ///mcc.password_hidden=密码:{0} + ///mcc.offline=§8您正在使用离线模式。 + ///mcc.session_invalid=§8缓存无效或已过期。 + ///mcc.session_valid=§8{0}的缓存仍然有效。 + ///mcc.profile_key_invalid=§8缓存的聊天签名密钥需要刷新。 + ///mcc.profile_key_valid=§8{0}的聊天 [rest of string was truncated]";. + /// + public static string Translation_zh_Hans { + get { + return ResourceManager.GetString("Translation_zh_Hans", resourceCulture); } } } diff --git a/MinecraftClient/DefaultConfigResource.resx b/MinecraftClient/DefaultConfigResource.resx index ed1a6338..0c6c67bd 100644 --- a/MinecraftClient/DefaultConfigResource.resx +++ b/MinecraftClient/DefaultConfigResource.resx @@ -148,7 +148,22 @@ Resources\config\MinecraftClient.ini;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8 - + + resources\lang\de.ini;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8 + + Resources\lang\en.ini;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8 + + resources\lang\fr.ini;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8 + + + resources\lang\ru.ini;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8 + + + resources\lang\vi.ini;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8 + + + resources\lang\zh-hans.ini;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8 + \ No newline at end of file diff --git a/MinecraftClient/FileMonitor.cs b/MinecraftClient/FileMonitor.cs index 378bb6b6..05c83208 100644 --- a/MinecraftClient/FileMonitor.cs +++ b/MinecraftClient/FileMonitor.cs @@ -22,7 +22,7 @@ namespace MinecraftClient /// Callback for file changes public FileMonitor(string folder, string filename, FileSystemEventHandler handler) { - if (Settings.DebugMessages) + if (Settings.Config.Logging.DebugMessages) { string callerClass = new System.Diagnostics.StackFrame(1).GetMethod()!.DeclaringType!.Name; ConsoleIO.WriteLineFormatted(Translations.Get("filemonitor.init", callerClass, Path.Combine(folder, filename))); @@ -40,7 +40,7 @@ namespace MinecraftClient } catch { - if (Settings.DebugMessages) + if (Settings.Config.Logging.DebugMessages) { string callerClass = new System.Diagnostics.StackFrame(1).GetMethod()!.DeclaringType!.Name; ConsoleIO.WriteLineFormatted(Translations.Get("filemonitor.fail", callerClass)); diff --git a/MinecraftClient/Logger/FileLogLogger.cs b/MinecraftClient/Logger/FileLogLogger.cs index f065ed83..8418ec6c 100644 --- a/MinecraftClient/Logger/FileLogLogger.cs +++ b/MinecraftClient/Logger/FileLogLogger.cs @@ -26,7 +26,7 @@ namespace MinecraftClient.Logger { try { - if (!Settings.SaveColorCodes) + if (!Settings.Config.Logging.SaveColorCodes) msg = ChatBot.GetVerbatim(msg); if (prependTimestamp) msg = GetTimestamp() + ' ' + msg; diff --git a/MinecraftClient/Logger/FilteredLogger.cs b/MinecraftClient/Logger/FilteredLogger.cs index d3878f89..5ad42efc 100644 --- a/MinecraftClient/Logger/FilteredLogger.cs +++ b/MinecraftClient/Logger/FilteredLogger.cs @@ -1,4 +1,5 @@ using System.Text.RegularExpressions; +using static MinecraftClient.Settings; namespace MinecraftClient.Logger { @@ -10,11 +11,23 @@ namespace MinecraftClient.Logger { Regex? regexToUse = null; // Convert to bool for XOR later. Whitelist = 0, Blacklist = 1 - bool filterMode = Settings.FilterMode == Settings.FilterModeEnum.Blacklist; + bool filterMode = Config.Logging.FilterMode == LoggingConfigHealper.LoggingConfig.FilterModeEnum.blacklist; switch (channel) { - case FilterChannel.Chat: regexToUse = Settings.ChatFilter; break; - case FilterChannel.Debug: regexToUse = Settings.DebugFilter; break; + case FilterChannel.Chat: + string chat = Config.Logging.ChatFilterRegex; + if (string.IsNullOrEmpty(chat)) + regexToUse = null; + else + regexToUse = new(chat); + break; + case FilterChannel.Debug: + string debug = Config.Logging.DebugFilterRegex; + if (string.IsNullOrEmpty(debug)) + regexToUse = null; + else + regexToUse = new(debug); + break; } if (regexToUse != null) { diff --git a/MinecraftClient/Mapping/Movement.cs b/MinecraftClient/Mapping/Movement.cs index 04cecd0e..28de9e7c 100644 --- a/MinecraftClient/Mapping/Movement.cs +++ b/MinecraftClient/Mapping/Movement.cs @@ -21,7 +21,7 @@ namespace MinecraftClient.Mapping /// Updated location after applying gravity public static Location HandleGravity(World world, Location location, ref double motionY) { - if (Settings.GravityEnabled) + if (Settings.InternalConfig.GravityEnabled) { Location onFoots = new(location.X, Math.Floor(location.Y), location.Z); Location belowFoots = Move(location, Direction.Down); diff --git a/MinecraftClient/McClient.cs b/MinecraftClient/McClient.cs index dc5265c5..f0b0b276 100644 --- a/MinecraftClient/McClient.cs +++ b/MinecraftClient/McClient.cs @@ -14,6 +14,7 @@ using MinecraftClient.Protocol.Keys; using MinecraftClient.Protocol.Message; using MinecraftClient.Protocol.Session; using MinecraftClient.Proxy; +using static MinecraftClient.Settings; namespace MinecraftClient { @@ -142,12 +143,11 @@ namespace MinecraftClient /// The server port to use /// Minecraft protocol version to use /// ForgeInfo item stating that Forge is enabled - /// The text or command to send. Will only be sent if singlecommand is set to true. - public McClient(SessionToken session, PlayerKeyPair? playerKeyPair, string server_ip, ushort port, int protocolversion, ForgeInfo? forgeInfo, string? command) + public McClient(SessionToken session, PlayerKeyPair? playerKeyPair, string server_ip, ushort port, int protocolversion, ForgeInfo? forgeInfo) { - terrainAndMovementsEnabled = Settings.TerrainAndMovements; - inventoryHandlingEnabled = Settings.InventoryHandling; - entityHandlingEnabled = Settings.EntityHandling; + terrainAndMovementsEnabled = Config.Main.Advanced.TerrainAndMovements; + inventoryHandlingEnabled = Config.Main.Advanced.InventoryHandling; + entityHandlingEnabled = Config.Main.Advanced.EntityHandling; sessionid = session.ID; if (!Guid.TryParse(session.PlayerID, out uuid)) @@ -159,64 +159,47 @@ namespace MinecraftClient this.protocolversion = protocolversion; this.playerKeyPair = playerKeyPair; - Log = Settings.LogToFile - ? new FileLogLogger(Settings.ExpandVars(Settings.LogFile), Settings.PrependTimestamp) + Log = Settings.Config.Logging.LogToFile + ? new FileLogLogger(Config.AppVar.ExpandVars(Settings.Config.Logging.LogFile), Settings.Config.Logging.PrependTimestamp) : new FilteredLogger(); - Log.DebugEnabled = Settings.DebugMessages; - Log.InfoEnabled = Settings.InfoMessages; - Log.ChatEnabled = Settings.ChatMessages; - Log.WarnEnabled = Settings.WarningMessages; - Log.ErrorEnabled = Settings.ErrorMessages; + Log.DebugEnabled = Config.Logging.DebugMessages; + Log.InfoEnabled = Config.Logging.InfoMessages; + Log.ChatEnabled = Config.Logging.ChatMessages; + Log.WarnEnabled = Config.Logging.WarningMessages; + Log.ErrorEnabled = Config.Logging.ErrorMessages; - if (command == null) - { - /* Load commands from Commands namespace */ - LoadCommands(); + /* Load commands from Commands namespace */ + LoadCommands(); - if (botsOnHold.Count == 0) - RegisterBots(); - } + if (botsOnHold.Count == 0) + RegisterBots(); try { client = ProxyHandler.NewTcpClient(host, port); client.ReceiveBufferSize = 1024 * 1024; - client.ReceiveTimeout = Settings.Timeout * 1000; // Default: 30 seconds + client.ReceiveTimeout = Config.Main.Advanced.TcpTimeout * 1000; // Default: 30 seconds handler = Protocol.ProtocolHandler.GetProtocolHandler(client, protocolversion, forgeInfo, this); Log.Info(Translations.Get("mcc.version_supported")); - if (command == null) - { - timeoutdetector = new(new Thread(new ParameterizedThreadStart(TimeoutDetector)), new CancellationTokenSource()); - timeoutdetector.Item1.Name = "MCC Connection timeout detector"; - timeoutdetector.Item1.Start(timeoutdetector.Item2.Token); - } + timeoutdetector = new(new Thread(new ParameterizedThreadStart(TimeoutDetector)), new CancellationTokenSource()); + timeoutdetector.Item1.Name = "MCC Connection timeout detector"; + timeoutdetector.Item1.Start(timeoutdetector.Item2.Token); try { if (handler.Login(this.playerKeyPair, session)) { - if (command != null) - { - handler.SendChatMessage(command, playerKeyPair); - Log.Info(Translations.Get("mcc.single_cmd", command)); - Thread.Sleep(5000); - handler.Disconnect(); - Thread.Sleep(1000); - } - else - { - foreach (ChatBot bot in botsOnHold) - BotLoad(bot, false); - botsOnHold.Clear(); + foreach (ChatBot bot in botsOnHold) + BotLoad(bot, false); + botsOnHold.Clear(); - Log.Info(Translations.Get("mcc.joined", (Settings.internalCmdChar == ' ' ? "" : "" + Settings.internalCmdChar))); + Log.Info(Translations.Get("mcc.joined", Config.Main.Advanced.InternalCmdChar.ToLogString())); - cmdprompt = new CancellationTokenSource(); - ConsoleInteractive.ConsoleReader.BeginReadThread(cmdprompt); - ConsoleInteractive.ConsoleReader.MessageReceived += ConsoleReaderOnMessageReceived; - ConsoleInteractive.ConsoleReader.OnKeyInput += ConsoleIO.AutocompleteHandler; - } + cmdprompt = new CancellationTokenSource(); + ConsoleInteractive.ConsoleReader.BeginReadThread(cmdprompt); + ConsoleInteractive.ConsoleReader.MessageReceived += ConsoleReaderOnMessageReceived; + ConsoleInteractive.ConsoleReader.OnKeyInput += ConsoleIO.AutocompleteHandler; } else { @@ -253,7 +236,7 @@ namespace MinecraftClient ReconnectionAttemptsLeft--; Program.Restart(); } - else if (command == null && Settings.interactiveMode) + else if (InternalConfig.InteractiveMode) { ConsoleInteractive.ConsoleReader.StopReadThread(); ConsoleInteractive.ConsoleReader.MessageReceived -= ConsoleReaderOnMessageReceived; @@ -269,24 +252,24 @@ namespace MinecraftClient /// private void RegisterBots(bool reload = false) { - if (Settings.AntiAFK_Enabled) { BotLoad(new AntiAFK(Settings.AntiAFK_Delay, Settings.AntiAFK_UseTerrain_Handling, Settings.AntiAFK_Walk_Range, Settings.AntiAFK_Walk_Retries)); } - if (Settings.Hangman_Enabled) { BotLoad(new HangmanGame(Settings.Hangman_English)); } - if (Settings.Alerts_Enabled) { BotLoad(new Alerts()); } - if (Settings.ChatLog_Enabled) { BotLoad(new ChatLog(Settings.ExpandVars(Settings.ChatLog_File), Settings.ChatLog_Filter, Settings.ChatLog_DateTime)); } - if (Settings.PlayerLog_Enabled) { BotLoad(new PlayerListLogger(Settings.PlayerLog_Delay, Settings.ExpandVars(Settings.PlayerLog_File))); } - if (Settings.AutoRelog_Enabled) { BotLoad(new AutoRelog(Settings.AutoRelog_Delay_Min, Settings.AutoRelog_Delay_Max, Settings.AutoRelog_Retries)); } - if (Settings.ScriptScheduler_Enabled) { BotLoad(new ScriptScheduler(Settings.ExpandVars(Settings.ScriptScheduler_TasksFile))); } - if (Settings.RemoteCtrl_Enabled) { BotLoad(new RemoteControl()); } - if (Settings.AutoRespond_Enabled) { BotLoad(new AutoRespond(Settings.AutoRespond_Matches, Settings.AutoRespond_MatchColors)); } - if (Settings.AutoAttack_Enabled) { BotLoad(new AutoAttack(Settings.AutoAttack_Mode, Settings.AutoAttack_Priority, Settings.AutoAttack_OverrideAttackSpeed, Settings.AutoAttack_CooldownSeconds, Settings.AutoAttack_Interaction)); } - if (Settings.AutoFishing_Enabled) { BotLoad(new AutoFishing()); } - if (Settings.AutoEat_Enabled) { BotLoad(new AutoEat(Settings.AutoEat_hungerThreshold)); } - if (Settings.Mailer_Enabled) { BotLoad(new Mailer()); } - if (Settings.AutoCraft_Enabled) { BotLoad(new AutoCraft(Settings.AutoCraft_configFile)); } - if (Settings.AutoDrop_Enabled) { BotLoad(new AutoDrop(Settings.AutoDrop_Mode, Settings.AutoDrop_items)); } - if (Settings.ReplayMod_Enabled && reload) { BotLoad(new ReplayCapture(Settings.ReplayMod_BackupInterval)); } - if (Settings.FollowPlayer_Enabled) { BotLoad(new FollowPlayer(Settings.FollowPlayer_UpdateLimit, Settings.FollowPlayer_UpdateLimit)); } - if (Settings.Map_Enabled) { BotLoad(new Map()); } + if (Config.ChatBot.AntiAFK.Enabled) { BotLoad(new AntiAFK()); } + if (Config.ChatBot.HangmanGame.Enabled) { BotLoad(new HangmanGame()); } + if (Config.ChatBot.Alerts.Enabled) { BotLoad(new Alerts()); } + if (Config.ChatBot.ChatLog.Enabled) { BotLoad(new ChatLog()); } + if (Config.ChatBot.PlayerListLogger.Enabled) { BotLoad(new PlayerListLogger()); } + if (Config.ChatBot.AutoRelog.Enabled) { BotLoad(new AutoRelog()); } + if (Config.ChatBot.ScriptScheduler.Enabled) { BotLoad(new ScriptScheduler()); } + if (Config.ChatBot.RemoteControl.Enabled) { BotLoad(new RemoteControl()); } + if (Config.ChatBot.AutoRespond.Enabled) { BotLoad(new AutoRespond()); } + if (Config.ChatBot.AutoAttack.Enabled) { BotLoad(new AutoAttack()); } + if (Config.ChatBot.AutoFishing.Enabled) { BotLoad(new AutoFishing()); } + if (Config.ChatBot.AutoEat.Enabled) { BotLoad(new AutoEat()); } + if (Config.ChatBot.Mailer.Enabled) { BotLoad(new Mailer()); } + if (Config.ChatBot.AutoCraft.Enabled) { BotLoad(new AutoCraft()); } + if (Config.ChatBot.AutoDrop.Enabled) { BotLoad(new AutoDrop()); } + if (Config.ChatBot.ReplayCapture.Enabled && reload) { BotLoad(new ReplayCapture()); } + if (Config.ChatBot.FollowPlayer.Enabled) { BotLoad(new FollowPlayer()); } + if (Config.ChatBot.Map.Enabled) { BotLoad(new Map()); } //Add your ChatBot here by uncommenting and adapting //BotLoad(new ChatBots.YourBot()); @@ -302,7 +285,7 @@ namespace MinecraftClient { string text = chatQueue.Dequeue(); handler.SendChatMessage(text, playerKeyPair); - nextMessageSendTime = DateTime.Now + Settings.messageCooldown; + nextMessageSendTime = DateTime.Now + TimeSpan.FromSeconds(Config.Main.Advanced.MessageCooldown); } } @@ -336,7 +319,7 @@ namespace MinecraftClient { lock (locationLock) { - for (int i = 0; i < Settings.MovementSpeed; i++) //Needs to run at 20 tps; MCC runs at 10 tps + for (int i = 0; i < Config.Main.Advanced.MovementSpeed; i++) //Needs to run at 20 tps; MCC runs at 10 tps { if (_yaw == null || _pitch == null) { @@ -349,10 +332,8 @@ namespace MinecraftClient Location next = path.Dequeue(); steps = Movement.Move2Steps(location, next, ref motionY); - if (Settings.MoveHeadWhileWalking) // Disable head movements to avoid anti-cheat triggers - { + if (Config.Main.Advanced.MoveHeadWhileWalking) // Disable head movements to avoid anti-cheat triggers UpdateLocation(location, next + new Location(0, 1, 0)); // Update yaw and pitch to look at next step - } } else { @@ -370,7 +351,7 @@ namespace MinecraftClient } } - if (Settings.AutoRespawn && respawnTicks > 0) + if (Config.Main.Advanced.AutoRespawn && respawnTicks > 0) { respawnTicks--; if (respawnTicks == 0) @@ -404,7 +385,7 @@ namespace MinecraftClient lock (lastKeepAliveLock) { - if (lastKeepAlive.AddSeconds(Settings.Timeout) < DateTime.Now) + if (lastKeepAlive.AddSeconds(Config.Main.Advanced.TcpTimeout) < DateTime.Now) { if (((CancellationToken)o!).IsCancellationRequested) return; @@ -572,11 +553,11 @@ namespace MinecraftClient text = text.Trim(); if (text.Length > 0) { - if (Settings.internalCmdChar == ' ' || text[0] == Settings.internalCmdChar) + if (Config.Main.Advanced.InternalCmdChar.ToChar() == ' ' || text[0] == Config.Main.Advanced.InternalCmdChar.ToChar()) { string? response_msg = ""; - string command = Settings.internalCmdChar == ' ' ? text : text[1..]; - if (!PerformInternalCommand(Settings.ExpandVars(command), ref response_msg, Settings.GetVariables()) && Settings.internalCmdChar == '/') + string command = Config.Main.Advanced.InternalCmdChar.ToChar() == ' ' ? text : text[1..]; + if (!PerformInternalCommand(Config.AppVar.ExpandVars(command), ref response_msg, Settings.Config.AppVar.GetVariables()) && Config.Main.Advanced.InternalCmdChar.ToChar() == '/') { SendText(text); } @@ -659,7 +640,7 @@ namespace MinecraftClient } else response_msg = Translations.Get("icmd.unknown", command_name); } - else response_msg = Translations.Get("icmd.list", String.Join(", ", cmd_names.ToArray()), Settings.internalCmdChar); + else response_msg = Translations.Get("icmd.list", String.Join(", ", cmd_names.ToArray()), Config.Main.Advanced.InternalCmdChar.ToChar()); } else if (cmds.ContainsKey(command_name)) { @@ -845,7 +826,6 @@ namespace MinecraftClient DispatchBotEvent(bot => bot.Initialize(), new ChatBot[] { b }); if (handler != null) DispatchBotEvent(bot => bot.AfterGameJoined(), new ChatBot[] { b }); - Settings.SingleCommand = ""; } /// @@ -2395,18 +2375,19 @@ namespace MinecraftClient /// public void OnGameJoined() { - if (!String.IsNullOrWhiteSpace(Settings.BrandInfo)) - handler.SendBrandInfo(Settings.BrandInfo.Trim()); + string? bandString = Config.Main.Advanced.BrandInfo.ToBrandString(); + if (!String.IsNullOrWhiteSpace(bandString)) + handler.SendBrandInfo(bandString.Trim()); - if (Settings.MCSettings_Enabled) + if (Config.MCSettings.Enabled) handler.SendClientSettings( - Settings.MCSettings_Locale, - Settings.MCSettings_RenderDistance, - Settings.MCSettings_Difficulty, - Settings.MCSettings_ChatMode, - Settings.MCSettings_ChatColors, - Settings.MCSettings_Skin_All, - Settings.MCSettings_MainHand); + Config.MCSettings.Locale, + Config.MCSettings.RenderDistance, + (byte)Config.MCSettings.Difficulty, + (byte)Config.MCSettings.ChatMode, + Config.MCSettings.ChatColors, + Config.MCSettings.Skin.GetByte(), + (byte)Config.MCSettings.MainHand); if (inventoryHandlingRequested) @@ -2484,15 +2465,15 @@ namespace MinecraftClient { case MovementType.Sneak: // https://minecraft.fandom.com/wiki/Sneaking#Effects - Sneaking 1.31m/s - Settings.MovementSpeed = 2; + Config.Main.Advanced.MovementSpeed = 2; break; case MovementType.Walk: // https://minecraft.fandom.com/wiki/Walking#Usage - Walking 4.317 m/s - Settings.MovementSpeed = 4; + Config.Main.Advanced.MovementSpeed = 4; break; case MovementType.Sprint: // https://minecraft.fandom.com/wiki/Sprinting#Usage - Sprinting 5.612 m/s - Settings.MovementSpeed = 5; + Config.Main.Advanced.MovementSpeed = 5; break; } } @@ -2601,7 +2582,7 @@ namespace MinecraftClient if (message.isSignedChat) { - if (!Settings.ShowIllegalSignedChat && !message.isSystemChat && !(bool)message.isSignatureLegal!) + if (!Config.Signature.ShowIllegalSignedChat && !message.isSystemChat && !(bool)message.isSignatureLegal!) return; messageText = ChatParser.ParseSignedChat(message, links); } @@ -2615,7 +2596,7 @@ namespace MinecraftClient Log.Chat(messageText); - if (Settings.DisplayChatLinks) + if (Config.Main.Advanced.ShowChatLinks) foreach (string link in links) Log.Chat(Translations.Get("mcc.link", link)); @@ -3024,14 +3005,14 @@ namespace MinecraftClient if (health <= 0) { - if (Settings.AutoRespawn) + if (Config.Main.Advanced.AutoRespawn) { Log.Info(Translations.Get("mcc.player_dead_respawn")); respawnTicks = 10; } else { - Log.Info(Translations.Get("mcc.player_dead", (Settings.internalCmdChar == ' ' ? "" : "" + Settings.internalCmdChar))); + Log.Info(Translations.Get("mcc.player_dead", Config.Main.Advanced.InternalCmdChar.ToLogString())); } DispatchBotEvent(bot => bot.OnDeath()); } diff --git a/MinecraftClient/MinecraftClient.csproj b/MinecraftClient/MinecraftClient.csproj index 7148da0b..b7f45d16 100644 --- a/MinecraftClient/MinecraftClient.csproj +++ b/MinecraftClient/MinecraftClient.csproj @@ -36,9 +36,10 @@ - + - + + NU1701 @@ -72,4 +73,9 @@ + + + + + diff --git a/MinecraftClient/Program.cs b/MinecraftClient/Program.cs index 70bbad1a..e25f18be 100644 --- a/MinecraftClient/Program.cs +++ b/MinecraftClient/Program.cs @@ -6,6 +6,7 @@ using System.Linq; using System.Reflection; using System.Runtime.InteropServices; using System.Text; +using System.Text.RegularExpressions; using System.Threading; using System.Threading.Tasks; using MinecraftClient.Inventory.ItemPalettes; @@ -16,6 +17,12 @@ using MinecraftClient.Protocol.Handlers.Forge; using MinecraftClient.Protocol.Keys; using MinecraftClient.Protocol.Session; using MinecraftClient.WinAPI; +using Tomlet; +using Tomlet.Models; +using static MinecraftClient.Settings; +using static MinecraftClient.Settings.MainConfigHealper.MainConfig.GeneralConfig; +using static MinecraftClient.Settings.MainConfigHealper.MainConfig.AdvancedConfig; +using static System.Net.Mime.MediaTypeNames; namespace MinecraftClient { @@ -104,12 +111,12 @@ namespace MinecraftClient ConsoleIO.DebugReadInput(); } - settingsIniPath = "MinecraftClient.ini"; - //Process ini configuration file - if (args.Length >= 1 && System.IO.File.Exists(args[0]) && Settings.ToLowerIfNeed(Path.GetExtension(args[0])) == ".ini") + bool needWriteDefaultSetting, newlyGenerated = false; + settingsIniPath = "MinecraftClient.ini"; + if (args.Length >= 1 && File.Exists(args[0]) && Settings.ToLowerIfNeed(Path.GetExtension(args[0])) == ".ini") { - Settings.LoadFile(args[0]); + needWriteDefaultSetting = Settings.LoadFromFile(args[0]); settingsIniPath = args[0]; //remove ini configuration file from arguments array @@ -117,14 +124,34 @@ namespace MinecraftClient args_tmp.RemoveAt(0); args = args_tmp.ToArray(); } - else if (System.IO.File.Exists("MinecraftClient.ini")) + else if (File.Exists("MinecraftClient.ini")) { - Settings.LoadFile("MinecraftClient.ini"); + needWriteDefaultSetting = Settings.LoadFromFile("MinecraftClient.ini"); + } + else + { + needWriteDefaultSetting = true; + newlyGenerated = true; } - else Settings.WriteDefaultSettings("MinecraftClient.ini"); - //Load external translation file. Should be called AFTER settings loaded - Translations.LoadExternalTranslationFile(Settings.Language); + if (needWriteDefaultSetting) + { + (string gameLanguage, string[] langList) = Translations.GetTranslationPriority(); + Translations.LoadTranslationFile(langList); + Config.Main.Advanced.Language = gameLanguage; + Settings.WriteToFile("MinecraftClient.ini", false); + if (newlyGenerated) + ConsoleIO.WriteLineFormatted(Translations.TryGet("mcc.settings_generated")); + ConsoleIO.WriteLine(Translations.TryGet("mcc.run_with_default_settings")); + } + else + { + //Load external translation file. Should be called AFTER settings loaded + Translations.LoadTranslationFile(Translations.GetTranslationPriority(Config.Main.Advanced.Language)); + if (!Config.Main.Advanced.Language.StartsWith("en")) + ConsoleIO.WriteLine(Translations.TryGet("mcc.help_us_translate")); + Settings.WriteToFile("MinecraftClient.ini", true); // format + } //Other command-line arguments if (args.Length >= 1) @@ -222,55 +249,56 @@ namespace MinecraftClient } catch (ArgumentException e) { - Settings.interactiveMode = false; + InternalConfig.InteractiveMode = false; HandleFailure(e.Message); return; } } - if (Settings.ConsoleTitle != "") + if (Config.Main.Advanced.ConsoleTitle != "") { - Settings.Username = "New Window"; - Console.Title = Settings.ExpandVars(Settings.ConsoleTitle); + InternalConfig.Username = "New Window"; + Console.Title = Config.AppVar.ExpandVars(Config.Main.Advanced.ConsoleTitle); } //Test line to troubleshoot invisible colors - if (Settings.DebugMessages) + if (Config.Logging.DebugMessages) { ConsoleIO.WriteLineFormatted(Translations.Get("debug.color_test", "[0123456789ABCDEF]: [§00§11§22§33§44§55§66§77§88§99§aA§bB§cC§dD§eE§fF§r]")); } //Load cached sessions from disk if necessary - if (Settings.SessionCaching == CacheType.Disk) + if (Config.Main.Advanced.SessionCache == CacheType.disk) { bool cacheLoaded = SessionCache.InitializeDiskCache(); - if (Settings.DebugMessages) + if (Config.Logging.DebugMessages) Translations.WriteLineFormatted(cacheLoaded ? "debug.session_cache_ok" : "debug.session_cache_fail"); } + // Setup exit cleaning code + ExitCleanUp.Add(() => { DoExit(0); }); + //Asking the user to type in missing data such as Username and Password - bool useBrowser = Settings.AccountType == ProtocolHandler.AccountType.Microsoft && Settings.LoginMethod == "browser"; - if (Settings.Login == "" && !useBrowser) + bool useBrowser = Config.Main.General.AccountType == LoginType.microsoft && Config.Main.General.Method == LoginMethod.browser; + if (string.IsNullOrEmpty(Config.Main.General.Account.Login) && !useBrowser) { ConsoleIO.WriteLine(ConsoleIO.BasicIO ? Translations.Get("mcc.login_basic_io") : Translations.Get("mcc.login")); - Settings.Login = ConsoleIO.ReadLine(); + Config.Main.General.Account.Login = ConsoleIO.ReadLine().Trim(); + if (string.IsNullOrEmpty(Config.Main.General.Account.Login)) + { + HandleFailure(Translations.Get("error.login.blocked"), false, ChatBot.DisconnectReason.LoginRejected); + return; + } } - if (Settings.Password == "" - && (Settings.SessionCaching == CacheType.None || !SessionCache.Contains(Settings.ToLowerIfNeed(Settings.Login))) - && !useBrowser) + if (string.IsNullOrEmpty(Config.Main.General.Account.Password) && !useBrowser && + (Config.Main.Advanced.SessionCache == CacheType.none || !SessionCache.Contains(Settings.ToLowerIfNeed(Config.Main.General.Account.Login)))) { RequestPassword(); } - - // Setup exit cleaning code - ExitCleanUp.Add(delegate () + else { - // Do NOT use Program.Exit() as creating new Thread cause program to freeze - if (client != null) { client.Disconnect(); ConsoleIO.Reset(); } - if (offlinePrompt != null) { offlinePrompt.Item2.Cancel(); offlinePrompt = null; ConsoleIO.Reset(); } - if (Settings.playerHeadAsIcon) { ConsoleIcon.RevertToMCCIcon(); } - }); - + InternalConfig.Password = Config.Main.General.Account.Password; + } startupargs = args; InitializeClient(); @@ -281,10 +309,10 @@ namespace MinecraftClient /// private static void RequestPassword() { - ConsoleIO.WriteLine(ConsoleIO.BasicIO ? Translations.Get("mcc.password_basic_io", Settings.Login) + "\n" : Translations.Get("mcc.password")); + ConsoleIO.WriteLine(ConsoleIO.BasicIO ? Translations.Get("mcc.password_basic_io", Config.Main.General.Account.Login) + "\n" : Translations.Get("mcc.password")); string? password = ConsoleIO.BasicIO ? Console.ReadLine() : ConsoleIO.ReadPassword(); if (password == null || password == string.Empty) { password = "-"; } - Settings.Password = password; + InternalConfig.Password = password; } /// @@ -292,23 +320,25 @@ namespace MinecraftClient /// private static void InitializeClient() { + InternalConfig.MinecraftVersion = Config.Main.Advanced.MinecraftVersion; + SessionToken session = new(); PlayerKeyPair? playerKeyPair = null; ProtocolHandler.LoginResult result = ProtocolHandler.LoginResult.LoginRequired; - string loginLower = Settings.ToLowerIfNeed(Settings.Login); - if (Settings.Password == "-") + string loginLower = Settings.ToLowerIfNeed(Config.Main.General.Account.Login); + if (InternalConfig.Password == "-") { Translations.WriteLineFormatted("mcc.offline"); result = ProtocolHandler.LoginResult.Success; session.PlayerID = "0"; - session.PlayerName = Settings.Login; + session.PlayerName = Config.Main.General.Account.Login; } else { // Validate cached session or login new session. - if (Settings.SessionCaching != CacheType.None && SessionCache.Contains(loginLower)) + if (Config.Main.Advanced.SessionCache != CacheType.none && SessionCache.Contains(loginLower)) { session = SessionCache.Get(loginLower); result = ProtocolHandler.GetTokenValidation(session); @@ -330,8 +360,8 @@ namespace MinecraftClient } if (result != ProtocolHandler.LoginResult.Success - && Settings.Password == "" - && Settings.AccountType == ProtocolHandler.AccountType.Mojang) + && InternalConfig.Password == "" + && Config.Main.General.AccountType == LoginType.mojang) RequestPassword(); } else ConsoleIO.WriteLineFormatted(Translations.Get("mcc.session_valid", session.PlayerName)); @@ -339,12 +369,12 @@ namespace MinecraftClient if (result != ProtocolHandler.LoginResult.Success) { - Translations.WriteLine("mcc.connecting", Settings.AccountType == ProtocolHandler.AccountType.Mojang ? "Minecraft.net" : "Microsoft"); - result = ProtocolHandler.GetLogin(Settings.Login, Settings.Password, Settings.AccountType, out session); + Translations.WriteLine("mcc.connecting", Config.Main.General.AccountType == LoginType.mojang ? "Minecraft.net" : "Microsoft"); + result = ProtocolHandler.GetLogin(Config.Main.General.Account.Login, InternalConfig.Password, Config.Main.General.AccountType, out session); } } - if (result == ProtocolHandler.LoginResult.Success && Settings.SessionCaching != CacheType.None) + if (result == ProtocolHandler.LoginResult.Success && Config.Main.Advanced.SessionCache != CacheType.none) SessionCache.Store(loginLower, session); if (result == ProtocolHandler.LoginResult.Success) @@ -352,17 +382,17 @@ namespace MinecraftClient if (result == ProtocolHandler.LoginResult.Success) { - if (Settings.AccountType == ProtocolHandler.AccountType.Microsoft && Settings.Password != "-" && Settings.LoginWithSecureProfile) + if (Config.Main.General.AccountType == LoginType.microsoft && InternalConfig.Password != "-" && Config.Signature.LoginWithSecureProfile) { // Load cached profile key from disk if necessary - if (Settings.ProfileKeyCaching == CacheType.Disk) + if (Config.Main.Advanced.ProfileKeyCache == CacheType.disk) { bool cacheKeyLoaded = KeysCache.InitializeDiskCache(); - if (Settings.DebugMessages) + if (Config.Logging.DebugMessages) Translations.WriteLineFormatted(cacheKeyLoaded ? "debug.keys_cache_ok" : "debug.keys_cache_fail"); } - if (Settings.ProfileKeyCaching != CacheType.None && KeysCache.Contains(loginLower)) + if (Config.Main.Advanced.ProfileKeyCache != CacheType.none && KeysCache.Contains(loginLower)) { playerKeyPair = KeysCache.Get(loginLower); if (playerKeyPair.NeedRefresh()) @@ -375,36 +405,36 @@ namespace MinecraftClient { Translations.WriteLineFormatted("mcc.fetching_key"); playerKeyPair = KeyUtils.GetNewProfileKeys(session.ID); - if (Settings.ProfileKeyCaching != CacheType.None && playerKeyPair != null) + if (Config.Main.Advanced.ProfileKeyCache != CacheType.none && playerKeyPair != null) { KeysCache.Store(loginLower, playerKeyPair); } } } - Settings.Username = session.PlayerName; + InternalConfig.Username = session.PlayerName; bool isRealms = false; - if (Settings.ConsoleTitle != "") - Console.Title = Settings.ExpandVars(Settings.ConsoleTitle); + if (Config.Main.Advanced.ConsoleTitle != "") + Console.Title = Config.AppVar.ExpandVars(Config.Main.Advanced.ConsoleTitle); - if (Settings.playerHeadAsIcon) - ConsoleIcon.SetPlayerIconAsync(Settings.Username); + if (Config.Main.Advanced.PlayerHeadAsIcon) + ConsoleIcon.SetPlayerIconAsync(InternalConfig.Username); - if (Settings.DebugMessages) + if (Config.Logging.DebugMessages) Translations.WriteLine("debug.session_id", session.ID); List availableWorlds = new(); - if (Settings.MinecraftRealmsEnabled && !String.IsNullOrEmpty(session.ID)) - availableWorlds = ProtocolHandler.RealmsListWorlds(Settings.Username, session.PlayerID, session.ID); + if (Config.Main.Advanced.MinecraftRealms && !String.IsNullOrEmpty(session.ID)) + availableWorlds = ProtocolHandler.RealmsListWorlds(InternalConfig.Username, session.PlayerID, session.ID); - if (Settings.ServerIP == "") + if (InternalConfig.ServerIP == string.Empty) { Translations.Write("mcc.ip"); string addressInput = ConsoleIO.ReadLine(); if (addressInput.StartsWith("realms:")) { - if (Settings.MinecraftRealmsEnabled) + if (Config.Main.Advanced.MinecraftRealms) { if (availableWorlds.Count == 0) { @@ -416,12 +446,12 @@ namespace MinecraftClient worldId = availableWorlds[worldIndex]; if (availableWorlds.Contains(worldId)) { - string RealmsAddress = ProtocolHandler.GetRealmsWorldServerAddress(worldId, Settings.Username, session.PlayerID, session.ID); + string RealmsAddress = ProtocolHandler.GetRealmsWorldServerAddress(worldId, InternalConfig.Username, session.PlayerID, session.ID); if (RealmsAddress != "") { addressInput = RealmsAddress; isRealms = true; - Settings.ServerVersion = MCHighestVersion; + InternalConfig.MinecraftVersion = MCHighestVersion; } else { @@ -441,37 +471,37 @@ namespace MinecraftClient return; } } - Settings.SetServerIP(addressInput); + Config.Main.SetServerIP(new MainConfigHealper.MainConfig.ServerInfoConfig(addressInput), true); } //Get server version int protocolversion = 0; ForgeInfo? forgeInfo = null; - if (Settings.ServerVersion != "" && Settings.ToLowerIfNeed(Settings.ServerVersion) != "auto") + if (InternalConfig.MinecraftVersion != "" && Settings.ToLowerIfNeed(InternalConfig.MinecraftVersion) != "auto") { - protocolversion = Protocol.ProtocolHandler.MCVer2ProtocolVersion(Settings.ServerVersion); + protocolversion = Protocol.ProtocolHandler.MCVer2ProtocolVersion(InternalConfig.MinecraftVersion); if (protocolversion != 0) - { - ConsoleIO.WriteLineFormatted(Translations.Get("mcc.use_version", Settings.ServerVersion, protocolversion)); - } - else ConsoleIO.WriteLineFormatted(Translations.Get("mcc.unknown_version", Settings.ServerVersion)); + ConsoleIO.WriteLineFormatted(Translations.Get("mcc.use_version", InternalConfig.MinecraftVersion, protocolversion)); + else + ConsoleIO.WriteLineFormatted(Translations.Get("mcc.unknown_version", InternalConfig.MinecraftVersion)); if (useMcVersionOnce) { useMcVersionOnce = false; - Settings.ServerVersion = ""; + InternalConfig.MinecraftVersion = ""; } } //Retrieve server info if version is not manually set OR if need to retrieve Forge information - if (!isRealms && (protocolversion == 0 || Settings.ServerAutodetectForge || (Settings.ServerForceForge && !ProtocolHandler.ProtocolMayForceForge(protocolversion)))) + if (!isRealms && (protocolversion == 0 || (Config.Main.Advanced.EnableForge == ForgeConfigType.auto) || + ((Config.Main.Advanced.EnableForge == ForgeConfigType.force) && !ProtocolHandler.ProtocolMayForceForge(protocolversion)))) { if (protocolversion != 0) Translations.WriteLine("mcc.forge"); else Translations.WriteLine("mcc.retrieve"); - if (!ProtocolHandler.GetServerInfo(Settings.ServerIP, Settings.ServerPort, ref protocolversion, ref forgeInfo)) + if (!ProtocolHandler.GetServerInfo(InternalConfig.ServerIP, InternalConfig.ServerPort, ref protocolversion, ref forgeInfo)) { HandleFailure(Translations.Get("error.ping"), true, ChatBots.AutoRelog.DisconnectReason.ConnectionLost); return; @@ -479,7 +509,7 @@ namespace MinecraftClient } //Force-enable Forge support? - if (!isRealms && Settings.ServerForceForge && forgeInfo == null) + if (!isRealms && (Config.Main.Advanced.EnableForge == ForgeConfigType.force) && forgeInfo == null) { if (ProtocolHandler.ProtocolMayForceForge(protocolversion)) { @@ -499,12 +529,11 @@ namespace MinecraftClient try { //Start the main TCP client - string? command = String.IsNullOrEmpty(Settings.SingleCommand) ? null : Settings.SingleCommand; - client = new McClient(session, playerKeyPair, Settings.ServerIP, Settings.ServerPort, protocolversion, forgeInfo, command); + client = new McClient(session, playerKeyPair, InternalConfig.ServerIP, InternalConfig.ServerPort, protocolversion, forgeInfo); //Update console title - if (Settings.ConsoleTitle != "") - Console.Title = Settings.ExpandVars(Settings.ConsoleTitle); + if (Config.Main.Advanced.ConsoleTitle != "") + Console.Title = Config.AppVar.ExpandVars(Config.Main.Advanced.ConsoleTitle); } catch (NotSupportedException) { @@ -543,7 +572,8 @@ namespace MinecraftClient public static void ReloadSettings() { if (settingsIniPath != null) - Settings.LoadFile(settingsIniPath); + if(Settings.LoadFromFile(settingsIniPath)) + ConsoleIO.WriteLine(Translations.TryGet("config.loading", settingsIniPath)); } /// @@ -563,22 +593,30 @@ namespace MinecraftClient System.Threading.Thread.Sleep(delaySeconds * 1000); } Translations.WriteLine("mcc.restart"); + ReloadSettings(); InitializeClient(); })).Start(); } + public static void DoExit(int exitcode = 0) + { + if (settingsIniPath != null) + { + Settings.WriteToFile(settingsIniPath, true); + ConsoleIO.WriteLineFormatted(Translations.TryGet("config.saving", settingsIniPath)); + } + if (client != null) { client.Disconnect(); ConsoleIO.Reset(); } + if (offlinePrompt != null) { offlinePrompt.Item2.Cancel(); offlinePrompt.Item1.Join(); offlinePrompt = null; ConsoleIO.Reset(); } + if (Config.Main.Advanced.PlayerHeadAsIcon) { ConsoleIcon.RevertToMCCIcon(); } + Environment.Exit(exitcode); + } + /// /// Disconnect the current client from the server and exit the app /// public static void Exit(int exitcode = 0) { - new Thread(new ThreadStart(delegate - { - if (client != null) { client.Disconnect(); ConsoleIO.Reset(); } - if (offlinePrompt != null) { offlinePrompt.Item2.Cancel(); offlinePrompt.Item1.Join(); offlinePrompt = null; ConsoleIO.Reset(); } - if (Settings.playerHeadAsIcon) { ConsoleIcon.RevertToMCCIcon(); } - Environment.Exit(exitcode); - })).Start(); + new Thread(new ThreadStart(() => { DoExit(exitcode); })).Start(); } /// @@ -595,7 +633,7 @@ namespace MinecraftClient ConsoleIO.Reset(); while (Console.KeyAvailable) Console.ReadKey(true); - Console.WriteLine(errorMessage); + ConsoleIO.WriteLine(errorMessage); if (disconnectReason.HasValue) { @@ -604,13 +642,13 @@ namespace MinecraftClient } } - if (Settings.interactiveMode) + if (InternalConfig.InteractiveMode) { if (versionError) { Translations.Write("mcc.server_version"); - Settings.ServerVersion = ConsoleInteractive.ConsoleReader.RequestImmediateInput(); - if (Settings.ServerVersion != "") + InternalConfig.MinecraftVersion = ConsoleInteractive.ConsoleReader.RequestImmediateInput(); + if (InternalConfig.MinecraftVersion != "") { useMcVersionOnce = true; Restart(); @@ -627,7 +665,8 @@ namespace MinecraftClient { bool exitThread = false; string command = " "; - ConsoleIO.WriteLineFormatted(Translations.Get("mcc.disconnected", (Settings.internalCmdChar == ' ' ? "" : "" + Settings.internalCmdChar))); + ConsoleIO.WriteLine(string.Empty); + ConsoleIO.WriteLineFormatted(Translations.Get("mcc.disconnected", Config.Main.Advanced.InternalCmdChar.ToLogString())); Translations.WriteLineFormatted("mcc.press_exit"); while (!cancellationTokenSource.IsCancellationRequested) @@ -645,13 +684,13 @@ namespace MinecraftClient { string message = ""; - if (Settings.internalCmdChar != ' ' - && command[0] == Settings.internalCmdChar) + if (Config.Main.Advanced.InternalCmdChar.ToChar() != ' ' + && command[0] == Config.Main.Advanced.InternalCmdChar.ToChar()) command = command[1..]; if (command.StartsWith("reco")) { - message = new Commands.Reco().Run(null, Settings.ExpandVars(command), null); + message = new Commands.Reco().Run(null, Config.AppVar.ExpandVars(command), null); if (message == "") { exitThread = true; @@ -660,7 +699,7 @@ namespace MinecraftClient } else if (command.StartsWith("connect")) { - message = new Commands.Connect().Run(null, Settings.ExpandVars(command), null); + message = new Commands.Connect().Run(null, Config.AppVar.ExpandVars(command), null); if (message == "") { exitThread = true; @@ -669,31 +708,26 @@ namespace MinecraftClient } else if (command.StartsWith("exit") || command.StartsWith("quit")) { - message = new Commands.Exit().Run(null, Settings.ExpandVars(command), null); + message = new Commands.Exit().Run(null, Config.AppVar.ExpandVars(command), null); } else if (command.StartsWith("help")) { ConsoleIO.WriteLineFormatted("§8MCC: " + - (Settings.internalCmdChar == ' ' - ? "" - : "" + Settings.internalCmdChar) + + Config.Main.Advanced.InternalCmdChar.ToLogString() + new Commands.Reco().GetCmdDescTranslated()); ConsoleIO.WriteLineFormatted("§8MCC: " + - (Settings.internalCmdChar == ' ' - ? "" - : "" + Settings.internalCmdChar) + + Config.Main.Advanced.InternalCmdChar.ToLogString() + new Commands.Connect().GetCmdDescTranslated()); } else - ConsoleIO.WriteLineFormatted(Translations.Get("icmd.unknown", - command.Split(' ')[0])); + ConsoleIO.WriteLineFormatted(Translations.Get("icmd.unknown", command.Split(' ')[0])); if (message != "") ConsoleIO.WriteLineFormatted("§8MCC: " + message); } else { - _ = new Commands.Exit().Run(null, Settings.ExpandVars(command), null); + _ = new Commands.Exit().Run(null, Config.AppVar.ExpandVars(command), null); } } diff --git a/MinecraftClient/Protocol/Handlers/PacketPalettes/PacketTypePalette.cs b/MinecraftClient/Protocol/Handlers/PacketPalettes/PacketTypePalette.cs index a65a0079..968988f7 100644 --- a/MinecraftClient/Protocol/Handlers/PacketPalettes/PacketTypePalette.cs +++ b/MinecraftClient/Protocol/Handlers/PacketPalettes/PacketTypePalette.cs @@ -61,7 +61,7 @@ namespace MinecraftClient.Protocol.Handlers.PacketPalettes } else if (forgeEnabled) { - if (Settings.DebugMessages) + if (Settings.Config.Logging.DebugMessages) ConsoleIO.WriteLogLine("Ignoring unknown packet ID of 0x" + packetId.ToString("X2")); return PacketTypesIn.Unknown; } @@ -92,7 +92,7 @@ namespace MinecraftClient.Protocol.Handlers.PacketPalettes } else if (forgeEnabled) { - if (Settings.DebugMessages) + if (Settings.Config.Logging.DebugMessages) ConsoleIO.WriteLogLine("Ignoring unknown packet ID of 0x" + packetId.ToString("X2")); return PacketTypesOut.Unknown; } diff --git a/MinecraftClient/Protocol/Handlers/Protocol16.cs b/MinecraftClient/Protocol/Handlers/Protocol16.cs index 73b7aebc..a84b61ea 100644 --- a/MinecraftClient/Protocol/Handlers/Protocol16.cs +++ b/MinecraftClient/Protocol/Handlers/Protocol16.cs @@ -13,6 +13,7 @@ using MinecraftClient.Protocol.Keys; using MinecraftClient.Protocol.Message; using MinecraftClient.Protocol.Session; using MinecraftClient.Proxy; +using static MinecraftClient.Settings; namespace MinecraftClient.Protocol.Handlers { @@ -494,7 +495,7 @@ namespace MinecraftClient.Protocol.Handlers if (serverID == "-") Translations.WriteLineFormatted("mcc.server_offline"); - else if (Settings.DebugMessages) + else if (Settings.Config.Logging.DebugMessages) ConsoleIO.WriteLineFormatted(Translations.Get("mcc.handshake", serverID)); return StartEncryption(uuid, username, sessionID, token, serverID, PublicServerkey, session); @@ -511,7 +512,7 @@ namespace MinecraftClient.Protocol.Handlers RSACryptoServiceProvider RSAService = CryptoHandler.DecodeRSAPublicKey(serverPublicKey)!; byte[] secretKey = CryptoHandler.ClientAESPrivateKey ?? CryptoHandler.GenerateAESPrivateKey(); - if (Settings.DebugMessages) + if (Settings.Config.Logging.DebugMessages) Translations.WriteLineFormatted("debug.crypto"); if (serverIDhash != "-") @@ -534,7 +535,7 @@ namespace MinecraftClient.Protocol.Handlers { session.ServerIDhash = serverIDhash; session.ServerPublicKey = serverPublicKey; - SessionCache.Store(Settings.Login.ToLower(), session); + SessionCache.Store(Config.Main.General.Account.Login.ToLower(), session); } else { @@ -862,7 +863,7 @@ namespace MinecraftClient.Protocol.Handlers Protocol16Handler ComTmp = new(tcp); string result = ComTmp.ReadNextString(); - if (Settings.DebugMessages) + if (Settings.Config.Logging.DebugMessages) { // May contain formatting codes, cannot use WriteLineFormatted Console.ForegroundColor = ConsoleColor.DarkGray; diff --git a/MinecraftClient/Protocol/Handlers/Protocol18.cs b/MinecraftClient/Protocol/Handlers/Protocol18.cs index 75c4ed47..78868cbb 100644 --- a/MinecraftClient/Protocol/Handlers/Protocol18.cs +++ b/MinecraftClient/Protocol/Handlers/Protocol18.cs @@ -22,6 +22,7 @@ using MinecraftClient.Protocol.Keys; using MinecraftClient.Protocol.Message; using MinecraftClient.Protocol.Session; using MinecraftClient.Proxy; +using static MinecraftClient.Settings; namespace MinecraftClient.Protocol.Handlers { @@ -461,8 +462,8 @@ namespace MinecraftClient.Protocol.Handlers { //Hide system messages or xp bar messages? messageType = dataTypes.ReadNextByte(packetData); - if ((messageType == 1 && !Settings.DisplaySystemMessages) - || (messageType == 2 && !Settings.DisplayXPBarMessages)) + if ((messageType == 1 && !Config.Main.Advanced.ShowSystemMessages) + || (messageType == 2 && !Config.Main.Advanced.ShowSystemMessages)) break; if (protocolVersion >= MC_1_16_5_Version) @@ -482,8 +483,8 @@ namespace MinecraftClient.Protocol.Handlers string? unsignedChatContent = hasUnsignedChatContent ? dataTypes.ReadNextString(packetData) : null; messageType = dataTypes.ReadNextVarInt(packetData); - if ((messageType == 1 && !Settings.DisplaySystemMessages) - || (messageType == 2 && !Settings.DisplayXPBarMessages)) + if ((messageType == 1 && !Config.Main.Advanced.ShowSystemMessages) + || (messageType == 2 && !Config.Main.Advanced.ShowXPBarMessages)) break; Guid senderUUID = dataTypes.ReadNextUUID(packetData); @@ -1603,7 +1604,7 @@ namespace MinecraftClient.Protocol.Handlers case PacketTypesIn.SystemChat: string systemMessage = dataTypes.ReadNextString(packetData); int msgType = dataTypes.ReadNextVarInt(packetData); - if ((msgType == 1 && !Settings.DisplaySystemMessages)) + if ((msgType == 1 && !Config.Main.Advanced.ShowSystemMessages)) break; handler.OnTextReceived(new(systemMessage, true, msgType, Guid.Empty, true)); break; @@ -1925,7 +1926,7 @@ namespace MinecraftClient.Protocol.Handlers { session.ServerIDhash = serverIDhash; session.ServerPublicKey = serverPublicKey; - SessionCache.Store(Settings.Login.ToLower(), session); + SessionCache.Store(Config.Main.General.Account.Login.ToLower(), session); } else { @@ -2119,7 +2120,7 @@ namespace MinecraftClient.Protocol.Handlers { string result = dataTypes.ReadNextString(packetData); //Get the Json data - if (Settings.DebugMessages) + if (Config.Logging.DebugMessages) { // May contain formatting codes, cannot use WriteLineFormatted Console.ForegroundColor = ConsoleColor.DarkGray; @@ -2230,7 +2231,7 @@ namespace MinecraftClient.Protocol.Handlers /// List< Argument Name, Argument Value > private List>? CollectCommandArguments(string command) { - if (!isOnlineMode || !Settings.SignMessageInCommand) + if (!isOnlineMode || !Config.Signature.SignMessageInCommand) return null; List> needSigned = new(); @@ -2371,7 +2372,7 @@ namespace MinecraftClient.Protocol.Handlers DateTimeOffset timeNow = DateTimeOffset.UtcNow; fields.AddRange(dataTypes.GetLong(timeNow.ToUnixTimeMilliseconds())); - if (!isOnlineMode || playerKeyPair == null || !Settings.SignChat) + if (!isOnlineMode || playerKeyPair == null || !Config.Signature.SignChat) { fields.AddRange(dataTypes.GetLong(0)); // Salt: Long fields.AddRange(dataTypes.GetVarInt(0)); // Signature Length: VarInt diff --git a/MinecraftClient/Protocol/Handlers/Protocol18Forge.cs b/MinecraftClient/Protocol/Handlers/Protocol18Forge.cs index d1be9b34..102d9fad 100644 --- a/MinecraftClient/Protocol/Handlers/Protocol18Forge.cs +++ b/MinecraftClient/Protocol/Handlers/Protocol18Forge.cs @@ -130,7 +130,7 @@ namespace MinecraftClient.Protocol.Handlers byte fmlProtocolVersion = dataTypes.ReadNextByte(packetData); - if (Settings.DebugMessages) + if (Settings.Config.Logging.DebugMessages) ConsoleIO.WriteLineFormatted(Translations.Get("forge.version", fmlProtocolVersion)); if (fmlProtocolVersion >= 1) @@ -140,7 +140,7 @@ namespace MinecraftClient.Protocol.Handlers SendForgeHandshakePacket(FMLHandshakeDiscriminator.ClientHello, new byte[] { fmlProtocolVersion }); // Then tell the server that we're running the same mods. - if (Settings.DebugMessages) + if (Settings.Config.Logging.DebugMessages) Translations.WriteLineFormatted("forge.send_mod"); byte[][] mods = new byte[forgeInfo.Mods.Count][]; for (int i = 0; i < forgeInfo.Mods.Count; i++) @@ -160,7 +160,7 @@ namespace MinecraftClient.Protocol.Handlers Thread.Sleep(2000); - if (Settings.DebugMessages) + if (Settings.Config.Logging.DebugMessages) Translations.WriteLineFormatted("forge.accept"); // Tell the server that yes, we are OK with the mods it has // even though we don't actually care what mods it has. @@ -182,7 +182,7 @@ namespace MinecraftClient.Protocol.Handlers // with blocks and items. int registrySize = dataTypes.ReadNextVarInt(packetData); - if (Settings.DebugMessages) + if (Settings.Config.Logging.DebugMessages) ConsoleIO.WriteLineFormatted(Translations.Get("forge.registry", registrySize)); fmlHandshakeState = FMLHandshakeClientState.PENDINGCOMPLETE; @@ -194,7 +194,7 @@ namespace MinecraftClient.Protocol.Handlers bool hasNextRegistry = dataTypes.ReadNextBool(packetData); string registryName = dataTypes.ReadNextString(packetData); int registrySize = dataTypes.ReadNextVarInt(packetData); - if (Settings.DebugMessages) + if (Settings.Config.Logging.DebugMessages) ConsoleIO.WriteLineFormatted(Translations.Get("forge.registry_2", registryName, registrySize)); if (!hasNextRegistry) fmlHandshakeState = FMLHandshakeClientState.PENDINGCOMPLETE; @@ -206,7 +206,7 @@ namespace MinecraftClient.Protocol.Handlers // Just say yes. if (discriminator != FMLHandshakeDiscriminator.HandshakeAck) return false; - if (Settings.DebugMessages) + if (Settings.Config.Logging.DebugMessages) Translations.WriteLineFormatted("forge.accept_registry"); SendForgeHandshakePacket(FMLHandshakeDiscriminator.HandshakeAck, new byte[] { (byte)FMLHandshakeClientState.PENDINGCOMPLETE }); @@ -220,7 +220,7 @@ namespace MinecraftClient.Protocol.Handlers SendForgeHandshakePacket(FMLHandshakeDiscriminator.HandshakeAck, new byte[] { (byte)FMLHandshakeClientState.COMPLETE }); - if (Settings.DebugMessages) + if (Settings.Config.Logging.DebugMessages) Translations.WriteLine("forge.complete"); fmlHandshakeState = FMLHandshakeClientState.DONE; return true; @@ -300,7 +300,7 @@ namespace MinecraftClient.Protocol.Handlers // // [1]: Version is usually set to "FML2" for FML stuff and "1" for mods - if (Settings.DebugMessages) + if (Settings.Config.Logging.DebugMessages) Translations.WriteLineFormatted("forge.fml2.mod"); List mods = new(); @@ -332,7 +332,7 @@ namespace MinecraftClient.Protocol.Handlers // We are supposed to validate server info against our set of installed mods, then reply with our list // In MCC, we just want to send a valid response so we'll reply back with data collected from the server. - if (Settings.DebugMessages) + if (Settings.Config.Logging.DebugMessages) Translations.WriteLineFormatted("forge.fml2.mod_send"); // Packet ID 2: Client to Server Mod List @@ -368,7 +368,7 @@ namespace MinecraftClient.Protocol.Handlers // Registry Snapshot: ForgeRegistry.java > Snapshot > read(PacketBuffer) // Not documented yet. We're ignoring this packet in MCC - if (Settings.DebugMessages) + if (Settings.Config.Logging.DebugMessages) { string registryName = dataTypes.ReadNextString(packetData); ConsoleIO.WriteLineFormatted(Translations.Get("forge.fml2.registry", registryName)); @@ -387,7 +387,7 @@ namespace MinecraftClient.Protocol.Handlers // [1] Config data may containt a standard Minecraft string readable with dataTypes.readNextString() // We're ignoring this packet in MCC - if (Settings.DebugMessages) + if (Settings.Config.Logging.DebugMessages) { string configName = dataTypes.ReadNextString(packetData); ConsoleIO.WriteLineFormatted(Translations.Get("forge.fml2.config", configName)); @@ -398,7 +398,7 @@ namespace MinecraftClient.Protocol.Handlers break; default: - if (Settings.DebugMessages) + if (Settings.Config.Logging.DebugMessages) ConsoleIO.WriteLineFormatted(Translations.Get("forge.fml2.unknown", packetID)); break; } @@ -413,7 +413,7 @@ namespace MinecraftClient.Protocol.Handlers return true; } } - else if (Settings.DebugMessages) + else if (Settings.Config.Logging.DebugMessages) { ConsoleIO.WriteLineFormatted(Translations.Get("forge.fml2.unknown_channel", fmlChannel)); } @@ -505,7 +505,7 @@ namespace MinecraftClient.Protocol.Handlers if (forgeInfo.Mods.Any()) { ConsoleIO.WriteLineFormatted(Translations.Get("forge.with_mod", forgeInfo.Mods.Count)); - if (Settings.DebugMessages) + if (Settings.Config.Logging.DebugMessages) { Translations.WriteLineFormatted("forge.mod_list"); foreach (ForgeInfo.ForgeMod mod in forgeInfo.Mods) diff --git a/MinecraftClient/Protocol/Message/ChatParser.cs b/MinecraftClient/Protocol/Message/ChatParser.cs index b47c4e08..dc29f421 100644 --- a/MinecraftClient/Protocol/Message/ChatParser.cs +++ b/MinecraftClient/Protocol/Message/ChatParser.cs @@ -5,13 +5,13 @@ using System.Net.Http; using System.Text; using System.Threading.Tasks; using MinecraftClient.Protocol.Message; +using static MinecraftClient.Settings; namespace MinecraftClient.Protocol { /// /// This class parses JSON chat data from MC 1.6+ and returns the appropriate string to be printed. /// - static class ChatParser { public enum MessageType @@ -47,7 +47,7 @@ namespace MinecraftClient.Protocol /// Returns the translated text public static string ParseSignedChat(ChatMessage message, List? links = null) { - string chatContent = Settings.ShowModifiedChat && message.unsignedContent != null ? message.unsignedContent : message.content; + string chatContent = Config.Signature.ShowModifiedChat && message.unsignedContent != null ? message.unsignedContent : message.content; string content = message.isJson ? ParseText(chatContent, links) : chatContent; string sender = message.displayName!; @@ -107,27 +107,27 @@ namespace MinecraftClient.Protocol string color = string.Empty; if (message.isSystemChat) { - if (Settings.MarkSystemMessage) + if (Config.Signature.MarkSystemMessage) color = "§z §r "; // Custom color code §z : Background Gray } else { if ((bool)message.isSignatureLegal!) { - if (Settings.ShowModifiedChat && message.unsignedContent != null) + if (Config.Signature.ShowModifiedChat && message.unsignedContent != null) { - if (Settings.MarkModifiedMsg) + if (Config.Signature.MarkModifiedMsg) color = "§x §r "; // Custom color code §x : Background Yellow } else { - if (Settings.MarkLegallySignedMsg) + if (Config.Signature.MarkLegallySignedMsg) color = "§y §r "; // Custom color code §y : Background Green } } else { - if (Settings.MarkIllegallySignedMsg) + if (Config.Signature.MarkIllegallySignedMsg) color = "§w §r "; // Custom color code §w : Background Red } } @@ -203,12 +203,12 @@ namespace MinecraftClient.Protocol if (!Directory.Exists("lang")) Directory.CreateDirectory("lang"); - string Language_File = "lang" + Path.DirectorySeparatorChar + Settings.Language + ".lang"; + string Language_File = "lang" + Path.DirectorySeparatorChar + Config.Main.Advanced.Language + ".lang"; //File not found? Try downloading language file from Mojang's servers? if (!File.Exists(Language_File)) { - ConsoleIO.WriteLineFormatted(Translations.Get("chat.download", Settings.Language)); + ConsoleIO.WriteLineFormatted(Translations.Get("chat.download", Config.Main.Advanced.Language)); HttpClient httpClient = new(); try { @@ -217,11 +217,11 @@ namespace MinecraftClient.Protocol string assets_index = fetch_index.Result; fetch_index.Dispose(); - string[] tmp = assets_index.Split(new string[] { "minecraft/lang/" + Settings.Language.ToLower() + ".json" }, StringSplitOptions.None); + string[] tmp = assets_index.Split(new string[] { "minecraft/lang/" + Config.Main.Advanced.Language.ToLower() + ".json" }, StringSplitOptions.None); tmp = tmp[1].Split(new string[] { "hash\": \"" }, StringSplitOptions.None); string hash = tmp[1].Split('"')[0]; //Translations file identifier on Mojang's servers string translation_file_location = Settings.TranslationsFile_Website_Download + '/' + hash[..2] + '/' + hash; - if (Settings.DebugMessages) + if (Settings.Config.Logging.DebugMessages) ConsoleIO.WriteLineFormatted(Translations.Get("chat.request", translation_file_location)); Task fetch_file = httpClient.GetStringAsync(translation_file_location); @@ -266,7 +266,7 @@ namespace MinecraftClient.Protocol } } - if (Settings.DebugMessages) + if (Settings.Config.Logging.DebugMessages) Translations.WriteLineFormatted("chat.loaded"); } else //No external dictionnary found. diff --git a/MinecraftClient/Protocol/MicrosoftAuthentication.cs b/MinecraftClient/Protocol/MicrosoftAuthentication.cs index cbb84a61..b782ea3d 100644 --- a/MinecraftClient/Protocol/MicrosoftAuthentication.cs +++ b/MinecraftClient/Protocol/MicrosoftAuthentication.cs @@ -6,6 +6,8 @@ using System.Globalization; using System.Linq; using System.Runtime.InteropServices; using System.Text.RegularExpressions; +using static MinecraftClient.Settings; +using static MinecraftClient.Settings.MainConfigHealper.MainConfig.GeneralConfig; namespace MinecraftClient.Protocol { @@ -204,7 +206,7 @@ namespace MinecraftClient.Protocol var response = request.Post("application/x-www-form-urlencoded", postData); - if (Settings.DebugMessages) + if (Settings.Config.Logging.DebugMessages) { ConsoleIO.WriteLine(response.ToString()); } @@ -271,7 +273,7 @@ namespace MinecraftClient.Protocol request.Headers.Add("x-xbl-contract-version", "0"); var accessToken = loginResponse.AccessToken; - if (Settings.LoginMethod == "browser") + if (Config.Main.General.Method == LoginMethod.browser) { // Our own client ID must have d= in front of the token or HTTP status 400 // "Stolen" client ID must not have d= in front of the token or HTTP status 400 @@ -288,7 +290,7 @@ namespace MinecraftClient.Protocol + "\"TokenType\": \"JWT\"" + "}"; var response = request.Post("application/json", payload); - if (Settings.DebugMessages) + if (Settings.Config.Logging.DebugMessages) { ConsoleIO.WriteLine(response.ToString()); } @@ -338,7 +340,7 @@ namespace MinecraftClient.Protocol + "\"TokenType\": \"JWT\"" + "}"; var response = request.Post("application/json", payload); - if (Settings.DebugMessages) + if (Settings.Config.Logging.DebugMessages) { ConsoleIO.WriteLine(response.ToString()); } @@ -418,7 +420,7 @@ namespace MinecraftClient.Protocol string payload = "{\"identityToken\": \"XBL3.0 x=" + userHash + ";" + xstsToken + "\"}"; var response = request.Post("application/json", payload); - if (Settings.DebugMessages) + if (Settings.Config.Logging.DebugMessages) { ConsoleIO.WriteLine(response.ToString()); } @@ -440,7 +442,7 @@ namespace MinecraftClient.Protocol request.Headers.Add("Authorization", string.Format("Bearer {0}", accessToken)); var response = request.Get(); - if (Settings.DebugMessages) + if (Settings.Config.Logging.DebugMessages) { ConsoleIO.WriteLine(response.ToString()); } @@ -456,7 +458,7 @@ namespace MinecraftClient.Protocol request.Headers.Add("Authorization", string.Format("Bearer {0}", accessToken)); var response = request.Get(); - if (Settings.DebugMessages) + if (Settings.Config.Logging.DebugMessages) { ConsoleIO.WriteLine(response.ToString()); } diff --git a/MinecraftClient/Protocol/ProfileKey/KeyUtils.cs b/MinecraftClient/Protocol/ProfileKey/KeyUtils.cs index 9d8f4dfd..94cce827 100644 --- a/MinecraftClient/Protocol/ProfileKey/KeyUtils.cs +++ b/MinecraftClient/Protocol/ProfileKey/KeyUtils.cs @@ -25,7 +25,7 @@ namespace MinecraftClient.Protocol.Keys response = request.Post("application/json", ""); - if (Settings.DebugMessages) + if (Settings.Config.Logging.DebugMessages) { ConsoleIO.WriteLine(response.Body.ToString()); } @@ -47,7 +47,7 @@ namespace MinecraftClient.Protocol.Keys { int code = (response == null) ? 0 : response.StatusCode; ConsoleIO.WriteLineFormatted("§cFetch profile key failed: HttpCode = " + code + ", Error = " + e.Message); - if (Settings.DebugMessages) + if (Settings.Config.Logging.DebugMessages) { ConsoleIO.WriteLineFormatted("§c" + e.StackTrace); } diff --git a/MinecraftClient/Protocol/ProfileKey/KeysCache.cs b/MinecraftClient/Protocol/ProfileKey/KeysCache.cs index 44998da4..c11ed0aa 100644 --- a/MinecraftClient/Protocol/ProfileKey/KeysCache.cs +++ b/MinecraftClient/Protocol/ProfileKey/KeysCache.cs @@ -4,6 +4,8 @@ using System.IO; using System.Runtime.Serialization.Formatters.Binary; using System.Timers; using MinecraftClient.Protocol.Session; +using static MinecraftClient.Settings; +using static MinecraftClient.Settings.MainConfigHealper.MainConfig.AdvancedConfig; namespace MinecraftClient.Protocol.Keys { @@ -46,11 +48,11 @@ namespace MinecraftClient.Protocol.Keys keys.Add(login, playerKeyPair); } - if (Settings.ProfileKeyCaching == CacheType.Disk && updatetimer.Enabled == true) + if (Config.Main.Advanced.ProfileKeyCache == CacheType.disk && updatetimer.Enabled == true) { pendingadds.Add(new KeyValuePair(login, playerKeyPair)); } - else if (Settings.ProfileKeyCaching == CacheType.Disk) + else if (Config.Main.Advanced.ProfileKeyCache == CacheType.disk) { SaveToDisk(); } @@ -114,7 +116,7 @@ namespace MinecraftClient.Protocol.Keys //User-editable keys cache file in text format if (File.Exists(KeysCacheFilePlaintext)) { - if (Settings.DebugMessages) + if (Settings.Config.Logging.DebugMessages) ConsoleIO.WriteLineFormatted(Translations.Get("cache.loading_keys", KeysCacheFilePlaintext)); try @@ -133,27 +135,27 @@ namespace MinecraftClient.Protocol.Keys { PlayerKeyPair playerKeyPair = PlayerKeyPair.FromString(value); keys[login] = playerKeyPair; - if (Settings.DebugMessages) + if (Settings.Config.Logging.DebugMessages) ConsoleIO.WriteLineFormatted(Translations.Get("cache.loaded_keys", playerKeyPair.ExpiresAt.ToString())); } catch (InvalidDataException e) { - if (Settings.DebugMessages) + if (Settings.Config.Logging.DebugMessages) ConsoleIO.WriteLineFormatted(Translations.Get("cache.ignore_string_keys", value, e.Message)); } catch (FormatException e) { - if (Settings.DebugMessages) + if (Settings.Config.Logging.DebugMessages) ConsoleIO.WriteLineFormatted(Translations.Get("cache.ignore_string_keys", value, e.Message)); } catch (ArgumentNullException e) { - if (Settings.DebugMessages) + if (Settings.Config.Logging.DebugMessages) ConsoleIO.WriteLineFormatted(Translations.Get("cache.ignore_string_keys", value, e.Message)); } } - else if (Settings.DebugMessages) + else if (Settings.Config.Logging.DebugMessages) { ConsoleIO.WriteLineFormatted(Translations.Get("cache.ignore_line_keys", line)); } @@ -174,7 +176,7 @@ namespace MinecraftClient.Protocol.Keys /// private static void SaveToDisk() { - if (Settings.DebugMessages) + if (Config.Logging.DebugMessages) Translations.WriteLineFormatted("cache.saving_keys"); List KeysCacheLines = new() diff --git a/MinecraftClient/Protocol/ProtocolHandler.cs b/MinecraftClient/Protocol/ProtocolHandler.cs index 7b12de0f..74a2fb5b 100644 --- a/MinecraftClient/Protocol/ProtocolHandler.cs +++ b/MinecraftClient/Protocol/ProtocolHandler.cs @@ -11,6 +11,8 @@ using MinecraftClient.Protocol.Handlers; using MinecraftClient.Protocol.Handlers.Forge; using MinecraftClient.Protocol.Session; using MinecraftClient.Proxy; +using static MinecraftClient.Settings; +using static MinecraftClient.Settings.MainConfigHealper.MainConfig.GeneralConfig; namespace MinecraftClient.Protocol { @@ -64,7 +66,7 @@ namespace MinecraftClient.Protocol { ConsoleIO.WriteLineFormatted(Translations.Get("mcc.not_found", domainVal, e.GetType().FullName, e.Message)); } - }, TimeSpan.FromSeconds(Settings.ResolveSrvRecordsShortTimeout ? 10 : 30)); + }, TimeSpan.FromSeconds(Config.Main.Advanced.ResolveSrvRecords == MainConfigHealper.MainConfig.AdvancedConfig.ResolveSrvRecordType.fast ? 10 : 30)); } domain = domainVal; @@ -99,7 +101,7 @@ namespace MinecraftClient.Protocol { ConsoleIO.WriteLineFormatted(String.Format("§8{0}: {1}", e.GetType().FullName, e.Message)); } - }, TimeSpan.FromSeconds(Settings.ResolveSrvRecordsShortTimeout ? 10 : 30))) + }, TimeSpan.FromSeconds(Config.Main.Advanced.ResolveSrvRecords == MainConfigHealper.MainConfig.AdvancedConfig.ResolveSrvRecordType.fast ? 10 : 30))) { if (protocolversion != 0 && protocolversion != protocolversionTmp) Translations.WriteLineFormatted("error.version_different"); @@ -420,16 +422,16 @@ namespace MinecraftClient.Protocol /// Password /// In case of successful login, will contain session information for multiplayer /// Returns the status of the login (Success, Failure, etc.) - public static LoginResult GetLogin(string user, string pass, AccountType type, out SessionToken session) + public static LoginResult GetLogin(string user, string pass, LoginType type, out SessionToken session) { - if (type == AccountType.Microsoft) + if (type == LoginType.microsoft) { - if (Settings.LoginMethod == "mcc") + if (Config.Main.General.Method == LoginMethod.mcc) return MicrosoftMCCLogin(user, pass, out session); else return MicrosoftBrowserLogin(out session, user); } - else if (type == AccountType.Mojang) + else if (type == LoginType.mojang) { return MojangLogin(user, pass, out session); } @@ -494,7 +496,7 @@ namespace MinecraftClient.Protocol } catch (System.Security.Authentication.AuthenticationException e) { - if (Settings.DebugMessages) + if (Settings.Config.Logging.DebugMessages) { ConsoleIO.WriteLineFormatted("§8" + e.ToString()); } @@ -502,7 +504,7 @@ namespace MinecraftClient.Protocol } catch (System.IO.IOException e) { - if (Settings.DebugMessages) + if (Settings.Config.Logging.DebugMessages) { ConsoleIO.WriteLineFormatted("§8" + e.ToString()); } @@ -514,7 +516,7 @@ namespace MinecraftClient.Protocol } catch (Exception e) { - if (Settings.DebugMessages) + if (Settings.Config.Logging.DebugMessages) { ConsoleIO.WriteLineFormatted("§8" + e.ToString()); } @@ -543,7 +545,7 @@ namespace MinecraftClient.Protocol { session = new SessionToken() { ClientID = Guid.NewGuid().ToString().Replace("-", "") }; ConsoleIO.WriteLineFormatted("§cMicrosoft authenticate failed: " + e.Message); - if (Settings.DebugMessages) + if (Settings.Config.Logging.DebugMessages) { ConsoleIO.WriteLineFormatted("§c" + e.StackTrace); } @@ -601,7 +603,7 @@ namespace MinecraftClient.Protocol session.PlayerID = profile.UUID; session.ID = accessToken; session.RefreshToken = msaResponse.RefreshToken; - Settings.Login = msaResponse.Email; + Config.Main.General.Account.Login = msaResponse.Email; return LoginResult.Success; } else @@ -612,7 +614,7 @@ namespace MinecraftClient.Protocol catch (Exception e) { ConsoleIO.WriteLineFormatted("§cMicrosoft authenticate failed: " + e.Message); - if (Settings.DebugMessages) + if (Settings.Config.Logging.DebugMessages) { ConsoleIO.WriteLineFormatted("§c" + e.StackTrace); } @@ -632,7 +634,7 @@ namespace MinecraftClient.Protocol var expTimestamp = long.Parse(json.Properties["exp"].StringValue, NumberStyles.Any, CultureInfo.CurrentCulture); var now = DateTime.Now; var tokenExp = UnixTimeStampToDateTime(expTimestamp); - if (Settings.DebugMessages) + if (Settings.Config.Logging.DebugMessages) { ConsoleIO.WriteLine("Access token expiration time is " + tokenExp.ToString()); } @@ -772,7 +774,7 @@ namespace MinecraftClient.Protocol catch (Exception e) { ConsoleIO.WriteLineFormatted("§8" + e.GetType().ToString() + ": " + e.Message); - if (Settings.DebugMessages) + if (Settings.Config.Logging.DebugMessages) { ConsoleIO.WriteLineFormatted("§8" + e.StackTrace); } @@ -815,7 +817,7 @@ namespace MinecraftClient.Protocol catch (Exception e) { ConsoleIO.WriteLineFormatted("§8" + e.GetType().ToString() + ": " + e.Message); - if (Settings.DebugMessages) + if (Settings.Config.Logging.DebugMessages) { ConsoleIO.WriteLineFormatted("§8" + e.StackTrace); } @@ -890,14 +892,14 @@ namespace MinecraftClient.Protocol { try { - if (Settings.DebugMessages) + if (Settings.Config.Logging.DebugMessages) ConsoleIO.WriteLineFormatted(Translations.Get("debug.request", host)); TcpClient client = ProxyHandler.NewTcpClient(host, 443, true); SslStream stream = new(client.GetStream()); stream.AuthenticateAsClient(host, null, SslProtocols.Tls12, true); // Enable TLS 1.2. Hotfix for #1780 - if (Settings.DebugMessages) + if (Settings.Config.Logging.DebugMessages) foreach (string line in headers) ConsoleIO.WriteLineFormatted("§8> " + line); @@ -905,7 +907,7 @@ namespace MinecraftClient.Protocol System.IO.StreamReader sr = new(stream); string raw_result = sr.ReadToEnd(); - if (Settings.DebugMessages) + if (Settings.Config.Logging.DebugMessages) { ConsoleIO.WriteLine(""); foreach (string line in raw_result.Split('\n')) @@ -915,7 +917,7 @@ namespace MinecraftClient.Protocol if (raw_result.StartsWith("HTTP/1.1")) { postResult = raw_result[(raw_result.IndexOf("\r\n\r\n") + 4)..]; - statusCode = Settings.str2int(raw_result.Split(' ')[1]); + statusCode = int.Parse(raw_result.Split(' ')[1], NumberStyles.Any, CultureInfo.CurrentCulture); } else statusCode = 520; //Web server is returning an unknown error } diff --git a/MinecraftClient/Protocol/ProxiedWebRequest.cs b/MinecraftClient/Protocol/ProxiedWebRequest.cs index 3fcde5fc..73d9fe26 100644 --- a/MinecraftClient/Protocol/ProxiedWebRequest.cs +++ b/MinecraftClient/Protocol/ProxiedWebRequest.cs @@ -109,7 +109,7 @@ namespace MinecraftClient.Protocol requestMessage.Add(body); } else requestMessage.Add(""); // - if (Settings.DebugMessages) + if (Settings.Config.Logging.DebugMessages) { foreach (string l in requestMessage) { diff --git a/MinecraftClient/Protocol/ReplayHandler.cs b/MinecraftClient/Protocol/ReplayHandler.cs index 610273e3..abaeecfc 100644 --- a/MinecraftClient/Protocol/ReplayHandler.cs +++ b/MinecraftClient/Protocol/ReplayHandler.cs @@ -398,7 +398,7 @@ namespace MinecraftClient.Protocol private static void WriteDebugLog(string t) { - if (Settings.DebugMessages && logOutput) + if (Settings.Config.Logging.DebugMessages && logOutput) WriteLog(t); } diff --git a/MinecraftClient/Protocol/Session/CacheType.cs b/MinecraftClient/Protocol/Session/CacheType.cs deleted file mode 100644 index 81faed00..00000000 --- a/MinecraftClient/Protocol/Session/CacheType.cs +++ /dev/null @@ -1,20 +0,0 @@ -namespace MinecraftClient.Protocol.Session -{ - public enum CacheType - { - /// - /// Do not perform any session caching, always perform login requests from scratch. - /// - None, - - /// - /// Cache session information in memory to reuse session tokens across server joins. - /// - Memory, - - /// - /// Cache session information in a SessionCache file to share session tokens between different MCC instances. - /// - Disk - }; -} diff --git a/MinecraftClient/Protocol/Session/SessionCache.cs b/MinecraftClient/Protocol/Session/SessionCache.cs index 232c5e5e..82ebe005 100644 --- a/MinecraftClient/Protocol/Session/SessionCache.cs +++ b/MinecraftClient/Protocol/Session/SessionCache.cs @@ -4,6 +4,8 @@ using System.IO; using System.Runtime.Serialization; using System.Runtime.Serialization.Formatters.Binary; using System.Timers; +using static MinecraftClient.Settings; +using static MinecraftClient.Settings.MainConfigHealper.MainConfig.AdvancedConfig; namespace MinecraftClient.Protocol.Session { @@ -54,11 +56,11 @@ namespace MinecraftClient.Protocol.Session sessions.Add(login, session); } - if (Settings.SessionCaching == CacheType.Disk && updatetimer.Enabled == true) + if (Config.Main.Advanced.SessionCache == CacheType.disk && updatetimer.Enabled == true) { pendingadds.Add(new KeyValuePair(login, session)); } - else if (Settings.SessionCaching == CacheType.Disk) + else if (Config.Main.Advanced.SessionCache == CacheType.disk) { SaveToDisk(); } @@ -122,7 +124,7 @@ namespace MinecraftClient.Protocol.Session //Grab sessions in the Minecraft directory if (File.Exists(SessionCacheFileMinecraft)) { - if (Settings.DebugMessages) + if (Config.Logging.DebugMessages) ConsoleIO.WriteLineFormatted(Translations.Get("cache.loading", Path.GetFileName(SessionCacheFileMinecraft))); Json.JSONData mcSession = new(Json.JSONData.DataType.String); try @@ -155,7 +157,7 @@ namespace MinecraftClient.Protocol.Session sessionItem["uuid"].StringValue.Replace("-", ""), clientID )); - if (Settings.DebugMessages) + if (Config.Logging.DebugMessages) ConsoleIO.WriteLineFormatted(Translations.Get("cache.loaded", login, session.ID)); sessions[login] = session; } @@ -169,7 +171,7 @@ namespace MinecraftClient.Protocol.Session //Serialized session cache file in binary format if (File.Exists(SessionCacheFileSerialized)) { - if (Settings.DebugMessages) + if (Config.Logging.DebugMessages) ConsoleIO.WriteLineFormatted(Translations.Get("cache.converting", SessionCacheFileSerialized)); try @@ -181,7 +183,7 @@ namespace MinecraftClient.Protocol.Session #pragma warning restore SYSLIB0011 // BinaryFormatter.Deserialize() is obsolete foreach (KeyValuePair item in sessionsTemp) { - if (Settings.DebugMessages) + if (Config.Logging.DebugMessages) ConsoleIO.WriteLineFormatted(Translations.Get("cache.loaded", item.Key, item.Value.ID)); sessions[item.Key] = item.Value; } @@ -199,7 +201,7 @@ namespace MinecraftClient.Protocol.Session //User-editable session cache file in text format if (File.Exists(SessionCacheFilePlaintext)) { - if (Settings.DebugMessages) + if (Config.Logging.DebugMessages) ConsoleIO.WriteLineFormatted(Translations.Get("cache.loading_session", SessionCacheFilePlaintext)); try @@ -215,17 +217,17 @@ namespace MinecraftClient.Protocol.Session { string login = Settings.ToLowerIfNeed(keyValue[0]); SessionToken session = SessionToken.FromString(keyValue[1]); - if (Settings.DebugMessages) + if (Config.Logging.DebugMessages) ConsoleIO.WriteLineFormatted(Translations.Get("cache.loaded", login, session.ID)); sessions[login] = session; } catch (InvalidDataException e) { - if (Settings.DebugMessages) + if (Config.Logging.DebugMessages) ConsoleIO.WriteLineFormatted(Translations.Get("cache.ignore_string", keyValue[1], e.Message)); } } - else if (Settings.DebugMessages) + else if (Config.Logging.DebugMessages) { ConsoleIO.WriteLineFormatted(Translations.Get("cache.ignore_line", line)); } @@ -246,7 +248,7 @@ namespace MinecraftClient.Protocol.Session /// private static void SaveToDisk() { - if (Settings.DebugMessages) + if (Config.Logging.DebugMessages) Translations.WriteLineFormatted("cache.saving"); List sessionCacheLines = new() diff --git a/MinecraftClient/Proxy/ProxyHandler.cs b/MinecraftClient/Proxy/ProxyHandler.cs index b62459bb..5d703dad 100644 --- a/MinecraftClient/Proxy/ProxyHandler.cs +++ b/MinecraftClient/Proxy/ProxyHandler.cs @@ -1,5 +1,7 @@ -using System.Net.Sockets; +using System; +using System.Net.Sockets; using Starksoft.Aspen.Proxy; +using Tomlet.Attributes; namespace MinecraftClient.Proxy { @@ -11,7 +13,45 @@ namespace MinecraftClient.Proxy public static class ProxyHandler { - public enum Type { HTTP, SOCKS4, SOCKS4a, SOCKS5 }; + public static Configs Config = new(); + + [TomlDoNotInlineObject] + public class Configs + { + [TomlInlineComment("$Config.Proxy.Enabled_Login$")] + public bool Enabled_Login = false; + + [TomlInlineComment("$Config.Proxy.Enabled_Ingame$")] + public bool Enabled_Ingame = false; + + [TomlInlineComment("$Config.Proxy.Server$")] + public ProxyInfoConfig Server = new("0.0.0.0", 8080); + + [TomlInlineComment("$Config.Proxy.Proxy_Type$")] + public ProxyType Proxy_Type = ProxyType.HTTP; + + [TomlInlineComment("$Config.Proxy.Username$")] + public string Username = ""; + + [TomlInlineComment("$Config.Proxy.Password$")] + public string Password = ""; + + public void OnSettingUpdate() { } + + public struct ProxyInfoConfig + { + public string Host; + public ushort Port; + + public ProxyInfoConfig(string host, ushort port) + { + Host = host; + Port = port; + } + } + + public enum ProxyType { HTTP, SOCKS4, SOCKS4a, SOCKS5 }; + } private static readonly ProxyClientFactory factory = new(); private static IProxyClient? proxy; @@ -28,27 +68,26 @@ namespace MinecraftClient.Proxy { try { - if (login ? Settings.ProxyEnabledLogin : Settings.ProxyEnabledIngame) + if (login ? Config.Enabled_Login : Config.Enabled_Ingame) { ProxyType innerProxytype = ProxyType.Http; - switch (Settings.proxyType) + switch (Config.Proxy_Type) { - case Type.HTTP: innerProxytype = ProxyType.Http; break; - case Type.SOCKS4: innerProxytype = ProxyType.Socks4; break; - case Type.SOCKS4a: innerProxytype = ProxyType.Socks4a; break; - case Type.SOCKS5: innerProxytype = ProxyType.Socks5; break; + case Configs.ProxyType.HTTP: innerProxytype = ProxyType.Http; break; + case Configs.ProxyType.SOCKS4: innerProxytype = ProxyType.Socks4; break; + case Configs.ProxyType.SOCKS4a: innerProxytype = ProxyType.Socks4a; break; + case Configs.ProxyType.SOCKS5: innerProxytype = ProxyType.Socks5; break; } - if (Settings.ProxyUsername != "" && Settings.ProxyPassword != "") - { - proxy = factory.CreateProxyClient(innerProxytype, Settings.ProxyHost, Settings.ProxyPort, Settings.ProxyUsername, Settings.ProxyPassword); - } - else proxy = factory.CreateProxyClient(innerProxytype, Settings.ProxyHost, Settings.ProxyPort); + if (Config.Username != "" && Config.Password != "") + proxy = factory.CreateProxyClient(innerProxytype, Config.Server.Host, Config.Server.Port, Config.Username, Config.Password); + else + proxy = factory.CreateProxyClient(innerProxytype, Config.Server.Host, Config.Server.Port); if (!proxy_ok) { - ConsoleIO.WriteLineFormatted(Translations.Get("proxy.connected", Settings.ProxyHost, Settings.ProxyPort)); + ConsoleIO.WriteLineFormatted(Translations.Get("proxy.connected", Config.Server.Host, Config.Server.Port)); proxy_ok = true; } diff --git a/MinecraftClient/Resources/lang/en.ini b/MinecraftClient/Resources/lang/en.ini index 444f5b10..7694728e 100644 --- a/MinecraftClient/Resources/lang/en.ini +++ b/MinecraftClient/Resources/lang/en.ini @@ -1,5 +1,8 @@ [mcc] # Messages from MCC itself +mcc.help_us_translate=Help us translate MCC: https://mccteam.github.io/guide/translation.html +mcc.run_with_default_settings=\nMCC is running with default settings. +mcc.settings_generated=§cSettings file MinecraftClient.ini has been generated. mcc.login=Login : mcc.login_basic_io=Please type the username or email of your choice. mcc.password=Password : @@ -67,7 +70,7 @@ error.forgeforce=Cannot force Forge support for this Minecraft version! error.login=Login failed : error.login.migrated=Account migrated, use e-mail as username. error.login.server=Login servers are unavailable. Please try again later. -error.login.blocked=Incorrect password, blacklisted IP or too many logins. +error.login.blocked=Incorrect username/password, blacklisted IP or too many logins. error.login.response=Invalid server response. error.login.premium=User not premium. error.login.network=Network error. @@ -643,3 +646,215 @@ bot.scriptScheduler.task=triggeronfirstlogin: {0}\n triggeronlogin: {1}\n trigge # TestBot bot.testBot.told=Bot: {0} told me : {1} bot.testBot.said=Bot: {0} said : {1} + + +[config] + +config.load=Settings have been loaded from {0} +config.load.fail=§cFailed to load settings:§r +config.saving=§aThe current setting is saved as {0} + +# Head +config.Head=Startup Config File\n\n# New to Minecraft Console Client? See README and sample configuration files here:\n# https://github.com/MCCTeam/Minecraft-Console-Client/tree/master/MinecraftClient/config\n\n# Want to upgrade to a newer version? See https://github.com/MCCTeam/Minecraft-Console-Client/#download + +# Main.General +config.Main.General.account=Login=Email or Name. Use "-" as password for offline mode. Leave blank to prompt user on startup. +config.Main.General.login=Server address and port. Host can be filled in with domain name or IP. +config.Main.General.server_info=Account type: mojang OR microsoft. Also affects interactive login in console. +config.Main.General.method=Microsoft Account sign-in method: mcc OR browser. + +# Main.Advanced +config.Main.Advanced=Make sure you understand what each setting does before changing anything! +config.Main.Advanced.language=Fill in with in-game locale code, https://minecraft.fandom.com/wiki/Language +config.Main.Advanced.console_title= +config.Main.Advanced.internal_cmd_char=Use 'none', 'slash' or 'backslash' +config.Main.Advanced.message_cooldown=Minimum delay in seconds between messages to avoid being kicked for spam. +config.Main.Advanced.bot_owners=Name list or myfile.txt, one name per line. /!\ Server admins can impersonate owners! +config.Main.Advanced.mc_version=Use 'auto' or '1.X.X' values. Allows to skip server info retrieval. +config.Main.Advanced.mc_forge=Use 'auto', 'no' or 'force'. Force-enabling only works for MC 1.13+. +config.Main.Advanced.brand_info=Use 'mcc', 'vanilla', or 'none'. This is how MCC identifies itself to the server. +config.Main.Advanced.chatbot_log_file=Leave empty for no logfile +config.Main.Advanced.private_msgs_cmd_name=Used by RemoteControl bot +config.Main.Advanced.show_system_messages=System messages for server ops +config.Main.Advanced.show_xpbar_messages=Messages displayed above xp bar, set this to false in case of xp bar spam +config.Main.Advanced.show_chat_links=Decode links embedded in chat messages and show them in console +config.Main.Advanced.show_inventory_layout=Show inventory layout as ASCII art in inventory command +config.Main.Advanced.terrain_and_movements=Uses more ram, cpu, bandwidth but allows you to move around +config.Main.Advanced.inventory_handling=Toggle inventory handling (beta) +config.Main.Advanced.entity_handling=Toggle entity handling (beta) +config.Main.Advanced.session_cache=How to retain session tokens. Use 'none', 'memory' or 'disk' +config.Main.Advanced.profilekey_cache=How to retain profile key. Use 'none', 'memory' or 'disk' +config.Main.Advanced.resolve_srv_records=Use 'no', 'fast' (5s timeout), or 'yes'. Required for joining some servers. +config.Main.Advanced.account_list=See README > 'Servers and Accounts file' for more info about this +config.Main.Advanced.server_list=See README > 'Servers and Accounts file' for more info about this +config.Main.Advanced.player_head_icon=Only works on Windows XP-8 or Windows 10 with old console +config.Main.Advanced.exit_on_failure=Disable pauses on error, for using MCC in non-interactive scripts +config.Main.Advanced.script_cache=Cache compiled scripts for faster load on low-end devices +config.Main.Advanced.timestamps=Prepend timestamps to chat messages +config.Main.Advanced.auto_respawn=Toggle auto respawn if client player was dead (make sure your spawn point is safe) +config.Main.Advanced.minecraft_realms=Enable support for joining Minecraft Realms worlds +config.Main.Advanced.move_head_while_walking=Enable head movement while walking to avoid anti-cheat triggers +config.Main.Advanced.timeout=Set a custom timeout in seconds (Default: 30). Use only if you know what you're doing. +config.Main.Advanced.enable_emoji=If turned off, the emoji will be replaced with a simpler character (for /chunk status) +config.Main.Advanced.movement_speed=A movement speed higher than 2 may be considered cheating. +config.Main.Advanced.language.invaild=The language code is invalid. + +# Signature +config.Signature=Chat settings (affects minecraft 1.19+) +config.Signature.LoginWithSecureProfile=Microsoft accounts only. If disabled, will not be able to sign chat and join servers configured with "enforce-secure-profile=true" +config.Signature.SignChat=Whether to sign the chat send from MCC +config.Signature.SignMessageInCommand=Whether to sign the messages contained in the commands sent by MCC. For example, the message in "/msg" and "/me" +config.Signature.MarkLegallySignedMsg=Use green color block to mark chat with legitimate signatures +config.Signature.MarkModifiedMsg=Use yellow color block to mark chat that have been modified by the server. +config.Signature.MarkIllegallySignedMsg=Use red color block to mark chat without legitimate signature +config.Signature.MarkSystemMessage=Use gray color block to mark system message (always without signature) +config.Signature.ShowModifiedChat=Set to true to display messages modified by the server, false to display the original signed messages +config.Signature.ShowIllegalSignedChat=Whether to display chat and messages in commands without legal signatures + +# Logging +config.Logging=Only affect the messages on console. +config.Logging.DebugMessages=Please enable this before submitting bug reports. Thanks! +config.Logging.ChatMessages=Show server chat messages +config.Logging.InfoMessages=Informative messages (i.e Most of the message from MCC) +config.Logging.WarningMessages=Show warning messages +config.Logging.ErrorMessages=Show error messages +config.Logging.ChatFilter=Regex for filtering chat message +config.Logging.DebugFilter=Regex for filtering debug message +config.Logging.FilterMode=blacklist OR whitelist. Blacklist hide message match regex. Whitelist show message match regex +config.Logging.LogToFile=Write log messages to file +config.Logging.LogFile=Log file name +config.Logging.PrependTimestamp=Prepend timestamp to messages in log file +config.Logging.SaveColorCodes=Keep color codes in the saved text (§b) + +# AppVars +config.AppVars.Variables=can be used in some other fields as %yourvar%\n# %username% and %serverip% are reserved variables. + +# Proxy +config.Proxy=Connect to a server via a proxy instead of connecting directly\n# If Mojang session services are blocked on your network, set enabled=login to login using proxy but connect directly to the server\n# If connecting to port 25565 (Minecraft) is blocked on your network, set enabled=true to login & connect using the proxy\n# /!\ Make sure your server rules allow Proxies or VPNs before setting enabled=true, or you may face consequences! +config.Proxy.Enabled_Login=Whether to connect to the login server through a proxy. +config.Proxy.Enabled_Ingame=Whether to connect to the game server through a proxy. +config.Proxy.Server=Proxy server must allow HTTPS for login, and non-443 ports for playing +config.Proxy.Proxy_Type=Supported types: HTTP, SOCKS4, SOCKS4a, SOCKS5 +config.Proxy.Username=Only required for password-protected proxies +config.Proxy.Password=Only required for password-protected proxies + +# ChatFormat +config.ChatFormat=MCC does it best to detect chat messages, but some server have unusual chat formats\n# When this happens, you'll need to configure chat format below, see README > 'Detecting chat messages'\n# Do not forget to uncomment (remove '#') these settings if modifying them +config.ChatFormat.Builtins=MCC support for common message formats. Set "false" to avoid conflicts with custom formats. + +# MCSettings +config.MCSettings=Settings below are sent to the server and only affect server-side things like your skin +config.MCSettings.Enabled=If disabled, settings below are not sent to the server +config.MCSettings.Locale=Use any language implemented in Minecraft +config.MCSettings.RenderDistance=Value range: [0 - 255] +config.MCSettings.Difficulty=MC 1.7- difficulty. peaceful, easy, normal, difficult +config.MCSettings.ChatMode=Use 'enabled', 'commands', or 'disabled'. Allows to mute yourself... +config.MCSettings.ChatColors=Allows disabling chat colors server-side +config.MCSettings.MainHand=MC 1.9+ main hand. left or right + +# ChatBot +config.ChatBot================================ #\n# Minecraft Console Client Bots #\n# =============================== # + +# ChatBot.Alerts +config.ChatBot.Alerts=Get alerted when specified words are detected in chat\n# Useful for moderating your server or detecting when someone is talking to you +config.ChatBot.Alerts.Beep_Enabled=Play a beep sound when a word is detected in addition to highlighting. +config.ChatBot.Alerts.Trigger_By_Words=Triggers an alert after receiving a specified keyword. +config.ChatBot.Alerts.Trigger_By_Rain=Trigger alerts when it rains and when it stops. +config.ChatBot.Alerts.Trigger_By_Thunderstorm=Triggers alerts at the beginning and end of thunderstorms. +config.ChatBot.Alerts.Matches_File=List of words/strings to alert you on, e.g. "Yourname" +config.ChatBot.Alerts.Excludes_File=List of words/strings to NOT alert you on, e.g. "" +config.ChatBot.Alerts.Log_To_File=Log alerts info a file. +config.ChatBot.Alerts.Log_File=The name of a file where alers logs will be written. + +# ChatBot.AntiAFK +config.ChatBot.AntiAfk=Send a command on a regular or random basis or make the bot walk around randomly to avoid automatic AFK disconnection\n# /!\ Make sure your server rules do not forbid anti-AFK mechanisms!\n# /!\ Make sure you keep the bot in an enclosure to prevent it wandering off if you're using terrain handling! (Recommended size 5x5x5) +config.ChatBot.AntiAfk.Delay=10 = 1s (Can also be a random number between 2 numbers, example: 50-600) (Default: 600) +config.ChatBot.AntiAfk.Command=Command to send to the server +config.ChatBot.AntiAfk.Use_Terrain_Handling=Use terrain handling to enable the bot to move around +config.ChatBot.AntiAfk.Walk_Range=The range the bot can move around randomly (Note: the bigger the range, the slower the bot will be) +config.ChatBot.AntiAfk.Walk_Retries=How many timec can the bot fail trying to move before using the command method + +# ChatBot.AutoAttack +config.ChatBot.AutoAttack=Automatically attack hostile mobs around you\n# You need to enable Entity Handling to use this bot\n# /!\ Make sure server rules allow your planned use of AutoAttack\n# /!\ SERVER PLUGINS may consider AutoAttack to be a CHEAT MOD and TAKE ACTION AGAINST YOUR ACCOUNT so DOUBLE CHECK WITH SERVER RULES! +config.ChatBot.AutoAttack.Mode=single or multi. single target one mob per attack. multi target all mobs in range per attack +config.ChatBot.AutoAttack.Priority=health or distance. Only needed when using single mode +config.ChatBot.AutoAttack.Cooldown_Time=How long to wait between each attack. Use auto to let MCC calculate it +config.ChatBot.AutoAttack.Interaction=Possible values: Interact, Attack (default), InteractAt (Interact and Attack) +config.ChatBot.AutoAttack.Attack_Hostile=Allow attacking hostile mobs +config.ChatBot.AutoAttack.Attack_Passive=Allow attacking passive mobs +config.ChatBot.AutoAttack.List_Mode=Wether to treat the entities list as a whitelist or as a blacklist +config.ChatBot.AutoAttack.Entites_List=All entity types can be found here: https://bit.ly/3Rg68lp + +# ChatBot.AutoCraft +config.ChatBot.AutoCraft=Automatically craft items in your inventory\n# See README > 'Using the AutoCraft bot' for how to use\n# You need to enable Inventory Handling to use this bot\n# You should also enable Terrain and Movements if you need to use a crafting table + +# ChatBot.AutoDrop +config.ChatBot.AutoDrop=Automatically drop items in inventory\n# You need to enable Inventory Handling to use this bot\n# See this file for an up-to-date list of item types you can use with this bot:\n# https://github.com/MCCTeam/Minecraft-Console-Client/blob/master/MinecraftClient/Inventory/ItemType.cs +config.ChatBot.AutoDrop.Mode=include, exclude or everything. Include: drop item IN the list. Exclude: drop item NOT IN the list +config.ChatBot.AutoDrop.Items=separate each item name with a comma ',': "ItemOne", "ItemTwo" + +# ChatBot.AutoEat +config.ChatBot.AutoEat=Automatically eat food when your Hunger value is low\n# You need to enable Inventory Handling to use this bot + +# ChatBot.AutoFishing +config.ChatBot.AutoFishing=Automatically catch fish using a fishing rod\n# Guide: https://mccteam.github.io/guide/chat-bots.html#auto-fishing\n# /!\ Make sure server rules allow automated farming before using this bot +config.ChatBot.AutoFishing.Antidespawn=Keep it as false if you have not changed it before. +config.ChatBot.AutoFishing.Mainhand=Use the main hand or the off hand to hold the rod. +config.ChatBot.AutoFishing.Auto_Start=Whether to start fishing automatically after entering a world. +config.ChatBot.AutoFishing.Cast_Delay=How soon to re-cast after successful fishing. +config.ChatBot.AutoFishing.Fishing_Delay=How long after entering the game to start fishing (seconds). +config.ChatBot.AutoFishing.Fishing_Timeout=Fishing timeout (seconds). Timeout will trigger a re-cast. +config.ChatBot.AutoFishing.Durability_Limit=Will not use rods with less durability than this (full durability is 64). Set to zero to disable this feature. +config.ChatBot.AutoFishing.Auto_Rod_Switch=Switch to a new rod from inventory after the current rod is unavailable. +config.ChatBot.AutoFishing.Stationary_Threshold=Hooks moving in the X and Z axes below this threshold will be considered stationary. +config.ChatBot.AutoFishing.Hook_Threshold=A stationary hook moving on the Y-axis above this threshold will be considered to have caught a fish. +config.ChatBot.AutoFishing.Log_Fish_Bobber=For debugging purposes, you can use this log to adjust the two thresholds mentioned above. +config.ChatBot.AutoFishing.Movements=Some plugins do not allow the player to fish in one place. This allows the player to change position/angle after each fish caught. Usage can be found in the Guide. + + +# ChatBot.AutoRelog +config.ChatBot.AutoRelog=Automatically relog when disconnected by server, for example because the server is restating\n# Put keywords/strings such as "Server is restarting" in kick messages file to relog when the message is seen\n# /!\ Use ignorekickmessage=true at own risk! Server staff might not appreciate if you auto-relog on manual kicks +config.ChatBot.AutoRelog.Delay=use 10 for 10 seconds, 10-60 for a random delay between 10 and 60 seconds +config.ChatBot.AutoRelog.Retries=retries when failing to relog to the server. use -1 for unlimited retries +config.ChatBot.AutoRelog.Ignore_Kick_Message=when set to true, autorelog will reconnect regardless of kick messages +config.ChatBot.AutoRelog.Kick_Messages_File=file with list of matches in kick messages that will trigger autorelog + +# ChatBot.AutoRespond +config.ChatBot.AutoRespond=Run commands or send messages automatically when a specified pattern is detected in chat\n# /!\ Server admins can spoof chat messages (/nick, /tellraw) so keep this in mind when implementing AutoRespond rules\n# /!\ This bot may get spammy depending on your rules, although the global messagecooldown setting can help you avoiding accidental spam +config.ChatBot.AutoRespond.Match_Colors=Do not remove colors from text (Note: Your matches will have to include color codes (ones using the § character) in order to work) + +# ChatBot.ChatLog +config.ChatBot.ChatLog=Logs chat messages in a file on disk. + +# ChatBot.FollowPlayer +config.ChatBot.FollowPlayer=Enabled you to make the bot follow you\n# NOTE: This is an experimental feature, the bot can be slow at times, you need to walk with a normal speed and to sometimes stop for it to be able to keep up with you\n# It's similar to making animals follow you when you're holding food in your hand.\n# This is due to a slow pathfinding algorithm, we're working on getting a better one\n# You can tweak the update limit and find what works best for you. (NOTE: Do not but a very low one, because you might achieve the opposite,\n# this might clog the thread for terain handling) and thus slow the bot even more.\n# /!\ Make sure server rules allow an option like this in the rules of the server before using this bot +config.ChatBot.FollowPlayer.Update_Limit=The rate at which the bot does calculations (10 = 1s) (Default: 5) (You can tweak this if you feel the bot is too slow) +config.ChatBot.FollowPlayer.Stop_At_Distance=Do not follow the player if he is in the range of 3 blocks (prevents the bot from pushing a player in an infinite loop) + +# ChatBot.HangmanGame +config.ChatBot.HangmanGame=A small game to demonstrate chat interactions. Players can guess mystery words one letter at a time.\n# You need to have ChatFormat working correctly and add yourself in botowners to start the game with /tell start\n# /!\ This bot may get a bit spammy if many players are interacting with it + +# ChatBot.Mailer +config.ChatBot.Mailer=Relay messages between players and servers, like a mail plugin\n# This bot can store messages when the recipients are offline, and send them when they join the server\n# /!\ Server admins can spoof PMs (/tellraw, /nick) so enable this bot only if you trust server admins + +# ChatBot.Map +config.ChatBot.Map=Allows you to render maps into .jpg images\n# This is useful for solving captchas which use maps\n# The maps are rendered into Rendered_Maps folder.\n# NOTE:\n# This feature is currently only useful for solving captchas which use maps.\n# If some servers have a very short time for solving captchas, enabe auto_render_on_update and prepare to open the file quickly.\n# On linux you can use FTP to access generated files.\n# In the future it might will be possible to display maps directly in the console with a separate command.\n# /!\ Make sure server rules allow bots to be used on the server, or you risk being punished. +config.ChatBot.Map.Should_Resize=Should the map be resized? (Default one is small 128x128) +config.ChatBot.Map.Resize_To=The size to resize the map to (Note: the bigger it is, the lower the quallity is) +config.ChatBot.Map.Auto_Render_On_Update=Automatically render the map once it's received or updated from/by the server +config.ChatBot.Map.Delete_All_On_Unload=Delete all rendered maps on unload/reload (Does not delete the images if you exit the client) +config.ChatBot.Map.Notify_On_First_Update=Get a notification when you have gotten a map from the server for the first time + +# ChatBot.PlayerListLogger +config.ChatBot.PlayerListLogger=Log the list of players periodically into a textual file +config.ChatBot.PlayerListLogger.Delay=10 = 1s + +# ChatBot.RemoteControl +config.ChatBot.RemoteControl=Send MCC console commands to your bot through server PMs (/tell)\n# You need to have ChatFormat working correctly and add yourself in botowners to use the bot\n# /!\ Server admins can spoof PMs (/tellraw, /nick) so enable RemoteControl only if you trust server admins + +# ChatBot.ReplayCapture +config.ChatBot.ReplayCapture=Enable recording of the game (/replay start) and replay it later using the Replay Mod (https://www.replaymod.com/)\n# Please note that due to technical limitations, the client player (you) will not be shown in the replay file\n# /!\ You SHOULD use /replay stop or exit the program gracefully with /quit OR THE REPLAY FILE MAY GET CORRUPT! +config.ChatBot.ReplayCapture.Backup_Interval=How long should replay file be auto-saved, in seconds. Use -1 to disable + +# ChatBot.ScriptScheduler +config.ChatBot.ScriptScheduler=Schedule commands and scripts to launch on various events such as server join, date/time or time interval\n# See README > 'Using the Script Scheduler' for more info diff --git a/MinecraftClient/Resources/lang/zh-CHS.ini b/MinecraftClient/Resources/lang/zh-Hans.ini similarity index 94% rename from MinecraftClient/Resources/lang/zh-CHS.ini rename to MinecraftClient/Resources/lang/zh-Hans.ini index 24417e4f..b9c78242 100644 --- a/MinecraftClient/Resources/lang/zh-CHS.ini +++ b/MinecraftClient/Resources/lang/zh-Hans.ini @@ -1,5 +1,8 @@ [mcc] # Messages from MCC itself +mcc.help_us_translate=帮助我们翻译MCC:https://mccteam.github.io/guide/translation.html +mcc.run_with_default_settings=\nMCC正在使用默认配置运行。 +mcc.settings_generated=§c配置文件 MinecraftClient.ini 已经生成。 mcc.login=登录: mcc.login_basic_io=请输入用户名或邮箱。 mcc.password=密码: @@ -30,7 +33,7 @@ mcc.single_cmd=§7已发送命令§8 {0} mcc.joined=已成功加入服务器。\n输入 '{0}quit' 离开服务器。 mcc.reconnect=等待5秒 (剩余{0}次尝试)... mcc.disconnect.lost=失去连接。 -mcc.disconnect.server=从服务器断开: +mcc.disconnect.server=从服务器断开连接: mcc.disconnect.login=连接失败: mcc.link=链接:{0} mcc.player_dead_respawn=你死了!1秒后自动重生。 @@ -65,7 +68,7 @@ error.forgeforce=无法为此Minecraft版本强制启动Forge支持! error.login=登录失败: error.login.migrated=帐户已迁移,使用电子邮件作为用户名。 error.login.server=登录服务器不可用。请稍后再试。 -error.login.blocked=密码错误、IP被禁用或登录次数过多。 +error.login.blocked=用户名/密码错误、IP被禁用或登录次数过多。 error.login.response=服务器响应无效。 error.login.premium=不是Premium用户。 error.login.network=网络错误。 @@ -528,3 +531,18 @@ bot.scriptScheduler.task=triggeronfirstlogin: {0}\n triggeronlogin: {1}\n trigge # TestBot bot.testBot.told=Bot:{0}对我说:{1} bot.testBot.said=Bot:{0}说:{1} + +[config] + +config.load=已从 {0} 加载设置。 +config.load.fail=§c加载设置时出错:§r +config.saving=§a当前设置已保存至 {0} + +# Head +config.Head=启动配置文件\n\n# 对 MCC(Minecraft 命令行客户端)不熟悉?请看 README 和示例配置文件:\n# https://github.com/MCCTeam/Minecraft-Console-Client/tree/master/MinecraftClient/config\n\n# 想升级到较新的版本吗?请访问 https://github.com/MCCTeam/Minecraft-Console-Client/#download + +# Main.General +config.Main.General.account=Login请填写邮箱或玩家名称。若要以离线模式登录请使用"-"作为密码。若留空则使用交互式登录。 +config.Main.General.login=游戏服务器的地址和端口,可填入域名或IP地址。(可删除端口字段,会解析SRV记录) +config.Main.General.server_info=帐户类型:mojang 或是 microsoft。此项设置也会影响交互式登录。 +config.Main.General.method=微软账户的登录方式:mcc 或是 browser(手动在网页上登录)。 diff --git a/MinecraftClient/Scripting/CSharpRunner.cs b/MinecraftClient/Scripting/CSharpRunner.cs index 65ea78a3..c3dd20f5 100644 --- a/MinecraftClient/Scripting/CSharpRunner.cs +++ b/MinecraftClient/Scripting/CSharpRunner.cs @@ -5,6 +5,7 @@ using System.IO; using System.Linq; using System.Text; using DynamicRun.Builder; +using static MinecraftClient.Settings; namespace MinecraftClient { @@ -43,7 +44,7 @@ namespace MinecraftClient lock (CompileCache) { ///Process and compile script only if not already compiled - if (!Settings.CacheScripts || !CompileCache.ContainsKey(scriptHash)) + if (!Config.Main.Advanced.CacheScript || !CompileCache.ContainsKey(scriptHash)) { //Process different sections of the script file bool scriptMain = true; @@ -111,10 +112,10 @@ namespace MinecraftClient //Retrieve compiled assembly assembly = result.Assembly; - if (Settings.CacheScripts) + if (Config.Main.Advanced.CacheScript) CompileCache[scriptHash] = assembly!; } - else if (Settings.CacheScripts) + else if (Config.Main.Advanced.CacheScript) assembly = CompileCache[scriptHash]; } @@ -293,7 +294,7 @@ namespace MinecraftClient if (localVars != null && localVars.ContainsKey(varName)) return localVars[varName]; else - return Settings.GetVar(varName); + return Settings.Config.AppVar.GetVar(varName); } /// @@ -305,7 +306,7 @@ namespace MinecraftClient { if (localVars != null && localVars.ContainsKey(varName)) localVars.Remove(varName); - return Settings.SetVar(varName, varValue); + return Settings.Config.AppVar.SetVar(varName, varValue); } /// @@ -347,7 +348,7 @@ namespace MinecraftClient /// True if the account was found and loaded public bool SetAccount(string accountAlias, bool andReconnect = false) { - bool result = Settings.SetAccount(accountAlias); + bool result = Settings.Config.Main.Advanced.SetAccount(accountAlias); if (result && andReconnect) ReconnectToTheServer(); return result; @@ -360,7 +361,7 @@ namespace MinecraftClient /// True if the server IP was valid and loaded, false otherwise public bool SetServer(string server, bool andReconnect = false) { - bool result = Settings.SetServerIP(server); + bool result = Settings.Config.Main.SetServerIP(new MainConfigHealper.MainConfig.ServerInfoConfig(server), true); if (result && andReconnect) ReconnectToTheServer(); return result; diff --git a/MinecraftClient/Scripting/ChatBot.cs b/MinecraftClient/Scripting/ChatBot.cs index 4007155d..51f04829 100644 --- a/MinecraftClient/Scripting/ChatBot.cs +++ b/MinecraftClient/Scripting/ChatBot.cs @@ -6,6 +6,7 @@ using System.Text; using System.Text.RegularExpressions; using MinecraftClient.Inventory; using MinecraftClient.Mapping; +using static MinecraftClient.Settings; namespace MinecraftClient { @@ -521,9 +522,9 @@ namespace MinecraftClient text = GetVerbatim(text); //User-defined regex for private chat messages - if (Settings.ChatFormat_Private != null) + if (Config.ChatFormat.Private != null) { - Match regexMatch = Settings.ChatFormat_Private.Match(text); + Match regexMatch = new Regex(Config.ChatFormat.Private).Match(text); if (regexMatch.Success && regexMatch.Groups.Count >= 3) { sender = regexMatch.Groups[1].Value; @@ -533,7 +534,7 @@ namespace MinecraftClient } //Built-in detection routine for private messages - if (Settings.ChatFormat_Builtins) + if (Config.ChatFormat.Builtins) { string[] tmp = text.Split(' '); try @@ -632,9 +633,9 @@ namespace MinecraftClient text = GetVerbatim(text); //User-defined regex for public chat messages - if (Settings.ChatFormat_Public != null) + if (Config.ChatFormat.Public != null) { - Match regexMatch = Settings.ChatFormat_Public.Match(text); + Match regexMatch = new Regex(Config.ChatFormat.Public).Match(text); if (regexMatch.Success && regexMatch.Groups.Count >= 3) { sender = regexMatch.Groups[1].Value; @@ -644,7 +645,7 @@ namespace MinecraftClient } //Built-in detection routine for public messages - if (Settings.ChatFormat_Builtins) + if (Config.ChatFormat.Builtins) { string[] tmp = text.Split(' '); @@ -735,9 +736,9 @@ namespace MinecraftClient text = GetVerbatim(text); //User-defined regex for teleport requests - if (Settings.ChatFormat_TeleportRequest != null) + if (Config.ChatFormat.TeleportRequest != null) { - Match regexMatch = Settings.ChatFormat_TeleportRequest.Match(text); + Match regexMatch = new Regex(Config.ChatFormat.TeleportRequest).Match(text); if (regexMatch.Success && regexMatch.Groups.Count >= 2) { sender = regexMatch.Groups[1].Value; @@ -746,7 +747,7 @@ namespace MinecraftClient } //Built-in detection routine for teleport requests - if (Settings.ChatFormat_Builtins) + if (Config.ChatFormat.Builtins) { string[] tmp = text.Split(' '); @@ -786,7 +787,26 @@ namespace MinecraftClient ConsoleIO.WriteLogLine(String.Format("[{0}] {1}", GetType().Name, text)); else Handler.Log.Info(String.Format("[{0}] {1}", GetType().Name, text)); - string logfile = Settings.ExpandVars(Settings.chatbotLogFile); + string logfile = Settings.Config.AppVar.ExpandVars(Config.Main.Advanced.ChatbotLogFile); + + if (!String.IsNullOrEmpty(logfile)) + { + if (!File.Exists(logfile)) + { + try { Directory.CreateDirectory(Path.GetDirectoryName(logfile)!); } + catch { return; /* Invalid path or access denied */ } + try { File.WriteAllText(logfile, ""); } + catch { return; /* Invalid file name or access denied */ } + } + + File.AppendAllLines(logfile, new string[] { GetTimestamp() + ' ' + text }); + } + } + + protected static void LogToConsole(string botName, object? text) + { + ConsoleIO.WriteLogLine(String.Format("[{0}] {1}", botName, text)); + string logfile = Settings.Config.AppVar.ExpandVars(Config.Main.Advanced.ChatbotLogFile); if (!String.IsNullOrEmpty(logfile)) { @@ -808,7 +828,7 @@ namespace MinecraftClient /// Debug log text to write protected void LogDebugToConsole(object text) { - if (Settings.DebugMessages) + if (Settings.Config.Logging.DebugMessages) LogToConsole(text); } @@ -840,7 +860,7 @@ namespace MinecraftClient /// Optional delay, in seconds, before restarting protected void ReconnectToTheServer(int ExtraAttempts = 3, int delaySeconds = 0) { - if (Settings.DebugMessages) + if (Settings.Config.Logging.DebugMessages) ConsoleIO.WriteLogLine(Translations.Get("chatbot.reconnect", GetType().Name)); McClient.ReconnectionAttemptsLeft = ExtraAttempts; Program.Restart(delaySeconds); @@ -873,7 +893,7 @@ namespace MinecraftClient /// Message protected void SendPrivateMessage(string player, string message) { - SendText(String.Format("/{0} {1} {2}", Settings.PrivateMsgsCmdName, player, message)); + SendText(String.Format("/{0} {1} {2}", Config.Main.Advanced.PrivateMsgsCmdName, player, message)); } /// diff --git a/MinecraftClient/Settings.cs b/MinecraftClient/Settings.cs index e2bce54c..8c3bcdee 100644 --- a/MinecraftClient/Settings.cs +++ b/MinecraftClient/Settings.cs @@ -1,330 +1,199 @@ using System; using System.Collections.Generic; -using System.Globalization; +using System.Diagnostics.CodeAnalysis; using System.IO; using System.Linq; +using System.Reflection.Metadata; using System.Runtime.CompilerServices; using System.Text; using System.Text.RegularExpressions; -using System.Threading.Tasks; -using MinecraftClient.Mapping; +using System.Threading; using MinecraftClient.Protocol; -using MinecraftClient.Protocol.Session; +using MinecraftClient.Proxy; +using Tomlet; +using Tomlet.Attributes; +using Tomlet.Models; +using static MinecraftClient.Settings.AppVarConfigHelper; +using static MinecraftClient.Settings.ChatBotConfigHealper; +using static MinecraftClient.Settings.ChatFormatConfigHelper; +using static MinecraftClient.Settings.LoggingConfigHealper; +using static MinecraftClient.Settings.MainConfigHealper; +using static MinecraftClient.Settings.MainConfigHealper.MainConfig.AdvancedConfig; +using static MinecraftClient.Settings.MCSettingsConfigHealper; +using static MinecraftClient.Settings.SignatureConfigHelper; namespace MinecraftClient { - /// - /// Contains main settings for Minecraft Console Client - /// Allows settings loading from an INI file - /// - public static class Settings { - //Minecraft Console Client client information used for BrandInfo setting - private const string MCCBrandInfo = "Minecraft-Console-Client/" + Program.Version; + // Minecraft Console Client client information used for BrandInfo setting + public const string MCCBrandInfo = "Minecraft-Console-Client/" + Program.Version; - //Main Settings. - //Login: Username or email adress used as login for Minecraft/Mojang account - //Username: The actual username of the user, obtained after login to the account - public static string Login = ""; - public static string Username = ""; - public static string Password = ""; - public static ProtocolHandler.AccountType AccountType = ProtocolHandler.AccountType.Mojang; - public static string LoginMethod = "mcc"; - public static string ServerIP = ""; - public static ushort ServerPort = 25565; - public static string ServerVersion = ""; - public static bool ServerForceForge = false; - public static bool ServerAutodetectForge = true; - public static string SingleCommand = ""; - public static string ConsoleTitle = ""; + //Other Settings + public static string TranslationsFile_FromMCDir = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + @"\.minecraft\assets\objects\48\482e0dae05abfa35ab5cb076e41fda77b4fb9a08"; //MC 1.19 en_GB.lang + public static string TranslationsFile_Website_Index = "https://piston-meta.mojang.com/v1/packages/b5c7548ddb9e584e84a5f762da5b78211c715a63/1.19.json"; + public static string TranslationsFile_Website_Download = "http://resources.download.minecraft.net"; - //Proxy Settings - public static bool ProxyEnabledLogin = false; - public static bool ProxyEnabledIngame = false; - public static string ProxyHost = ""; - public static int ProxyPort = 0; - public static Proxy.ProxyHandler.Type proxyType = Proxy.ProxyHandler.Type.HTTP; - public static string ProxyUsername = ""; - public static string ProxyPassword = ""; + public static GlobalConfig Config = new(); - //Minecraft Settings - public static bool MCSettings_Enabled = true; - public static string MCSettings_Locale = "en_US"; - public static byte MCSettings_Difficulty = 0; - public static byte MCSettings_RenderDistance = 8; - public static byte MCSettings_ChatMode = 0; - public static bool MCSettings_ChatColors = true; - public static byte MCSettings_MainHand = 0; - public static bool MCSettings_Skin_Hat = true; - public static bool MCSettings_Skin_Cape = true; - public static bool MCSettings_Skin_Jacket = false; - public static bool MCSettings_Skin_Sleeve_Left = false; - public static bool MCSettings_Skin_Sleeve_Right = false; - public static bool MCSettings_Skin_Pants_Left = false; - public static bool MCSettings_Skin_Pants_Right = false; - public static byte MCSettings_Skin_All + public static class InternalConfig { - get + public static string ServerIP = String.Empty; + + public static ushort ServerPort = 25565; + + public static string Username = string.Empty; + + public static string Password = string.Empty; + + public static string MinecraftVersion = string.Empty; + + public static bool InteractiveMode = true; + + public static bool GravityEnabled = true; + } + + public class GlobalConfig + { + public HeadComment Head = new(); + + public MainConfig Main { - return (byte)( - ((MCSettings_Skin_Cape ? 1 : 0) << 0) - | ((MCSettings_Skin_Jacket ? 1 : 0) << 1) - | ((MCSettings_Skin_Sleeve_Left ? 1 : 0) << 2) - | ((MCSettings_Skin_Sleeve_Right ? 1 : 0) << 3) - | ((MCSettings_Skin_Pants_Left ? 1 : 0) << 4) - | ((MCSettings_Skin_Pants_Right ? 1 : 0) << 5) - | ((MCSettings_Skin_Hat ? 1 : 0) << 6) - ); + get { return MainConfigHealper.Config; } + set { MainConfigHealper.Config = value; MainConfigHealper.Config.OnSettingUpdate(); } + } + + [TomlPrecedingComment("$config.Signature$")] + public SignatureConfig Signature + { + get { return SignatureConfigHelper.Config; } + set { SignatureConfigHelper.Config = value; SignatureConfigHelper.Config.OnSettingUpdate(); } + } + + [TomlPrecedingComment("$config.Logging$")] + public LoggingConfig Logging + { + get { return LoggingConfigHealper.Config; } + set { LoggingConfigHealper.Config = value; LoggingConfigHealper.Config.OnSettingUpdate(); } + } + + public AppVarConfig AppVar + { + get { return AppVarConfigHelper.Config; } + set { AppVarConfigHelper.Config = value; AppVarConfigHelper.Config.OnSettingUpdate(); } + } + + [TomlPrecedingComment("$config.Proxy$")] + public ProxyHandler.Configs Proxy + { + get { return ProxyHandler.Config; } + set { ProxyHandler.Config = value; ProxyHandler.Config.OnSettingUpdate(); } + } + + [TomlPrecedingComment("$config.MCSettings$")] + public MCSettingsConfig MCSettings + { + get { return MCSettingsConfigHealper.Config; } + set { MCSettingsConfigHealper.Config = value; MCSettingsConfigHealper.Config.OnSettingUpdate(); } + } + + [TomlPrecedingComment("$config.ChatFormat$")] + public ChatFormatConfig ChatFormat + { + get { return ChatFormatConfigHelper.Config; } + set { ChatFormatConfigHelper.Config = value; ChatFormatConfigHelper.Config.OnSettingUpdate(); } + } + + [TomlPrecedingComment("$config.ChatBot$")] + public ChatBotConfig ChatBot + { + get { return ChatBotConfigHealper.Config; } + set { ChatBotConfigHealper.Config = value; } + } + + [TomlDoNotInlineObject] + public class HeadComment + { + [TomlPrecedingComment("$config.Head$")] + [TomlProperty("Current Version (Do not edit this)")] + public string Version { get; set; } = Program.BuildInfo ?? Program.MCHighestVersion; } } - //Other Settings - public static string TranslationsFile_FromMCDir = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + @"\.minecraft\assets\objects\8b\8bf1298bd44b0e5b21d747394a8acd2c218e09ed"; //MC 1.17 en_GB.lang - public static string TranslationsFile_Website_Index = "https://launchermeta.mojang.com/v1/packages/e5af543d9b3ce1c063a97842c38e50e29f961f00/1.17.json"; - public static string TranslationsFile_Website_Download = "http://resources.download.minecraft.net"; - public static TimeSpan messageCooldown = TimeSpan.FromSeconds(2); - public static List Bots_Owners = new(); - public static string Language = "en_GB"; - public static bool interactiveMode = true; - public static char internalCmdChar = '/'; - public static bool playerHeadAsIcon = false; - public static string chatbotLogFile = ""; - public static bool CacheScripts = true; - public static string? BrandInfo = MCCBrandInfo; - public static bool DisplaySystemMessages = true; - public static bool DisplayXPBarMessages = true; - public static bool DisplayChatLinks = true; - public static bool DisplayInventoryLayout = true; - public static bool TerrainAndMovements = false; - public static bool GravityEnabled = true; - public static bool InventoryHandling = false; - public static string PrivateMsgsCmdName = "tell"; - public static CacheType SessionCaching = CacheType.Disk; - public static CacheType ProfileKeyCaching = CacheType.Disk; - public static bool ResolveSrvRecords = true; - public static bool ResolveSrvRecordsShortTimeout = true; - public static bool EntityHandling = false; - public static bool AutoRespawn = false; - public static bool MinecraftRealmsEnabled = true; - public static bool MoveHeadWhileWalking = true; - public static int Timeout = 30; - public static bool EnableEmoji = true; - public static int MovementSpeed = 2; - - // Signature - public static bool LoginWithSecureProfile = true; - public static bool SignChat = true; - public static bool SignMessageInCommand = true; - public static bool MarkLegallySignedMsg = false; - public static bool MarkModifiedMsg = true; - public static bool MarkIllegallySignedMsg = true; - public static bool MarkSystemMessage = false; - public static bool ShowModifiedChat = true; - public static bool ShowIllegalSignedChat = true; - - // Logging - public enum FilterModeEnum { Blacklist, Whitelist } - public static bool DebugMessages = false; - public static bool ChatMessages = true; - public static bool InfoMessages = true; - public static bool WarningMessages = true; - public static bool ErrorMessages = true; - public static Regex? ChatFilter = null; - public static Regex? DebugFilter = null; - public static FilterModeEnum FilterMode = FilterModeEnum.Blacklist; - public static bool LogToFile = false; - public static string LogFile = "console-log.txt"; - public static bool PrependTimestamp = false; - public static bool SaveColorCodes = false; - - //AntiAFK Settings - public static bool AntiAFK_Enabled = false; - public static string AntiAFK_Delay = "600"; - public static string AntiAFK_Command = "/ping"; - public static bool AntiAFK_UseTerrain_Handling = false; - public static int AntiAFK_Walk_Range = 5; - public static int AntiAFK_Walk_Retries = 20; - - //Hangman Settings - public static bool Hangman_Enabled = false; - public static bool Hangman_English = true; - public static string Hangman_FileWords_EN = "hangman-en.txt"; - public static string Hangman_FileWords_FR = "hangman-fr.txt"; - - //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"; - public static string Alerts_ExcludesFile = "alerts-exclude.txt"; - public static string Alerts_LogFile = "alerts-log.txt"; - - //ChatLog Settings - public static bool ChatLog_Enabled = false; - public static bool ChatLog_DateTime = true; - public static string ChatLog_File = "chatlog.txt"; - public static ChatBots.ChatLog.MessageFilter ChatLog_Filter = ChatBots.ChatLog.MessageFilter.AllMessages; - - //PlayerListLog Settings - public static bool PlayerLog_Enabled = false; - public static string PlayerLog_File = "playerlog.txt"; - public static int PlayerLog_Delay = 600; - - //AutoRelog Settings - public static bool AutoRelog_Enabled = false; - public static int AutoRelog_Delay_Min = 10; - public static int AutoRelog_Delay_Max = 10; - public static int AutoRelog_Retries = 3; - public static bool AutoRelog_IgnoreKickMessage = false; - public static string AutoRelog_KickMessagesFile = "kickmessages.txt"; - - //Script Scheduler Settings - public static bool ScriptScheduler_Enabled = false; - public static string ScriptScheduler_TasksFile = "tasks.ini"; - - //Remote Control - public static bool RemoteCtrl_Enabled = false; - public static bool RemoteCtrl_AutoTpaccept = true; - public static bool RemoteCtrl_AutoTpaccept_Everyone = false; - - //Chat Message Parsing - public static bool ChatFormat_Builtins = true; - public static Regex? ChatFormat_Public = null; - public static Regex? ChatFormat_Private = null; - public static Regex? ChatFormat_TeleportRequest = null; - - //Auto Respond - public static bool AutoRespond_Enabled = false; - public static string AutoRespond_Matches = "matches.ini"; - public static bool AutoRespond_MatchColors = false; - - //Auto Attack - public static bool AutoAttack_Enabled = false; - public static string AutoAttack_Mode = "single"; - public static string AutoAttack_Priority = "distance"; - public static bool AutoAttack_OverrideAttackSpeed = false; - public static double AutoAttack_CooldownSeconds = 1; - public static InteractType AutoAttack_Interaction = InteractType.Attack; - public static bool AutoAttack_Attack_Hostile = true; - public static bool AutoAttack_Attack_Passive = false; - public static string AutoAttack_ListMode = "blacklist"; - public static string AutoAttack_ListFile = "autoattack-list.txt"; - - //Auto Fishing - public static bool AutoFishing_Enabled = false; - public static bool AutoFishing_Antidespawn = false; - public static bool AutoFishing_Mainhand = true; - public static bool AutoFishing_AutoStart = true; - public static double AutoFishing_CastDelay = 0.4; - public static double AutoFishing_FishingDelay = 3.0; - public static double AutoFishing_FishingTimeout = 300.0; - public static double AutoFishing_DurabilityLimit = 2; - public static bool AutoFishing_AutoRodSwitch = true; - public static double AutoFishing_StationaryThreshold = 0.001; - public static double AutoFishing_HookThreshold = 0.2; - public static bool AutoFishing_LogFishingBobber = false; - public static double[,]? AutoFishing_Location = null; - - //Auto Eating - public static bool AutoEat_Enabled = false; - public static int AutoEat_hungerThreshold = 6; - - //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"; - public static string Mailer_IgnoreListFile = "MailerIgnoreList.ini"; - public static bool Mailer_PublicInteractions = false; - public static int Mailer_MaxMailsPerPlayer = 10; - public static int Mailer_MaxDatabaseSize = 10000; - public static int Mailer_MailRetentionDays = 30; - - //AutoDrop - public static bool AutoDrop_Enabled = false; - public static string AutoDrop_Mode = "include"; - public static string AutoDrop_items = ""; - - // Replay Mod - public static bool ReplayMod_Enabled = false; - public static int ReplayMod_BackupInterval = 3000; - - // Follow Player - public static bool FollowPlayer_Enabled = false; - public static int FollowPlayer_UpdateLimit = 10; - public static int FollowPlayer_StopAtDistance = 3; - - // Map - public static bool Map_Enabled = false; - public static bool Map_Should_Resize = false; - public static int Map_Resize_To = 256; - public static bool Map_Auto_Render_On_Update = false; - public static bool Map_Delete_All_On_Unload = true; - public static bool Map_Notify_On_First_Update = true; - - //Custom app variables and Minecraft accounts - private static readonly Dictionary AppVars = new(); - private static readonly Dictionary> Accounts = new(); - private static readonly Dictionary> Servers = new(); - - //Temporary Server Alias storage when server list is not loaded yet - private static string? ServerAliasTemp = null; - - //Mapping for settings sections in the INI file - private enum Section { Default, Main, AppVars, Proxy, MCSettings, AntiAFK, Hangman, Alerts, ChatLog, AutoRelog, ScriptScheduler, RemoteControl, ChatFormat, AutoRespond, AutoAttack, AutoFishing, AutoEat, AutoCraft, AutoDrop, Mailer, ReplayMod, FollowPlayer, PlayerListLogger, Map, Logging, Signature }; - - /// - /// Get settings section from name - /// - /// Section name - /// Section enum - private static Section GetSection(string name) + public static bool LoadFromFile(string filepath) { - if (Enum.TryParse(name, true, out Section pMode)) - return pMode; - return Section.Default; - } - - /// - /// Load settings from the given INI file - /// - /// File to load - public static void LoadFile(string file) - { - Task.Factory.StartNew(() => ConsoleIO.WriteLogLine("[Settings] Loading Settings from " + Path.GetFullPath(file))); - if (File.Exists(file)) + TomlDocument document; + try + { + document = TomlParser.ParseFile(filepath); + } + catch (Exception ex) { try { - Section section = Section.Default; - foreach (var lineRAW in File.ReadLines(file)) + // The old configuration file has been backed up as A. + string configString = File.ReadAllText(filepath); + if (configString.Contains("Some settings missing here after an upgrade?")) { - string line = lineRAW.Split('#')[0].Trim(); - if (line.Length > 1) - { - 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[(argName.Length + 1)..]; - LoadSingleSetting(section, argName, argValue); - } - } - } + string newFilePath = Path.ChangeExtension(filepath, ".backup.ini"); + File.Copy(filepath, newFilePath, true); + ConsoleIO.WriteLineFormatted("§cPlease use the newly generated MinecraftClient.ini"); + ConsoleIO.WriteLineFormatted("§cThe old MinecraftClient.ini has been backed up as " + newFilePath); + return true; } } - catch (IOException) { } + catch { } + ConsoleIO.WriteLineFormatted(Translations.GetOrNull("config.load.fail") ?? "§cFailed to load settings:§r"); + ConsoleIO.WriteLine(ex.Message); + ConsoleIO.WriteLine(Translations.GetOrNull("mcc.run_with_default_settings") ?? "\nMCC is running with default settings."); + return false; + } + + Config = TomletMain.To(document); + + return false; + } + + public static void WriteToFile(string filepath, bool backupOldFile) + { + string tomlString = TomletMain.TomlStringFrom(Config); + + string[] tomlList = tomlString.Split('\n'); + StringBuilder newConfig = new(); + foreach (string line in tomlList) + { + Match match = Regex.Match(line, @"^(.*)\s?#\s\$(.+)\$\s*$"); + if (match.Success && match.Groups.Count == 3) + { + string config = match.Groups[1].Value, comment = match.Groups[2].Value; + if (config.Length > 0) + newConfig.Append(config).Append(' ', Math.Max(1, 45 - config.Length) - 1); + newConfig.Append("# ").AppendLine(Translations.TryGet(comment).ReplaceLineEndings()); + } + else + { + newConfig.AppendLine(line); + } + } + + bool needUpdate = true; + string newConfigStr = newConfig.ToString(); + if (File.Exists(filepath)) + { + try + { + string oldConfigStr = File.ReadAllText(filepath); + if (oldConfigStr == newConfigStr) + needUpdate = false; + } + catch { } + } + + if (needUpdate) + { + if (backupOldFile && File.Exists(filepath)) + File.Copy(filepath, Path.ChangeExtension(filepath, ".backup.ini"), true); + File.WriteAllText(filepath, newConfigStr); } } @@ -344,19 +213,7 @@ namespace MinecraftClient //Load settings as --setting=value and --section.setting=value if (!argument.Contains('=')) throw new ArgumentException(Translations.Get("error.setting.argument_syntax", argument)); - Section section = Section.Main; - string argName = argument[2..].Split('=')[0]; - string argValue = argument[(argName.Length + 3)..]; - if (argName.Contains('.')) - { - string sectionName = argName.Split('.')[0]; - section = GetSection(sectionName); - if (section == Section.Default) - throw new ArgumentException(Translations.Get("error.setting.unknown_section", argument, sectionName)); - argName = argName.Split('.')[1]; - } - if (!LoadSingleSetting(section, argName, argValue)) - throw new ArgumentException(Translations.Get("error.setting.unknown_or_invalid", argument)); + throw new NotImplementedException(); } else if (argument.StartsWith("-") && argument.Length > 1) { @@ -367,679 +224,830 @@ namespace MinecraftClient { switch (positionalIndex) { - case 0: Login = argument; break; - case 1: Password = argument; break; - case 2: if (!SetServerIP(argument)) ServerAliasTemp = argument; break; - case 3: SingleCommand = argument; break; + case 0: + Config.Main.General.Account.Login = argument; + break; + case 1: + InternalConfig.Password = argument; + break; + case 2: + Config.Main.SetServerIP(new MainConfig.ServerInfoConfig(argument), true); + break; + case 3: + // SingleCommand = argument; + break; } positionalIndex++; } } } - /// - /// Load a single setting from INI file or command-line argument - /// - /// Settings section - /// Setting name - /// Setting value - /// TRUE if setting was valid - private static bool LoadSingleSetting(Section section, string argName, string argValue) + public static class MainConfigHealper { - switch (section) + public static MainConfig Config = new(); + + [TomlDoNotInlineObject] + public class MainConfig { - case Section.Main: - switch (ToLowerIfNeed(argName)) - { - case "login": Login = argValue; return true; - case "password": Password = argValue; return true; - case "type": - AccountType = argValue == "mojang" - ? ProtocolHandler.AccountType.Mojang - : ProtocolHandler.AccountType.Microsoft; return true; - case "method": - 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; - case "consoletitle": ConsoleTitle = argValue; return true; - case "timestamps": ConsoleIO.EnableTimestamps = str2bool(argValue); return true; - case "exitonfailure": interactiveMode = !str2bool(argValue); return true; - case "playerheadicon": playerHeadAsIcon = str2bool(argValue); return true; - case "chatbotlogfile": chatbotLogFile = argValue; return true; - case "mcversion": ServerVersion = argValue; return true; - case "messagecooldown": messageCooldown = TimeSpan.FromSeconds(str2int(argValue)); return true; - case "scriptcache": CacheScripts = str2bool(argValue); return true; - case "showsystemmessages": DisplaySystemMessages = str2bool(argValue); return true; - case "showxpbarmessages": DisplayXPBarMessages = str2bool(argValue); return true; - case "showchatlinks": DisplayChatLinks = str2bool(argValue); return true; - case "showinventorylayout": DisplayInventoryLayout = str2bool(argValue); return true; - case "terrainandmovements": TerrainAndMovements = str2bool(argValue); return true; - case "entityhandling": EntityHandling = str2bool(argValue); return true; - case "enableentityhandling": EntityHandling = str2bool(argValue); return true; - case "inventoryhandling": InventoryHandling = str2bool(argValue); 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; - case "minecraftrealms": MinecraftRealmsEnabled = str2bool(argValue); return true; - case "moveheadwhilewalking": MoveHeadWhileWalking = str2bool(argValue); return true; - case "timeout": Timeout = str2int(argValue); return true; - case "enableemoji": EnableEmoji = str2bool(argValue); return true; - case "movementspwwd": MovementSpeed = str2int(argValue); return true; + public GeneralConfig General = new(); - case "botowners": - Bots_Owners.Clear(); - 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)) - Bots_Owners.Add(name.Trim()); - return true; + [TomlPrecedingComment("$config.Main.Advanced$")] + public AdvancedConfig Advanced = new(); - case "internalcmdchar": - argValue = ToLowerIfNeed(argValue); - switch (argValue) - { - case "none": internalCmdChar = ' '; break; - case "slash": internalCmdChar = '/'; break; - case "backslash": internalCmdChar = '\\'; break; - } - return true; - case "sessioncache": - if (argValue == "none") { SessionCaching = CacheType.None; } - else if (argValue == "memory") { SessionCaching = CacheType.Memory; } - else if (argValue == "disk") { SessionCaching = CacheType.Disk; } - return true; - - case "profilekeycache": - if (argValue == "none") { ProfileKeyCaching = CacheType.None; } - else if (argValue == "memory") { ProfileKeyCaching = CacheType.Memory; } - else if (argValue == "disk") { ProfileKeyCaching = CacheType.Disk; } - return true; - - case "accountlist": - if (File.Exists(argValue)) - { - foreach (string account_line in File.ReadAllLines(argValue)) - { - //Each line contains account data: 'Alias,Login,Password' - string[] account_data = account_line.Split('#')[0].Trim().Split(','); - if (account_data.Length == 3) - Accounts[ToLowerIfNeed(account_data[0])] - = new KeyValuePair(account_data[1], account_data[2]); - } - - //Try user value against aliases after load - SetAccount(Login); - } - return true; - - case "serverlist": - if (File.Exists(argValue)) - { - //Backup current server info - string server_host_temp = ServerIP; - ushort server_port_temp = ServerPort; - - foreach (string server_line in File.ReadAllLines(argValue)) - { - //Each line contains server data: 'Alias,Host:Port' - string[] server_data = server_line.Split('#')[0].Trim().Split(','); - server_data[0] = ToLowerIfNeed(server_data[0]); - if (server_data.Length == 2 - && server_data[0] != "localhost" - && !server_data[0].Contains('.') - && SetServerIP(server_data[1])) - Servers[server_data[0]] - = new KeyValuePair(ServerIP, ServerPort); - } - - //Restore current server info - ServerIP = server_host_temp; - ServerPort = server_port_temp; - - //Try server value against aliases after load - if (!String.IsNullOrEmpty(ServerAliasTemp)) - { - SetServerIP(ServerAliasTemp); - ServerAliasTemp = null; - } - } - return true; - - case "brandinfo": - BrandInfo = ToLowerIfNeed(argValue.Trim()) switch - { - "mcc" => MCCBrandInfo, - "vanilla" => "vanilla", - _ => null, - }; - return true; - - case "resolvesrvrecords": - if (ToLowerIfNeed(argValue.Trim()) == "fast") - { - ResolveSrvRecords = true; - ResolveSrvRecordsShortTimeout = true; - } - else - { - ResolveSrvRecords = str2bool(argValue); - ResolveSrvRecordsShortTimeout = false; - } - return true; - - case "mcforge": - if (ToLowerIfNeed(argValue) == "auto") - { - ServerAutodetectForge = true; - ServerForceForge = false; - } - else - { - ServerAutodetectForge = false; - ServerForceForge = str2bool(argValue); - } - return true; - } - break; - - case Section.Signature: - switch (ToLowerIfNeed(argName)) - { - case "login_with_secure_profile": LoginWithSecureProfile = str2bool(argValue); return true; - case "sign_chat": SignChat = str2bool(argValue); return true; - case "sign_message_in_command": SignMessageInCommand = str2bool(argValue); return true; - case "mark_legally_signed_msg": MarkLegallySignedMsg = str2bool(argValue); return true; - case "mark_modified_msg": MarkModifiedMsg = str2bool(argValue); return true; - case "mark_illegally_signed_msg": MarkIllegallySignedMsg = str2bool(argValue); return true; - case "mark_system_message": MarkSystemMessage = str2bool(argValue); return true; - case "show_modified_chat": ShowModifiedChat = str2bool(argValue); return true; - case "show_illegal_signed_chat": ShowIllegalSignedChat = str2bool(argValue); return true; - } - break; - - case Section.Logging: - switch (ToLowerIfNeed(argName)) - { - case "debugmessages": DebugMessages = str2bool(argValue); return true; - case "chatmessages": ChatMessages = str2bool(argValue); return true; - case "warningmessages": WarningMessages = str2bool(argValue); return true; - case "errormessages": ErrorMessages = str2bool(argValue); return true; - case "infomessages": InfoMessages = str2bool(argValue); return true; - case "chatfilter": ChatFilter = new Regex(argValue); return true; - case "debugfilter": DebugFilter = new Regex(argValue); return true; - case "filtermode": - if (ToLowerIfNeed(argValue).StartsWith("white")) - FilterMode = FilterModeEnum.Whitelist; - else - FilterMode = FilterModeEnum.Blacklist; - return true; - case "logtofile": LogToFile = str2bool(argValue); return true; - case "logfile": LogFile = argValue; return true; - case "prependtimestamp": PrependTimestamp = str2bool(argValue); return true; - case "savecolorcodes": SaveColorCodes = str2bool(argValue); return true; - } - break; - - case Section.Alerts: - 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; - case "logtofile": Alerts_File_Logging = str2bool(argValue); return true; - case "logfile": Alerts_LogFile = argValue; return true; - } - break; - - case Section.AntiAFK: - switch (ToLowerIfNeed(argName)) - { - case "enabled": AntiAFK_Enabled = str2bool(argValue); return true; - case "delay": AntiAFK_Delay = argValue; return true; - case "command": AntiAFK_Command = argValue == "" ? "/ping" : argValue; return true; - case "use_terrain_handling": AntiAFK_UseTerrain_Handling = str2bool(argValue); return true; - case "walk_range": AntiAFK_Walk_Range = str2int(argValue); return true; - case "walk_retries": AntiAFK_Walk_Retries = str2int(argValue); return true; - } - break; - - case Section.AutoRelog: - switch (ToLowerIfNeed(argName)) - { - case "enabled": AutoRelog_Enabled = str2bool(argValue); return true; - case "retries": AutoRelog_Retries = str2int(argValue); return true; - case "ignorekickmessage": AutoRelog_IgnoreKickMessage = str2bool(argValue); return true; - case "kickmessagesfile": AutoRelog_KickMessagesFile = argValue; return true; - - case "delay": - string[] delayParts = argValue.Split('-'); - if (delayParts.Length == 1) - { - AutoRelog_Delay_Min = str2int(delayParts[0]); - AutoRelog_Delay_Max = AutoRelog_Delay_Min; - } - else - { - AutoRelog_Delay_Min = str2int(delayParts[0]); - AutoRelog_Delay_Max = str2int(delayParts[1]); - } - return true; - } - break; - - case Section.ChatLog: - switch (ToLowerIfNeed(argName)) - { - case "enabled": ChatLog_Enabled = str2bool(argValue); return true; - case "timestamps": ChatLog_DateTime = str2bool(argValue); return true; - case "filter": ChatLog_Filter = ChatBots.ChatLog.str2filter(argValue); return true; - case "logfile": ChatLog_File = argValue; return true; - } - break; - - case Section.Hangman: - switch (ToLowerIfNeed(argName)) - { - case "enabled": Hangman_Enabled = str2bool(argValue); return true; - case "english": Hangman_English = str2bool(argValue); return true; - case "wordsfile": Hangman_FileWords_EN = argValue; return true; - case "fichiermots": Hangman_FileWords_FR = argValue; return true; - } - break; - - case Section.ScriptScheduler: - switch (ToLowerIfNeed(argName)) - { - case "enabled": ScriptScheduler_Enabled = str2bool(argValue); return true; - case "tasksfile": ScriptScheduler_TasksFile = argValue; return true; - } - break; - - case Section.RemoteControl: - switch (ToLowerIfNeed(argName)) - { - case "enabled": RemoteCtrl_Enabled = str2bool(argValue); return true; - case "autotpaccept": RemoteCtrl_AutoTpaccept = str2bool(argValue); return true; - case "tpaccepteveryone": RemoteCtrl_AutoTpaccept_Everyone = str2bool(argValue); return true; - } - break; - - case Section.ChatFormat: - switch (ToLowerIfNeed(argName)) - { - case "builtins": ChatFormat_Builtins = str2bool(argValue); return true; - case "public": ChatFormat_Public = new Regex(argValue); return true; - case "private": ChatFormat_Private = new Regex(argValue); return true; - case "tprequest": ChatFormat_TeleportRequest = new Regex(argValue); return true; - } - break; - - case Section.Proxy: - switch (ToLowerIfNeed(argName)) - { - case "enabled": - ProxyEnabledLogin = ProxyEnabledIngame = str2bool(argValue); - if (ToLowerIfNeed(argValue.Trim()) == "login") - ProxyEnabledLogin = true; - return true; - case "type": - 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; } - else if (argValue == "socks5") { proxyType = Proxy.ProxyHandler.Type.SOCKS5; } - return true; - case "server": - string[] host_splitted = argValue.Split(':'); - if (host_splitted.Length == 1) - { - ProxyHost = host_splitted[0]; - ProxyPort = 80; - } - else if (host_splitted.Length == 2) - { - ProxyHost = host_splitted[0]; - ProxyPort = str2int(host_splitted[1]); - } - return true; - case "username": ProxyUsername = argValue; return true; - case "password": ProxyPassword = argValue; return true; - } - break; - - case Section.AppVars: - SetVar(argName, argValue); - return true; - - case Section.AutoRespond: - switch (ToLowerIfNeed(argName)) - { - case "enabled": AutoRespond_Enabled = str2bool(argValue); return true; - case "matchesfile": AutoRespond_Matches = argValue; return true; - case "matchcolors": AutoRespond_MatchColors = str2bool(argValue); return true; - } - break; - - case Section.AutoAttack: - switch (ToLowerIfNeed(argName)) - { - case "enabled": AutoAttack_Enabled = str2bool(argValue); return true; - case "mode": AutoAttack_Mode = ToLowerIfNeed(argValue); return true; - case "priority": AutoAttack_Priority = ToLowerIfNeed(argValue); return true; - case "cooldownseconds": - if (ToLowerIfNeed(argValue) == "auto") - { - AutoAttack_OverrideAttackSpeed = false; - } - else - { - AutoAttack_OverrideAttackSpeed = true; - AutoAttack_CooldownSeconds = str2float(argValue); - } - return true; - case "interaction": - return Enum.TryParse(argValue, true, out AutoAttack_Interaction); - case "attackhostile": - AutoAttack_Attack_Hostile = str2bool(argValue); return true; - case "attackpassive": - AutoAttack_Attack_Passive = str2bool(argValue); return true; - case "listmode": - AutoAttack_ListMode = argValue; return true; - case "listfile": - AutoAttack_ListFile = argValue; return true; - } - break; - - case Section.AutoFishing: - switch (ToLowerIfNeed(argName)) - { - case "enabled": AutoFishing_Enabled = str2bool(argValue); return true; - case "antidespawn": AutoFishing_Antidespawn = str2bool(argValue); return true; - case "main_hand": AutoFishing_Mainhand = str2bool(argValue); return true; - case "auto_start": AutoFishing_AutoStart = str2bool(argValue); return true; - case "cast_delay": AutoFishing_CastDelay = str2double(argValue); return true; - case "fishing_delay": AutoFishing_FishingDelay = str2double(argValue); return true; - case "fishing_timeout": AutoFishing_FishingTimeout = str2double(argValue); return true; - case "durability_limit": AutoFishing_DurabilityLimit = str2int(argValue); return true; - case "auto_rod_switch": AutoFishing_AutoRodSwitch = str2bool(argValue); return true; - case "stationary_threshold": AutoFishing_StationaryThreshold = str2double(argValue); return true; - case "hook_threshold": AutoFishing_HookThreshold = str2double(argValue); return true; - case "log_fishing_bobber": AutoFishing_LogFishingBobber = str2bool(argValue); return true; - case "location": AutoFishing_Location = str2locationList(argValue); return true; - } - break; - - case Section.AutoEat: - switch (ToLowerIfNeed(argName)) - { - case "enabled": AutoEat_Enabled = str2bool(argValue); return true; - case "threshold": AutoEat_hungerThreshold = str2int(argValue); return true; - } - break; - - case Section.AutoCraft: - switch (ToLowerIfNeed(argName)) - { - case "enabled": AutoCraft_Enabled = str2bool(argValue); return true; - case "configfile": AutoCraft_configFile = argValue; return true; - } - break; - - case Section.AutoDrop: - switch (ToLowerIfNeed(argName)) - { - case "enabled": AutoDrop_Enabled = str2bool(argValue); return true; - case "mode": AutoDrop_Mode = argValue; return true; - case "items": AutoDrop_items = argValue; return true; - } - break; - - case Section.MCSettings: - switch (ToLowerIfNeed(argName)) - { - case "enabled": MCSettings_Enabled = str2bool(argValue); return true; - case "locale": MCSettings_Locale = argValue; return true; - case "difficulty": - switch (ToLowerIfNeed(argValue)) - { - case "peaceful": MCSettings_Difficulty = 0; break; - case "easy": MCSettings_Difficulty = 1; break; - case "normal": MCSettings_Difficulty = 2; break; - case "difficult": MCSettings_Difficulty = 3; break; - } - return true; - case "renderdistance": - MCSettings_RenderDistance = 2; - if (argValue.All(Char.IsDigit)) - { - MCSettings_RenderDistance = (byte)str2int(argValue); - } - else - { - switch (ToLowerIfNeed(argValue)) - { - case "tiny": MCSettings_RenderDistance = 2; break; - case "short": MCSettings_RenderDistance = 4; break; - case "medium": MCSettings_RenderDistance = 8; break; - case "far": MCSettings_RenderDistance = 16; break; - } - } - return true; - case "chatmode": - switch (ToLowerIfNeed(argValue)) - { - case "enabled": MCSettings_ChatMode = 0; break; - case "commands": MCSettings_ChatMode = 1; break; - case "disabled": MCSettings_ChatMode = 2; break; - } - return true; - case "chatcolors": MCSettings_ChatColors = str2bool(argValue); return true; - case "skin_cape": MCSettings_Skin_Cape = str2bool(argValue); return true; - case "skin_jacket": MCSettings_Skin_Jacket = str2bool(argValue); return true; - case "skin_sleeve_left": MCSettings_Skin_Sleeve_Left = str2bool(argValue); return true; - case "skin_sleeve_right": MCSettings_Skin_Sleeve_Right = str2bool(argValue); return true; - case "skin_pants_left": MCSettings_Skin_Pants_Left = 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 "main_hand": - switch (ToLowerIfNeed(argValue)) - { - case "left": MCSettings_MainHand = 0; break; - case "right": MCSettings_MainHand = 1; break; - } - return true; - } - break; - - case Section.Mailer: - switch (ToLowerIfNeed(argName)) - { - case "enabled": Mailer_Enabled = str2bool(argValue); return true; - case "database": Mailer_DatabaseFile = argValue; return true; - case "ignorelist": Mailer_IgnoreListFile = argValue; return true; - case "publicinteractions": Mailer_PublicInteractions = str2bool(argValue); return true; - case "maxmailsperplayer": Mailer_MaxMailsPerPlayer = str2int(argValue); return true; - case "maxdatabasesize": Mailer_MaxDatabaseSize = str2int(argValue); return true; - case "retentiondays": Mailer_MailRetentionDays = str2int(argValue); return true; - } - break; - - case Section.ReplayMod: - switch (ToLowerIfNeed(argName)) - { - case "enabled": ReplayMod_Enabled = str2bool(argValue); return true; - case "backupinterval": ReplayMod_BackupInterval = str2int(argValue); return true; - } - break; - - case Section.FollowPlayer: - switch (ToLowerIfNeed(argName)) - { - case "enabled": FollowPlayer_Enabled = str2bool(argValue); return true; - case "update_limit": FollowPlayer_UpdateLimit = str2int(argValue); return true; - case "stop_at_distance": FollowPlayer_StopAtDistance = str2int(argValue); return true; - } - break; - case Section.PlayerListLogger: - switch (ToLowerIfNeed(argName)) - { - case "enabled": PlayerLog_Enabled = str2bool(argValue); return true; - case "log_file": PlayerLog_File = argValue; return true; - case "log_delay": PlayerLog_Delay = str2int(argValue); return true; - } - break; - case Section.Map: - switch (ToLowerIfNeed(argName)) - { - case "enabled": Map_Enabled = str2bool(argValue); return true; - case "resize_map": Map_Should_Resize = str2bool(argValue); return true; - case "resize_to": Map_Resize_To = str2int(argValue); return true; - case "auto_render_on_update": Map_Auto_Render_On_Update = str2bool(argValue); return true; - case "delete_rendered_on_unload": Map_Delete_All_On_Unload = str2bool(argValue); return true; - case "notify_on_first_update": Map_Notify_On_First_Update = str2bool(argValue); return true; - } - break; - } - return false; - } - - /// - /// Write an INI file with default settings - /// - /// File to (over)write - 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, - DefaultConfigResource.MinecraftClient.Split(new[] { "\r\n", "\r", "\n" }, StringSplitOptions.None)); - - // Write configuration file with current version number - File.WriteAllText(settingsfile, - "# Minecraft Console Client v" - + Program.Version - + Environment.NewLine - + settingsContents, Encoding.UTF8); - } - - /// - /// Convert the specified string to an integer, defaulting to zero if invalid argument - /// - /// String to parse as an integer - /// Integer value - public static int str2int(string str) - { - try - { - return Convert.ToInt32(str.Trim()); - } - catch - { - ConsoleIO.WriteLogLine(Translations.Get("error.setting.str2int", str)); - return 0; - } - } - - /// - /// Convert the specified string to a float number, defaulting to zero if invalid argument - /// - /// String to parse as a float number - /// Float number - public static float str2float(string str) - { - if (float.TryParse(str.Trim(), NumberStyles.Any, CultureInfo.CurrentCulture, out float num)) - return num; - else - { - ConsoleIO.WriteLogLine(Translations.Get("error.setting.str2int", str)); - return 0; - } - } - - /// - /// Convert the specified string to a double number, defaulting to zero if invalid argument - /// - /// String to parse as a float number - /// Double number - public static double str2double(string str) - { - if (double.TryParse(str.Trim(), NumberStyles.Any, CultureInfo.CurrentCulture, out double num)) - return num; - else - { - ConsoleIO.WriteLogLine(Translations.Get("error.setting.str2double", str)); - return 0; - } - } - - /// - /// Convert the specified string to a boolean value, defaulting to false if invalid argument - /// - /// String to parse as a boolean - /// Boolean value - public static bool str2bool(string str) - { - if (String.IsNullOrEmpty(str)) - return false; - str = str.Trim().ToLowerInvariant(); - return str == "true" || str == "1"; - } - - /// - /// Convert the specified string to a list of location, returning null if invalid argument - /// - /// String to parse as a location list - /// Location list (null or double[*,5] or double[*,3] or double[*,2]) - public static double[,]? str2locationList(string str) - { - string[] locationStrList = str.Split(';', StringSplitOptions.RemoveEmptyEntries); - double[,]? res = null; - int codLen = 0; - for (int i = 0; i < locationStrList.Length; ++i) - { - string[] coordinates_str_list = locationStrList[i].Split(',', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries); - int curCodLen = coordinates_str_list.Length; - if ((curCodLen == 2 || curCodLen == 3 || curCodLen == 5) && (i == 0 || curCodLen == codLen)) + [NonSerialized] + public static readonly string[] AvailableLang = { - if (i == 0) - { - res = new double[locationStrList.Length, curCodLen]; - codLen = curCodLen; - } + "af_za", "ar_sa", "ast_es", "az_az", "ba_ru", "bar", "be_by", "bg_bg", "br_fr", "brb", "bs_ba", "ca_es", + "cs_cz", "cy_gb", "da_dk", "de_at", "de_ch", "de_de", "el_gr", "en_au", "en_ca", "en_gb", "en_nz", "eo_uy", + "es_ar", "es_cl", "es_ec", "es_es", "es_mx", "es_uy", "es_ve", "esan", "et_ee", "eu_es", "fa_ir", "fi_fi", + "fil_ph", "fo_fo", "fr_ca", "fr_fr", "fra_de", "fur_it", "fy_nl", "ga_ie", "gd_gb", "gl_es", "haw_us", "he_il", + "hi_in", "hr_hr", "hu_hu", "hy_am", "id_id", "ig_ng", "io_en", "is_is", "isv", "it_it", "ja_jp", "jbo_en", + "ka_ge", "kk_kz", "kn_in", "ko_kr", "ksh", "kw_gb", "la_la", "lb_lu", "li_li", "lmo", "lt_lt", "lv_lv", "lzh", + "mk_mk", "mn_mn", "ms_my", "mt_mt", "nds_de", "nl_be", "nl_nl", "nn_no", "oc_fr", "ovd", "pl_pl", "pt_br", + "pt_pt", "qya_aa", "ro_ro", "rpr", "ru_ru", "se_no", "sk_sk", "sl_si", "so_so", "sq_al", "sr_sp", "sv_se", + "sxu", "szl", "ta_in", "th_th", "tl_ph", "tlh_aa", "tok", "tr_tr", "tt_ru", "uk_ua", "val_es", "vec_it", + "vi_vn", "yi_de", "yo_ng", "zh_cn", "zh_hk", "zh_tw", "zlm_arab" + }; - for (int j = 0; j < curCodLen; ++j) + /// + /// Load server information in ServerIP and ServerPort variables from a "serverip:port" couple or server alias + /// + /// True if the server IP was valid and loaded, false otherwise + public bool SetServerIP(ServerInfoConfig serverInfo, bool checkAlias) + { + string serverStr = serverInfo.Host.ToLower(); + string[] sip = serverStr.Split(new[] { ":", ":" }, StringSplitOptions.None); + string host = sip[0]; + ushort port = 25565; + + if (sip.Length > 1) { - if (!double.TryParse(coordinates_str_list[j], NumberStyles.Any, CultureInfo.CurrentCulture, out res![i, j])) + if (serverInfo.Port != null) { - ConsoleIO.WriteLogLine(Translations.Get("error.setting.str2locationList.convert_fail", coordinates_str_list[j])); - return null; + port = (ushort)serverInfo.Port; + } + else + { + try { port = Convert.ToUInt16(sip[1]); } + catch (FormatException) { return false; } } } + + if (host == "localhost" || host.Contains('.')) + { + //Server IP (IP or domain names contains at least a dot) + if (sip.Length == 1 && serverInfo.Port == null && host.Contains('.') && host.Any(c => char.IsLetter(c)) && + Settings.Config.Main.Advanced.ResolveSrvRecords != MainConfigHealper.MainConfig.AdvancedConfig.ResolveSrvRecordType.no) + //Domain name without port may need Minecraft SRV Record lookup + ProtocolHandler.MinecraftServiceLookup(ref host, ref port); + InternalConfig.ServerIP = host; + InternalConfig.ServerPort = port; + return true; + } + else if (checkAlias && Advanced.ServerList.TryGetValue(serverStr, out ServerInfoConfig serverStr2)) + { + return SetServerIP(serverStr2, false); + } + + return false; } - else + + public void OnSettingUpdate() { - ConsoleIO.WriteLogLine(Translations.Get("error.setting.str2locationList.format_err", locationStrList[i])); - return null; + ConsoleIO.EnableTimestamps = Advanced.Timestamps; + + InternalConfig.InteractiveMode = !Advanced.ExitOnFailure; + + General.Account.Login ??= string.Empty; + General.Account.Password ??= string.Empty; + + General.Server.Host ??= string.Empty; + + if (Advanced.MessageCooldown < 0) + Advanced.MessageCooldown = 0; + + if (Advanced.TcpTimeout < 1) + Advanced.TcpTimeout = 1; + + if (Advanced.MovementSpeed < 1) + Advanced.MovementSpeed = 1; + + Advanced.Language = Regex.Replace(Advanced.Language, @"[^-^_^\w^*\d]", string.Empty).Replace('-', '_'); + if (!AvailableLang.Contains(Advanced.Language)) + { + Advanced.Language = Translations.GetTranslationPriority().Item1; + ConsoleIO.WriteLogLine("[Settings] " + Translations.GetOrNull("config.Main.Advanced.language.invaild") ?? "The language code is invalid."); + } + + if (!string.IsNullOrWhiteSpace(General.Server.Host)) + { + string[] sip = General.Server.Host.Split(new[] { ":", ":" }, StringSplitOptions.None); + General.Server.Host = sip[0]; + + if (sip.Length > 1) + { + try { General.Server.Port = Convert.ToUInt16(sip[1]); } + catch (FormatException) { } + } + } + + SetServerIP(General.Server, true); + } + + [TomlDoNotInlineObject] + public class GeneralConfig + { + [TomlInlineComment("$config.Main.General.account$")] + public AccountInfoConfig Account = new(string.Empty, string.Empty); + + [TomlInlineComment("$config.Main.General.login$")] + public ServerInfoConfig Server = new(string.Empty); + + [TomlInlineComment("$config.Main.General.server_info$")] + public LoginType AccountType = LoginType.microsoft; + + [TomlInlineComment("$config.Main.General.method$")] + public LoginMethod Method = LoginMethod.mcc; + + public enum LoginType { mojang, microsoft }; + + public enum LoginMethod { mcc, browser }; + } + + [TomlDoNotInlineObject] + public class AdvancedConfig + { + [TomlInlineComment("$config.Main.Advanced.language$")] + public string Language = "en_GB"; + + // [TomlInlineComment("$config.Main.Advanced.console_title$")] + public string ConsoleTitle = "%username%@%serverip% - Minecraft Console Client"; + + [TomlInlineComment("$config.Main.Advanced.internal_cmd_char$")] + public InternalCmdCharType InternalCmdChar = InternalCmdCharType.slash; + + [TomlInlineComment("$config.Main.Advanced.message_cooldown$")] + public int MessageCooldown = 2; + + [TomlInlineComment("$config.Main.Advanced.bot_owners$")] + public List BotOwners = new() { "Player1", "Player2" }; + + [TomlInlineComment("$config.Main.Advanced.mc_version$")] + public string MinecraftVersion = "auto"; + + [TomlInlineComment("$config.Main.Advanced.mc_forge$")] + public ForgeConfigType EnableForge = ForgeConfigType.auto; + + [TomlInlineComment("$config.Main.Advanced.brand_info$")] + public BrandInfoType BrandInfo = BrandInfoType.mcc; + + [TomlInlineComment("$config.Main.Advanced.chatbot_log_file$")] + public string ChatbotLogFile = ""; + + [TomlInlineComment("$config.Main.Advanced.private_msgs_cmd_name$")] + public string PrivateMsgsCmdName = "tell"; + + [TomlInlineComment("$config.Main.Advanced.show_system_messages$")] + public bool ShowSystemMessages = true; + + [TomlInlineComment("$config.Main.Advanced.show_xpbar_messages$")] + public bool ShowXPBarMessages = true; + + [TomlInlineComment("$config.Main.Advanced.show_chat_links$")] + public bool ShowChatLinks = true; + + [TomlInlineComment("$config.Main.Advanced.show_inventory_layout$")] + public bool ShowInventoryLayout = true; + + [TomlInlineComment("$config.Main.Advanced.terrain_and_movements$")] + public bool TerrainAndMovements = false; + + [TomlInlineComment("$config.Main.Advanced.inventory_handling$")] + public bool InventoryHandling = false; + + [TomlInlineComment("$config.Main.Advanced.entity_handling$")] + public bool EntityHandling = false; + + [TomlInlineComment("$config.Main.Advanced.session_cache$")] + public CacheType SessionCache = CacheType.disk; + + [TomlInlineComment("$config.Main.Advanced.profilekey_cache$")] + public CacheType ProfileKeyCache = CacheType.disk; + + [TomlInlineComment("$config.Main.Advanced.resolve_srv_records$")] + public ResolveSrvRecordType ResolveSrvRecords = ResolveSrvRecordType.fast; + + [TomlInlineComment("$config.Main.Advanced.account_list$")] + public Dictionary AccountList = new() { + { "AccountNikename1", new AccountInfoConfig("login1", "pass1") }, + { "AccountNikename2", new AccountInfoConfig("login2", "pass2") }, + }; + + [TomlInlineComment("$config.Main.Advanced.server_list$")] + public Dictionary ServerList = new() { + { "ServerNickname1", new ServerInfoConfig("test1.server.com") }, + { "ServerNickname2", new ServerInfoConfig("test2.server.com", 12345) }, + }; + + [TomlInlineComment("$config.Main.Advanced.player_head_icon$")] + public bool PlayerHeadAsIcon = true; + + [TomlInlineComment("$config.Main.Advanced.exit_on_failure$")] + public bool ExitOnFailure = false; + + [TomlInlineComment("$config.Main.Advanced.script_cache$")] + public bool CacheScript = true; + + [TomlInlineComment("$config.Main.Advanced.timestamps$")] + public bool Timestamps = false; + + [TomlInlineComment("$config.Main.Advanced.auto_respawn$")] + public bool AutoRespawn = false; + + [TomlInlineComment("$config.Main.Advanced.minecraft_realms$")] + public bool MinecraftRealms = false; + + [TomlInlineComment("$config.Main.Advanced.move_head_while_walking$")] + public bool MoveHeadWhileWalking = true; + + [TomlInlineComment("$config.Main.Advanced.timeout$")] + public int TcpTimeout = 30; + + [TomlInlineComment("$config.Main.Advanced.enable_emoji$")] + public bool EnableEmoji = true; + + [TomlInlineComment("$config.Main.Advanced.movement_speed$")] + public int MovementSpeed = 2; + + /// + /// Load login/password using an account alias + /// + /// True if the account was found and loaded + public bool SetAccount(string accountAlias) + { + if (AccountList.TryGetValue(accountAlias, out AccountInfoConfig accountInfo)) + { + Settings.Config.Main.General.Account = accountInfo; + return true; + } + else + { + return false; + } + } + + public enum InternalCmdCharType { none, slash, backslash }; + + public enum BrandInfoType { mcc, vanilla, empty }; + + public enum CacheType { none, memory, disk }; + + public enum ResolveSrvRecordType { no, fast, yes }; + + public enum ForgeConfigType { no, auto, force }; + } + + public struct AccountInfoConfig + { + public string Login = string.Empty, Password = string.Empty; + + public AccountInfoConfig(string Login) + { + this.Login = Login; + this.Password = "-"; + } + + public AccountInfoConfig(string Login, string Password) + { + this.Login = Login; + this.Password = Password; + } + } + + public struct ServerInfoConfig + { + public string Host = string.Empty; + public ushort? Port = null; + + public ServerInfoConfig(string Host) + { + string[] sip = Host.Split(new[] { ":", ":" }, StringSplitOptions.None); + this.Host = sip[0]; + + if (sip.Length > 1) + { + try { this.Port = Convert.ToUInt16(sip[1]); } + catch (FormatException) { } + } + } + + public ServerInfoConfig(string Host, ushort Port) + { + this.Host = Host.Split(new[] { ":", ":" }, StringSplitOptions.None)[0]; + this.Port = Port; + } } } - return res; } + public static class SignatureConfigHelper + { + public static SignatureConfig Config = new(); + + [TomlDoNotInlineObject] + public class SignatureConfig + { + [TomlInlineComment("$config.Signature.LoginWithSecureProfile$")] + public bool LoginWithSecureProfile = true; + + [TomlInlineComment("$config.Signature.SignChat$")] + public bool SignChat = true; + + [TomlInlineComment("$config.Signature.SignMessageInCommand$")] + public bool SignMessageInCommand = true; + + [TomlInlineComment("$config.Signature.MarkLegallySignedMsg$")] + public bool MarkLegallySignedMsg = false; + + [TomlInlineComment("$config.Signature.MarkModifiedMsg$")] + public bool MarkModifiedMsg = true; + + [TomlInlineComment("$config.Signature.MarkIllegallySignedMsg$")] + public bool MarkIllegallySignedMsg = true; + + [TomlInlineComment("$config.Signature.MarkSystemMessage$")] + public bool MarkSystemMessage = false; + + [TomlInlineComment("$config.Signature.ShowModifiedChat$")] + public bool ShowModifiedChat = true; + + [TomlInlineComment("$config.Signature.ShowIllegalSignedChat$")] + public bool ShowIllegalSignedChat = true; + + public void OnSettingUpdate() { } + } + } + + public static class LoggingConfigHealper + { + public static LoggingConfig Config = new(); + + [TomlDoNotInlineObject] + public class LoggingConfig + { + [TomlInlineComment("$config.Logging.DebugMessages$")] + public bool DebugMessages = false; + + [TomlInlineComment("$config.Logging.ChatMessages$")] + public bool ChatMessages = true; + + [TomlInlineComment("$config.Logging.InfoMessages$")] + public bool InfoMessages = true; + + [TomlInlineComment("$config.Logging.WarningMessages$")] + public bool WarningMessages = true; + + [TomlInlineComment("$config.Logging.ErrorMessages$")] + public bool ErrorMessages = true; + + [TomlInlineComment("$config.Logging.ChatFilter$")] + public string ChatFilterRegex = @".*"; + + [TomlInlineComment("$config.Logging.DebugFilter$")] + public string DebugFilterRegex = @".*"; + + [TomlInlineComment("$config.Logging.FilterMode$")] + public FilterModeEnum FilterMode = FilterModeEnum.whitelist; + + [TomlInlineComment("$config.Logging.LogToFile$")] + public bool LogToFile = false; + + [TomlInlineComment("$config.Logging.LogFile$")] + public string LogFile = @"console-log.txt"; + + [TomlInlineComment("$config.Logging.PrependTimestamp$")] + public bool PrependTimestamp = false; + + [TomlInlineComment("$config.Logging.SaveColorCodes$")] + public bool SaveColorCodes = false; + + public void OnSettingUpdate() { } + + public enum FilterModeEnum { blacklist, whitelist } + } + } + + public static class AppVarConfigHelper + { + public static AppVarConfig Config = new(); + + [TomlDoNotInlineObject] + public class AppVarConfig + { + [TomlPrecedingComment("$config.AppVars.Variables$")] + private readonly Dictionary VarStirng = new() { + { "your_var", "your_value" }, + { "your var 2", "your value 2" }, + }; + + public void OnSettingUpdate() { } + + + [NonSerialized] + private readonly Dictionary VarObject = new(); + + [NonSerialized] + readonly object varLock = new(); + + /// + /// Set a custom %variable% which will be available through expandVars() + /// + /// Name of the variable + /// Value of the variable + /// True if the parameters were valid + public bool SetVar(string varName, object varData) + { + varName = Settings.ToLowerIfNeed(new string(varName.TakeWhile(char.IsLetterOrDigit).ToArray())); + if (varName.Length > 0) + { + bool isString = varData.GetType() == typeof(string); + lock (varLock) + { + if (isString) + { + if (VarObject.ContainsKey(varName)) + VarObject.Remove(varName); + VarStirng[varName] = (string)varData; + } + else + { + if (VarStirng.ContainsKey(varName)) + VarStirng.Remove(varName); + VarObject[varName] = varData; + } + } + return true; + } + else + { + return false; + } + } + + /// + /// Get a custom %variable% or null if the variable does not exist + /// + /// Variable name + /// The value or null if the variable does not exists + public object? GetVar(string varName) + { + if (VarStirng.TryGetValue(varName, out string? valueString)) + return valueString; + else if (VarObject.TryGetValue(varName, out object? valueObject)) + return valueObject; + else + return null; + } + + /// + /// Get a custom %variable% or null if the variable does not exist + /// + /// Variable name + /// The value or null if the variable does not exists + public bool TryGetVar(string varName, [NotNullWhen(true)] out object? varData) + { + if (VarStirng.TryGetValue(varName, out string? valueString)) + { + varData = valueString; + return true; + } + else if (VarObject.TryGetValue(varName, out object? valueObject)) + { + varData = valueObject; + return true; + } + else + { + varData = null; + return false; + } + } + + /// + /// Get a dictionary containing variables (names and value) + /// + /// A IDictionary containing a name and a vlaue key pairs of variables + public Dictionary GetVariables() + { + Dictionary res = new(VarObject); + foreach ((string varName, string varData) in VarStirng) + res.Add(varName, varData); + return res; + } + + /// + /// Replace %variables% with their value from global AppVars + /// + /// String to parse + /// Optional local variables overriding global variables + /// Modifier string + public string ExpandVars(string str, Dictionary? localVars = null) + { + StringBuilder result = new(); + for (int i = 0; i < str.Length; i++) + { + if (str[i] == '%') + { + bool varname_ok = false; + StringBuilder var_name = new(); + + for (int j = i + 1; j < str.Length; j++) + { + if (!char.IsLetterOrDigit(str[j]) && str[j] != '_') + { + if (str[j] == '%') + varname_ok = var_name.Length > 0; + break; + } + else var_name.Append(str[j]); + } + + if (varname_ok) + { + string varname = var_name.ToString(); + string varname_lower = Settings.ToLowerIfNeed(varname); + i = i + varname.Length + 1; + + switch (varname_lower) + { + case "username": result.Append(InternalConfig.Username); break; + case "login": result.Append(Settings.Config.Main.General.Account.Login); break; + case "serverip": result.Append(InternalConfig.ServerIP); break; + case "serverport": result.Append(InternalConfig.ServerPort); break; + case "datetime": + DateTime time = DateTime.Now; + result.Append(String.Format("{0}-{1}-{2} {3}:{4}:{5}", + time.Year.ToString("0000"), + time.Month.ToString("00"), + time.Day.ToString("00"), + time.Hour.ToString("00"), + time.Minute.ToString("00"), + time.Second.ToString("00"))); + + break; + default: + if (localVars != null && localVars.ContainsKey(varname_lower)) + result.Append(localVars[varname_lower].ToString()); + else if (TryGetVar(varname_lower, out object? var_value)) + result.Append(var_value.ToString()); + else + result.Append("%" + varname + '%'); + break; + } + } + else result.Append(str[i]); + } + else result.Append(str[i]); + } + return result.ToString(); + } + } + } + + public static class MCSettingsConfigHealper + { + public static MCSettingsConfig Config = new(); + + [TomlDoNotInlineObject] + public class MCSettingsConfig + { + [TomlInlineComment("$config.MCSettings.Enabled$")] + public bool Enabled = true; + + [TomlInlineComment("$config.MCSettings.Locale$")] + public string Locale = "en_US"; + + [TomlInlineComment("$config.MCSettings.RenderDistance$")] + public byte RenderDistance = 8; + + [TomlInlineComment("$config.MCSettings.Difficulty$")] + public DifficultyType Difficulty = DifficultyType.peaceful; + + [TomlInlineComment("$config.MCSettings.ChatMode$")] + public ChatModeType ChatMode = ChatModeType.enabled; + + [TomlInlineComment("$config.MCSettings.ChatColors$")] + public bool ChatColors = true; + + [TomlInlineComment("$config.MCSettings.MainHand$")] + public MainHandType MainHand = MainHandType.left; + + public SkinInfo Skin = new(); + + public void OnSettingUpdate() { } + + public enum DifficultyType { peaceful, easy, normal, difficult }; + + public enum ChatModeType { enabled, commands, disabled }; + + public enum MainHandType { left, right }; + + public struct SkinInfo + { + public bool Cape = true, Hat = true, Jacket = false; + public bool Sleeve_Left = false, Sleeve_Right = false; + public bool Pants_Left = false, Pants_Right = false; + + public SkinInfo() { } + + public SkinInfo(bool Cape, bool Hat, bool Jacket, bool Sleeve_Left, bool Sleeve_Right, bool Pants_Left, bool Pants_Right) + { + this.Cape = Cape; + this.Hat = Hat; + this.Jacket = Jacket; + this.Sleeve_Left = Sleeve_Left; + this.Sleeve_Right = Sleeve_Right; + this.Pants_Left = Pants_Left; + this.Pants_Right = Pants_Right; + } + + public byte GetByte() + { + return (byte)( + ((Cape ? 1 : 0) << 0) + | ((Jacket ? 1 : 0) << 1) + | ((Sleeve_Left ? 1 : 0) << 2) + | ((Sleeve_Right ? 1 : 0) << 3) + | ((Pants_Left ? 1 : 0) << 4) + | ((Pants_Right ? 1 : 0) << 5) + | ((Hat ? 1 : 0) << 6) + ); + } + } + } + } + + public static class ChatFormatConfigHelper + { + public static ChatFormatConfig Config = new(); + + [TomlDoNotInlineObject] + public class ChatFormatConfig + { + [TomlInlineComment("$config.ChatFormat.Builtins$")] + public bool Builtins = true; + + public string Public = @"^<([a-zA-Z0-9_]+)> (.+)$"; + + public string Private = @"^([a-zA-Z0-9_]+) whispers to you: (.+)$"; + + public string TeleportRequest = @"^([a-zA-Z0-9_]+) has requested (?:to|that you) teleport to (?:you|them)\.$"; + + public void OnSettingUpdate() { } + } + } + + public static class ChatBotConfigHealper + { + public static ChatBotConfig Config = new(); + + [TomlDoNotInlineObject] + public class ChatBotConfig + { + [TomlPrecedingComment("$config.ChatBot.Alerts$")] + public ChatBots.Alerts.Configs Alerts + { + get { return ChatBots.Alerts.Config; } + set { ChatBots.Alerts.Config = value; ChatBots.Alerts.Config.OnSettingUpdate(); } + } + + [TomlPrecedingComment("$config.ChatBot.AntiAFK$")] + public ChatBots.AntiAFK.Configs AntiAFK + { + get { return ChatBots.AntiAFK.Config; } + set { ChatBots.AntiAFK.Config = value; ChatBots.AntiAFK.Config.OnSettingUpdate(); } + } + + [TomlPrecedingComment("$config.ChatBot.AutoAttack$")] + public ChatBots.AutoAttack.Configs AutoAttack + { + get { return ChatBots.AutoAttack.Config; } + set { ChatBots.AutoAttack.Config = value; ChatBots.AutoAttack.Config.OnSettingUpdate(); } + } + + [TomlPrecedingComment("$config.ChatBot.AutoCraft$")] + public ChatBots.AutoCraft.Configs AutoCraft + { + get { return ChatBots.AutoCraft.Config; } + set { ChatBots.AutoCraft.Config = value; ChatBots.AutoCraft.Config.OnSettingUpdate(); } + } + + [TomlPrecedingComment("$config.ChatBot.AutoDrop$")] + public ChatBots.AutoDrop.Configs AutoDrop + { + get { return ChatBots.AutoDrop.Config; } + set { ChatBots.AutoDrop.Config = value; ChatBots.AutoDrop.Config.OnSettingUpdate(); } + } + + [TomlPrecedingComment("$config.ChatBot.AutoEat$")] + public ChatBots.AutoEat.Configs AutoEat + { + get { return ChatBots.AutoEat.Config; } + set { ChatBots.AutoEat.Config = value; ChatBots.AutoEat.Config.OnSettingUpdate(); } + } + + [TomlPrecedingComment("$config.ChatBot.AutoFishing$")] + public ChatBots.AutoFishing.Configs AutoFishing + { + get { return ChatBots.AutoFishing.Config; } + set { ChatBots.AutoFishing.Config = value; ChatBots.AutoFishing.Config.OnSettingUpdate(); } + } + + [TomlPrecedingComment("$config.ChatBot.AutoRelog$")] + public ChatBots.AutoRelog.Configs AutoRelog + { + get { return ChatBots.AutoRelog.Config; } + set { ChatBots.AutoRelog.Config = value; ChatBots.AutoRelog.Config.OnSettingUpdate(); } + } + + [TomlPrecedingComment("$config.ChatBot.AutoRespond$")] + public ChatBots.AutoRespond.Configs AutoRespond + { + get { return ChatBots.AutoRespond.Config; } + set { ChatBots.AutoRespond.Config = value; ChatBots.AutoRespond.Config.OnSettingUpdate(); } + } + + [TomlPrecedingComment("$config.ChatBot.ChatLog$")] + public ChatBots.ChatLog.Configs ChatLog + { + get { return ChatBots.ChatLog.Config; } + set { ChatBots.ChatLog.Config = value; ChatBots.ChatLog.Config.OnSettingUpdate(); } + } + + [TomlPrecedingComment("$config.ChatBot.FollowPlayer$")] + public ChatBots.FollowPlayer.Configs FollowPlayer + { + get { return ChatBots.FollowPlayer.Config; } + set { ChatBots.FollowPlayer.Config = value; ChatBots.FollowPlayer.Config.OnSettingUpdate(); } + } + + [TomlPrecedingComment("$config.ChatBot.HangmanGame$")] + public ChatBots.HangmanGame.Configs HangmanGame + { + get { return ChatBots.HangmanGame.Config; } + set { ChatBots.HangmanGame.Config = value; ChatBots.HangmanGame.Config.OnSettingUpdate(); } + } + + [TomlPrecedingComment("$config.ChatBot.Mailer$")] + public ChatBots.Mailer.Configs Mailer + { + get { return ChatBots.Mailer.Config; } + set { ChatBots.Mailer.Config = value; ChatBots.Mailer.Config.OnSettingUpdate(); } + } + + [TomlPrecedingComment("$config.ChatBot.Map$")] + public ChatBots.Map.Configs Map + { + get { return ChatBots.Map.Config; } + set { ChatBots.Map.Config = value; ChatBots.Map.Config.OnSettingUpdate(); } + } + + [TomlPrecedingComment("$config.ChatBot.PlayerListLogger$")] + public ChatBots.PlayerListLogger.Configs PlayerListLogger + { + get { return ChatBots.PlayerListLogger.Config; } + set { ChatBots.PlayerListLogger.Config = value; ChatBots.PlayerListLogger.Config.OnSettingUpdate(); } + } + + [TomlPrecedingComment("$config.ChatBot.RemoteControl$")] + public ChatBots.RemoteControl.Configs RemoteControl + { + get { return ChatBots.RemoteControl.Config; } + set { ChatBots.RemoteControl.Config = value; ChatBots.RemoteControl.Config.OnSettingUpdate(); } + } + + [TomlPrecedingComment("$config.ChatBot.ReplayCapture$")] + public ChatBots.ReplayCapture.Configs ReplayCapture + { + get { return ChatBots.ReplayCapture.Config; } + set { ChatBots.ReplayCapture.Config = value; ChatBots.ReplayCapture.Config.OnSettingUpdate(); } + } + + [TomlPrecedingComment("$config.ChatBot.ScriptScheduler$")] + public ChatBots.ScriptScheduler.Configs ScriptScheduler + { + get { return ChatBots.ScriptScheduler.Config; } + set { ChatBots.ScriptScheduler.Config = value; ChatBots.ScriptScheduler.Config.OnSettingUpdate(); } + } + } + } + + [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] public static string ToLowerIfNeed(string str) { - const string lookupStringL = -"---------------------------------!-#$%&-()*+,-./0123456789:;<=>?@abcdefghijklmnopqrstuvwxyz[-]^_`abcdefghijklmnopqrstuvwxyz{|}~-"; + const string lookupStringL = "---------------------------------!-#$%&-()*+,-./0123456789:;<=>?@abcdefghijklmnopqrstuvwxyz[-]^_`abcdefghijklmnopqrstuvwxyz{|}~-"; bool needLower = false; foreach (Char c in str) @@ -1064,173 +1072,44 @@ namespace MinecraftClient return str; } } + } - /// - /// Load login/password using an account alias - /// - /// True if the account was found and loaded - public static bool SetAccount(string accountAlias) + public static class InternalCmdCharTypeExtensions + { + public static char ToChar(this InternalCmdCharType type) { - accountAlias = Settings.ToLowerIfNeed(accountAlias); - if (Accounts.ContainsKey(accountAlias)) + return type switch { - Settings.Login = Accounts[accountAlias].Key; - Settings.Password = Accounts[accountAlias].Value; - return true; - } - else return false; + InternalCmdCharType.none => ' ', + InternalCmdCharType.slash => '/', + InternalCmdCharType.backslash => '\\', + _ => '/', + }; } - /// - /// Load server information in ServerIP and ServerPort variables from a "serverip:port" couple or server alias - /// - /// True if the server IP was valid and loaded, false otherwise - public static bool SetServerIP(string server) + public static string ToLogString(this InternalCmdCharType type) { - server = ToLowerIfNeed(server); - string[] sip = server.Split(':'); - string host = sip[0]; - ushort port = 25565; - - if (sip.Length > 1) + return type switch { - try - { - port = Convert.ToUInt16(sip[1]); - } - catch (FormatException) { return false; } - } - - if (host == "localhost" || host.Contains('.')) - { - //Server IP (IP or domain names contains at least a dot) - if (sip.Length == 1 && host.Contains('.') && host.Any(c => char.IsLetter(c)) && ResolveSrvRecords) - //Domain name without port may need Minecraft SRV Record lookup - ProtocolHandler.MinecraftServiceLookup(ref host, ref port); - ServerIP = host; - ServerPort = port; - return true; - } - else if (Servers.ContainsKey(server)) - { - //Server Alias (if no dot then treat the server as an alias) - ServerIP = Servers[server].Key; - ServerPort = Servers[server].Value; - return true; - } - - return false; + InternalCmdCharType.none => string.Empty, + InternalCmdCharType.slash => @"/", + InternalCmdCharType.backslash => @"\", + _ => @"/", + }; } - - /// - /// Set a custom %variable% which will be available through expandVars() - /// - /// Name of the variable - /// Value of the variable - /// True if the parameters were valid - public static bool SetVar(string varName, object varData) + } + + public static class BrandInfoTypeExtensions + { + public static string? ToBrandString(this BrandInfoType info) { - lock (AppVars) + return info switch { - varName = Settings.ToLowerIfNeed(new string(varName.TakeWhile(char.IsLetterOrDigit).ToArray())); - if (varName.Length > 0) - { - AppVars[varName] = varData; - return true; - } - else return false; - } - } - - /// - /// Get a custom %variable% or null if the variable does not exist - /// - /// Variable name - /// The value or null if the variable does not exists - public static object? GetVar(string varName) - { - if (AppVars.ContainsKey(varName)) - return AppVars[varName]; - return null; - } - - /// - /// Get a dictionary containing variables (names and value) - /// - /// A IDictionary containing a name and a vlaue key pairs of variables - public static Dictionary GetVariables() - { - return AppVars; - } - - /// - /// Replace %variables% with their value from global AppVars - /// - /// String to parse - /// Optional local variables overriding global variables - /// Modifier string - public static string ExpandVars(string str, Dictionary? localVars = null) - { - StringBuilder result = new(); - for (int i = 0; i < str.Length; i++) - { - if (str[i] == '%') - { - bool varname_ok = false; - StringBuilder var_name = new(); - - for (int j = i + 1; j < str.Length; j++) - { - if (!char.IsLetterOrDigit(str[j]) && str[j] != '_') - { - if (str[j] == '%') - varname_ok = var_name.Length > 0; - break; - } - else var_name.Append(str[j]); - } - - if (varname_ok) - { - string varname = var_name.ToString(); - string varname_lower = Settings.ToLowerIfNeed(varname); - i = i + varname.Length + 1; - - switch (varname_lower) - { - case "username": result.Append(Username); break; - case "login": result.Append(Login); break; - case "serverip": result.Append(ServerIP); break; - case "serverport": result.Append(ServerPort); break; - case "datetime": - DateTime time = DateTime.Now; - result.Append(String.Format("{0}-{1}-{2} {3}:{4}:{5}", - time.Year.ToString("0000"), - time.Month.ToString("00"), - time.Day.ToString("00"), - time.Hour.ToString("00"), - time.Minute.ToString("00"), - time.Second.ToString("00"))); - - break; - default: - if (localVars != null && localVars.ContainsKey(varname_lower)) - { - result.Append(localVars[varname_lower].ToString()); - } - else if (AppVars.ContainsKey(varname_lower)) - { - result.Append(AppVars[varname_lower].ToString()); - } - else result.Append("%" + varname + '%'); - break; - } - } - else result.Append(str[i]); - } - else result.Append(str[i]); - } - return result.ToString(); + BrandInfoType.mcc => Settings.MCCBrandInfo, + BrandInfoType.vanilla => "vanilla", + BrandInfoType.empty => null, + _ => null, + }; } } } diff --git a/MinecraftClient/Translations.cs b/MinecraftClient/Translations.cs index 1bcf9c16..81776efb 100644 --- a/MinecraftClient/Translations.cs +++ b/MinecraftClient/Translations.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Diagnostics; using System.Globalization; using System.IO; using System.Text; @@ -15,7 +16,7 @@ namespace MinecraftClient /// public static class Translations { - private static readonly Dictionary translations; + private static readonly Dictionary translations = new(); private static readonly string translationFilePath = "lang" + Path.DirectorySeparatorChar + "mcc"; private static readonly string defaultTranslation = "en.ini"; private static readonly Regex translationKeyRegex = new(@"\(\[(.*?)\]\)", RegexOptions.Compiled); // Extract string inside ([ ]) @@ -52,6 +53,21 @@ namespace MinecraftClient return msgName; } + /// + /// Return a tranlation for the requested text. Support string formatting. If not found, return the original text + /// + /// text identifier + /// + /// Translated text or original text if not found + /// Useful when not sure msgName is a translation mapping key or a normal text + public static string? GetOrNull(string msgName, params object?[] args) + { + if (translations.ContainsKey(msgName)) + return Get(msgName, args); + else + return null; + } + /// /// Replace the translation key inside a sentence to translated text. Wrap the key in ([translation.key]) /// @@ -75,32 +91,495 @@ namespace MinecraftClient return Get(m.Groups[1].Value); } - /// - /// Initialize translations depending on system language. - /// English is the default for all unknown system languages. - /// - static Translations() + public static Tuple GetTranslationPriority() { - translations = new Dictionary(); - LoadDefaultTranslationsFile(); + string gameLanguage = "en_gb"; + List name = new(); + + string systemLanguage = string.IsNullOrWhiteSpace(CultureInfo.CurrentCulture.Name) + ? CultureInfo.CurrentCulture.Parent.Name + : CultureInfo.CurrentCulture.Name; + + switch (systemLanguage) + { + case "af": + case "af-ZA": + gameLanguage = "af_za"; + break; + case "ar": + case "ar-AE": + case "ar-BH": + case "ar-DZ": + case "ar-EG": + case "ar-IQ": + case "ar-JO": + case "ar-KW": + case "ar-LB": + case "ar-LY": + case "ar-MA": + case "ar-OM": + case "ar-QA": + case "ar-SA": + case "ar-SY": + case "ar-TN": + case "ar-YE": + gameLanguage = "ar_sa"; + break; + case "az": + case "az-Cyrl-AZ": + case "az-Latn-AZ": + gameLanguage = "az_az"; + break; + case "be": + case "be-BY": + gameLanguage = "be_by"; + break; + case "bg": + case "bg-BG": + gameLanguage = "bg_bg"; + break; + case "bs-Latn-BA": + gameLanguage = "bs_ba"; + break; + case "ca": + case "ca-ES": + gameLanguage = "ca_es"; + break; + case "cs": + case "cs-CZ": + gameLanguage = "cs_cz"; + break; + case "cy-GB": + gameLanguage = "cy_gb"; + break; + case "da": + case "da-DK": + gameLanguage = "da_dk"; + break; + case "de": + case "de-DE": + case "de-LI": + case "de-LU": + gameLanguage = "de_de"; + name.Add("de"); + break; + case "de-AT": + gameLanguage = "de_at"; + name.Add("de"); + break; + case "de-CH": + gameLanguage = "de_ch"; + name.Add("de"); + break; + case "dv": + case "dv-MV": + break; + case "el": + case "el-GR": + gameLanguage = "el_gr"; + break; + case "en": + case "en-029": + case "en-BZ": + case "en-IE": + case "en-JM": + case "en-PH": + case "en-TT": + case "en-ZA": + case "en-ZW": + case "en-GB": + gameLanguage = "en_gb"; + break; + case "en-AU": + gameLanguage = "en_au"; + break; + case "en-CA": + gameLanguage = "en_ca"; + break; + case "en-US": + gameLanguage = "en_us"; + break; + case "en-NZ": + gameLanguage = "en_nz"; + break; + case "es": + case "es-BO": + case "es-CO": + case "es-CR": + case "es-DO": + case "es-ES": + case "es-GT": + case "es-HN": + case "es-NI": + case "es-PA": + case "es-PE": + case "es-PR": + case "es-PY": + case "es-SV": + gameLanguage = "es_es"; + break; + case "es-AR": + gameLanguage = "es_ar"; + break; + case "es-CL": + gameLanguage = "es_cl"; + break; + case "es-EC": + gameLanguage = "es_ec"; + break; + case "es-MX": + gameLanguage = "es_mx"; + break; + case "es-UY": + gameLanguage = "es_uy"; + break; + case "es-VE": + gameLanguage = "es_ve"; + break; + case "et": + case "et-EE": + gameLanguage = "et_ee"; + break; + case "eu": + case "eu-ES": + gameLanguage = "eu_es"; + break; + case "fa": + case "fa-IR": + gameLanguage = "fa_ir"; + break; + case "fi": + case "fi-FI": + gameLanguage = "fi_fi"; + break; + case "fo": + case "fo-FO": + gameLanguage = "fo_fo"; + break; + case "fr": + case "fr-BE": + case "fr-FR": + case "fr-CH": + case "fr-LU": + case "fr-MC": + gameLanguage = "fr_fr"; + name.Add("fr"); + break; + case "fr-CA": + gameLanguage = "fr_ca"; + name.Add("fr"); + break; + case "gl": + case "gl-ES": + gameLanguage = "gl_es"; + break; + case "gu": + case "gu-IN": + break; + case "he": + case "he-IL": + gameLanguage = "he_il"; + break; + case "hi": + case "hi-IN": + gameLanguage = "hi_in"; + break; + case "hr": + case "hr-BA": + case "hr-HR": + gameLanguage = "hr_hr"; + break; + case "hu": + case "hu-HU": + gameLanguage = "hu_hu"; + break; + case "hy": + case "hy-AM": + gameLanguage = "hy_am"; + break; + case "id": + case "id-ID": + gameLanguage = "id_id"; + break; + case "is": + case "is-IS": + gameLanguage = "is_is"; + break; + case "it": + case "it-CH": + case "it-IT": + gameLanguage = "it_it"; + break; + case "ja": + case "ja-JP": + gameLanguage = "ja_jp"; + break; + case "ka": + case "ka-GE": + gameLanguage = "ka_ge"; + break; + case "kk": + case "kk-KZ": + gameLanguage = "kk_kz"; + break; + case "kn": + case "kn-IN": + gameLanguage = "kn_in"; + break; + case "kok": + case "kok-IN": + break; + case "ko": + case "ko-KR": + gameLanguage = "ko_kr"; + break; + case "ky": + case "ky-KG": + break; + case "lt": + case "lt-LT": + gameLanguage = "lt_lt"; + break; + case "lv": + case "lv-LV": + gameLanguage = "lv_lv"; + break; + case "mi-NZ": + break; + case "mk": + case "mk-MK": + gameLanguage = "mk_mk"; + break; + case "mn": + case "mn-MN": + gameLanguage = "mn_mn"; + break; + case "mr": + case "mr-IN": + break; + case "ms": + case "ms-BN": + case "ms-MY": + gameLanguage = "ms_my"; + break; + case "mt-MT": + gameLanguage = "mt_mt"; + break; + case "nb-NO": + break; + case "nl": + case "nl-NL": + gameLanguage = "nl_nl"; + break; + case "nl-BE": + gameLanguage = "nl_be"; + break; + case "nn-NO": + gameLanguage = "nn_no"; + break; + case "no": + gameLanguage = "no_no‌"; + break; + case "ns-ZA": + break; + case "pa": + case "pa-IN": + break; + case "pl": + case "pl-PL": + gameLanguage = "pl_pl‌"; + break; + case "pt": + case "pt-PT": + gameLanguage = "pt_pt‌"; + break; + case "pt-BR": + gameLanguage = "pt_br‌"; + break; + case "quz-BO": + break; + case "quz-EC": + break; + case "quz-PE": + break; + case "ro": + case "ro-RO": + gameLanguage = "ro_ro‌"; + break; + case "ru": + case "ru-RU": + gameLanguage = "ru_ru"; + name.Add("ru"); + break; + case "sa": + case "sa-IN": + break; + case "se-FI": + case "se-NO": + case "se-SE": + gameLanguage = "se_no"; + break; + case "sk": + case "sk-SK": + gameLanguage = "sk_sk"; + break; + case "sl": + case "sl-SI": + gameLanguage = "sl_si"; + break; + case "sma-NO": + break; + case "sma-SE": + break; + case "smj-NO": + break; + case "smj-SE": + break; + case "smn-FI": + break; + case "sms-FI": + break; + case "sq": + case "sq-AL": + gameLanguage = "sq_al"; + break; + case "sr": + case "sr-Cyrl-BA": + case "sr-Cyrl-CS": + case "sr-Latn-BA": + case "sr-Latn-CS": + gameLanguage = "sr_sp"; + break; + case "sv": + case "sv-FI": + case "sv-SE": + gameLanguage = "sv_se"; + break; + case "sw": + case "sw-KE": + break; + case "syr": + case "syr-SY": + break; + case "ta": + case "ta-IN": + gameLanguage = "ta_in"; + break; + case "te": + case "te-IN": + break; + case "th": + case "th-TH": + gameLanguage = "th_th"; + break; + case "tn-ZA": + break; + case "tr": + case "tr-TR": + gameLanguage = "tr_tr"; + break; + case "tt": + case "tt-RU": + gameLanguage = "tt_ru"; + break; + case "uk": + case "uk-UA": + gameLanguage = "uk_ua"; + break; + case "ur": + case "ur-PK": + break; + case "uz": + case "uz-Cyrl-UZ": + case "uz-Latn-UZ": + break; + case "vi": + case "vi-VN": + gameLanguage = "vi_vn"; + name.Add("vi"); + break; + case "xh-ZA": + break; + case "zh-Hans": /* CurrentCulture.Parent.Name */ + case "zh": + case "zh-CN": + case "zh-CHS": + case "zh-SG": + gameLanguage = "zh_cn"; + name.Add("zh_Hans"); + name.Add("zh_Hant"); + break; + case "zh-Hant": /* CurrentCulture.Parent.Name */ + case "zh-HK": + case "zh-CHT": + case "zh-MO": + gameLanguage = "zh_hk"; + name.Add("zh_Hant"); + name.Add("zh_Hans"); + break; + case "zh-TW": + gameLanguage = "zh_tw"; + name.Add("zh_Hant"); + name.Add("zh_Hans"); + break; + case "zu-ZA": + break; + } + + name.Add("en"); + + return new(gameLanguage, name.ToArray()); + } + + public static string[] GetTranslationPriority(string gameLanguage) + { + List name = new(); + + switch (gameLanguage) + { + case "de_at": + case "de_ch": + case "de_de": + name.Add("de"); + break; + case "en_au": + case "en_ca": + case "en_gb": + case "en_nz": + case "en_pt": + case "en_ud": + case "en_us": + break; + case "fr_ca": + case "fr_fr": + name.Add("fr"); + break; + case "ru_ru": + name.Add("ru"); + break; + case "vi_vn": + name.Add("vi"); + break; + case "zh_cn": + name.Add("zh_Hans"); + name.Add("zh_Hant"); + break; + case "zh_hk": + case "zh_tw": + name.Add("zh_Hant"); + name.Add("zh_Hans"); + break; + } + + name.Add("en"); + + return name.ToArray(); } /// - /// Load default translation file (English) + /// Load translation files /// - /// - /// This will be loaded during program start up. - /// - private static void LoadDefaultTranslationsFile() - { - string[] engLang = DefaultConfigResource.TranslationEnglish.Split(new[] { "\r\n", "\r", "\n" }, StringSplitOptions.None); // use embedded translations - ParseTranslationContent(engLang); - } - - /// - /// Load translation file depends on system language or by giving a file path. Default to English if translation file does not exist - /// - public static void LoadExternalTranslationFile(string language) + public static void LoadTranslationFile(string[] languageList) { /* * External translation files @@ -108,44 +587,39 @@ namespace MinecraftClient * Lang/abc.ini, e.g. Lang/eng.ini which is the default language file * Useful for adding new translations of fixing typos without recompiling */ - - // Try to convert Minecraft language file name to two letters language name - if (language == "zh_cn") - language = "zh-CHS"; - else if (language == "zh_tw") - language = "zh-CHT"; - else - language = language.Split('_')[0]; - - string systemLanguage = string.IsNullOrEmpty(CultureInfo.CurrentCulture.Parent.Name) // Parent.Name might be empty - ? CultureInfo.CurrentCulture.Name - : CultureInfo.CurrentCulture.Parent.Name; string baseDir = AppDomain.CurrentDomain.BaseDirectory; string langDir = baseDir + ((baseDir.EndsWith(Path.DirectorySeparatorChar) ? String.Empty : Path.DirectorySeparatorChar) + translationFilePath + Path.DirectorySeparatorChar); - string langFileSystemLanguage = langDir + systemLanguage + ".ini"; - string langFileConfigLanguage = langDir + language + ".ini"; - if (File.Exists(langFileConfigLanguage)) - {// Language set in ini config - ParseTranslationContent(File.ReadAllLines(langFileConfigLanguage)); - return; - } - else + foreach (string lang in languageList) { - if (Settings.DebugMessages) - ConsoleIO.WriteLogLine("[Translations] No translation file found for " + language + ". (Looked '" + langFileConfigLanguage + "'"); - } + bool fileLoaded = false; + string langFileName = string.Format("{0}{1}.ini", langDir, lang); - if (File.Exists(langFileSystemLanguage)) - {// Fallback to system language - ParseTranslationContent(File.ReadAllLines(langFileSystemLanguage)); - return; - } - else - { - if (Settings.DebugMessages) - ConsoleIO.WriteLogLine("[Translations] No translation file found for system language (" + systemLanguage + "). (Looked '" + langFileSystemLanguage + "'"); + if (File.Exists(langFileName)) // Language set in ini config + { + fileLoaded = true; + Dictionary trans = ParseTranslationContent(File.ReadAllLines(langFileName)); + foreach ((string key, string value) in trans) + if (!string.IsNullOrWhiteSpace(value) && !translations.ContainsKey(key)) + translations.Add(key, value); + } + + string? resourseLangFile = DefaultConfigResource.ResourceManager.GetString("Translation_" + lang); + if (resourseLangFile != null) + { + fileLoaded = true; + Dictionary trans = ParseTranslationContent(resourseLangFile.Split(new[] { "\r\n", "\r", "\n" }, StringSplitOptions.None)); + foreach ((string key, string value) in trans) + if (!string.IsNullOrWhiteSpace(value) && !translations.ContainsKey(key)) + translations.Add(key, value); + } + + if (!fileLoaded) + { + if (Settings.Config.Logging.DebugMessages) + ConsoleIO.WriteLogLine("[Translations] No translation file found for " + lang + ". (Looked '" + langFileName + "'"); + } } } @@ -153,8 +627,9 @@ namespace MinecraftClient /// Parse the given array to translation map /// /// Content of the translation file (in ini format) - private static void ParseTranslationContent(string[] content) + private static Dictionary ParseTranslationContent(string[] content) { + Dictionary translations = new(); foreach (string lineRaw in content) { string line = lineRaw.Trim(); @@ -172,6 +647,7 @@ namespace MinecraftClient translations[translationName] = translationValue; } } + return translations; } /// @@ -185,7 +661,7 @@ namespace MinecraftClient { Directory.CreateDirectory(translationFilePath); } - File.WriteAllText(defaultPath, DefaultConfigResource.TranslationEnglish, Encoding.UTF8); + File.WriteAllText(defaultPath, DefaultConfigResource.Translation_en, Encoding.UTF8); } #region Console writing method wrapper diff --git a/MinecraftClient/WinAPI/ConsoleIcon.cs b/MinecraftClient/WinAPI/ConsoleIcon.cs index 5d8ee345..36492f7c 100644 --- a/MinecraftClient/WinAPI/ConsoleIcon.cs +++ b/MinecraftClient/WinAPI/ConsoleIcon.cs @@ -67,6 +67,16 @@ namespace MinecraftClient.WinAPI imageStream.Dispose(); httpWebRequest.Dispose(); } + catch (AggregateException ae) + { + foreach (var ex in ae.InnerExceptions) + { + if (ex is HttpRequestException) //Skin not found? Reset to default icon + RevertToMCCIcon(); + else + throw ex; + } + } catch (HttpRequestException) //Skin not found? Reset to default icon { RevertToMCCIcon(); diff --git a/MinecraftClient/WinAPI/ExitCleanUp.cs b/MinecraftClient/WinAPI/ExitCleanUp.cs index 1de9864f..0c68d04c 100644 --- a/MinecraftClient/WinAPI/ExitCleanUp.cs +++ b/MinecraftClient/WinAPI/ExitCleanUp.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Runtime.InteropServices; +using System.Threading; namespace MinecraftClient.WinAPI { @@ -79,9 +80,10 @@ namespace MinecraftClient.WinAPI } [DllImport("Kernel32")] - private static extern bool SetConsoleCtrlHandler(ConsoleCtrlHandler handler, bool add); - private delegate bool ConsoleCtrlHandler(CtrlType sig); - private static readonly ConsoleCtrlHandler? _handler; + private static extern bool SetConsoleCtrlHandler(EventHandler handler, bool add); + + private delegate bool EventHandler(CtrlType sig); + static EventHandler? _handler; enum CtrlType { From e4952dbee0b32be8ae5ddddb8547067739992073 Mon Sep 17 00:00:00 2001 From: BruceChen Date: Wed, 5 Oct 2022 15:39:42 +0800 Subject: [PATCH 02/14] Delete MinecraftClient.ini --- MinecraftClient/ChatBots/Alerts.cs | 4 + MinecraftClient/ChatBots/AntiAFK.cs | 2 + MinecraftClient/ChatBots/AutoCraft.cs | 5 +- MinecraftClient/ChatBots/AutoRelog.cs | 2 + MinecraftClient/ChatBots/AutoRespond.cs | 2 + MinecraftClient/ChatBots/ChatLog.cs | 2 + MinecraftClient/ChatBots/HangmanGame.cs | 6 +- MinecraftClient/ChatBots/Mailer.cs | 3 + MinecraftClient/ChatBots/PlayerListLogger.cs | 2 + MinecraftClient/ChatBots/ScriptScheduler.cs | 2 + .../DefaultConfigResource.Designer.cs | 56 +-- MinecraftClient/DefaultConfigResource.resx | 3 - .../Resources/config/MinecraftClient.ini | 319 ------------------ 13 files changed, 46 insertions(+), 362 deletions(-) delete mode 100644 MinecraftClient/Resources/config/MinecraftClient.ini diff --git a/MinecraftClient/ChatBots/Alerts.cs b/MinecraftClient/ChatBots/Alerts.cs index 51a82a18..0682f6f6 100644 --- a/MinecraftClient/ChatBots/Alerts.cs +++ b/MinecraftClient/ChatBots/Alerts.cs @@ -45,6 +45,10 @@ namespace MinecraftClient.ChatBots public void OnSettingUpdate() { + Matches_File ??= string.Empty; + Excludes_File ??= string.Empty; + Log_File ??= string.Empty; + if (!Enabled) return; bool checkSuccessed = true; diff --git a/MinecraftClient/ChatBots/AntiAFK.cs b/MinecraftClient/ChatBots/AntiAFK.cs index 9408cd5e..e166a432 100644 --- a/MinecraftClient/ChatBots/AntiAFK.cs +++ b/MinecraftClient/ChatBots/AntiAFK.cs @@ -48,6 +48,8 @@ namespace MinecraftClient.ChatBots (Delay.min, Delay.max) = (Delay.max, Delay.min); LogToConsole(BotName, Translations.TryGet("bot.antiafk.swapping")); } + + Command ??= string.Empty; } public struct Range diff --git a/MinecraftClient/ChatBots/AutoCraft.cs b/MinecraftClient/ChatBots/AutoCraft.cs index 74876699..0b3b93de 100644 --- a/MinecraftClient/ChatBots/AutoCraft.cs +++ b/MinecraftClient/ChatBots/AutoCraft.cs @@ -22,7 +22,10 @@ namespace MinecraftClient.ChatBots public string configFile = @"autocraft\config.ini"; - public void OnSettingUpdate() { } + public void OnSettingUpdate() + { + configFile ??= string.Empty; + } } private bool waitingForMaterials = false; diff --git a/MinecraftClient/ChatBots/AutoRelog.cs b/MinecraftClient/ChatBots/AutoRelog.cs index 40b9c169..f48288a9 100644 --- a/MinecraftClient/ChatBots/AutoRelog.cs +++ b/MinecraftClient/ChatBots/AutoRelog.cs @@ -33,6 +33,8 @@ namespace MinecraftClient.ChatBots public void OnSettingUpdate() { + Kick_Messages_File ??= string.Empty; + if (Delay.min > Delay.max) (Delay.min, Delay.max) = (Delay.max, Delay.min); diff --git a/MinecraftClient/ChatBots/AutoRespond.cs b/MinecraftClient/ChatBots/AutoRespond.cs index d05ba350..4ff83a6b 100644 --- a/MinecraftClient/ChatBots/AutoRespond.cs +++ b/MinecraftClient/ChatBots/AutoRespond.cs @@ -31,6 +31,8 @@ namespace MinecraftClient.ChatBots public void OnSettingUpdate() { + Matches_File ??= string.Empty; + if (!Enabled) return; if (!File.Exists(Matches_File)) diff --git a/MinecraftClient/ChatBots/ChatLog.cs b/MinecraftClient/ChatBots/ChatLog.cs index 7da2f887..7031255d 100644 --- a/MinecraftClient/ChatBots/ChatLog.cs +++ b/MinecraftClient/ChatBots/ChatLog.cs @@ -29,6 +29,8 @@ namespace MinecraftClient.ChatBots public void OnSettingUpdate() { + Log_File ??= string.Empty; + if (!Enabled) return; string Log_File_Full = Settings.Config.AppVar.ExpandVars(Log_File); diff --git a/MinecraftClient/ChatBots/HangmanGame.cs b/MinecraftClient/ChatBots/HangmanGame.cs index 281ed68e..0eb923c9 100644 --- a/MinecraftClient/ChatBots/HangmanGame.cs +++ b/MinecraftClient/ChatBots/HangmanGame.cs @@ -26,7 +26,11 @@ namespace MinecraftClient.ChatBots public string FileWords_FR = "hangman-fr.txt"; - public void OnSettingUpdate() { } + public void OnSettingUpdate() + { + FileWords_EN ??= string.Empty; + FileWords_FR ??= string.Empty; + } } private int vie = 0; diff --git a/MinecraftClient/ChatBots/Mailer.cs b/MinecraftClient/ChatBots/Mailer.cs index a596b9f4..51eada78 100644 --- a/MinecraftClient/ChatBots/Mailer.cs +++ b/MinecraftClient/ChatBots/Mailer.cs @@ -36,6 +36,9 @@ namespace MinecraftClient.ChatBots public void OnSettingUpdate() { + DatabaseFile ??= string.Empty; + IgnoreListFile ??= string.Empty; + if (!Enabled) return; bool checkSuccessed = true; diff --git a/MinecraftClient/ChatBots/PlayerListLogger.cs b/MinecraftClient/ChatBots/PlayerListLogger.cs index a8c6e333..3ab8364d 100644 --- a/MinecraftClient/ChatBots/PlayerListLogger.cs +++ b/MinecraftClient/ChatBots/PlayerListLogger.cs @@ -28,6 +28,8 @@ namespace MinecraftClient.ChatBots public void OnSettingUpdate() { + File ??= string.Empty; + if (Delay < 10) Delay = 10; } diff --git a/MinecraftClient/ChatBots/ScriptScheduler.cs b/MinecraftClient/ChatBots/ScriptScheduler.cs index bd5296ad..ad95a76b 100644 --- a/MinecraftClient/ChatBots/ScriptScheduler.cs +++ b/MinecraftClient/ChatBots/ScriptScheduler.cs @@ -27,6 +27,8 @@ namespace MinecraftClient.ChatBots public void OnSettingUpdate() { + Tasks_File ??= string.Empty; + if (!Enabled) return; string Tasks_File_Full = Settings.Config.AppVar.ExpandVars(Tasks_File); diff --git a/MinecraftClient/DefaultConfigResource.Designer.cs b/MinecraftClient/DefaultConfigResource.Designer.cs index 6fa58c16..39a2ddf8 100644 --- a/MinecraftClient/DefaultConfigResource.Designer.cs +++ b/MinecraftClient/DefaultConfigResource.Designer.cs @@ -22,7 +22,7 @@ namespace MinecraftClient { [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")] [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - public class DefaultConfigResource { + internal class DefaultConfigResource { private static global::System.Resources.ResourceManager resourceMan; @@ -36,7 +36,7 @@ namespace MinecraftClient { /// Returns the cached ResourceManager instance used by this class. /// [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] - public static global::System.Resources.ResourceManager ResourceManager { + internal static global::System.Resources.ResourceManager ResourceManager { get { if (object.ReferenceEquals(resourceMan, null)) { global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("MinecraftClient.DefaultConfigResource", typeof(DefaultConfigResource).Assembly); @@ -51,7 +51,7 @@ namespace MinecraftClient { /// resource lookups using this strongly typed resource class. /// [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] - public static global::System.Globalization.CultureInfo Culture { + internal static global::System.Globalization.CultureInfo Culture { get { return resourceCulture; } @@ -75,7 +75,7 @@ namespace MinecraftClient { ///║║ 5 ║ 6 ║ 7 ║ 8 ║ 9 ║10 ║11 ║12 ║13 ║║ ///║╠═══╬═══╬═══╬═══╬══ [rest of string was truncated]";. /// - public static string ContainerType_BrewingStand { + internal static string ContainerType_BrewingStand { get { return ResourceManager.GetString("ContainerType_BrewingStand", resourceCulture); } @@ -96,7 +96,7 @@ namespace MinecraftClient { ///║║10 ║11 ║12 ║13 ║14 ║15 ║16 ║17 ║18 ║║ ///║╠═══╬═══╬═══╬═══╬══ [rest of string was truncated]";. /// - public static string ContainerType_Crafting { + internal static string ContainerType_Crafting { get { return ResourceManager.GetString("ContainerType_Crafting", resourceCulture); } @@ -117,7 +117,7 @@ namespace MinecraftClient { ///║╔═══╦═══╦═══╦═══╦═══╦═══╦═══╦═══╦═══╗║ ///║║ 3 ║ 4 ║ 5 ║ 6 ║ 7 [rest of string was truncated]";. /// - public static string ContainerType_Furnace { + internal static string ContainerType_Furnace { get { return ResourceManager.GetString("ContainerType_Furnace", resourceCulture); } @@ -138,7 +138,7 @@ namespace MinecraftClient { ///║║ 9 ║10 ║11 ║12 ║13 ║14 ║15 ║16 ║17 ║║ ///║╠═══╬═══╬═══╬═══╬══ [rest of string was truncated]";. /// - public static string ContainerType_Generic_3x3 { + internal static string ContainerType_Generic_3x3 { get { return ResourceManager.GetString("ContainerType_Generic_3x3", resourceCulture); } @@ -159,7 +159,7 @@ namespace MinecraftClient { ///║║27 ║28 ║29 ║30 ║31 ║32 ║33 ║34 ║35 ║║ ///║╠═══╬═══╬═══╬═══╬══ [rest of string was truncated]";. /// - public static string ContainerType_Generic_9x3 { + internal static string ContainerType_Generic_9x3 { get { return ResourceManager.GetString("ContainerType_Generic_9x3", resourceCulture); } @@ -180,7 +180,7 @@ namespace MinecraftClient { ///║║36 ║37 ║38 ║39 ║40 ║41 ║42 ║43 ║44 ║║ ///║╠═══╬═══╬═══╬═══╬══ [rest of string was truncated]";. /// - public static string ContainerType_Generic_9x6 { + internal static string ContainerType_Generic_9x6 { get { return ResourceManager.GetString("ContainerType_Generic_9x6", resourceCulture); } @@ -201,7 +201,7 @@ namespace MinecraftClient { ///║ ╚══╝ ╚══╝ ║ ///║ [rest of string was truncated]";. /// - public static string ContainerType_Grindstone { + internal static string ContainerType_Grindstone { get { return ResourceManager.GetString("ContainerType_Grindstone", resourceCulture); } @@ -222,7 +222,7 @@ namespace MinecraftClient { ///║║23 ║24 ║25 ║26 ║27 ║28 ║29 ║30 ║31 ║║ ///║╚═══╩═══╩═══╩═══╩══ [rest of string was truncated]";. /// - public static string ContainerType_Hopper { + internal static string ContainerType_Hopper { get { return ResourceManager.GetString("ContainerType_Hopper", resourceCulture); } @@ -243,32 +243,12 @@ namespace MinecraftClient { ///║║ 9 ║10 ║11 ║12 ║13 ║14 ║15 ║16 ║17 ║║ ///║╠═══╬═══╬═══╬═══╬══ [rest of string was truncated]";. /// - public static string ContainerType_PlayerInventory { + internal static string ContainerType_PlayerInventory { get { return ResourceManager.GetString("ContainerType_PlayerInventory", resourceCulture); } } - /// - /// Looks up a localized string similar to # Startup Config File - /// - ///# New to Minecraft Console Client? See README and sample configuration files here: - ///# https://github.com/MCCTeam/Minecraft-Console-Client/tree/master/MinecraftClient/config - /// - ///# Want to upgrade to a newer version? See https://github.com/MCCTeam/Minecraft-Console-Client/#download - ///# Some settings missing here after an upgrade? Try to delete this file and relaunch MCC to generate a new one - /// - ///[Main] - ///# General settings - ///# Leave blank to prompt user on startup - ///# Use "-" as password fo [rest of string was truncated]";. - /// - public static string MinecraftClient { - get { - return ResourceManager.GetString("MinecraftClient", resourceCulture); - } - } - /// /// Looks up a localized string similar to [mcc] ///# Messages from MCC itself @@ -284,7 +264,7 @@ namespace MinecraftClient { ///mcc.ip=Server-IP : ///mcc.use_version=§8B [rest of string was truncated]";. /// - public static string Translation_de { + internal static string Translation_de { get { return ResourceManager.GetString("Translation_de", resourceCulture); } @@ -303,7 +283,7 @@ namespace MinecraftClient { ///mcc.password_hidden=Password : {0} ///mcc.offline=§8You chose [rest of string was truncated]";. /// - public static string Translation_en { + internal static string Translation_en { get { return ResourceManager.GetString("Translation_en", resourceCulture); } @@ -323,7 +303,7 @@ namespace MinecraftClient { ///mcc.connecting=Connexion à {0}... /// [rest of string was truncated]";. /// - public static string Translation_fr { + internal static string Translation_fr { get { return ResourceManager.GetString("Translation_fr", resourceCulture); } @@ -344,7 +324,7 @@ namespace MinecraftClient { ///mcc.ip=IP сервера: ///mc [rest of string was truncated]";. /// - public static string Translation_ru { + internal static string Translation_ru { get { return ResourceManager.GetString("Translation_ru", resourceCulture); } @@ -365,7 +345,7 @@ namespace MinecraftClient { ///mcc.ip=Địa chỉ máy chủ: ///mcc.use_version=§8Sử dụng Minecraft phiên bản [rest of string was truncated]";. /// - public static string Translation_vi { + internal static string Translation_vi { get { return ResourceManager.GetString("Translation_vi", resourceCulture); } @@ -388,7 +368,7 @@ namespace MinecraftClient { ///mcc.profile_key_invalid=§8缓存的聊天签名密钥需要刷新。 ///mcc.profile_key_valid=§8{0}的聊天 [rest of string was truncated]";. /// - public static string Translation_zh_Hans { + internal static string Translation_zh_Hans { get { return ResourceManager.GetString("Translation_zh_Hans", resourceCulture); } diff --git a/MinecraftClient/DefaultConfigResource.resx b/MinecraftClient/DefaultConfigResource.resx index 0c6c67bd..112ddc61 100644 --- a/MinecraftClient/DefaultConfigResource.resx +++ b/MinecraftClient/DefaultConfigResource.resx @@ -145,9 +145,6 @@ Resources\containers\ContainerType.PlayerInventory.txt;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8 - - Resources\config\MinecraftClient.ini;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8 - resources\lang\de.ini;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8 diff --git a/MinecraftClient/Resources/config/MinecraftClient.ini b/MinecraftClient/Resources/config/MinecraftClient.ini deleted file mode 100644 index bf862aac..00000000 --- a/MinecraftClient/Resources/config/MinecraftClient.ini +++ /dev/null @@ -1,319 +0,0 @@ -# Startup Config File - -# New to Minecraft Console Client? See README and sample configuration files here: -# https://github.com/MCCTeam/Minecraft-Console-Client/tree/master/MinecraftClient/config - -# Want to upgrade to a newer version? See https://github.com/MCCTeam/Minecraft-Console-Client/#download -# Some settings missing here after an upgrade? Try to delete this file and relaunch MCC to generate a new one - -[Main] -# General settings -# Leave blank to prompt user on startup -# Use "-" as password for offline mode -login= -password= -serverip= -type=microsoft # Account type. mojang or microsoft. Also affects interactive login in console. -method=mcc # Microsoft Account sign-in method. mcc OR browser - -# Advanced settings -# Make sure you understand what each setting does before changing anything! -language=en_GB -consoletitle=%username%@%serverip% - Minecraft Console Client -internalcmdchar=slash # Use 'none', 'slash' or 'backslash' -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! -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. -chatbotlogfile= # Leave empty for no logfile -privatemsgscmdname=tell # Used by RemoteControl bot -showsystemmessages=true # System messages for server ops -showxpbarmessages=true # Messages displayed above xp bar, set this to false in case of xp bar spam -showchatlinks=true # Decode links embedded in chat messages and show them in console -showinventorylayout=true # Show inventory layout as ASCII art in inventory command -terrainandmovements=false # Uses more ram, cpu, bandwidth but allows you to move around -inventoryhandling=false # Toggle inventory handling (beta) -entityhandling=false # Toggle entity handling (beta) -sessioncache=disk # How to retain session tokens. Use 'none', 'memory' or 'disk' -profilekeycache=disk # How to retain profile key. Use 'none', 'memory' or 'disk' -resolvesrvrecords=fast # Use 'false', 'fast' (5s timeout), or 'true'. Required for joining some servers. -accountlist=accounts.txt # See README > 'Servers and Accounts file' for more info about this file -serverlist=servers.txt # See README > 'Servers and Accounts file' for more info about this file -playerheadicon=true # Only works on Windows XP-8 or Windows 10 with old console -exitonfailure=false # Disable pauses on error, for using MCC in non-interactive scripts -scriptcache=true # Cache compiled scripts for faster load on low-end devices -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=false # 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. -enableemoji=true # If turned off, the emoji will be replaced with a simpler character (for /chunk status) -movementspeed=2 # A movement speed higher than 2 may be considered cheating. - -[Signature] -# Chat settings (affects minecraft 1.19+) -login_with_secure_profile=true # Microsoft accounts only. If disabled, will not be able to sign chat and join servers configured with "enforce-secure-profile=true" -sign_chat=true # Whether to sign the chat send from MCC -sign_message_in_command=true # Whether to sign the messages contained in the commands sent by MCC. For example, the message in "/msg" and "/me" -mark_legally_signed_msg=false # Use green color block to mark chat with legitimate signatures -mark_modified_msg=true # Use yellow color block to mark chat that have been modified by the server. -mark_illegally_signed_msg=true # Use red color block to mark chat without legitimate signature -mark_system_message=false # Use gray color block to mark system message (always without signature) -show_modified_chat=true # Set to true to display messages modified by the server, false to display the original signed messages -show_illegal_signed_chat=true # Whether to display chat and messages in commands without legal signatures - -[Logging] -# Only affect the messages on console. -debugmessages=false # Please enable this before submitting bug reports. Thanks! -chatmessages=true # Show server chat messages -warningmessages=true # Show warning messages -errormessages=true # Show error messages -infomessages=true # Informative messages (i.e Most of the message from MCC) -#chatfilter= # Regex for filtering chat message -#debugfilter= # Regex for filtering debug message -filtermode=blacklist # blacklist OR whitelist. Blacklist hide message match regex. Whitelist show message match regex -logtofile=false # Write log messages to file -logfile=console-log-%username%-%serverip%.txt # Log file name -prependtimestamp=false # Prepend timestamp to messages in log file -savecolorcodes=false # Keep color codes in the saved text (§b) - -[AppVars] -# yourvar=yourvalue -# can be used in some other fields as %yourvar% -# %username% and %serverip% are reserved variables. - -[Proxy] -# Connect to a server via a proxy instead of connecting directly -# If Mojang session services are blocked on your network, set enabled=login to login using proxy but connect directly to the server -# If connecting to port 25565 (Minecraft) is blocked on your network, set enabled=true to login & connect using the proxy -# /!\ Make sure your server rules allow Proxies or VPNs before setting enabled=true, or you may face consequences! -enabled=false # Use 'false', 'true', or 'login' for login only -type=HTTP # Supported types: HTTP, SOCKS4, SOCKS4a, SOCKS5 -server=0.0.0.0:0000 # Proxy server must allow HTTPS for login, and non-443 ports for playing -username= # Only required for password-protected proxies -password= # Only required for password-protected proxies - -[ChatFormat] -# MCC does it best to detect chat messages, but some server have unusual chat formats -# When this happens, you'll need to configure chat format below, see README > 'Detecting chat messages' -# Do not forget to uncomment (remove '#') these settings if modifying them -builtins=true # MCC support for common message formats. Set "false" to avoid conflicts with custom formats. -# public=^<([a-zA-Z0-9_]+)> (.+)$ -# private=^([a-zA-Z0-9_]+) whispers to you: (.+)$ -# tprequest=^([a-zA-Z0-9_]+) has requested (?:to|that you) teleport to (?:you|them)\.$ - -[MCSettings] -# Settings below are sent to the server and only affect server-side things like your skin -enabled=true # If disabled, settings below are not sent to the server -locale=en_US # Use any language implemented in Minecraft -renderdistance=medium # Use tiny, short, medium, far, or chunk amount [0 - 255] -difficulty=normal # MC 1.7- difficulty. peaceful, easy, normal, difficult -chatmode=enabled # Use 'enabled', 'commands', or 'disabled'. Allows to mute yourself... -chatcolors=true # Allows disabling chat colors server-side -main_hand=left # MC 1.9+ main hand. left or right -skin_cape=true -skin_hat=true -skin_jacket=false -skin_sleeve_left=false -skin_sleeve_right=false -skin_pants_left=false -skin_pants_right=false - -# =============================== # -# Minecraft Console Client Bots # -# =============================== # - -# Although Minecraft Console Client is only a Chat client by default, it can also do many more things -# Below you will find configuration sections to enable Bots that can automatically perform tasks for you -# BY ENABLING BOTS, YOU AGREE TO COMPLY WITH SERVER RULES, AND FACE CONSEQUENCES FROM SERVER STAFF IF YOU DON'T - -[Alerts] -# 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 -logtofile=false # Log alerts info a file -logfile=alerts-log.txt # The name of a file where alers logs will be written - -[AntiAFK] -# Send a command on a regular or random basis or make the bot walk around randomly to avoid automatic AFK disconnection -# /!\ Make sure your server rules do not forbid anti-AFK mechanisms! -# /!\ Make sure you keep the bot in an enclosure to prevent it wandering off if you're using terrain handling! (Recommended size 5x5x5) -enabled=false -delay=600 # 10 = 1s (Can also be a random number between 2 numbers, example: 50-600) (Default: 600) -command=/ping # Command to send to the server -use_terrain_handling=false # Use terrain handling to enable the bot to move around -walk_range=5 # The range the bot can move around randomly (Note: the bigger the range, the slower the bot will be) -walk_retries=20 # How many timec can the bot fail trying to move before using the command method - -[AutoRelog] -# Automatically relog when disconnected by server, for example because the server is restating -# Put keywords/strings such as "Server is restarting" in kick messages file to relog when the message is seen -# /!\ Use ignorekickmessage=true at own risk! Server staff might not appreciate if you auto-relog on manual kicks -enabled=false -delay=10 # use 10 for 10 seconds, 10-60 for a random delay between 10 and 60 seconds -retries=3 # retries when failing to relog to the server. use -1 for unlimited retries -kickmessagesfile=kickmessages.txt # file with list of matches in kick messages that will trigger autorelog -ignorekickmessage=false # when set to true, autorelog will reconnect regardless of kick messages - -[ChatLog] -# Logs chat messages in a file on disk -enabled=false -timestamps=true -filter=messages -logfile=chatlog-%username%-%serverip%.txt - -[Hangman] -# A small game to demonstrate chat interactions. Players can guess mystery words one letter at a time. -# You need to have ChatFormat working correctly and add yourself in botowners to start the game with /tell start -# /!\ This bot may get a bit spammy if many players are interacting with it -enabled=false -english=true -wordsfile=hangman-en.txt -fichiermots=hangman-fr.txt - -[ScriptScheduler] -# Schedule commands and scripts to launch on various events such as server join, date/time or time interval -# See README > 'Using the Script Scheduler' for more info -enabled=false -tasksfile=tasks.ini - -[RemoteControl] -# Send MCC console commands to your bot through server PMs (/tell) -# You need to have ChatFormat working correctly and add yourself in botowners to use the bot -# /!\ Server admins can spoof PMs (/tellraw, /nick) so enable RemoteControl only if you trust server admins -enabled=false -autotpaccept=true -tpaccepteveryone=false - -[AutoRespond] -# Run commands or send messages automatically when a specified pattern is detected in chat -# /!\ Server admins can spoof chat messages (/nick, /tellraw) so keep this in mind when implementing AutoRespond rules -# /!\ This bot may get spammy depending on your rules, although the global messagecooldown setting can help you avoiding accidental spam -enabled=false -matchesfile=matches.ini -matchcolors=false # Do not remove colors from text (Note: Your matches will have to include color codes (ones using the § character) in order to work) - -[AutoAttack] -# Automatically attack hostile mobs around you -# You need to enable Entity Handling to use this bot -# /!\ Make sure server rules allow your planned use of AutoAttack -# /!\ SERVER PLUGINS may consider AutoAttack to be a CHEAT MOD and TAKE ACTION AGAINST YOUR ACCOUNT so DOUBLE CHECK WITH SERVER RULES! -enabled=false -mode=single # single or multi. single target one mob per attack. multi target all mobs in range per attack -priority=distance # health or distance. Only needed when using single mode -cooldownseconds=auto # How long to wait between each attack. Use auto to let MCC calculate it -interaction=Attack # Possible values: Interact, Attack (default), InteractAt (Interact and Attack) -attackhostile=true # Allow attacking hostile mobs -attackpassive=false # Allow attacking passive mobs -listmode=blacklist # Wether to treat the list from the file bellow as a whitelist or as a blacklist -# A path to the file which contains blacklisted or whitelisted entities, entity types are written on a new line -# All entity types can be found here: https://bit.ly/3Rg68lp -# The file is not created by default. -listfile=autoattack-list.txt - -[AutoFishing] -# Automatically catch fish using a fishing rod -# Guide: https://mccteam.github.io/guide/chat-bots.html#auto-fishing -# /!\ Make sure server rules allow automated farming before using this bot -enabled=false -antidespawn=false -main_hand=true # Use the main hand or the off hand to hold the rod. -auto_start=true # Whether to start fishing automatically after entering a world. -cast_delay=0.4 # How soon to re-cast after successful fishing. -fishing_delay=3.0 # How long after entering the game to start fishing (seconds). -fishing_timeout=300.0 # Fishing timeout (seconds). Timeout will trigger a re-cast. -durability_limit=2 # Will not use rods with less durability than this (full durability is 64). Set to zero to disable this feature. -auto_rod_switch=true # Switch to a new rod from inventory after the current rod is unavailable. -stationary_threshold=0.001 # Hooks moving in the X and Z axes below this threshold will be considered stationary. -hook_threshold=0.2 # A stationary hook moving on the Y-axis above this threshold will be considered to have caught a fish. -log_fishing_bobber=false # For debugging purposes, you can use this log to adjust the two thresholds mentioned above. -location= # Some plugins do not allow the player to fish in one place. This allows the player to change position/angle after each fish caught. - # Floating-point numbers can be used for both coordinates and angles. Leave blank to disable this function. - # Change the angle only (recommended): location=yaw_1, pitch_1; yaw_2, pitch_2; ...; yaw_n, pitch_n - # Change position only: location=x1, y1, z1; x2, y2, z2; ...; xn, yn, zn - # Change both angle and position: location=x1, y1, z1, yaw_1, pitch_1; x2, y2, z2, yaw_2, pitch_2; ... ;xn, yn, zn, yaw_n, pitch_n - -[AutoEat] -# Automatically eat food when your Hunger value is low -# You need to enable Inventory Handling to use this bot -enabled=false -threshold=6 - -[AutoCraft] -# Automatically craft items in your inventory -# See README > 'Using the AutoCraft bot' for how to use -# You need to enable Inventory Handling to use this bot -# You should also enable Terrain and Movements if you need to use a crafting table -enabled=false -configfile=autocraft\config.ini - -[Mailer] -# Relay messages between players and servers, like a mail plugin -# This bot can store messages when the recipients are offline, and send them when they join the server -# /!\ Server admins can spoof PMs (/tellraw, /nick) so enable this bot only if you trust server admins -enabled=false -database=MailerDatabase.ini -ignorelist=MailerIgnoreList.ini -publicinteractions=false -maxmailsperplayer=10 -maxdatabasesize=10000 -retentiondays=30 - -[AutoDrop] -# Automatically drop items in inventory -# You need to enable Inventory Handling to use this bot -enabled=false -mode=include # include, exclude or everything. Include: drop item IN the list. Exclude: drop item NOT IN the list -items= # separate each item name with a comma ',': ItemOne,ItemTwo -# See this file for an up-to-date list of item types you can use with this bot: -# https://github.com/MCCTeam/Minecraft-Console-Client/blob/master/MinecraftClient/Inventory/ItemType.cs - -[ReplayMod] -# Enable recording of the game (/replay start) and replay it later using the Replay Mod (https://www.replaymod.com/) -# Please note that due to technical limitations, the client player (you) will not be shown in the replay file -# /!\ You SHOULD use /replay stop or exit the program gracefully with /quit OR THE REPLAY FILE MAY GET CORRUPT! -enabled=false -backupinterval=300 # How long should replay file be auto-saved, in seconds. Use -1 to disable - -[FollowPlayer] -# Enabled you to make the bot follow you -# NOTE: This is an experimental feature, the bot can be slow at times, you need to walk with a normal speed and to sometimes stop for it to be able to keep up with you -# It's similar to making animals follow you when you're holding food in your hand. -# This is due to a slow pathfinding algorithm, we're working on getting a better one -# You can tweak the update limit and find what works best for you. (NOTE: Do not but a very low one, because you might achieve the opposite, -# this might clog the thread for terain handling) and thus slow the bot even more. -# /!\ Make sure server rules allow an option like this in the rules of the server before using this bot -enabled=false -update_limit=10 # The rate at which the bot does calculations (10 = 1s) (Default: 5) (You can tweak this if you feel the bot is too slow) -stop_at_distance=3 # Do not follow the player if he is in the range of 3 blocks (prevents the bot from pushing a player in an infinite loop) - -[PlayerListLogger] -# Log the list of players periodically into a textual file -enabled=false -log_file=playerlog.txt -log_delay=600 # 10 = 1s - -[Map] -# Allows you to render maps into .jpg images -# This is useful for solving captchas which use maps -# The maps are rendered into Rendered_Maps folder. -# NOTE: -# This feature is currently only useful for solving captchas which use maps. -# If some servers have a very short time for solving captchas, enabe auto_render_on_update and prepare to open the file quickly. -# On linux you can use FTP to access generated files. -# In the future it might will be possible to display maps directly in the console with a separate command. -# /!\ Make sure server rules allow bots to be used on the server, or you risk being punished. -enabled=false -resize_map=false # Should the map be resized? (Default one is small 128x128) -resize_to=256 # The size to resize the map to (Note: the bigger it is, the lower the quallity is) -auto_render_on_update=false # Automatically render the map once it's received or updated from/by the server -delete_rendered_on_unload=true # Delete all rendered maps on unload/reload (Does not delete the images if you exit the client) -notify_on_first_update=false # Get a notification when you have gotten a map from the server for the first time - # Note: Will be printed for each map in vicinity, could cause spam if there are a lot of maps \ No newline at end of file From e0678ea7a5a259a15271759a5a96f91fa6dcf4b4 Mon Sep 17 00:00:00 2001 From: BruceChen Date: Wed, 5 Oct 2022 17:10:10 +0800 Subject: [PATCH 03/14] Merge ScriptScheduler's config --- MinecraftClient/ChatBots/ScriptScheduler.cs | 296 +++++++++----------- MinecraftClient/McClient.cs | 2 +- MinecraftClient/Program.cs | 15 +- 3 files changed, 141 insertions(+), 172 deletions(-) diff --git a/MinecraftClient/ChatBots/ScriptScheduler.cs b/MinecraftClient/ChatBots/ScriptScheduler.cs index ad95a76b..a502c3a4 100644 --- a/MinecraftClient/ChatBots/ScriptScheduler.cs +++ b/MinecraftClient/ChatBots/ScriptScheduler.cs @@ -3,7 +3,9 @@ using System.Collections.Generic; using System.Globalization; using System.IO; using System.Text; +using System.Threading.Tasks; using Tomlet.Attributes; +using static MinecraftClient.ChatBots.ScriptScheduler.Configs; namespace MinecraftClient.ChatBots { @@ -23,155 +25,126 @@ namespace MinecraftClient.ChatBots public bool Enabled = false; - public string Tasks_File = @"tasks.ini"; + public TaskConfig[] TaskList = new TaskConfig[] { new() }; public void OnSettingUpdate() { - Tasks_File ??= string.Empty; - - if (!Enabled) return; - - string Tasks_File_Full = Settings.Config.AppVar.ExpandVars(Tasks_File); - if (!File.Exists(Tasks_File_Full)) + foreach (TaskConfig task in TaskList) + { + //Look for a valid action + if (!String.IsNullOrWhiteSpace(task.Action)) + { + //Look for a valid trigger + if (task.Trigger_On_Login + || task.Trigger_On_First_Login + || (task.Trigger_On_Times.Enable && task.Trigger_On_Times.Times.Length > 0) + || (task.Trigger_On_Interval.Enable && task.Trigger_On_Interval.MinTime > 0)) + { + if (Settings.Config.Logging.DebugMessages) + LogToConsole(BotName, Translations.TryGet("bot.scriptScheduler.loaded_task", Task2String(task))); + task.Trigger_On_Interval_Countdown = task.Trigger_On_Interval.MinTime; //Init countdown for interval + } + else + { + if (Settings.Config.Logging.DebugMessages) + LogToConsole(BotName, Translations.TryGet("bot.scriptScheduler.no_trigger", Task2String(task))); + } + } + else + { + task.Action ??= string.Empty; + if (Settings.Config.Logging.DebugMessages) + LogToConsole(BotName, Translations.TryGet("bot.scriptScheduler.no_action", Task2String(task))); + } + } + + if (Enabled && TaskList.Length == 0) { - LogToConsole(BotName, Translations.TryGet("bot.scriptScheduler.not_found", Path.GetFullPath(Tasks_File_Full))); LogToConsole(BotName, Translations.TryGet("general.bot_unload")); Enabled = false; } } + + public class TaskConfig + { + public string Task_Name = "Task Name (Can be empty)"; + public bool Trigger_On_First_Login = false; + public bool Trigger_On_Login = false; + public TriggerOnTimeConfig Trigger_On_Times = new(false, new TimeSpan[] { new(23, 59, 59) }); + public TriggerOnIntervalConfig Trigger_On_Interval = new(false, 1, 10); + public string Action = "send /hello"; + + [NonSerialized] + public bool Trigger_On_Time_Already_Triggered = false; + + [NonSerialized] + public int Trigger_On_Interval_Countdown = 0; + + public struct TriggerOnTimeConfig + { + public bool Enable = false; + public TimeSpan[] Times; + + public TriggerOnTimeConfig(bool Enable, TimeSpan[] Time) + { + this.Enable = Enable; + this.Times = Time; + } + + public TriggerOnTimeConfig(TimeSpan[] Time) + { + this.Enable = true; + this.Times = Time; + } + } + + public struct TriggerOnIntervalConfig + { + public bool Enable = false; + public int MinTime, MaxTime; + + public TriggerOnIntervalConfig(int value) + { + this.Enable = true; + value = Math.Max(value, 10); + MinTime = MaxTime = value; + } + + public TriggerOnIntervalConfig(bool Enable, int value) + { + this.Enable = Enable; + value = Math.Max(value, 10); + MinTime = MaxTime = value; + } + + public TriggerOnIntervalConfig(int min, int max) + { + min = Math.Max(min, 10); + max = Math.Max(max, 10); + this.MinTime = min; + this.MaxTime = max; + } + + public TriggerOnIntervalConfig(bool Enable, int min, int max) + { + this.Enable = Enable; + min = Math.Max(min, 10); + max = Math.Max(max, 10); + this.MinTime = min; + this.MaxTime = max; + } + } + } } - private class TaskDesc - { - public string? action = null; - public bool triggerOnFirstLogin = false; - public bool triggerOnLogin = false; - public bool triggerOnTime = false; - public bool triggerOnInterval = false; - public int triggerOnInterval_Interval = 0; - public int triggerOnInterval_Interval_Max = 0; - public int triggerOnInterval_Interval_Countdown = 0; - public List triggerOnTime_Times = new(); - public bool triggerOnTime_alreadyTriggered = false; - } + private Random random = new(); private static bool firstlogin_done = false; private bool serverlogin_done = false; - private readonly List tasks = new(); private int verifytasks_timeleft = 10; private readonly int verifytasks_delay = 10; - public override void Initialize() - { - //Load the given file from the startup parameters - string Tasks_File_Full = Settings.Config.AppVar.ExpandVars(Config.Tasks_File); - if (File.Exists(Tasks_File_Full)) - { - LogDebugToConsoleTranslated("bot.scriptScheduler.loading", System.IO.Path.GetFullPath(Tasks_File_Full)); - TaskDesc? current_task = null; - string[] lines = System.IO.File.ReadAllLines(Tasks_File_Full, Encoding.UTF8); - foreach (string lineRAW in lines) - { - string line = lineRAW.Split('#')[0].Trim(); - if (line.Length > 0) - { - if (line[0] == '[' && line[^1] == ']') - { - switch (line[1..^1].ToLower()) - { - case "task": - CheckAddTask(current_task); - current_task = new TaskDesc(); //Create a blank task - break; - } - } - else if (current_task != null) - { - string argName = line.Split('=')[0]; - if (line.Length > (argName.Length + 1)) - { - string argValue = line[(argName.Length + 1)..]; - switch (argName.ToLower()) - { - case "triggeronfirstlogin": current_task.triggerOnFirstLogin = bool.Parse(argValue); break; - case "triggeronlogin": current_task.triggerOnLogin = bool.Parse(argValue); break; - case "triggerontime": current_task.triggerOnTime = bool.Parse(argValue); break; - case "triggeroninterval": current_task.triggerOnInterval = bool.Parse(argValue); break; - case "timevalue": try { current_task.triggerOnTime_Times.Add(DateTime.ParseExact(argValue, "HH:mm", CultureInfo.InvariantCulture)); } catch { } break; - case "timeinterval": - int interval; - int intervalMax = 0; - - if (argValue.Contains('-')) - { - string[] parts = argValue.Split("-"); - if (parts.Length == 2) - { - interval = int.Parse(parts[0].Trim(), NumberStyles.Any, CultureInfo.CurrentCulture); - intervalMax = int.Parse(parts[1].Trim(), NumberStyles.Any, CultureInfo.CurrentCulture); - } - else - { - interval = 1; - } - } - else - { - interval = int.Parse(argValue, NumberStyles.Any, CultureInfo.CurrentCulture); - } - - current_task.triggerOnInterval_Interval = interval; - current_task.triggerOnInterval_Interval_Max = intervalMax; - - break; - case "script": current_task.action = "script " + argValue; break; //backward compatibility with older tasks.ini - case "action": current_task.action = argValue; break; - } - } - } - } - } - CheckAddTask(current_task); - } - else - { - LogToConsoleTranslated("bot.scriptScheduler.not_found", Path.GetFullPath(Tasks_File_Full)); - UnloadBot(); //No need to keep the bot active - } - } - - private void CheckAddTask(TaskDesc? current_task) - { - //Check if we built a valid task before adding it - if (current_task != null) - { - //Look for a valid action - if (!String.IsNullOrWhiteSpace(current_task.action)) - { - //Look for a valid trigger - if (current_task.triggerOnLogin - || current_task.triggerOnFirstLogin - || (current_task.triggerOnTime && current_task.triggerOnTime_Times.Count > 0) - || (current_task.triggerOnInterval && current_task.triggerOnInterval_Interval > 0)) - { - - LogDebugToConsoleTranslated("bot.scriptScheduler.loaded_task", Task2String(current_task)); - current_task.triggerOnInterval_Interval_Countdown = current_task.triggerOnInterval_Interval; //Init countdown for interval - tasks.Add(current_task); - } - else - { - LogDebugToConsoleTranslated("bot.scriptScheduler.no_trigger", Task2String(current_task)); - } - } - else - { - LogDebugToConsoleTranslated("bot.scriptScheduler.no_action", Task2String(current_task)); - } - } - } - public override void Update() { if (verifytasks_timeleft <= 0) @@ -179,55 +152,50 @@ namespace MinecraftClient.ChatBots verifytasks_timeleft = verifytasks_delay; if (serverlogin_done) { - foreach (TaskDesc task in tasks) + foreach (TaskConfig task in Config.TaskList) { - if (task.triggerOnTime) + if (task.Trigger_On_Times.Enable) { bool matching_time_found = false; - foreach (DateTime time in task.triggerOnTime_Times) + foreach (TimeSpan time in task.Trigger_On_Times.Times) { - if (time.Hour == DateTime.Now.Hour && time.Minute == DateTime.Now.Minute) + if (time.Hours == DateTime.Now.Hour && time.Minutes == DateTime.Now.Minute) { matching_time_found = true; - if (!task.triggerOnTime_alreadyTriggered) + if (!task.Trigger_On_Time_Already_Triggered) { - task.triggerOnTime_alreadyTriggered = true; - LogDebugToConsoleTranslated("bot.scriptScheduler.running_time", task.action); - PerformInternalCommand(task.action!); + task.Trigger_On_Time_Already_Triggered = true; + LogDebugToConsoleTranslated("bot.scriptScheduler.running_time", task.Action); + PerformInternalCommand(task.Action); } } } if (!matching_time_found) - task.triggerOnTime_alreadyTriggered = false; + task.Trigger_On_Time_Already_Triggered = false; } - if (task.triggerOnInterval) + if (task.Trigger_On_Interval.Enable) { - if (task.triggerOnInterval_Interval_Countdown == 0) + if (task.Trigger_On_Interval_Countdown == 0) { - int time = task.triggerOnInterval_Interval; - - if (task.triggerOnInterval_Interval_Max != 0) - time = new Random().Next(task.triggerOnInterval_Interval, task.triggerOnInterval_Interval_Max); - - task.triggerOnInterval_Interval_Countdown = time; - LogDebugToConsoleTranslated("bot.scriptScheduler.running_inverval", task.action); - PerformInternalCommand(task.action!); + task.Trigger_On_Interval_Countdown = random.Next(task.Trigger_On_Interval.MinTime, task.Trigger_On_Interval.MaxTime); + LogDebugToConsoleTranslated("bot.scriptScheduler.running_inverval", task.Action); + PerformInternalCommand(task.Action); } - else task.triggerOnInterval_Interval_Countdown--; + else task.Trigger_On_Interval_Countdown--; } } } else { - foreach (TaskDesc task in tasks) + foreach (TaskConfig task in Config.TaskList) { - if (task.triggerOnLogin || (firstlogin_done == false && task.triggerOnFirstLogin)) + if (task.Trigger_On_Login || (firstlogin_done == false && task.Trigger_On_First_Login)) { - LogDebugToConsoleTranslated("bot.scriptScheduler.running_login", task.action); - PerformInternalCommand(task.action!); + LogDebugToConsoleTranslated("bot.scriptScheduler.running_login", task.Action); + PerformInternalCommand(task.Action); } } @@ -244,17 +212,17 @@ namespace MinecraftClient.ChatBots return false; } - private static string Task2String(TaskDesc task) + private static string Task2String(TaskConfig task) { return Translations.Get( "bot.scriptScheduler.task", - task.triggerOnFirstLogin, - task.triggerOnLogin, - task.triggerOnTime, - task.triggerOnInterval, - String.Join(", ", task.triggerOnTime_Times), - task.triggerOnInterval_Interval, - task.action + task.Trigger_On_First_Login, + task.Trigger_On_Login, + task.Trigger_On_Times.Enable, + task.Trigger_On_Interval.Enable, + task.Trigger_On_Times.Times, + task.Trigger_On_Interval.MinTime + '-' + task.Trigger_On_Interval.MaxTime, + task.Action ); } } diff --git a/MinecraftClient/McClient.cs b/MinecraftClient/McClient.cs index f0b0b276..6f9e85c5 100644 --- a/MinecraftClient/McClient.cs +++ b/MinecraftClient/McClient.cs @@ -452,7 +452,7 @@ namespace MinecraftClient if (timeoutdetector != null) { - if (Thread.CurrentThread != timeoutdetector.Item1) + if (timeoutdetector != null && Thread.CurrentThread != timeoutdetector.Item1) timeoutdetector.Item2.Cancel(); timeoutdetector = null; } diff --git a/MinecraftClient/Program.cs b/MinecraftClient/Program.cs index e25f18be..90fda3da 100644 --- a/MinecraftClient/Program.cs +++ b/MinecraftClient/Program.cs @@ -290,6 +290,7 @@ namespace MinecraftClient return; } } + InternalConfig.Username = Config.Main.General.Account.Login; if (string.IsNullOrEmpty(Config.Main.General.Account.Password) && !useBrowser && (Config.Main.Advanced.SessionCache == CacheType.none || !SessionCache.Contains(Settings.ToLowerIfNeed(Config.Main.General.Account.Login)))) { @@ -333,7 +334,7 @@ namespace MinecraftClient Translations.WriteLineFormatted("mcc.offline"); result = ProtocolHandler.LoginResult.Success; session.PlayerID = "0"; - session.PlayerName = Config.Main.General.Account.Login; + session.PlayerName = InternalConfig.Username; } else { @@ -372,14 +373,14 @@ namespace MinecraftClient Translations.WriteLine("mcc.connecting", Config.Main.General.AccountType == LoginType.mojang ? "Minecraft.net" : "Microsoft"); result = ProtocolHandler.GetLogin(Config.Main.General.Account.Login, InternalConfig.Password, Config.Main.General.AccountType, out session); } + + if (result == ProtocolHandler.LoginResult.Success && Config.Main.Advanced.SessionCache != CacheType.none) + SessionCache.Store(loginLower, session); + + if (result == ProtocolHandler.LoginResult.Success) + session.SessionPreCheckTask = Task.Factory.StartNew(() => session.SessionPreCheck()); } - if (result == ProtocolHandler.LoginResult.Success && Config.Main.Advanced.SessionCache != CacheType.none) - SessionCache.Store(loginLower, session); - - if (result == ProtocolHandler.LoginResult.Success) - session.SessionPreCheckTask = Task.Factory.StartNew(() => session.SessionPreCheck()); - if (result == ProtocolHandler.LoginResult.Success) { if (Config.Main.General.AccountType == LoginType.microsoft && InternalConfig.Password != "-" && Config.Signature.LoginWithSecureProfile) From a118dc96e9f229318cce51a608a072290cb2e003 Mon Sep 17 00:00:00 2001 From: BruceChen Date: Wed, 5 Oct 2022 17:33:21 +0800 Subject: [PATCH 04/14] Merge AutoRelog's configs --- MinecraftClient/ChatBots/AntiAFK.cs | 6 ++-- MinecraftClient/ChatBots/AutoRelog.cs | 39 +++++---------------- MinecraftClient/ChatBots/ScriptScheduler.cs | 11 +++--- MinecraftClient/Resources/lang/en.ini | 2 +- 4 files changed, 18 insertions(+), 40 deletions(-) diff --git a/MinecraftClient/ChatBots/AntiAFK.cs b/MinecraftClient/ChatBots/AntiAFK.cs index e166a432..5f9234a6 100644 --- a/MinecraftClient/ChatBots/AntiAFK.cs +++ b/MinecraftClient/ChatBots/AntiAFK.cs @@ -43,6 +43,9 @@ namespace MinecraftClient.ChatBots LogToConsole(BotName, Translations.TryGet("bot.antiafk.invalid_walk_range")); } + Delay.min = Math.Max(10, Delay.min); + Delay.max = Math.Max(10, Delay.max); + if (Delay.min > Delay.max) { (Delay.min, Delay.max) = (Delay.max, Delay.min); @@ -58,14 +61,11 @@ namespace MinecraftClient.ChatBots public Range(int value) { - value = Math.Max(value, 10); min = max = value; } public Range(int min, int max) { - min = Math.Max(min, 10); - max = Math.Max(max, 10); this.min = min; this.max = max; } diff --git a/MinecraftClient/ChatBots/AutoRelog.cs b/MinecraftClient/ChatBots/AutoRelog.cs index f48288a9..a5f03bd6 100644 --- a/MinecraftClient/ChatBots/AutoRelog.cs +++ b/MinecraftClient/ChatBots/AutoRelog.cs @@ -28,18 +28,22 @@ namespace MinecraftClient.ChatBots [TomlInlineComment("$config.ChatBot.AutoRelog.Ignore_Kick_Message$")] public bool Ignore_Kick_Message = false; - [TomlInlineComment("$config.ChatBot.AutoRelog.Kick_Messages_File$")] - public string Kick_Messages_File = @"kickmessages.txt"; + [TomlInlineComment("$config.ChatBot.AutoRelog.Kick_Messages$")] + public string[] Kick_Messages = new string[] { "Reason1", "Reason2" }; public void OnSettingUpdate() { - Kick_Messages_File ??= string.Empty; - + Delay.min = Math.Max(1, Delay.min); + Delay.max = Math.Max(1, Delay.max); if (Delay.min > Delay.max) (Delay.min, Delay.max) = (Delay.max, Delay.min); if (Retries == -1) Retries = int.MaxValue; + + if (Enabled) + for (int i = 0; i < Kick_Messages.Length; i++) + Kick_Messages[i] = Kick_Messages[i].ToLower(); } public struct Range @@ -48,14 +52,11 @@ namespace MinecraftClient.ChatBots public Range(int value) { - value = Math.Max(value, 1); min = max = value; } public Range(int min, int max) { - min = Math.Max(min, 1); - max = Math.Max(max, 1); this.min = min; this.max = max; } @@ -63,7 +64,6 @@ namespace MinecraftClient.ChatBots } private static readonly Random random = new(); - private string[] dictionary = Array.Empty(); /// /// This bot automatically re-join the server if kick message contains predefined string @@ -83,27 +83,6 @@ namespace MinecraftClient.ChatBots { LogDebugToConsoleTranslated("bot.autoRelog.no_kick_msg"); } - else - { - if (System.IO.File.Exists(Config.Kick_Messages_File)) - { - LogDebugToConsoleTranslated("bot.autoRelog.loading", System.IO.Path.GetFullPath(Config.Kick_Messages_File)); - - dictionary = System.IO.File.ReadAllLines(Config.Kick_Messages_File, Encoding.UTF8); - - for (int i = 0; i < dictionary.Length; i++) - { - LogDebugToConsoleTranslated("bot.autoRelog.loaded", dictionary[i]); - dictionary[i] = dictionary[i].ToLower(); - } - } - else - { - LogToConsoleTranslated("bot.autoRelog.not_found", System.IO.Path.GetFullPath(Config.Kick_Messages_File)); - - LogDebugToConsoleTranslated("bot.autoRelog.curr_dir", System.IO.Directory.GetCurrentDirectory()); - } - } } public override bool OnDisconnect(DisconnectReason reason, string message) @@ -125,7 +104,7 @@ namespace MinecraftClient.ChatBots return true; } - foreach (string msg in dictionary) + foreach (string msg in Config.Kick_Messages) { if (comp.Contains(msg)) { diff --git a/MinecraftClient/ChatBots/ScriptScheduler.cs b/MinecraftClient/ChatBots/ScriptScheduler.cs index a502c3a4..ca5bc001 100644 --- a/MinecraftClient/ChatBots/ScriptScheduler.cs +++ b/MinecraftClient/ChatBots/ScriptScheduler.cs @@ -31,6 +31,11 @@ namespace MinecraftClient.ChatBots { foreach (TaskConfig task in TaskList) { + task.Trigger_On_Interval.MinTime = Math.Max(1, task.Trigger_On_Interval.MinTime); + task.Trigger_On_Interval.MaxTime = Math.Max(1, task.Trigger_On_Interval.MaxTime); + if (task.Trigger_On_Interval.MinTime > task.Trigger_On_Interval.MaxTime) + (task.Trigger_On_Interval.MinTime, task.Trigger_On_Interval.MaxTime) = (task.Trigger_On_Interval.MaxTime, task.Trigger_On_Interval.MinTime); + //Look for a valid action if (!String.IsNullOrWhiteSpace(task.Action)) { @@ -106,21 +111,17 @@ namespace MinecraftClient.ChatBots public TriggerOnIntervalConfig(int value) { this.Enable = true; - value = Math.Max(value, 10); MinTime = MaxTime = value; } public TriggerOnIntervalConfig(bool Enable, int value) { this.Enable = Enable; - value = Math.Max(value, 10); MinTime = MaxTime = value; } public TriggerOnIntervalConfig(int min, int max) { - min = Math.Max(min, 10); - max = Math.Max(max, 10); this.MinTime = min; this.MaxTime = max; } @@ -128,8 +129,6 @@ namespace MinecraftClient.ChatBots public TriggerOnIntervalConfig(bool Enable, int min, int max) { this.Enable = Enable; - min = Math.Max(min, 10); - max = Math.Max(max, 10); this.MinTime = min; this.MaxTime = max; } diff --git a/MinecraftClient/Resources/lang/en.ini b/MinecraftClient/Resources/lang/en.ini index 7694728e..58dc2248 100644 --- a/MinecraftClient/Resources/lang/en.ini +++ b/MinecraftClient/Resources/lang/en.ini @@ -817,7 +817,7 @@ config.ChatBot.AutoRelog=Automatically relog when disconnected by server, for ex config.ChatBot.AutoRelog.Delay=use 10 for 10 seconds, 10-60 for a random delay between 10 and 60 seconds config.ChatBot.AutoRelog.Retries=retries when failing to relog to the server. use -1 for unlimited retries config.ChatBot.AutoRelog.Ignore_Kick_Message=when set to true, autorelog will reconnect regardless of kick messages -config.ChatBot.AutoRelog.Kick_Messages_File=file with list of matches in kick messages that will trigger autorelog +config.ChatBot.AutoRelog.Kick_Messages=If the kickout message matches any of the strings, then autorelog will be triggered. # ChatBot.AutoRespond config.ChatBot.AutoRespond=Run commands or send messages automatically when a specified pattern is detected in chat\n# /!\ Server admins can spoof chat messages (/nick, /tellraw) so keep this in mind when implementing AutoRespond rules\n# /!\ This bot may get spammy depending on your rules, although the global messagecooldown setting can help you avoiding accidental spam From 25dfcd8856e225fb5dc4da751609c03357cbe75e Mon Sep 17 00:00:00 2001 From: BruceChen Date: Wed, 5 Oct 2022 19:16:33 +0800 Subject: [PATCH 05/14] Merge AutoCraft's config --- MinecraftClient/ChatBots/AutoCraft.cs | 374 +++++++++----------------- MinecraftClient/Resources/lang/en.ini | 7 +- MinecraftClient/Settings.cs | 4 +- 3 files changed, 138 insertions(+), 247 deletions(-) diff --git a/MinecraftClient/ChatBots/AutoCraft.cs b/MinecraftClient/ChatBots/AutoCraft.cs index 0b3b93de..173f1394 100644 --- a/MinecraftClient/ChatBots/AutoCraft.cs +++ b/MinecraftClient/ChatBots/AutoCraft.cs @@ -5,6 +5,7 @@ using System.Linq; using MinecraftClient.Inventory; using MinecraftClient.Mapping; using Tomlet.Attributes; +using static MinecraftClient.ChatBots.AutoCraft.Configs; namespace MinecraftClient.ChatBots { @@ -20,12 +21,105 @@ namespace MinecraftClient.ChatBots public bool Enabled = false; - public string configFile = @"autocraft\config.ini"; + [TomlInlineComment("$config.ChatBot.AutoCraft.Table_Location$")] + public LocationConfig Table_Location = new(123, 65, 456); + + [TomlInlineComment("$config.ChatBot.AutoCraft.On_Failure$")] + public OnFailConfig On_Failure = OnFailConfig.abort; + + [TomlPrecedingComment("$config.ChatBot.AutoCraft.Recipes$")] + public RecipeConfig[] Recipes = new RecipeConfig[] + { + new RecipeConfig( + Name: "Recipe Name 1", + Type: CraftTypeConfig.player, + Result: ItemType.StoneBricks, + Slots: new ItemType[4] { ItemType.Stone, ItemType.Stone, ItemType.Stone, ItemType.Stone } + ), + new RecipeConfig( + Name: "Recipe Name 2", + Type: CraftTypeConfig.table, + Result: ItemType.StoneBricks, + Slots: new ItemType[9] { + ItemType.Stone, ItemType.Stone, ItemType.Null, + ItemType.Stone, ItemType.Stone, ItemType.Null, + ItemType.Null, ItemType.Null, ItemType.Null, + } + ), + }; + + [NonSerialized] + public Location _Table_Location = Location.Zero; public void OnSettingUpdate() { - configFile ??= string.Empty; + _Table_Location = new Location(Table_Location.X, Table_Location.Y, Table_Location.Z).ToFloor(); + foreach (RecipeConfig recipe in Recipes) + { + recipe.Name ??= string.Empty; + + int fixLength = -1; + if (recipe.Type == CraftTypeConfig.player && recipe.Slots.Length != 4) + fixLength = 4; + else if (recipe.Type == CraftTypeConfig.table && recipe.Slots.Length != 9) + fixLength = 9; + + if (fixLength > 0) + { + ItemType[] Slots = new ItemType[fixLength]; + for (int i = 0; i < fixLength; ++i) + Slots[i] = (i < recipe.Slots.Length) ? recipe.Slots[i] : ItemType.Null; + recipe.Slots = Slots; + LogToConsole(BotName, Translations.TryGet("bot.autocraft.invaild_slots")); + } + + if (recipe.Result == ItemType.Air || recipe.Result == ItemType.Null) + { + LogToConsole(BotName, Translations.TryGet("bot.autocraft.invaild_result")); + } + } } + + public struct LocationConfig + { + public double X, Y, Z; + + public LocationConfig(double X, double Y, double Z) + { + this.X = X; + this.Y = Y; + this.Z = Z; + } + } + + public enum OnFailConfig { abort, wait } + + public class RecipeConfig + { + public string Name = "Recipe Name"; + + public CraftTypeConfig Type = CraftTypeConfig.player; + + public ItemType Result = ItemType.Air; + + public ItemType[] Slots = new ItemType[9] { + ItemType.Null, ItemType.Null, ItemType.Null, + ItemType.Null, ItemType.Null, ItemType.Null, + ItemType.Null, ItemType.Null, ItemType.Null, + }; + + public RecipeConfig() { } + + public RecipeConfig(string Name, CraftTypeConfig Type, ItemType Result, ItemType[] Slots) + { + this.Name = Name; + this.Type = Type; + this.Result = Result; + this.Slots = Slots; + } + } + + public enum CraftTypeConfig { player, table } } private bool waitingForMaterials = false; @@ -37,18 +131,12 @@ namespace MinecraftClient.ChatBots private Recipe? recipeInUse; private readonly List actionSteps = new(); - private Location tableLocation = new(); - private bool abortOnFailure = true; private int updateDebounceValue = 2; private int updateDebounce = 0; private readonly int updateTimeoutValue = 10; private int updateTimeout = 0; private string timeoutAction = "unspecified"; - private string lastRecipe = ""; // Used in parsing recipe config - - private readonly Dictionary recipes = new(); - private void ResetVar() { craftingFailed = false; @@ -187,7 +275,6 @@ namespace MinecraftClient.ChatBots } RegisterChatBotCommand("autocraft", Translations.Get("bot.autoCraft.cmd"), GetHelp(), CommandHandler); RegisterChatBotCommand("ac", Translations.Get("bot.autoCraft.alias"), GetHelp(), CommandHandler); - LoadConfig(); } public string CommandHandler(string cmd, string[] args) @@ -196,32 +283,37 @@ namespace MinecraftClient.ChatBots { switch (args[0]) { - case "load": - LoadConfig(); - return ""; case "list": - string names = string.Join(", ", recipes.Keys.ToList()); - return Translations.Get("bot.autoCraft.cmd.list", recipes.Count, names); - case "reload": - recipes.Clear(); - LoadConfig(); - return ""; - case "resetcfg": - WriteDefaultConfig(); - return Translations.Get("bot.autoCraft.cmd.resetcfg"); + string names = string.Join(", ", Config.Recipes.ToList()); + return Translations.Get("bot.autoCraft.cmd.list", Config.Recipes.Length, names); case "start": if (args.Length >= 2) { string name = args[1]; - if (recipes.ContainsKey(name)) + + bool hasRecipe = false; + RecipeConfig? recipe = null; + foreach (RecipeConfig recipeConfig in Config.Recipes) + { + if (recipeConfig.Name == name) + { + hasRecipe = true; + recipe = recipeConfig; + break; + } + } + + if (hasRecipe) { ResetVar(); - PrepareCrafting(recipes[name]); + PrepareCrafting(recipe!); return ""; } - else return Translations.Get("bot.autoCraft.recipe_not_exist"); + else + return Translations.Get("bot.autoCraft.recipe_not_exist"); } - else return Translations.Get("bot.autoCraft.no_recipe_name"); + else + return Translations.Get("bot.autoCraft.no_recipe_name"); case "stop": StopCrafting(); return Translations.Get("bot.autoCraft.stop"); @@ -256,220 +348,6 @@ namespace MinecraftClient.ChatBots }; } - #region Config handling - - public void LoadConfig() - { - if (!File.Exists(Config.configFile)) - { - if (!Directory.Exists(Config.configFile)) - { - Directory.CreateDirectory(@"autocraft"); - } - WriteDefaultConfig(); - LogDebugToConsoleTranslated("bot.autoCraft.debug.no_config"); - } - try - { - ParseConfig(); - LogToConsoleTranslated("bot.autoCraft.loaded"); - } - catch (Exception e) - { - LogToConsoleTranslated("bot.autoCraft.error.config", "\n" + e.Message); - } - } - - private void WriteDefaultConfig() - { - string[] content = - { - "[AutoCraft]", - "# A valid autocraft config must begin with [AutoCraft]", - "", - "tablelocation=0,65,0 # Location of the crafting table if you intended to use it. Terrain and movements must be enabled. Format: x,y,z", - "onfailure=abort # What to do on crafting failure, abort or wait", - "", - "# You can define multiple recipes in a single config file", - "# This is an example of how to define a recipe", - "[Recipe]", - "name=whatever # name could be whatever you like. This field must be defined first", - "type=player # crafting table type: player or table", - "result=StoneButton # the resulting item", - "", - "# define slots with their deserved item", - "slot1=Stone # slot start with 1, count from left to right, top to bottom", - "# For the naming of the items, please see", - "# https://github.com/MCCTeam/Minecraft-Console-Client/blob/master/MinecraftClient/Inventory/ItemType.cs" - }; - File.WriteAllLines(Config.configFile, content); - } - - private void ParseConfig() - { - string[] content = File.ReadAllLines(Config.configFile); - if (content.Length <= 0) - { - throw new Exception(Translations.Get("bot.autoCraft.exception.empty", Config.configFile)); - } - if (content[0].ToLower() != "[autocraft]") - { - throw new Exception(Translations.Get("bot.autoCraft.exception.invalid", Config.configFile)); - } - - // local variable for use in parsing config - string section = ""; - Dictionary recipes = new(); - - foreach (string l in content) - { - // ignore comment start with # - if (l.StartsWith("#")) - continue; - string line = l.Split('#')[0].Trim(); - if (line.Length <= 0) - continue; - - if (line[0] == '[' && line[^1] == ']') - { - section = line[1..^1].ToLower(); - continue; - } - - string key = line.Split('=')[0].ToLower(); - if (!(line.Length > (key.Length + 1))) - continue; - string value = line[(key.Length + 1)..]; - switch (section) - { - case "recipe": ParseRecipe(key, value); break; - case "autocraft": ParseMain(key, value); break; - } - } - - // check and save recipe - foreach (var pair in recipes) - { - if ((pair.Value.CraftingAreaType == ContainerType.PlayerInventory - || pair.Value.CraftingAreaType == ContainerType.Crafting) - && (pair.Value.Materials != null - && pair.Value.Materials.Count > 0) - && pair.Value.ResultItem != ItemType.Air) - { - // checking pass - this.recipes.Add(pair.Key, pair.Value); - } - else - { - throw new Exception(Translations.Get("bot.autoCraft.exception.item_miss", pair.Key)); - } - } - - - } - - #region Method for parsing different section of config - - private void ParseMain(string key, string value) - { - switch (key) - { - case "tablelocation": - string[] values = value.Split(','); - if (values.Length == 3) - { - tableLocation.X = Convert.ToInt32(values[0]); - tableLocation.Y = Convert.ToInt32(values[1]); - tableLocation.Z = Convert.ToInt32(values[2]); - } - else throw new Exception(Translations.Get("bot.autoCraft.exception.invalid_table", key)); - break; - case "onfailure": - abortOnFailure = value.ToLower() == "abort"; - break; - case "updatedebounce": - updateDebounceValue = Convert.ToInt32(value); - break; - } - } - - private void ParseRecipe(string key, string value) - { - if (key.StartsWith("slot")) - { - int slot = Convert.ToInt32(key[^1].ToString()); - if (slot > 0 && slot < 10) - { - if (recipes.ContainsKey(lastRecipe)) - { - if (Enum.TryParse(value, true, out ItemType itemType)) - { - Dictionary? materials = recipes[lastRecipe].Materials; - if (materials != null && materials.Count > 0) - { - materials.Add(slot, itemType); - } - else - { - recipes[lastRecipe].Materials = new Dictionary() - { - { slot, itemType } - }; - } - return; - } - else - { - throw new Exception(Translations.Get("bot.autoCraft.exception.item_name", lastRecipe, key)); - } - } - else - { - throw new Exception(Translations.Get("bot.autoCraft.exception.name_miss")); - } - } - else - { - throw new Exception(Translations.Get("bot.autoCraft.exception.slot", key)); - } - } - else - { - switch (key) - { - case "name": - if (!recipes.ContainsKey(value)) - { - recipes.Add(value, new Recipe()); - lastRecipe = value; - } - else - { - throw new Exception(Translations.Get("bot.autoCraft.exception.duplicate", value)); - } - break; - case "type": - if (recipes.ContainsKey(lastRecipe)) - { - recipes[lastRecipe].CraftingAreaType = value.ToLower() == "player" ? ContainerType.PlayerInventory : ContainerType.Crafting; - } - break; - case "result": - if (recipes.ContainsKey(lastRecipe)) - { - if (Enum.TryParse(value, true, out ItemType itemType)) - { - recipes[lastRecipe].ResultItem = itemType; - } - } - break; - } - } - } - #endregion - - #endregion - #region Core part of auto-crafting public override void OnInventoryUpdate(int inventoryId) @@ -538,9 +416,19 @@ namespace MinecraftClient.ChatBots /// Prepare the crafting action steps by the given recipe name and start crafting /// /// Name of the recipe to craft - private void PrepareCrafting(string name) + private void PrepareCrafting(RecipeConfig recipeConfig) { - PrepareCrafting(recipes[name]); + Dictionary materials = new(); + for (int i = 0; i < recipeConfig.Slots.Length; ++i) + if (recipeConfig.Slots[i] != ItemType.Null) + materials[i] = recipeConfig.Slots[i]; + + ItemType ResultItem = recipeConfig.Result; + + ContainerType CraftingAreaType = + (recipeConfig.Type == CraftTypeConfig.player) ? ContainerType.PlayerInventory : ContainerType.Crafting; + + PrepareCrafting(new Recipe(materials, ResultItem, CraftingAreaType)); } /// @@ -561,7 +449,7 @@ namespace MinecraftClient.ChatBots if (inventoryInUse == -2) { // table required but not found. Try to open one - OpenTable(tableLocation); + OpenTable(Config._Table_Location); waitingForTable = true; SetTimeout(Translations.Get("bot.autoCraft.table_not_found")); return; @@ -711,7 +599,7 @@ namespace MinecraftClient.ChatBots // Inform user the missing meterial name LogToConsoleTranslated("bot.autoCraft.missing_material", actionSteps[index - 1].ItemType.ToString()); } - if (abortOnFailure) + if (Config.On_Failure == OnFailConfig.abort) { StopCrafting(); LogToConsoleTranslated("bot.autoCraft.aborted"); diff --git a/MinecraftClient/Resources/lang/en.ini b/MinecraftClient/Resources/lang/en.ini index 58dc2248..52ee50c4 100644 --- a/MinecraftClient/Resources/lang/en.ini +++ b/MinecraftClient/Resources/lang/en.ini @@ -501,6 +501,8 @@ bot.autoCraft.exception.name_miss=Missing recipe name while parsing a recipe bot.autoCraft.exception.slot=Invalid slot field in recipe: {0} bot.autoCraft.exception.duplicate=Duplicate recipe name specified: {0} bot.autoCraft.debug.no_config=No config found. Writing a new one. +bot.autocraft.invaild_slots=The number of slots does not match and has been adjusted automatically. +bot.autocraft.invaild_invaild_result=Invalid result item! # AutoDrop bot.autoDrop.cmd=AutoDrop ChatBot command @@ -787,6 +789,9 @@ config.ChatBot.AutoAttack.Entites_List=All entity types can be found here: https # ChatBot.AutoCraft config.ChatBot.AutoCraft=Automatically craft items in your inventory\n# See README > 'Using the AutoCraft bot' for how to use\n# You need to enable Inventory Handling to use this bot\n# You should also enable Terrain and Movements if you need to use a crafting table +config.ChatBot.AutoCraft.Table_Location=Location of the crafting table if you intended to use it. Terrain and movements must be enabled. +config.ChatBot.AutoCraft.On_Failure=What to do on crafting failure, "abort" or "wait". +config.ChatBot.AutoCraft.Recipes=Recipes.Name: The name can be whatever you like and it is used to represent the recipe.\n# Recipes.Type: crafting table type: player or table\n# Recipes.Result: the resulting item\n# Recipes.Slots: All slots, counting from left to right, top to bottom. Please fill in "Null" for empty slots.\n# For the naming of the items, please see:\n# https://github.com/MCCTeam/Minecraft-Console-Client/blob/master/MinecraftClient/Inventory/ItemType.cs # ChatBot.AutoDrop config.ChatBot.AutoDrop=Automatically drop items in inventory\n# You need to enable Inventory Handling to use this bot\n# See this file for an up-to-date list of item types you can use with this bot:\n# https://github.com/MCCTeam/Minecraft-Console-Client/blob/master/MinecraftClient/Inventory/ItemType.cs @@ -809,7 +814,7 @@ config.ChatBot.AutoFishing.Auto_Rod_Switch=Switch to a new rod from inventory af config.ChatBot.AutoFishing.Stationary_Threshold=Hooks moving in the X and Z axes below this threshold will be considered stationary. config.ChatBot.AutoFishing.Hook_Threshold=A stationary hook moving on the Y-axis above this threshold will be considered to have caught a fish. config.ChatBot.AutoFishing.Log_Fish_Bobber=For debugging purposes, you can use this log to adjust the two thresholds mentioned above. -config.ChatBot.AutoFishing.Movements=Some plugins do not allow the player to fish in one place. This allows the player to change position/angle after each fish caught. Usage can be found in the Guide. +config.ChatBot.AutoFishing.Movements=This allows the player to change position/angle after each fish caught. Usage can be found in the Guide. # ChatBot.AutoRelog diff --git a/MinecraftClient/Settings.cs b/MinecraftClient/Settings.cs index 8c3bcdee..c68c9ad0 100644 --- a/MinecraftClient/Settings.cs +++ b/MinecraftClient/Settings.cs @@ -126,6 +126,7 @@ namespace MinecraftClient try { document = TomlParser.ParseFile(filepath); + Config = TomletMain.To(document); } catch (Exception ex) { @@ -148,9 +149,6 @@ namespace MinecraftClient ConsoleIO.WriteLine(Translations.GetOrNull("mcc.run_with_default_settings") ?? "\nMCC is running with default settings."); return false; } - - Config = TomletMain.To(document); - return false; } From 642a85661f06afe1f29868efb6877e9883ffe151 Mon Sep 17 00:00:00 2001 From: BruceChen Date: Wed, 5 Oct 2022 19:39:21 +0800 Subject: [PATCH 06/14] Merge Alerts's config --- MinecraftClient/ChatBots/Alerts.cs | 47 +++++---------------------- MinecraftClient/ChatBots/AutoCraft.cs | 12 +++---- MinecraftClient/ChatBots/AutoRelog.cs | 2 +- MinecraftClient/Resources/lang/en.ini | 4 +-- MinecraftClient/Settings.cs | 7 ++-- 5 files changed, 21 insertions(+), 51 deletions(-) diff --git a/MinecraftClient/ChatBots/Alerts.cs b/MinecraftClient/ChatBots/Alerts.cs index 0682f6f6..42274ebb 100644 --- a/MinecraftClient/ChatBots/Alerts.cs +++ b/MinecraftClient/ChatBots/Alerts.cs @@ -31,22 +31,20 @@ namespace MinecraftClient.ChatBots [TomlInlineComment("$config.ChatBot.Alerts.Trigger_By_Thunderstorm$")] public bool Trigger_By_Thunderstorm = false; - [TomlInlineComment("$config.ChatBot.Alerts.Matches_File$")] - public string Matches_File = @"alerts.txt"; - - [TomlInlineComment("$config.ChatBot.Alerts.Excludes_File$")] - public string Excludes_File = @"alerts-exclude.txt"; - [TomlInlineComment("$config.ChatBot.Alerts.Log_To_File$")] public bool Log_To_File = false; [TomlInlineComment("$config.ChatBot.Alerts.Log_File$")] public string Log_File = @"alerts-log.txt"; + [TomlPrecedingComment("$config.ChatBot.Alerts.Matches_File$")] + public string[] Matches = new string[] { "Yourname", " whispers ", "-> me", "admin", ".com" }; + + [TomlPrecedingComment("$config.ChatBot.Alerts.Excludes_File$")] + public string[] Excludes = new string[] { "myserver.com", "Yourname>:", "Player Yourname", "Yourname joined", "Yourname left", "[Lockette] (Admin)", " Yourname:", "Yourname is" }; + public void OnSettingUpdate() { - Matches_File ??= string.Empty; - Excludes_File ??= string.Empty; Log_File ??= string.Empty; if (!Enabled) return; @@ -55,18 +53,6 @@ namespace MinecraftClient.ChatBots if (Trigger_By_Words) { - if (!System.IO.File.Exists(Matches_File)) - { - checkSuccessed = false; - LogToConsole(BotName, "File not found: " + System.IO.Path.GetFullPath(Matches_File)); - } - - if (!System.IO.File.Exists(Excludes_File)) - { - checkSuccessed = false; - LogToConsole(BotName, "File not found: " + System.IO.Path.GetFullPath(Excludes_File)); - } - if (Log_To_File) { try @@ -76,7 +62,7 @@ namespace MinecraftClient.ChatBots catch { checkSuccessed = false; - LogToConsole(BotName, "Can't write logs to " + System.IO.Path.GetFullPath(Excludes_File)); + LogToConsole(BotName, "Can't write logs to " + System.IO.Path.GetFullPath(Log_File)); } } } @@ -89,25 +75,10 @@ namespace MinecraftClient.ChatBots } } - private string[] dictionary = Array.Empty(); - private string[] excludelist = Array.Empty(); - float curRainLevel = 0; float curThunderLevel = 0; const float threshold = 0.2f; - /// - /// Intitialize the Alerts bot - /// - public override void Initialize() - { - if (Config.Trigger_By_Words) - { - dictionary = LoadDistinctEntriesFromFile(Config.Matches_File); - excludelist = LoadDistinctEntriesFromFile(Config.Excludes_File); - } - } - /// /// Process text received from the server to display alerts /// @@ -120,10 +91,10 @@ namespace MinecraftClient.ChatBots text = GetVerbatim(text).ToLower(); //Proceed only if no exclusions are found in text - if (!excludelist.Any(exclusion => text.Contains(exclusion))) + if (!Config.Excludes.Any(exclusion => text.Contains(exclusion))) { //Show an alert for each alert item found in text, if any - foreach (string alert in dictionary.Where(alert => text.Contains(alert))) + foreach (string alert in Config.Matches.Where(alert => text.Contains(alert))) { if (Config.Beep_Enabled) Console.Beep(); //Text found ! diff --git a/MinecraftClient/ChatBots/AutoCraft.cs b/MinecraftClient/ChatBots/AutoCraft.cs index 173f1394..7a74cd4d 100644 --- a/MinecraftClient/ChatBots/AutoCraft.cs +++ b/MinecraftClient/ChatBots/AutoCraft.cs @@ -21,11 +21,11 @@ namespace MinecraftClient.ChatBots public bool Enabled = false; - [TomlInlineComment("$config.ChatBot.AutoCraft.Table_Location$")] - public LocationConfig Table_Location = new(123, 65, 456); + [TomlInlineComment("$config.ChatBot.AutoCraft.CraftingTable$")] + public LocationConfig CraftingTable = new(123, 65, 456); - [TomlInlineComment("$config.ChatBot.AutoCraft.On_Failure$")] - public OnFailConfig On_Failure = OnFailConfig.abort; + [TomlInlineComment("$config.ChatBot.AutoCraft.OnFailure$")] + public OnFailConfig OnFailure = OnFailConfig.abort; [TomlPrecedingComment("$config.ChatBot.AutoCraft.Recipes$")] public RecipeConfig[] Recipes = new RecipeConfig[] @@ -53,7 +53,7 @@ namespace MinecraftClient.ChatBots public void OnSettingUpdate() { - _Table_Location = new Location(Table_Location.X, Table_Location.Y, Table_Location.Z).ToFloor(); + _Table_Location = new Location(CraftingTable.X, CraftingTable.Y, CraftingTable.Z).ToFloor(); foreach (RecipeConfig recipe in Recipes) { recipe.Name ??= string.Empty; @@ -599,7 +599,7 @@ namespace MinecraftClient.ChatBots // Inform user the missing meterial name LogToConsoleTranslated("bot.autoCraft.missing_material", actionSteps[index - 1].ItemType.ToString()); } - if (Config.On_Failure == OnFailConfig.abort) + if (Config.OnFailure == OnFailConfig.abort) { StopCrafting(); LogToConsoleTranslated("bot.autoCraft.aborted"); diff --git a/MinecraftClient/ChatBots/AutoRelog.cs b/MinecraftClient/ChatBots/AutoRelog.cs index a5f03bd6..dd4473e5 100644 --- a/MinecraftClient/ChatBots/AutoRelog.cs +++ b/MinecraftClient/ChatBots/AutoRelog.cs @@ -29,7 +29,7 @@ namespace MinecraftClient.ChatBots public bool Ignore_Kick_Message = false; [TomlInlineComment("$config.ChatBot.AutoRelog.Kick_Messages$")] - public string[] Kick_Messages = new string[] { "Reason1", "Reason2" }; + public string[] Kick_Messages = new string[] { "Connection has been lost", "Server is restarting", "Server is full", "Too Many people" }; public void OnSettingUpdate() { diff --git a/MinecraftClient/Resources/lang/en.ini b/MinecraftClient/Resources/lang/en.ini index 52ee50c4..a560c077 100644 --- a/MinecraftClient/Resources/lang/en.ini +++ b/MinecraftClient/Resources/lang/en.ini @@ -789,8 +789,8 @@ config.ChatBot.AutoAttack.Entites_List=All entity types can be found here: https # ChatBot.AutoCraft config.ChatBot.AutoCraft=Automatically craft items in your inventory\n# See README > 'Using the AutoCraft bot' for how to use\n# You need to enable Inventory Handling to use this bot\n# You should also enable Terrain and Movements if you need to use a crafting table -config.ChatBot.AutoCraft.Table_Location=Location of the crafting table if you intended to use it. Terrain and movements must be enabled. -config.ChatBot.AutoCraft.On_Failure=What to do on crafting failure, "abort" or "wait". +config.ChatBot.AutoCraft.CraftingTable=Location of the crafting table if you intended to use it. Terrain and movements must be enabled. +config.ChatBot.AutoCraft.OnFailure=What to do on crafting failure, "abort" or "wait". config.ChatBot.AutoCraft.Recipes=Recipes.Name: The name can be whatever you like and it is used to represent the recipe.\n# Recipes.Type: crafting table type: player or table\n# Recipes.Result: the resulting item\n# Recipes.Slots: All slots, counting from left to right, top to bottom. Please fill in "Null" for empty slots.\n# For the naming of the items, please see:\n# https://github.com/MCCTeam/Minecraft-Console-Client/blob/master/MinecraftClient/Inventory/ItemType.cs # ChatBot.AutoDrop diff --git a/MinecraftClient/Settings.cs b/MinecraftClient/Settings.cs index c68c9ad0..c3525b2b 100644 --- a/MinecraftClient/Settings.cs +++ b/MinecraftClient/Settings.cs @@ -26,8 +26,7 @@ namespace MinecraftClient { public static class Settings { - // Minecraft Console Client client information used for BrandInfo setting - public const string MCCBrandInfo = "Minecraft-Console-Client/" + Program.Version; + private const int CommentsAlignPosition = 45; //Other Settings public static string TranslationsFile_FromMCDir = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + @"\.minecraft\assets\objects\48\482e0dae05abfa35ab5cb076e41fda77b4fb9a08"; //MC 1.19 en_GB.lang @@ -165,7 +164,7 @@ namespace MinecraftClient { string config = match.Groups[1].Value, comment = match.Groups[2].Value; if (config.Length > 0) - newConfig.Append(config).Append(' ', Math.Max(1, 45 - config.Length) - 1); + newConfig.Append(config).Append(' ', Math.Max(1, CommentsAlignPosition - config.Length) - 1); newConfig.Append("# ").AppendLine(Translations.TryGet(comment).ReplaceLineEndings()); } else @@ -1103,7 +1102,7 @@ namespace MinecraftClient { return info switch { - BrandInfoType.mcc => Settings.MCCBrandInfo, + BrandInfoType.mcc => "Minecraft-Console-Client/" + Program.Version, BrandInfoType.vanilla => "vanilla", BrandInfoType.empty => null, _ => null, From 48fcdce4adfc18a62af9e193fbe9c5e899ce00f1 Mon Sep 17 00:00:00 2001 From: BruceChen Date: Wed, 5 Oct 2022 20:00:27 +0800 Subject: [PATCH 07/14] Merge AutoFishing's config --- MinecraftClient/ChatBots/AutoFishing.cs | 16 ++++++++++++---- MinecraftClient/ChatBots/AutoRelog.cs | 2 +- MinecraftClient/Resources/lang/en.ini | 3 ++- MinecraftClient/Resources/lang/zh-Hans.ini | 2 +- 4 files changed, 16 insertions(+), 7 deletions(-) diff --git a/MinecraftClient/ChatBots/AutoFishing.cs b/MinecraftClient/ChatBots/AutoFishing.cs index 6ff0d303..2c8719b8 100644 --- a/MinecraftClient/ChatBots/AutoFishing.cs +++ b/MinecraftClient/ChatBots/AutoFishing.cs @@ -56,8 +56,16 @@ namespace MinecraftClient.ChatBots [TomlInlineComment("$config.ChatBot.AutoFishing.Log_Fish_Bobber$")] public bool Log_Fish_Bobber = false; - [TomlInlineComment("$config.ChatBot.AutoFishing.Movements$")] - public LocationConfig[] Movements = Array.Empty(); + [TomlInlineComment("$config.ChatBot.AutoFishing.Enable_Move$")] + public bool Enable_Move = false; + + [TomlPrecedingComment("$config.ChatBot.AutoFishing.Movements$")] + public LocationConfig[] Movements = new LocationConfig[] + { + new LocationConfig(12.34f, -23.45f), + new LocationConfig(123.45, 64, -654.32, -25.14f, 36.25f), + new LocationConfig(-1245.63, 63.5, 1.2), + }; public void OnSettingUpdate() { @@ -249,7 +257,7 @@ namespace MinecraftClient.ChatBots case FishingState.StartMove: if (--counter < 0) { - if (Config.Movements.Length > 0) + if (Config.Enable_Move && Config.Movements.Length > 0) { if (GetTerrainEnabled()) { @@ -399,7 +407,7 @@ namespace MinecraftClient.ChatBots public void OnCaughtFish() { ++fishCount; - if (Config.Movements.Length > 0) + if (Config.Enable_Move && Config.Movements.Length > 0) LogToConsole(GetTimestamp() + ": " + Translations.Get("bot.autoFish.caught_at", fishingBobber!.Location.X, fishingBobber!.Location.Y, fishingBobber!.Location.Z, fishCount)); else diff --git a/MinecraftClient/ChatBots/AutoRelog.cs b/MinecraftClient/ChatBots/AutoRelog.cs index dd4473e5..90ec350c 100644 --- a/MinecraftClient/ChatBots/AutoRelog.cs +++ b/MinecraftClient/ChatBots/AutoRelog.cs @@ -28,7 +28,7 @@ namespace MinecraftClient.ChatBots [TomlInlineComment("$config.ChatBot.AutoRelog.Ignore_Kick_Message$")] public bool Ignore_Kick_Message = false; - [TomlInlineComment("$config.ChatBot.AutoRelog.Kick_Messages$")] + [TomlPrecedingComment("$config.ChatBot.AutoRelog.Kick_Messages$")] public string[] Kick_Messages = new string[] { "Connection has been lost", "Server is restarting", "Server is full", "Too Many people" }; public void OnSettingUpdate() diff --git a/MinecraftClient/Resources/lang/en.ini b/MinecraftClient/Resources/lang/en.ini index a560c077..868245c7 100644 --- a/MinecraftClient/Resources/lang/en.ini +++ b/MinecraftClient/Resources/lang/en.ini @@ -814,7 +814,8 @@ config.ChatBot.AutoFishing.Auto_Rod_Switch=Switch to a new rod from inventory af config.ChatBot.AutoFishing.Stationary_Threshold=Hooks moving in the X and Z axes below this threshold will be considered stationary. config.ChatBot.AutoFishing.Hook_Threshold=A stationary hook moving on the Y-axis above this threshold will be considered to have caught a fish. config.ChatBot.AutoFishing.Log_Fish_Bobber=For debugging purposes, you can use this log to adjust the two thresholds mentioned above. -config.ChatBot.AutoFishing.Movements=This allows the player to change position/angle after each fish caught. Usage can be found in the Guide. +config.ChatBot.AutoFishing.Enable_Move=This allows the player to change position/angle after each fish caught. +config.ChatBot.AutoFishing.Movements=It will move in order "1->2->3->4->3->2->1->2->..." and can change position or angle or both each time. It is recommended to change the facing only. # ChatBot.AutoRelog diff --git a/MinecraftClient/Resources/lang/zh-Hans.ini b/MinecraftClient/Resources/lang/zh-Hans.ini index b9c78242..e432645a 100644 --- a/MinecraftClient/Resources/lang/zh-Hans.ini +++ b/MinecraftClient/Resources/lang/zh-Hans.ini @@ -543,6 +543,6 @@ config.Head=启动配置文件\n\n# 对 MCC(Minecraft 命令行客户端)不 # Main.General config.Main.General.account=Login请填写邮箱或玩家名称。若要以离线模式登录请使用"-"作为密码。若留空则使用交互式登录。 -config.Main.General.login=游戏服务器的地址和端口,可填入域名或IP地址。(可删除端口字段,会解析SRV记录) +config.Main.General.login=游戏服务器的地址和端口,可填入域名或IP地址。(可删除端口字段,会自动解析SRV记录) config.Main.General.server_info=帐户类型:mojang 或是 microsoft。此项设置也会影响交互式登录。 config.Main.General.method=微软账户的登录方式:mcc 或是 browser(手动在网页上登录)。 From 7f2ede8ad2be86f2d7ddfc531924da87e18870fd Mon Sep 17 00:00:00 2001 From: BruceChen Date: Wed, 5 Oct 2022 20:41:37 +0800 Subject: [PATCH 08/14] Delete unused sample files --- MinecraftClient/ChatBots/ScriptScheduler.cs | 31 +++++++++++- MinecraftClient/Program.cs | 10 ++-- MinecraftClient/Resources/lang/en.ini | 8 ++-- MinecraftClient/Settings.cs | 12 ++--- MinecraftClient/config/alerts-exclude.txt | 8 ---- MinecraftClient/config/alerts.txt | 37 --------------- MinecraftClient/config/kickmessages.txt | 4 -- MinecraftClient/config/sample-accounts.txt | 14 ------ MinecraftClient/config/sample-servers.txt | 18 ------- MinecraftClient/config/sample-tasks.ini | 52 --------------------- 10 files changed, 45 insertions(+), 149 deletions(-) delete mode 100644 MinecraftClient/config/alerts-exclude.txt delete mode 100644 MinecraftClient/config/alerts.txt delete mode 100644 MinecraftClient/config/kickmessages.txt delete mode 100644 MinecraftClient/config/sample-accounts.txt delete mode 100644 MinecraftClient/config/sample-servers.txt delete mode 100644 MinecraftClient/config/sample-tasks.ini diff --git a/MinecraftClient/ChatBots/ScriptScheduler.cs b/MinecraftClient/ChatBots/ScriptScheduler.cs index ca5bc001..21c22551 100644 --- a/MinecraftClient/ChatBots/ScriptScheduler.cs +++ b/MinecraftClient/ChatBots/ScriptScheduler.cs @@ -25,7 +25,24 @@ namespace MinecraftClient.ChatBots public bool Enabled = false; - public TaskConfig[] TaskList = new TaskConfig[] { new() }; + public TaskConfig[] TaskList = new TaskConfig[] { + new TaskConfig( + Task_Name: "Task Name 1", + Trigger_On_First_Login: false, + Trigger_On_Login: false, + Trigger_On_Times: new(true, new TimeSpan[] { new(14, 00, 00) }), + Trigger_On_Interval: new(true, 10, 20), + Action: "send /hello" + ), + new TaskConfig( + Task_Name: "Task Name 2", + Trigger_On_First_Login: false, + Trigger_On_Login: true, + Trigger_On_Times: new(false, Array.Empty() ), + Trigger_On_Interval: new(false, 1, 10), + Action: "send /login pass" + ), + }; public void OnSettingUpdate() { @@ -85,6 +102,18 @@ namespace MinecraftClient.ChatBots [NonSerialized] public int Trigger_On_Interval_Countdown = 0; + public TaskConfig() { } + + public TaskConfig(string Task_Name, bool Trigger_On_First_Login, bool Trigger_On_Login, TriggerOnTimeConfig Trigger_On_Times, TriggerOnIntervalConfig Trigger_On_Interval, string Action) + { + this.Task_Name = Task_Name; + this.Trigger_On_First_Login = Trigger_On_First_Login; + this.Trigger_On_Login = Trigger_On_Login; + this.Trigger_On_Times = Trigger_On_Times; + this.Trigger_On_Interval = Trigger_On_Interval; + this.Action = Action; + } + public struct TriggerOnTimeConfig { public bool Enable = false; diff --git a/MinecraftClient/Program.cs b/MinecraftClient/Program.cs index 90fda3da..f8fa9d7a 100644 --- a/MinecraftClient/Program.cs +++ b/MinecraftClient/Program.cs @@ -59,8 +59,11 @@ namespace MinecraftClient /// static void Main(string[] args) { - new Thread(() => + Task.Run(() => { + // "ToLower" require "CultureInfo" to be initialized on first run, which can take a lot of time. + _ = "a".ToLower(); + //Take advantage of Windows 10 / Mac / Linux UTF-8 console if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { @@ -76,10 +79,7 @@ namespace MinecraftClient // Fix issue #2119 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 ConsoleIO.LogPrefix = "§8[MCC] "; diff --git a/MinecraftClient/Resources/lang/en.ini b/MinecraftClient/Resources/lang/en.ini index 868245c7..0d449649 100644 --- a/MinecraftClient/Resources/lang/en.ini +++ b/MinecraftClient/Resources/lang/en.ini @@ -687,8 +687,8 @@ config.Main.Advanced.entity_handling=Toggle entity handling (beta) config.Main.Advanced.session_cache=How to retain session tokens. Use 'none', 'memory' or 'disk' config.Main.Advanced.profilekey_cache=How to retain profile key. Use 'none', 'memory' or 'disk' config.Main.Advanced.resolve_srv_records=Use 'no', 'fast' (5s timeout), or 'yes'. Required for joining some servers. -config.Main.Advanced.account_list=See README > 'Servers and Accounts file' for more info about this -config.Main.Advanced.server_list=See README > 'Servers and Accounts file' for more info about this +config.Main.Advanced.account_list=AccountList: It allows a fast account switching without directly using the credentials\n# Usage examples: "/tell reco Player2", "/connect Player1" +config.Main.Advanced.server_list=ServerList: It allows an easier and faster server switching with short aliases instead of full server IP\n# Aliases cannot contain dots or spaces, and the name "localhost" cannot be used as an alias.\n# Usage examples: "/tell connect Server1", "/connect Server2" config.Main.Advanced.player_head_icon=Only works on Windows XP-8 or Windows 10 with old console config.Main.Advanced.exit_on_failure=Disable pauses on error, for using MCC in non-interactive scripts config.Main.Advanced.script_cache=Cache compiled scripts for faster load on low-end devices @@ -814,8 +814,8 @@ config.ChatBot.AutoFishing.Auto_Rod_Switch=Switch to a new rod from inventory af config.ChatBot.AutoFishing.Stationary_Threshold=Hooks moving in the X and Z axes below this threshold will be considered stationary. config.ChatBot.AutoFishing.Hook_Threshold=A stationary hook moving on the Y-axis above this threshold will be considered to have caught a fish. config.ChatBot.AutoFishing.Log_Fish_Bobber=For debugging purposes, you can use this log to adjust the two thresholds mentioned above. -config.ChatBot.AutoFishing.Enable_Move=This allows the player to change position/angle after each fish caught. -config.ChatBot.AutoFishing.Movements=It will move in order "1->2->3->4->3->2->1->2->..." and can change position or angle or both each time. It is recommended to change the facing only. +config.ChatBot.AutoFishing.Enable_Move=This allows the player to change position/facing after each fish caught. +config.ChatBot.AutoFishing.Movements=It will move in order "1->2->3->4->3->2->1->2->..." and can change position or facing or both each time. It is recommended to change the facing only. # ChatBot.AutoRelog diff --git a/MinecraftClient/Settings.cs b/MinecraftClient/Settings.cs index c3525b2b..51daeb85 100644 --- a/MinecraftClient/Settings.cs +++ b/MinecraftClient/Settings.cs @@ -435,16 +435,16 @@ namespace MinecraftClient [TomlInlineComment("$config.Main.Advanced.resolve_srv_records$")] public ResolveSrvRecordType ResolveSrvRecords = ResolveSrvRecordType.fast; - [TomlInlineComment("$config.Main.Advanced.account_list$")] + [TomlPrecedingComment("$config.Main.Advanced.account_list$")] public Dictionary AccountList = new() { - { "AccountNikename1", new AccountInfoConfig("login1", "pass1") }, - { "AccountNikename2", new AccountInfoConfig("login2", "pass2") }, + { "AccountNikename1", new AccountInfoConfig("playerone@email.com", "thepassword") }, + { "AccountNikename2", new AccountInfoConfig("TestBot", "-") }, }; - [TomlInlineComment("$config.Main.Advanced.server_list$")] + [TomlPrecedingComment("$config.Main.Advanced.server_list$")] public Dictionary ServerList = new() { - { "ServerNickname1", new ServerInfoConfig("test1.server.com") }, - { "ServerNickname2", new ServerInfoConfig("test2.server.com", 12345) }, + { "ServerAlias1", new ServerInfoConfig("mc.awesomeserver.com") }, + { "ServerAlias2", new ServerInfoConfig("192.168.1.27", 12345) }, }; [TomlInlineComment("$config.Main.Advanced.player_head_icon$")] diff --git a/MinecraftClient/config/alerts-exclude.txt b/MinecraftClient/config/alerts-exclude.txt deleted file mode 100644 index 9d4263a5..00000000 --- a/MinecraftClient/config/alerts-exclude.txt +++ /dev/null @@ -1,8 +0,0 @@ -myserver.com -Yourname>: -Player Yourname -Yourname joined -Yourname left -[Lockette] (Admin) - Yourname: -Yourname is \ No newline at end of file diff --git a/MinecraftClient/config/alerts.txt b/MinecraftClient/config/alerts.txt deleted file mode 100644 index 8db71581..00000000 --- a/MinecraftClient/config/alerts.txt +++ /dev/null @@ -1,37 +0,0 @@ -Yourname - whispers --> me -admin -.com -.net -.fr -.us -.uk -!!!! -???? -aaaa -zzzz -eeee -rrrr -tttt -yyyy -uuuu -iiii -oooo -pppp -qqqq -ssss -dddd -ffff -gggg -hhhh -jjjj -kkkk -llll -mmmm -wwww -xxxx -cccc -vvvv -bbbb -nnnn \ No newline at end of file diff --git a/MinecraftClient/config/kickmessages.txt b/MinecraftClient/config/kickmessages.txt deleted file mode 100644 index f9fe3ecc..00000000 --- a/MinecraftClient/config/kickmessages.txt +++ /dev/null @@ -1,4 +0,0 @@ -Connection has been lost -Server is restarting -Server is full -Too Many people \ No newline at end of file diff --git a/MinecraftClient/config/sample-accounts.txt b/MinecraftClient/config/sample-accounts.txt deleted file mode 100644 index f2326621..00000000 --- a/MinecraftClient/config/sample-accounts.txt +++ /dev/null @@ -1,14 +0,0 @@ -# Minecraft Console Client -# Account list file - -# Put account data as comma separated values -# Values are: Alias,Login,Password -# It allows a fast account switching -# without directly using the credentials - -# Usage examples: -# /tell reco Player2 -# /connect Player1 - -Player1,playerone@email.com,thepassword -Player2,TestBot,- \ No newline at end of file diff --git a/MinecraftClient/config/sample-servers.txt b/MinecraftClient/config/sample-servers.txt deleted file mode 100644 index 2657da3b..00000000 --- a/MinecraftClient/config/sample-servers.txt +++ /dev/null @@ -1,18 +0,0 @@ -# Minecraft Console Client -# Server list file - -# Put server data as comma separated values -# Values are: Alias,ServerIP:Port -# Aliases cannot contains dots or spaces -# The name "localhost" cannot be used as an alias -# It allows an easier and faster server switching -# with short aliases instead of full server IP -# It also adds a bit of privacy for remote control - -# Usage examples: -# /tell connect Server1 -# /connect Server2 - -Server1,localhost -Server2,mc.awesomeserver.com:25567 -Server3,192.168.1.27:1348 # Example of LAN server \ No newline at end of file diff --git a/MinecraftClient/config/sample-tasks.ini b/MinecraftClient/config/sample-tasks.ini deleted file mode 100644 index 6681f3a8..00000000 --- a/MinecraftClient/config/sample-tasks.ini +++ /dev/null @@ -1,52 +0,0 @@ -# Minecraft Console Client -# ScriptScheduler Tasks -# Example config file - -# Structure of a task: [Task] Followed by triggers and other settings. -# The example below contains all the possible fields for a task -# Time is HH:mm format, several different hours can be provided -# Action command can be "script" or any other internal command - -[Task] -triggerOnFirstLogin=false -triggerOnLogin=false -triggerOnTime=true -triggerOnInterval=false -timeValue=19:30 -timeValue=08:10 -timeInterval=0 -action=script event.txt - -# Another minimal example: some properties may be omitted -# This is highly recommended for improving task readability - -[Task] -triggerOnFirstLogin=true -action=script startup.txt - -# Intervals can be random -# To define a random interval between 2 numbers, use -, example: 1-100 -[Task] -triggerOnInterval=true -timeInterval=1-15 -action=send I am triggered! - -# Of course, the tasks file can contain as much tasks as you want. -# Another example triggered on logging in and every night at midnight: - -[Task] -triggerOnLogin=true -triggerOnTime=true -timeValue=00:00 -action=log It's midnight! - -# Example of task occuring every 30 seconds -# Could be used for jumping as antiAFK method - -[Task] -triggerOnInterval=true -timeInterval=30 -action=move up - -# Enjoy! -# - ORelio From 510b67906b5d270d796668e6e6764535ce7a04cf Mon Sep 17 00:00:00 2001 From: BruceChen Date: Wed, 5 Oct 2022 23:14:19 +0800 Subject: [PATCH 09/14] Update the translation part of the document. --- MinecraftClient/Program.cs | 3 ++- MinecraftClient/Resources/lang/en.ini | 5 ++--- MinecraftClient/Resources/lang/zh-Hans.ini | 2 +- README.md | 11 +++++++---- 4 files changed, 12 insertions(+), 9 deletions(-) diff --git a/MinecraftClient/Program.cs b/MinecraftClient/Program.cs index f8fa9d7a..7b8aea5c 100644 --- a/MinecraftClient/Program.cs +++ b/MinecraftClient/Program.cs @@ -49,6 +49,7 @@ namespace MinecraftClient public const string MCLowestVersion = "1.4.6"; public const string MCHighestVersion = "1.19.2"; public static readonly string? BuildInfo = null; + private const string TranslationUrl = "https://mccteam.github.io/guide/contibuting.html#translations"; private static Tuple? offlinePrompt = null; private static bool useMcVersionOnce = false; @@ -149,7 +150,7 @@ namespace MinecraftClient //Load external translation file. Should be called AFTER settings loaded Translations.LoadTranslationFile(Translations.GetTranslationPriority(Config.Main.Advanced.Language)); if (!Config.Main.Advanced.Language.StartsWith("en")) - ConsoleIO.WriteLine(Translations.TryGet("mcc.help_us_translate")); + ConsoleIO.WriteLine(Translations.TryGet("mcc.help_us_translate", TranslationUrl)); Settings.WriteToFile("MinecraftClient.ini", true); // format } diff --git a/MinecraftClient/Resources/lang/en.ini b/MinecraftClient/Resources/lang/en.ini index 0d449649..3176e207 100644 --- a/MinecraftClient/Resources/lang/en.ini +++ b/MinecraftClient/Resources/lang/en.ini @@ -1,6 +1,6 @@ [mcc] # Messages from MCC itself -mcc.help_us_translate=Help us translate MCC: https://mccteam.github.io/guide/translation.html +mcc.help_us_translate=Help us translate MCC: {0} mcc.run_with_default_settings=\nMCC is running with default settings. mcc.settings_generated=§cSettings file MinecraftClient.ini has been generated. mcc.login=Login : @@ -667,8 +667,7 @@ config.Main.General.method=Microsoft Account sign-in method: mcc OR browser. # Main.Advanced config.Main.Advanced=Make sure you understand what each setting does before changing anything! -config.Main.Advanced.language=Fill in with in-game locale code, https://minecraft.fandom.com/wiki/Language -config.Main.Advanced.console_title= +config.Main.Advanced.language=Fill in with in-game locale code, https://github.com/MCCTeam/Minecraft-Console-Client/discussions/2239 config.Main.Advanced.internal_cmd_char=Use 'none', 'slash' or 'backslash' config.Main.Advanced.message_cooldown=Minimum delay in seconds between messages to avoid being kicked for spam. config.Main.Advanced.bot_owners=Name list or myfile.txt, one name per line. /!\ Server admins can impersonate owners! diff --git a/MinecraftClient/Resources/lang/zh-Hans.ini b/MinecraftClient/Resources/lang/zh-Hans.ini index e432645a..c4a249df 100644 --- a/MinecraftClient/Resources/lang/zh-Hans.ini +++ b/MinecraftClient/Resources/lang/zh-Hans.ini @@ -1,6 +1,6 @@ [mcc] # Messages from MCC itself -mcc.help_us_translate=帮助我们翻译MCC:https://mccteam.github.io/guide/translation.html +mcc.help_us_translate=帮助我们翻译MCC:{0} mcc.run_with_default_settings=\nMCC正在使用默认配置运行。 mcc.settings_generated=§c配置文件 MinecraftClient.ini 已经生成。 mcc.login=登录: diff --git a/README.md b/README.md index 5fa01eb9..bc542419 100644 --- a/README.md +++ b/README.md @@ -45,11 +45,14 @@ If you'd like to contribute to Minecraft Console Client, great, just fork the re ## Translating Minecraft Console Client 🌍 -If you would like to translate Minecraft Console Client to a different language, please download the translation file from [the lang folder](https://github.com/MCCTeam/Minecraft-Console-Client/tree/master/MinecraftClient/Resources/lang) or just fork the repository. Once you finished the translation work, submit a pull request or send us the file through an [Issue](https://github.com/MCCTeam/Minecraft-Console-Client/issues) in case you are not familiar with Git. +Check out: [How to update or add translations for MCC](https://mccteam.github.io/guide/contibuting.html#translations). -To use the translated language file, place it under `lang/mcc/` folder and set your language in `.ini` config. You may create the directory if it does not exist. - -For the names of the translation file, please see [this comment](https://github.com/MCCTeam/Minecraft-Console-Client/pull/1282#issuecomment-711150715). +MCC now has translations in the following languages (Alphabetical order) : + * `de.ini` : Deutsch - German + * `fr.ini` : Français (France) - French + * `ru.ini` : Русский (Russkiy) - Russian + * `vi.ini` : Tiếng Việt (Việt Nam) - Vietnamese + * `zh-Hans.ini` : 简体中文(中国大陆) - Chinese Simplified (China; Mandarin) ## Building from the source 🏗️ From d05170a1e24977d1b23e4f62a6f536220281d811 Mon Sep 17 00:00:00 2001 From: BruceChen Date: Wed, 5 Oct 2022 23:28:51 +0800 Subject: [PATCH 10/14] Update readme --- README-zh-Hans.md | 12 ++++++++---- README.md | 3 ++- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/README-zh-Hans.md b/README-zh-Hans.md index a439b51a..57d68fe5 100644 --- a/README-zh-Hans.md +++ b/README-zh-Hans.md @@ -45,11 +45,15 @@ ## 翻译 Minecraft 控制台客户端 (MCC) 🌍 -如果你想将 Minecraft 控制台客户端 (MCC) 翻译成其他语言,请从 [lang 文件夹](https://github.com/MCCTeam/Minecraft-Console-Client/tree/master/MinecraftClient/Resources/lang)下载翻译文件或直接 fork 仓库。一旦你完成了翻译工作,请提交一个 Pull Request。如果你不熟悉 Git 的话,你也可以通过 [Issue](https://github.com/MCCTeam/Minecraft-Console-Client/issues) 将文件发送给我们。 +请查看:[如何为MCC添加或更新翻译](https://mccteam.github.io/guide/contibuting.html#translations)。 -要使用翻译后的语言文件,请将其放在 `lang/mcc/` 文件夹下,并在 `.ini` 配置文件中设置语言。如果该目录不存在,你可以创建它。 - -对于翻译文件的名称,请参阅[此评论](https://github.com/MCCTeam/Minecraft-Console-Client/pull/1282#issuecomment-711150715)。 +MCC 现在支持这些语言(按字母顺序排列): + * `de.ini` : Deutsch - German + * `en.ini` : English - English + * `fr.ini` : Français (France) - French + * `ru.ini` : Русский (Russkiy) - Russian + * `vi.ini` : Tiếng Việt (Việt Nam) - Vietnamese + * `zh-Hans.ini` : 简体中文(中国大陆) - Chinese Simplified (China; Mandarin) ## 从源码构建 🏗️ diff --git a/README.md b/README.md index bc542419..3fac11aa 100644 --- a/README.md +++ b/README.md @@ -47,8 +47,9 @@ If you'd like to contribute to Minecraft Console Client, great, just fork the re Check out: [How to update or add translations for MCC](https://mccteam.github.io/guide/contibuting.html#translations). -MCC now has translations in the following languages (Alphabetical order) : +MCC now supports the following languages (Alphabetical order) : * `de.ini` : Deutsch - German + * `en.ini` : English - English * `fr.ini` : Français (France) - French * `ru.ini` : Русский (Russkiy) - Russian * `vi.ini` : Tiếng Việt (Việt Nam) - Vietnamese From 6f456cb1d7b1d93114e5755a910aae382270aff5 Mon Sep 17 00:00:00 2001 From: BruceChen Date: Thu, 6 Oct 2022 11:03:56 +0800 Subject: [PATCH 11/14] Update readme --- MinecraftClient/ChatBots/AutoCraft.cs | 4 ++-- README.md | 4 +++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/MinecraftClient/ChatBots/AutoCraft.cs b/MinecraftClient/ChatBots/AutoCraft.cs index 7a74cd4d..5ecf060f 100644 --- a/MinecraftClient/ChatBots/AutoCraft.cs +++ b/MinecraftClient/ChatBots/AutoCraft.cs @@ -31,13 +31,13 @@ namespace MinecraftClient.ChatBots public RecipeConfig[] Recipes = new RecipeConfig[] { new RecipeConfig( - Name: "Recipe Name 1", + Name: "Recipe-Name-1", Type: CraftTypeConfig.player, Result: ItemType.StoneBricks, Slots: new ItemType[4] { ItemType.Stone, ItemType.Stone, ItemType.Stone, ItemType.Stone } ), new RecipeConfig( - Name: "Recipe Name 2", + Name: "Recipe-Name-2", Type: CraftTypeConfig.table, Result: ItemType.StoneBricks, Slots: new ItemType[9] { diff --git a/README.md b/README.md index 3fac11aa..39a969a7 100644 --- a/README.md +++ b/README.md @@ -6,6 +6,8 @@ [Documentation](https://mccteam.github.io/) | [Download](#download) | [Installation](https://mccteam.github.io/guide/installation.html) | [Configuration](https://mccteam.github.io/guide/configuration.html) | [Usage](https://mccteam.github.io/guide/usage.html) +[English](https://github.com/MCCTeam/Minecraft-Console-Client/blob/master/README.md) | [Nederlands](https://github.com/MCCTeam/Minecraft-Console-Client/blob/master/README-nl.md) | [Türkçe](https://github.com/MCCTeam/Minecraft-Console-Client/blob/master/README-tr.md) | [Tiếng Việt](https://github.com/MCCTeam/Minecraft-Console-Client/blob/master/README-vi-vn.md) | [简体中文](https://github.com/MCCTeam/Minecraft-Console-Client/blob/master/README-zh-Hans.md) + [![GitHub Actions build status](https://github.com/MCCTeam/Minecraft-Console-Client/actions/workflows/build-and-release.yml/badge.svg)](https://github.com/MCCTeam/Minecraft-Console-Client/releases/latest) Discord server @@ -50,7 +52,7 @@ Check out: [How to update or add translations for MCC](https://mccteam.github.io MCC now supports the following languages (Alphabetical order) : * `de.ini` : Deutsch - German * `en.ini` : English - English - * `fr.ini` : Français (France) - French + * `fr.ini` : Français (France) - French * `ru.ini` : Русский (Russkiy) - Russian * `vi.ini` : Tiếng Việt (Việt Nam) - Vietnamese * `zh-Hans.ini` : 简体中文(中国大陆) - Chinese Simplified (China; Mandarin) From bdcc22b465d30d3a0cf04471a2d93f5ccadfbdf1 Mon Sep 17 00:00:00 2001 From: BruceChen Date: Thu, 6 Oct 2022 14:53:05 +0800 Subject: [PATCH 12/14] Add update detection --- MinecraftClient/ChatBots/AutoAttack.cs | 1 - MinecraftClient/ChatBots/AutoCraft.cs | 1 - MinecraftClient/ChatBots/AutoFishing.cs | 1 - MinecraftClient/ChatBots/AutoRelog.cs | 1 - MinecraftClient/ChatBots/ChatLog.cs | 1 - MinecraftClient/ChatBots/PlayerListLogger.cs | 1 - MinecraftClient/ChatBots/ScriptScheduler.cs | 5 - .../DefaultConfigResource.Designer.cs | 12 +- MinecraftClient/Inventory/Item.cs | 4 +- MinecraftClient/Mapping/RaycastHelper.cs | 6 - MinecraftClient/Program.cs | 78 ++++++++--- .../Protocol/ProfileKey/KeysCache.cs | 1 - MinecraftClient/Proxy/ProxyHandler.cs | 3 +- MinecraftClient/Resources/lang/en.ini | 5 +- MinecraftClient/Resources/lang/zh-Hans.ini | 7 +- MinecraftClient/Settings.cs | 129 +++++++++++++++--- MinecraftClient/Translations.cs | 1 - MinecraftClient/WinAPI/ExitCleanUp.cs | 1 - 18 files changed, 193 insertions(+), 65 deletions(-) diff --git a/MinecraftClient/ChatBots/AutoAttack.cs b/MinecraftClient/ChatBots/AutoAttack.cs index 522a8202..ab5a6b64 100644 --- a/MinecraftClient/ChatBots/AutoAttack.cs +++ b/MinecraftClient/ChatBots/AutoAttack.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.IO; using MinecraftClient.Mapping; using Tomlet.Attributes; diff --git a/MinecraftClient/ChatBots/AutoCraft.cs b/MinecraftClient/ChatBots/AutoCraft.cs index 5ecf060f..bf3dac79 100644 --- a/MinecraftClient/ChatBots/AutoCraft.cs +++ b/MinecraftClient/ChatBots/AutoCraft.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.IO; using System.Linq; using MinecraftClient.Inventory; using MinecraftClient.Mapping; diff --git a/MinecraftClient/ChatBots/AutoFishing.cs b/MinecraftClient/ChatBots/AutoFishing.cs index 2c8719b8..7c1a5c72 100644 --- a/MinecraftClient/ChatBots/AutoFishing.cs +++ b/MinecraftClient/ChatBots/AutoFishing.cs @@ -3,7 +3,6 @@ using MinecraftClient.Inventory; using MinecraftClient.Mapping; using Tomlet.Attributes; using static MinecraftClient.ChatBots.AutoFishing.Configs; -using static MinecraftClient.ChatBots.AutoFishing.Configs.LocationConfig; namespace MinecraftClient.ChatBots { diff --git a/MinecraftClient/ChatBots/AutoRelog.cs b/MinecraftClient/ChatBots/AutoRelog.cs index 90ec350c..d47f04f5 100644 --- a/MinecraftClient/ChatBots/AutoRelog.cs +++ b/MinecraftClient/ChatBots/AutoRelog.cs @@ -1,5 +1,4 @@ using System; -using System.Text; using Tomlet.Attributes; namespace MinecraftClient.ChatBots diff --git a/MinecraftClient/ChatBots/ChatLog.cs b/MinecraftClient/ChatBots/ChatLog.cs index 7031255d..041b58cb 100644 --- a/MinecraftClient/ChatBots/ChatLog.cs +++ b/MinecraftClient/ChatBots/ChatLog.cs @@ -1,7 +1,6 @@ using System; using System.IO; using Tomlet.Attributes; -using static System.Net.WebRequestMethods; namespace MinecraftClient.ChatBots { diff --git a/MinecraftClient/ChatBots/PlayerListLogger.cs b/MinecraftClient/ChatBots/PlayerListLogger.cs index 3ab8364d..e1266d92 100644 --- a/MinecraftClient/ChatBots/PlayerListLogger.cs +++ b/MinecraftClient/ChatBots/PlayerListLogger.cs @@ -1,5 +1,4 @@ using System; -using System.Linq; using System.Text; using Tomlet.Attributes; diff --git a/MinecraftClient/ChatBots/ScriptScheduler.cs b/MinecraftClient/ChatBots/ScriptScheduler.cs index 21c22551..a977874d 100644 --- a/MinecraftClient/ChatBots/ScriptScheduler.cs +++ b/MinecraftClient/ChatBots/ScriptScheduler.cs @@ -1,9 +1,4 @@ using System; -using System.Collections.Generic; -using System.Globalization; -using System.IO; -using System.Text; -using System.Threading.Tasks; using Tomlet.Attributes; using static MinecraftClient.ChatBots.ScriptScheduler.Configs; diff --git a/MinecraftClient/DefaultConfigResource.Designer.cs b/MinecraftClient/DefaultConfigResource.Designer.cs index 39a2ddf8..4293b373 100644 --- a/MinecraftClient/DefaultConfigResource.Designer.cs +++ b/MinecraftClient/DefaultConfigResource.Designer.cs @@ -273,15 +273,16 @@ namespace MinecraftClient { /// /// Looks up a localized string similar to [mcc] ///# Messages from MCC itself - ///mcc.help_us_translate=Help us translate MCC: https://mccteam.github.io/guide/translation.html + ///mcc.help_us_translate=Help us translate MCC: {0} ///mcc.run_with_default_settings=\nMCC is running with default settings. ///mcc.settings_generated=§cSettings file MinecraftClient.ini has been generated. + ///mcc.has_update=§eNew version of MCC available: {0} ///mcc.login=Login : ///mcc.login_basic_io=Please type the username or email of your choice. ///mcc.password=Password : ///mcc.password_basic_io=Please type the password for {0}. ///mcc.password_hidden=Password : {0} - ///mcc.offline=§8You chose [rest of string was truncated]";. + ///mcc.offline=§8Yo [rest of string was truncated]";. /// internal static string Translation_en { get { @@ -354,10 +355,11 @@ namespace MinecraftClient { /// /// Looks up a localized string similar to [mcc] ///# Messages from MCC itself - ///mcc.help_us_translate=帮助我们翻译MCC:https://mccteam.github.io/guide/translation.html + ///mcc.help_us_translate=帮助我们翻译MCC:{0} ///mcc.run_with_default_settings=\nMCC正在使用默认配置运行。 ///mcc.settings_generated=§c配置文件 MinecraftClient.ini 已经生成。 - ///mcc.login=登录: + ///mcc.has_update=§e新版本的MCC已经推出:{0} + ///mcc.login=账户名: ///mcc.login_basic_io=请输入用户名或邮箱。 ///mcc.password=密码: ///mcc.password_basic_io=请输入{0}的密码。 @@ -366,7 +368,7 @@ namespace MinecraftClient { ///mcc.session_invalid=§8缓存无效或已过期。 ///mcc.session_valid=§8{0}的缓存仍然有效。 ///mcc.profile_key_invalid=§8缓存的聊天签名密钥需要刷新。 - ///mcc.profile_key_valid=§8{0}的聊天 [rest of string was truncated]";. + ///mcc.profile_key_valid=§8{0}的聊天签名密钥缓存仍然有效 [rest of string was truncated]";. /// internal static string Translation_zh_Hans { get { diff --git a/MinecraftClient/Inventory/Item.cs b/MinecraftClient/Inventory/Item.cs index 6d21a5fb..37e72017 100644 --- a/MinecraftClient/Inventory/Item.cs +++ b/MinecraftClient/Inventory/Item.cs @@ -1,8 +1,8 @@ using System; using System.Collections.Generic; -using System.Text; -using System.Linq; using System.Globalization; +using System.Linq; +using System.Text; namespace MinecraftClient.Inventory { diff --git a/MinecraftClient/Mapping/RaycastHelper.cs b/MinecraftClient/Mapping/RaycastHelper.cs index 764d55e1..a1afecef 100644 --- a/MinecraftClient/Mapping/RaycastHelper.cs +++ b/MinecraftClient/Mapping/RaycastHelper.cs @@ -1,10 +1,4 @@ using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using Microsoft.CodeAnalysis; -using MinecraftClient.Protocol; namespace MinecraftClient.Mapping { diff --git a/MinecraftClient/Program.cs b/MinecraftClient/Program.cs index 7b8aea5c..734fd420 100644 --- a/MinecraftClient/Program.cs +++ b/MinecraftClient/Program.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Globalization; using System.IO; using System.Linq; +using System.Net.Http; using System.Reflection; using System.Runtime.InteropServices; using System.Text; @@ -18,11 +19,9 @@ using MinecraftClient.Protocol.Keys; using MinecraftClient.Protocol.Session; using MinecraftClient.WinAPI; using Tomlet; -using Tomlet.Models; using static MinecraftClient.Settings; -using static MinecraftClient.Settings.MainConfigHealper.MainConfig.GeneralConfig; using static MinecraftClient.Settings.MainConfigHealper.MainConfig.AdvancedConfig; -using static System.Net.Mime.MediaTypeNames; +using static MinecraftClient.Settings.MainConfigHealper.MainConfig.GeneralConfig; namespace MinecraftClient { @@ -49,11 +48,10 @@ namespace MinecraftClient public const string MCLowestVersion = "1.4.6"; public const string MCHighestVersion = "1.19.2"; public static readonly string? BuildInfo = null; - private const string TranslationUrl = "https://mccteam.github.io/guide/contibuting.html#translations"; private static Tuple? offlinePrompt = null; private static bool useMcVersionOnce = false; - private static string? settingsIniPath = null; + private static string settingsIniPath = "MinecraftClient.ini"; /// /// The main entry point of Minecraft Console Client @@ -114,7 +112,6 @@ namespace MinecraftClient //Process ini configuration file bool needWriteDefaultSetting, newlyGenerated = false; - settingsIniPath = "MinecraftClient.ini"; if (args.Length >= 1 && File.Exists(args[0]) && Settings.ToLowerIfNeed(Path.GetExtension(args[0])) == ".ini") { needWriteDefaultSetting = Settings.LoadFromFile(args[0]); @@ -140,7 +137,7 @@ namespace MinecraftClient (string gameLanguage, string[] langList) = Translations.GetTranslationPriority(); Translations.LoadTranslationFile(langList); Config.Main.Advanced.Language = gameLanguage; - Settings.WriteToFile("MinecraftClient.ini", false); + WriteBackSettings(false); if (newlyGenerated) ConsoleIO.WriteLineFormatted(Translations.TryGet("mcc.settings_generated")); ConsoleIO.WriteLine(Translations.TryGet("mcc.run_with_default_settings")); @@ -150,8 +147,15 @@ namespace MinecraftClient //Load external translation file. Should be called AFTER settings loaded Translations.LoadTranslationFile(Translations.GetTranslationPriority(Config.Main.Advanced.Language)); if (!Config.Main.Advanced.Language.StartsWith("en")) - ConsoleIO.WriteLine(Translations.TryGet("mcc.help_us_translate", TranslationUrl)); - Settings.WriteToFile("MinecraftClient.ini", true); // format + ConsoleIO.WriteLine(Translations.TryGet("mcc.help_us_translate", Settings.TranslationDocUrl)); + WriteBackSettings(true); // format + } + + bool needPromptUpdate = true; + if (Settings.CheckUpdate(Config.Head.CurrentVersion, Config.Head.LatestVersion)) + { + needPromptUpdate = false; + ConsoleIO.WriteLineFormatted(Translations.TryGet("mcc.has_update", Settings.GithubLatestReleaseUrl)); } //Other command-line arguments @@ -256,6 +260,41 @@ namespace MinecraftClient } } + // Check for updates + Task.Run(() => + { + HttpClientHandler httpClientHandler = new() { AllowAutoRedirect = false }; + HttpClient httpClient = new(httpClientHandler); + Task? httpWebRequest = null; + try + { + httpWebRequest = httpClient.GetAsync(Settings.GithubLatestReleaseUrl, HttpCompletionOption.ResponseHeadersRead); + httpWebRequest.Wait(); + HttpResponseMessage res = httpWebRequest.Result; + if (res.Headers.Location != null) + { + Match match = Regex.Match(res.Headers.Location.ToString(), Settings.GithubReleaseUrl + @"/tag/(\d{4})(\d{2})(\d{2})-(\d+)"); + if (match.Success && match.Groups.Count == 5) + { + string year = match.Groups[1].Value, month = match.Groups[2].Value, day = match.Groups[3].Value, run = match.Groups[4].Value; + string latestVersion = string.Format("GitHub build {0}, built on {1}-{2}-{3}", run, year, month, day); + if (needPromptUpdate) + if (Settings.CheckUpdate(Config.Head.CurrentVersion, Config.Head.LatestVersion)) + ConsoleIO.WriteLineFormatted(Translations.TryGet("mcc.has_update", Settings.GithubLatestReleaseUrl)); + if (latestVersion != Config.Head.LatestVersion) + { + Config.Head.LatestVersion = latestVersion; + WriteBackSettings(false); + } + } + } + } + catch (Exception) { } + finally { httpWebRequest?.Dispose(); } + httpClient.Dispose(); + httpClientHandler.Dispose(); + }); + if (Config.Main.Advanced.ConsoleTitle != "") { InternalConfig.Username = "New Window"; @@ -573,9 +612,16 @@ namespace MinecraftClient /// public static void ReloadSettings() { - if (settingsIniPath != null) - if(Settings.LoadFromFile(settingsIniPath)) - ConsoleIO.WriteLine(Translations.TryGet("config.loading", settingsIniPath)); + if(Settings.LoadFromFile(settingsIniPath)) + ConsoleIO.WriteLine(Translations.TryGet("config.loading", settingsIniPath)); + } + + /// + /// Write-back settings + /// + public static void WriteBackSettings(bool enableBackup = true) + { + Settings.WriteToFile(settingsIniPath, enableBackup); } /// @@ -602,11 +648,9 @@ namespace MinecraftClient public static void DoExit(int exitcode = 0) { - if (settingsIniPath != null) - { - Settings.WriteToFile(settingsIniPath, true); - ConsoleIO.WriteLineFormatted(Translations.TryGet("config.saving", settingsIniPath)); - } + WriteBackSettings(true); + ConsoleIO.WriteLineFormatted(Translations.TryGet("config.saving", settingsIniPath)); + if (client != null) { client.Disconnect(); ConsoleIO.Reset(); } if (offlinePrompt != null) { offlinePrompt.Item2.Cancel(); offlinePrompt.Item1.Join(); offlinePrompt = null; ConsoleIO.Reset(); } if (Config.Main.Advanced.PlayerHeadAsIcon) { ConsoleIcon.RevertToMCCIcon(); } diff --git a/MinecraftClient/Protocol/ProfileKey/KeysCache.cs b/MinecraftClient/Protocol/ProfileKey/KeysCache.cs index c11ed0aa..b9bfc7f3 100644 --- a/MinecraftClient/Protocol/ProfileKey/KeysCache.cs +++ b/MinecraftClient/Protocol/ProfileKey/KeysCache.cs @@ -3,7 +3,6 @@ using System.Collections.Generic; using System.IO; using System.Runtime.Serialization.Formatters.Binary; using System.Timers; -using MinecraftClient.Protocol.Session; using static MinecraftClient.Settings; using static MinecraftClient.Settings.MainConfigHealper.MainConfig.AdvancedConfig; diff --git a/MinecraftClient/Proxy/ProxyHandler.cs b/MinecraftClient/Proxy/ProxyHandler.cs index 5d703dad..9bbf56eb 100644 --- a/MinecraftClient/Proxy/ProxyHandler.cs +++ b/MinecraftClient/Proxy/ProxyHandler.cs @@ -1,5 +1,4 @@ -using System; -using System.Net.Sockets; +using System.Net.Sockets; using Starksoft.Aspen.Proxy; using Tomlet.Attributes; diff --git a/MinecraftClient/Resources/lang/en.ini b/MinecraftClient/Resources/lang/en.ini index 3176e207..3bc150ef 100644 --- a/MinecraftClient/Resources/lang/en.ini +++ b/MinecraftClient/Resources/lang/en.ini @@ -3,6 +3,7 @@ mcc.help_us_translate=Help us translate MCC: {0} mcc.run_with_default_settings=\nMCC is running with default settings. mcc.settings_generated=§cSettings file MinecraftClient.ini has been generated. +mcc.has_update=§eNew version of MCC available: {0} mcc.login=Login : mcc.login_basic_io=Please type the username or email of your choice. mcc.password=Password : @@ -654,10 +655,12 @@ bot.testBot.said=Bot: {0} said : {1} config.load=Settings have been loaded from {0} config.load.fail=§cFailed to load settings:§r +config.write.fail=§cFailed to write to settings file {0}§r +config.backup.fail=§cFailed to write to backup file {0}§r config.saving=§aThe current setting is saved as {0} # Head -config.Head=Startup Config File\n\n# New to Minecraft Console Client? See README and sample configuration files here:\n# https://github.com/MCCTeam/Minecraft-Console-Client/tree/master/MinecraftClient/config\n\n# Want to upgrade to a newer version? See https://github.com/MCCTeam/Minecraft-Console-Client/#download +config.Head=Startup Config File\n\n# New to Minecraft Console Client? Check out this document: https://mccteam.github.io/guide/configuration.html\n\n# Want to upgrade to a newer version? See https://github.com/MCCTeam/Minecraft-Console-Client/#download # Main.General config.Main.General.account=Login=Email or Name. Use "-" as password for offline mode. Leave blank to prompt user on startup. diff --git a/MinecraftClient/Resources/lang/zh-Hans.ini b/MinecraftClient/Resources/lang/zh-Hans.ini index c4a249df..c13d96f1 100644 --- a/MinecraftClient/Resources/lang/zh-Hans.ini +++ b/MinecraftClient/Resources/lang/zh-Hans.ini @@ -3,7 +3,8 @@ mcc.help_us_translate=帮助我们翻译MCC:{0} mcc.run_with_default_settings=\nMCC正在使用默认配置运行。 mcc.settings_generated=§c配置文件 MinecraftClient.ini 已经生成。 -mcc.login=登录: +mcc.has_update=§e新版本的MCC已经推出:{0} +mcc.login=账户名: mcc.login_basic_io=请输入用户名或邮箱。 mcc.password=密码: mcc.password_basic_io=请输入{0}的密码。 @@ -536,10 +537,12 @@ bot.testBot.said=Bot:{0}说:{1} config.load=已从 {0} 加载设置。 config.load.fail=§c加载设置时出错:§r +config.write.fail=§保存备份文件({0})时出错:§r +config.backup.fail=§c写入设置文件({0})时出错:§r config.saving=§a当前设置已保存至 {0} # Head -config.Head=启动配置文件\n\n# 对 MCC(Minecraft 命令行客户端)不熟悉?请看 README 和示例配置文件:\n# https://github.com/MCCTeam/Minecraft-Console-Client/tree/master/MinecraftClient/config\n\n# 想升级到较新的版本吗?请访问 https://github.com/MCCTeam/Minecraft-Console-Client/#download +config.Head=启动配置文件\n\n# 对 MCC(Minecraft 命令行客户端)不熟悉?请看这个文档:https://mccteam.github.io/guide/configuration.html\n\n# 想升级到较新的版本吗?请访问 https://github.com/MCCTeam/Minecraft-Console-Client/#download # Main.General config.Main.General.account=Login请填写邮箱或玩家名称。若要以离线模式登录请使用"-"作为密码。若留空则使用交互式登录。 diff --git a/MinecraftClient/Settings.cs b/MinecraftClient/Settings.cs index 51daeb85..aabc6833 100644 --- a/MinecraftClient/Settings.cs +++ b/MinecraftClient/Settings.cs @@ -3,11 +3,9 @@ using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using System.IO; using System.Linq; -using System.Reflection.Metadata; using System.Runtime.CompilerServices; using System.Text; using System.Text.RegularExpressions; -using System.Threading; using MinecraftClient.Protocol; using MinecraftClient.Proxy; using Tomlet; @@ -16,6 +14,7 @@ using Tomlet.Models; using static MinecraftClient.Settings.AppVarConfigHelper; using static MinecraftClient.Settings.ChatBotConfigHealper; using static MinecraftClient.Settings.ChatFormatConfigHelper; +using static MinecraftClient.Settings.HeadCommentHealper; using static MinecraftClient.Settings.LoggingConfigHealper; using static MinecraftClient.Settings.MainConfigHealper; using static MinecraftClient.Settings.MainConfigHealper.MainConfig.AdvancedConfig; @@ -27,12 +26,17 @@ namespace MinecraftClient public static class Settings { private const int CommentsAlignPosition = 45; + private readonly static Regex CommentRegex = new(@"^(.*)\s?#\s\$([\w\.]+)\$\s*$$", RegexOptions.Compiled); //Other Settings public static string TranslationsFile_FromMCDir = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + @"\.minecraft\assets\objects\48\482e0dae05abfa35ab5cb076e41fda77b4fb9a08"; //MC 1.19 en_GB.lang public static string TranslationsFile_Website_Index = "https://piston-meta.mojang.com/v1/packages/b5c7548ddb9e584e84a5f762da5b78211c715a63/1.19.json"; public static string TranslationsFile_Website_Download = "http://resources.download.minecraft.net"; + public const string TranslationDocUrl = "https://mccteam.github.io/guide/contibuting.html#translations"; + public const string GithubReleaseUrl = "https://github.com/MCCTeam/Minecraft-Console-Client/releases"; + public const string GithubLatestReleaseUrl = GithubReleaseUrl + "/latest"; + public static GlobalConfig Config = new(); public static class InternalConfig @@ -54,7 +58,12 @@ namespace MinecraftClient public class GlobalConfig { - public HeadComment Head = new(); + [TomlPrecedingComment("$config.Head$")] + public HeadComment Head + { + get { return HeadCommentHealper.Config; } + set { HeadCommentHealper.Config = value; HeadCommentHealper.Config.OnSettingUpdate(); } + } public MainConfig Main { @@ -110,13 +119,6 @@ namespace MinecraftClient set { ChatBotConfigHealper.Config = value; } } - [TomlDoNotInlineObject] - public class HeadComment - { - [TomlPrecedingComment("$config.Head$")] - [TomlProperty("Current Version (Do not edit this)")] - public string Version { get; set; } = Program.BuildInfo ?? Program.MCHighestVersion; - } } public static bool LoadFromFile(string filepath) @@ -159,10 +161,10 @@ namespace MinecraftClient StringBuilder newConfig = new(); foreach (string line in tomlList) { - Match match = Regex.Match(line, @"^(.*)\s?#\s\$(.+)\$\s*$"); - if (match.Success && match.Groups.Count == 3) + Match matchComment = CommentRegex.Match(line); + if (matchComment.Success && matchComment.Groups.Count == 3) { - string config = match.Groups[1].Value, comment = match.Groups[2].Value; + string config = matchComment.Groups[1].Value, comment = matchComment.Groups[2].Value; if (config.Length > 0) newConfig.Append(config).Append(' ', Math.Max(1, CommentsAlignPosition - config.Length) - 1); newConfig.Append("# ").AppendLine(Translations.TryGet(comment).ReplaceLineEndings()); @@ -188,9 +190,28 @@ namespace MinecraftClient if (needUpdate) { + bool backupSuccessed = true; if (backupOldFile && File.Exists(filepath)) - File.Copy(filepath, Path.ChangeExtension(filepath, ".backup.ini"), true); - File.WriteAllText(filepath, newConfigStr); + { + string backupFilePath = Path.ChangeExtension(filepath, ".backup.ini"); + try { File.Copy(filepath, backupFilePath, true); } + catch (Exception ex) + { + backupSuccessed = false; + ConsoleIO.WriteLineFormatted(Translations.TryGet("config.backup.fail", backupFilePath)); + ConsoleIO.WriteLine(ex.Message); + } + } + + if (backupSuccessed) + { + try { File.WriteAllText(filepath, newConfigStr); } + catch (Exception ex) + { + ConsoleIO.WriteLineFormatted(Translations.TryGet("config.write.fail", filepath)); + ConsoleIO.WriteLine(ex.Message); + } + } } } @@ -239,6 +260,27 @@ namespace MinecraftClient } } + public static class HeadCommentHealper + { + public static HeadComment Config = new(); + + [TomlDoNotInlineObject] + public class HeadComment + { + [TomlProperty("Current Version")] + public string CurrentVersion { get; set; } = Program.BuildInfo ?? Program.MCHighestVersion; + + [TomlProperty("Latest Version")] + public string LatestVersion { get; set; } = "Unknown"; + + public void OnSettingUpdate() + { + CurrentVersion = Program.BuildInfo ?? Program.MCHighestVersion; + LatestVersion ??= "Unknown"; + } + } + } + public static class MainConfigHealper { public static MainConfig Config = new(); @@ -273,7 +315,7 @@ namespace MinecraftClient /// True if the server IP was valid and loaded, false otherwise public bool SetServerIP(ServerInfoConfig serverInfo, bool checkAlias) { - string serverStr = serverInfo.Host.ToLower(); + string serverStr = ToLowerIfNeed(serverInfo.Host); string[] sip = serverStr.Split(new[] { ":", ":" }, StringSplitOptions.None); string host = sip[0]; ushort port = 25565; @@ -1069,6 +1111,61 @@ namespace MinecraftClient return str; } } + + public static bool CheckUpdate(string? current, string? latest) + { + if (current == null || latest == null) + return false; + Regex reg = new(@"\w+\sbuild\s(\d+),\sbuilt\son\s(\d{4})[-\/\.\s]?(\d{2})[-\/\.\s]?(\d{2}).*"); + Regex reg2 = new(@"\w+\sbuild\s(\d+),\sbuilt\son\s\w+\s(\d{2})[-\/\.\s]?(\d{2})[-\/\.\s]?(\d{4}).*"); + + DateTime? curTime = null, latestTime = null; + + Match curMatch = reg.Match(current); + if (curMatch.Success && curMatch.Groups.Count == 5) + { + try { curTime = new(int.Parse(curMatch.Groups[2].Value), int.Parse(curMatch.Groups[3].Value), int.Parse(curMatch.Groups[4].Value)); } + catch { curTime = null; } + } + if (curTime == null) + { + curMatch = reg2.Match(current); + try { curTime = new(int.Parse(curMatch.Groups[4].Value), int.Parse(curMatch.Groups[3].Value), int.Parse(curMatch.Groups[2].Value)); } + catch { curTime = null; } + } + if (curTime == null) + return false; + + Match latestMatch = reg.Match(latest); + if (latestMatch.Success && latestMatch.Groups.Count == 5) + { + try { latestTime = new(int.Parse(latestMatch.Groups[2].Value), int.Parse(latestMatch.Groups[3].Value), int.Parse(latestMatch.Groups[4].Value)); } + catch { latestTime = null; } + } + if (latestTime == null) + { + latestMatch = reg2.Match(latest); + try { latestTime = new(int.Parse(latestMatch.Groups[4].Value), int.Parse(latestMatch.Groups[3].Value), int.Parse(latestMatch.Groups[2].Value)); } + catch { latestTime = null; } + } + if (latestTime == null) + return false; + + int curBuildId, latestBuildId; + try + { + curBuildId = int.Parse(curMatch.Groups[1].Value); + latestBuildId = int.Parse(latestMatch.Groups[1].Value); + } + catch { return false; } + + if (latestTime > curTime) + return true; + else if (latestTime >= curTime && latestBuildId > curBuildId) + return true; + else + return false; + } } public static class InternalCmdCharTypeExtensions diff --git a/MinecraftClient/Translations.cs b/MinecraftClient/Translations.cs index 81776efb..3d79003e 100644 --- a/MinecraftClient/Translations.cs +++ b/MinecraftClient/Translations.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.Diagnostics; using System.Globalization; using System.IO; using System.Text; diff --git a/MinecraftClient/WinAPI/ExitCleanUp.cs b/MinecraftClient/WinAPI/ExitCleanUp.cs index 0c68d04c..98f93fe1 100644 --- a/MinecraftClient/WinAPI/ExitCleanUp.cs +++ b/MinecraftClient/WinAPI/ExitCleanUp.cs @@ -1,7 +1,6 @@ using System; using System.Collections.Generic; using System.Runtime.InteropServices; -using System.Threading; namespace MinecraftClient.WinAPI { From e44192ab7b4a3d47315533b0ac33405b831fb2fc Mon Sep 17 00:00:00 2001 From: BruceChen Date: Thu, 6 Oct 2022 18:12:32 +0800 Subject: [PATCH 13/14] Update translations --- MinecraftClient/ChatBots/AntiAFK.cs | 19 ++- MinecraftClient/ChatBots/AutoDrop.cs | 1 - MinecraftClient/ChatBots/AutoFishing.cs | 14 +- MinecraftClient/ChatBots/AutoRelog.cs | 20 ++- MinecraftClient/ChatBots/FollowPlayer.cs | 4 +- MinecraftClient/ChatBots/PlayerListLogger.cs | 8 +- MinecraftClient/Logger/FilteredLogger.cs | 11 +- MinecraftClient/Proxy/ProxyHandler.cs | 12 +- MinecraftClient/Resources/lang/en.ini | 163 +++++++++---------- MinecraftClient/Resources/lang/zh-Hans.ini | 4 +- MinecraftClient/Scripting/ChatBot.cs | 6 +- MinecraftClient/Settings.cs | 30 ++-- 12 files changed, 160 insertions(+), 132 deletions(-) diff --git a/MinecraftClient/ChatBots/AntiAFK.cs b/MinecraftClient/ChatBots/AntiAFK.cs index 5f9234a6..6c6008b2 100644 --- a/MinecraftClient/ChatBots/AntiAFK.cs +++ b/MinecraftClient/ChatBots/AntiAFK.cs @@ -21,7 +21,7 @@ namespace MinecraftClient.ChatBots public bool Enabled = false; [TomlInlineComment("$config.ChatBot.AntiAfk.Delay$")] - public Range Delay = new(600); + public Range Delay = new(60); [TomlInlineComment("$config.ChatBot.AntiAfk.Command$")] public string Command = "/ping"; @@ -35,6 +35,9 @@ namespace MinecraftClient.ChatBots [TomlInlineComment("$config.ChatBot.AntiAfk.Walk_Retries$")] public int Walk_Retries = 20; + [NonSerialized] + public int _DelayMin, _DelayMax; + public void OnSettingUpdate() { if (Walk_Range <= 0) @@ -43,8 +46,11 @@ namespace MinecraftClient.ChatBots LogToConsole(BotName, Translations.TryGet("bot.antiafk.invalid_walk_range")); } - Delay.min = Math.Max(10, Delay.min); - Delay.max = Math.Max(10, Delay.max); + Delay.min = Math.Max(1.0, Delay.min); + Delay.max = Math.Max(1.0, Delay.max); + + Delay.min = Math.Min(int.MaxValue / 10, Delay.min); + Delay.max = Math.Min(int.MaxValue / 10, Delay.max); if (Delay.min > Delay.max) { @@ -52,12 +58,15 @@ namespace MinecraftClient.ChatBots LogToConsole(BotName, Translations.TryGet("bot.antiafk.swapping")); } + _DelayMin = (int)Math.Round(Delay.min * 10); + _DelayMax = (int)Math.Round(Delay.max * 10); + Command ??= string.Empty; } public struct Range { - public int min, max; + public double min, max; public Range(int value) { @@ -99,7 +108,7 @@ namespace MinecraftClient.ChatBots { count++; - if (count == random.Next(Config.Delay.min, Config.Delay.max)) + if (count == random.Next(Config._DelayMin, Config._DelayMax)) { DoAntiAfkStuff(); count = 0; diff --git a/MinecraftClient/ChatBots/AutoDrop.cs b/MinecraftClient/ChatBots/AutoDrop.cs index c962cfaf..a4e3f073 100644 --- a/MinecraftClient/ChatBots/AutoDrop.cs +++ b/MinecraftClient/ChatBots/AutoDrop.cs @@ -22,7 +22,6 @@ namespace MinecraftClient.ChatBots [TomlInlineComment("$config.ChatBot.AutoDrop.Mode$")] public DropMode Mode = DropMode.include; - [TomlInlineComment("$config.ChatBot.AutoDrop.Items$")] public List Items = new() { ItemType.Cobblestone, ItemType.Dirt }; public void OnSettingUpdate() { } diff --git a/MinecraftClient/ChatBots/AutoFishing.cs b/MinecraftClient/ChatBots/AutoFishing.cs index 7c1a5c72..91e4b4d3 100644 --- a/MinecraftClient/ChatBots/AutoFishing.cs +++ b/MinecraftClient/ChatBots/AutoFishing.cs @@ -61,8 +61,8 @@ namespace MinecraftClient.ChatBots [TomlPrecedingComment("$config.ChatBot.AutoFishing.Movements$")] public LocationConfig[] Movements = new LocationConfig[] { - new LocationConfig(12.34f, -23.45f), - new LocationConfig(123.45, 64, -654.32, -25.14f, 36.25f), + new LocationConfig(12.34, -23.45), + new LocationConfig(123.45, 64, -654.32, -25.14, 36.25), new LocationConfig(-1245.63, 63.5, 1.2), }; @@ -94,7 +94,7 @@ namespace MinecraftClient.ChatBots public Coordination? XYZ; public Facing? facing; - public LocationConfig(float yaw, float pitch) + public LocationConfig(double yaw, double pitch) { this.XYZ = null; this.facing = new(yaw, pitch); @@ -106,7 +106,7 @@ namespace MinecraftClient.ChatBots this.facing = null; } - public LocationConfig(double x, double y, double z, float yaw, float pitch) + public LocationConfig(double x, double y, double z, double yaw, double pitch) { this.XYZ = new(x, y, z); this.facing = new(yaw, pitch); @@ -124,9 +124,9 @@ namespace MinecraftClient.ChatBots public struct Facing { - public float yaw, pitch; + public double yaw, pitch; - public Facing(float yaw, float pitch) + public Facing(double yaw, double pitch) { this.yaw = yaw; this.pitch = pitch; } @@ -437,7 +437,7 @@ namespace MinecraftClient.ChatBots LocationConfig curConfig = locationList[curLocationIdx]; if (curConfig.facing != null) - (nextYaw, nextPitch) = (curConfig.facing.Value.yaw, curConfig.facing.Value.pitch); + (nextYaw, nextPitch) = ((float)curConfig.facing.Value.yaw, (float)curConfig.facing.Value.pitch); else (nextYaw, nextPitch) = (GetYaw(), GetPitch()); diff --git a/MinecraftClient/ChatBots/AutoRelog.cs b/MinecraftClient/ChatBots/AutoRelog.cs index d47f04f5..71f078ca 100644 --- a/MinecraftClient/ChatBots/AutoRelog.cs +++ b/MinecraftClient/ChatBots/AutoRelog.cs @@ -19,7 +19,7 @@ namespace MinecraftClient.ChatBots public bool Enabled = false; [TomlInlineComment("$config.ChatBot.AutoRelog.Delay$")] - public Range Delay = new(10); + public Range Delay = new(3); [TomlInlineComment("$config.ChatBot.AutoRelog.Retries$")] public int Retries = 3; @@ -30,13 +30,23 @@ namespace MinecraftClient.ChatBots [TomlPrecedingComment("$config.ChatBot.AutoRelog.Kick_Messages$")] public string[] Kick_Messages = new string[] { "Connection has been lost", "Server is restarting", "Server is full", "Too Many people" }; + [NonSerialized] + public int _DelayMin, _DelayMax; + public void OnSettingUpdate() { - Delay.min = Math.Max(1, Delay.min); - Delay.max = Math.Max(1, Delay.max); + Delay.min = Math.Max(0.1, Delay.min); + Delay.max = Math.Max(0.1, Delay.max); + + Delay.min = Math.Min(int.MaxValue / 10, Delay.min); + Delay.max = Math.Min(int.MaxValue / 10, Delay.max); + if (Delay.min > Delay.max) (Delay.min, Delay.max) = (Delay.max, Delay.min); + _DelayMin = (int)Math.Round(Delay.min * 10); + _DelayMax = (int)Math.Round(Delay.max * 10); + if (Retries == -1) Retries = int.MaxValue; @@ -47,7 +57,7 @@ namespace MinecraftClient.ChatBots public struct Range { - public int min, max; + public double min, max; public Range(int value) { @@ -120,7 +130,7 @@ namespace MinecraftClient.ChatBots private void LaunchDelayedReconnection(string? msg) { - int delay = random.Next(Config.Delay.min, Config.Delay.max); + int delay = random.Next(Config._DelayMin, Config._DelayMax); LogDebugToConsoleTranslated(String.IsNullOrEmpty(msg) ? "bot.autoRelog.reconnect_always" : "bot.autoRelog.reconnect", msg); LogToConsoleTranslated("bot.autoRelog.wait", delay); System.Threading.Thread.Sleep(delay * 1000); diff --git a/MinecraftClient/ChatBots/FollowPlayer.cs b/MinecraftClient/ChatBots/FollowPlayer.cs index 37fbe221..c05355d0 100644 --- a/MinecraftClient/ChatBots/FollowPlayer.cs +++ b/MinecraftClient/ChatBots/FollowPlayer.cs @@ -18,7 +18,7 @@ namespace MinecraftClient.ChatBots public bool Enabled = false; [TomlInlineComment("$config.ChatBot.FollowPlayer.Update_Limit$")] - public int Update_Limit = 10; + public double Update_Limit = 1; [TomlInlineComment("$config.ChatBot.FollowPlayer.Stop_At_Distance$")] public double Stop_At_Distance = 3.0; @@ -113,7 +113,7 @@ namespace MinecraftClient.ChatBots public override void OnEntityMove(Entity entity) { - if (_updateCounter < Config.Update_Limit) + if (_updateCounter < (int)(Config.Update_Limit * 10)) return; _updateCounter = 0; diff --git a/MinecraftClient/ChatBots/PlayerListLogger.cs b/MinecraftClient/ChatBots/PlayerListLogger.cs index e1266d92..4d6424ce 100644 --- a/MinecraftClient/ChatBots/PlayerListLogger.cs +++ b/MinecraftClient/ChatBots/PlayerListLogger.cs @@ -23,14 +23,14 @@ namespace MinecraftClient.ChatBots public string File = "playerlog.txt"; [TomlInlineComment("$config.ChatBot.PlayerListLogger.Delay$")] - public int Delay = 600; + public double Delay = 60; public void OnSettingUpdate() { File ??= string.Empty; - if (Delay < 10) - Delay = 10; + if (Delay < 1.0) + Delay = 1.0; } } @@ -39,7 +39,7 @@ namespace MinecraftClient.ChatBots public override void Update() { count++; - if (count == Config.Delay) + if (count == (int)(Config.Delay * 10)) { DateTime now = DateTime.Now; diff --git a/MinecraftClient/Logger/FilteredLogger.cs b/MinecraftClient/Logger/FilteredLogger.cs index 5ad42efc..168e126b 100644 --- a/MinecraftClient/Logger/FilteredLogger.cs +++ b/MinecraftClient/Logger/FilteredLogger.cs @@ -9,9 +9,11 @@ namespace MinecraftClient.Logger protected bool ShouldDisplay(FilterChannel channel, string msg) { + if (Config.Logging.FilterMode == LoggingConfigHealper.LoggingConfig.FilterModeEnum.disable) + return true; + Regex? regexToUse = null; // Convert to bool for XOR later. Whitelist = 0, Blacklist = 1 - bool filterMode = Config.Logging.FilterMode == LoggingConfigHealper.LoggingConfig.FilterModeEnum.blacklist; switch (channel) { case FilterChannel.Chat: @@ -33,7 +35,12 @@ namespace MinecraftClient.Logger { // IsMatch and white/blacklist result can be represented using XOR // e.g. matched(true) ^ blacklist(true) => shouldn't log(false) - return regexToUse.IsMatch(msg) ^ filterMode; + if (Config.Logging.FilterMode == LoggingConfigHealper.LoggingConfig.FilterModeEnum.blacklist) + return !regexToUse.IsMatch(msg); + else if (Config.Logging.FilterMode == LoggingConfigHealper.LoggingConfig.FilterModeEnum.whitelist) + return regexToUse.IsMatch(msg); + else + return true; } else return true; } diff --git a/MinecraftClient/Proxy/ProxyHandler.cs b/MinecraftClient/Proxy/ProxyHandler.cs index 9bbf56eb..8a0e225d 100644 --- a/MinecraftClient/Proxy/ProxyHandler.cs +++ b/MinecraftClient/Proxy/ProxyHandler.cs @@ -17,22 +17,22 @@ namespace MinecraftClient.Proxy [TomlDoNotInlineObject] public class Configs { - [TomlInlineComment("$Config.Proxy.Enabled_Login$")] + [TomlInlineComment("$config.Proxy.Enabled_Login$")] public bool Enabled_Login = false; - [TomlInlineComment("$Config.Proxy.Enabled_Ingame$")] + [TomlInlineComment("$config.Proxy.Enabled_Ingame$")] public bool Enabled_Ingame = false; - [TomlInlineComment("$Config.Proxy.Server$")] + [TomlInlineComment("$config.Proxy.Server$")] public ProxyInfoConfig Server = new("0.0.0.0", 8080); - [TomlInlineComment("$Config.Proxy.Proxy_Type$")] + [TomlInlineComment("$config.Proxy.Proxy_Type$")] public ProxyType Proxy_Type = ProxyType.HTTP; - [TomlInlineComment("$Config.Proxy.Username$")] + [TomlInlineComment("$config.Proxy.Username$")] public string Username = ""; - [TomlInlineComment("$Config.Proxy.Password$")] + [TomlInlineComment("$config.Proxy.Password$")] public string Password = ""; public void OnSettingUpdate() { } diff --git a/MinecraftClient/Resources/lang/en.ini b/MinecraftClient/Resources/lang/en.ini index 3bc150ef..cb617770 100644 --- a/MinecraftClient/Resources/lang/en.ini +++ b/MinecraftClient/Resources/lang/en.ini @@ -616,7 +616,7 @@ cmd.follow.already_stopped=Already stopped cmd.follow.stopping=Stopped following! cmd.follow.invalid_name=Invalid or empty player name provided! cmd.follow.invalid_player=The specified player is either not connected out out of the range! -cmd.follow.cant_reach_player=Can\'t reach the player, he is either in chunks that are not loaded, too far away or not reachable by a bot due to obstacles like gaps or water bodies! +cmd.follow.cant_reach_player=Can not reach the player, he is either in chunks that are not loaded, too far away or not reachable by a bot due to obstacles like gaps or water bodies! cmd.follow.already_following=Already following {0}! cmd.follow.switched=Switched to following {0}! cmd.follow.started=Started following {0}! @@ -660,51 +660,51 @@ config.backup.fail=§cFailed to write to backup file {0}§r config.saving=§aThe current setting is saved as {0} # Head -config.Head=Startup Config File\n\n# New to Minecraft Console Client? Check out this document: https://mccteam.github.io/guide/configuration.html\n\n# Want to upgrade to a newer version? See https://github.com/MCCTeam/Minecraft-Console-Client/#download +config.Head=Startup Config File\n# Please do not record extraneous data in this file as it will be overwritten by MCC.\n\n# New to Minecraft Console Client? Check out this document: https://mccteam.github.io/guide/configuration.html\n# Want to upgrade to a newer version? See https://github.com/MCCTeam/Minecraft-Console-Client/#download # Main.General config.Main.General.account=Login=Email or Name. Use "-" as password for offline mode. Leave blank to prompt user on startup. -config.Main.General.login=Server address and port. Host can be filled in with domain name or IP. -config.Main.General.server_info=Account type: mojang OR microsoft. Also affects interactive login in console. -config.Main.General.method=Microsoft Account sign-in method: mcc OR browser. +config.Main.General.login=The address of the game server, "Host" can be filled in with domain name or IP address. (The "Port" field can be deleted, it will be resolved automatically) +config.Main.General.server_info=Account type: "mojang" OR "microsoft". Also affects interactive login in console. +config.Main.General.method=Microsoft Account sign-in method: "mcc" OR "browser". If the login always fails, please try to use the "browser" once. # Main.Advanced config.Main.Advanced=Make sure you understand what each setting does before changing anything! -config.Main.Advanced.language=Fill in with in-game locale code, https://github.com/MCCTeam/Minecraft-Console-Client/discussions/2239 -config.Main.Advanced.internal_cmd_char=Use 'none', 'slash' or 'backslash' -config.Main.Advanced.message_cooldown=Minimum delay in seconds between messages to avoid being kicked for spam. -config.Main.Advanced.bot_owners=Name list or myfile.txt, one name per line. /!\ Server admins can impersonate owners! -config.Main.Advanced.mc_version=Use 'auto' or '1.X.X' values. Allows to skip server info retrieval. -config.Main.Advanced.mc_forge=Use 'auto', 'no' or 'force'. Force-enabling only works for MC 1.13+. -config.Main.Advanced.brand_info=Use 'mcc', 'vanilla', or 'none'. This is how MCC identifies itself to the server. -config.Main.Advanced.chatbot_log_file=Leave empty for no logfile -config.Main.Advanced.private_msgs_cmd_name=Used by RemoteControl bot -config.Main.Advanced.show_system_messages=System messages for server ops -config.Main.Advanced.show_xpbar_messages=Messages displayed above xp bar, set this to false in case of xp bar spam -config.Main.Advanced.show_chat_links=Decode links embedded in chat messages and show them in console -config.Main.Advanced.show_inventory_layout=Show inventory layout as ASCII art in inventory command -config.Main.Advanced.terrain_and_movements=Uses more ram, cpu, bandwidth but allows you to move around -config.Main.Advanced.inventory_handling=Toggle inventory handling (beta) -config.Main.Advanced.entity_handling=Toggle entity handling (beta) -config.Main.Advanced.session_cache=How to retain session tokens. Use 'none', 'memory' or 'disk' -config.Main.Advanced.profilekey_cache=How to retain profile key. Use 'none', 'memory' or 'disk' -config.Main.Advanced.resolve_srv_records=Use 'no', 'fast' (5s timeout), or 'yes'. Required for joining some servers. +config.Main.Advanced.language=Fill in with in-game locale code, check https://github.com/MCCTeam/Minecraft-Console-Client/discussions/2239 +config.Main.Advanced.internal_cmd_char=Use "none", "slash"(/) or "backslash"(\). +config.Main.Advanced.message_cooldown=Controls the minimum interval (in seconds) between sending each message to the server. +config.Main.Advanced.bot_owners=Set the owner of the bot. /!\ Server admins can impersonate owners! +config.Main.Advanced.mc_version=Use "auto" or "1.X.X" values. Allows to skip server info retrieval. +config.Main.Advanced.mc_forge=Use "auto", "no" or "force". Force-enabling only works for MC 1.13+. +config.Main.Advanced.brand_info=Use "mcc", "vanilla", or "none". This is how MCC identifies itself to the server. +config.Main.Advanced.chatbot_log_file=Leave empty for no logfile. +config.Main.Advanced.private_msgs_cmd_name=For remote control of the bot. +config.Main.Advanced.show_system_messages=System messages for server ops. +config.Main.Advanced.show_xpbar_messages=Messages displayed above xp bar, set this to false in case of xp bar spam. +config.Main.Advanced.show_chat_links=Decode links embedded in chat messages and show them in console. +config.Main.Advanced.show_inventory_layout=Show inventory layout as ASCII art in inventory command. +config.Main.Advanced.terrain_and_movements=Uses more ram, cpu, bandwidth but allows you to move around. +config.Main.Advanced.inventory_handling=Toggle inventory handling (beta). +config.Main.Advanced.entity_handling=Toggle entity handling (beta). +config.Main.Advanced.session_cache=How to retain session tokens. Use "none", "memory" or "disk". +config.Main.Advanced.profilekey_cache=How to retain profile key. Use "none", "memory" or "disk". +config.Main.Advanced.resolve_srv_records=Use "no", "fast" (5s timeout), or "yes". Required for joining some servers. config.Main.Advanced.account_list=AccountList: It allows a fast account switching without directly using the credentials\n# Usage examples: "/tell reco Player2", "/connect Player1" config.Main.Advanced.server_list=ServerList: It allows an easier and faster server switching with short aliases instead of full server IP\n# Aliases cannot contain dots or spaces, and the name "localhost" cannot be used as an alias.\n# Usage examples: "/tell connect Server1", "/connect Server2" -config.Main.Advanced.player_head_icon=Only works on Windows XP-8 or Windows 10 with old console -config.Main.Advanced.exit_on_failure=Disable pauses on error, for using MCC in non-interactive scripts -config.Main.Advanced.script_cache=Cache compiled scripts for faster load on low-end devices -config.Main.Advanced.timestamps=Prepend timestamps to chat messages -config.Main.Advanced.auto_respawn=Toggle auto respawn if client player was dead (make sure your spawn point is safe) -config.Main.Advanced.minecraft_realms=Enable support for joining Minecraft Realms worlds -config.Main.Advanced.move_head_while_walking=Enable head movement while walking to avoid anti-cheat triggers -config.Main.Advanced.timeout=Set a custom timeout in seconds (Default: 30). Use only if you know what you're doing. -config.Main.Advanced.enable_emoji=If turned off, the emoji will be replaced with a simpler character (for /chunk status) +config.Main.Advanced.player_head_icon=Only works on Windows XP-8 or Windows 10 with old console. +config.Main.Advanced.exit_on_failure=Whether to exit directly when an error occurs, for using MCC in non-interactive scripts. +config.Main.Advanced.script_cache=Cache compiled scripts for faster load on low-end devices. +config.Main.Advanced.timestamps=Prepend timestamps to chat messages. +config.Main.Advanced.auto_respawn=Toggle auto respawn if client player was dead (make sure your spawn point is safe). +config.Main.Advanced.minecraft_realms=Enable support for joining Minecraft Realms worlds. +config.Main.Advanced.move_head_while_walking=Enable head movement while walking to avoid anti-cheat triggers. +config.Main.Advanced.timeout=Customize the TCP connection timeout with the server. (in seconds) +config.Main.Advanced.enable_emoji=If turned off, the emoji will be replaced with a simpler character (for /chunk status). config.Main.Advanced.movement_speed=A movement speed higher than 2 may be considered cheating. config.Main.Advanced.language.invaild=The language code is invalid. # Signature -config.Signature=Chat settings (affects minecraft 1.19+) +config.Signature=Chat signature related settings (affects minecraft 1.19+) config.Signature.LoginWithSecureProfile=Microsoft accounts only. If disabled, will not be able to sign chat and join servers configured with "enforce-secure-profile=true" config.Signature.SignChat=Whether to sign the chat send from MCC config.Signature.SignMessageInCommand=Whether to sign the messages contained in the commands sent by MCC. For example, the message in "/msg" and "/me" @@ -716,19 +716,19 @@ config.Signature.ShowModifiedChat=Set to true to display messages modified by th config.Signature.ShowIllegalSignedChat=Whether to display chat and messages in commands without legal signatures # Logging -config.Logging=Only affect the messages on console. +config.Logging=This setting affects only the messages in the console. config.Logging.DebugMessages=Please enable this before submitting bug reports. Thanks! -config.Logging.ChatMessages=Show server chat messages -config.Logging.InfoMessages=Informative messages (i.e Most of the message from MCC) -config.Logging.WarningMessages=Show warning messages -config.Logging.ErrorMessages=Show error messages -config.Logging.ChatFilter=Regex for filtering chat message -config.Logging.DebugFilter=Regex for filtering debug message -config.Logging.FilterMode=blacklist OR whitelist. Blacklist hide message match regex. Whitelist show message match regex -config.Logging.LogToFile=Write log messages to file -config.Logging.LogFile=Log file name -config.Logging.PrependTimestamp=Prepend timestamp to messages in log file -config.Logging.SaveColorCodes=Keep color codes in the saved text (§b) +config.Logging.ChatMessages=Show server chat messages. +config.Logging.InfoMessages=Informative messages. (i.e Most of the message from MCC) +config.Logging.WarningMessages=Show warning messages. +config.Logging.ErrorMessages=Show error messages. +config.Logging.ChatFilter=Regex for filtering chat message. +config.Logging.DebugFilter=Regex for filtering debug message. +config.Logging.FilterMode="disable" or "blacklist" OR "whitelist". Blacklist hide message match regex. Whitelist show message match regex. +config.Logging.LogToFile=Write log messages to file. +config.Logging.LogFile=Log file name. +config.Logging.PrependTimestamp=Prepend timestamp to messages in log file. +config.Logging.SaveColorCodes=Keep color codes in the saved text.(look like "§b") # AppVars config.AppVars.Variables=can be used in some other fields as %yourvar%\n# %username% and %serverip% are reserved variables. @@ -737,24 +737,25 @@ config.AppVars.Variables=can be used in some other fields as %yourvar%\n# %usern config.Proxy=Connect to a server via a proxy instead of connecting directly\n# If Mojang session services are blocked on your network, set enabled=login to login using proxy but connect directly to the server\n# If connecting to port 25565 (Minecraft) is blocked on your network, set enabled=true to login & connect using the proxy\n# /!\ Make sure your server rules allow Proxies or VPNs before setting enabled=true, or you may face consequences! config.Proxy.Enabled_Login=Whether to connect to the login server through a proxy. config.Proxy.Enabled_Ingame=Whether to connect to the game server through a proxy. -config.Proxy.Server=Proxy server must allow HTTPS for login, and non-443 ports for playing -config.Proxy.Proxy_Type=Supported types: HTTP, SOCKS4, SOCKS4a, SOCKS5 -config.Proxy.Username=Only required for password-protected proxies -config.Proxy.Password=Only required for password-protected proxies +config.Proxy.Server=Proxy server must allow HTTPS for login, and non-443 ports for playing. +config.Proxy.Proxy_Type=Supported types: "HTTP", "SOCKS4", "SOCKS4a", "SOCKS5". +config.Proxy.Username=Only required for password-protected proxies. +config.Proxy.Password=Only required for password-protected proxies. # ChatFormat config.ChatFormat=MCC does it best to detect chat messages, but some server have unusual chat formats\n# When this happens, you'll need to configure chat format below, see README > 'Detecting chat messages'\n# Do not forget to uncomment (remove '#') these settings if modifying them config.ChatFormat.Builtins=MCC support for common message formats. Set "false" to avoid conflicts with custom formats. +config.ChatFormat.UserDefined=Whether to use the custom regular expressions below for detection. # MCSettings -config.MCSettings=Settings below are sent to the server and only affect server-side things like your skin -config.MCSettings.Enabled=If disabled, settings below are not sent to the server -config.MCSettings.Locale=Use any language implemented in Minecraft -config.MCSettings.RenderDistance=Value range: [0 - 255] -config.MCSettings.Difficulty=MC 1.7- difficulty. peaceful, easy, normal, difficult +config.MCSettings=Settings below are sent to the server and only affect server-side things like your skin. +config.MCSettings.Enabled=If disabled, settings below are not sent to the server. +config.MCSettings.Locale=Use any language implemented in Minecraft. +config.MCSettings.RenderDistance=Value range: [0 - 255]. +config.MCSettings.Difficulty=MC 1.7- difficulty. peaceful, easy, normal, difficult. config.MCSettings.ChatMode=Use 'enabled', 'commands', or 'disabled'. Allows to mute yourself... -config.MCSettings.ChatColors=Allows disabling chat colors server-side -config.MCSettings.MainHand=MC 1.9+ main hand. left or right +config.MCSettings.ChatColors=Allows disabling chat colors server-side. +config.MCSettings.MainHand=MC 1.9+ main hand. left or right. # ChatBot config.ChatBot================================ #\n# Minecraft Console Client Bots #\n# =============================== # @@ -765,28 +766,28 @@ config.ChatBot.Alerts.Beep_Enabled=Play a beep sound when a word is detected in config.ChatBot.Alerts.Trigger_By_Words=Triggers an alert after receiving a specified keyword. config.ChatBot.Alerts.Trigger_By_Rain=Trigger alerts when it rains and when it stops. config.ChatBot.Alerts.Trigger_By_Thunderstorm=Triggers alerts at the beginning and end of thunderstorms. -config.ChatBot.Alerts.Matches_File=List of words/strings to alert you on, e.g. "Yourname" -config.ChatBot.Alerts.Excludes_File=List of words/strings to NOT alert you on, e.g. "" +config.ChatBot.Alerts.Matches_File=List of words/strings to alert you on. +config.ChatBot.Alerts.Excludes_File=List of words/strings to NOT alert you on. config.ChatBot.Alerts.Log_To_File=Log alerts info a file. config.ChatBot.Alerts.Log_File=The name of a file where alers logs will be written. # ChatBot.AntiAFK config.ChatBot.AntiAfk=Send a command on a regular or random basis or make the bot walk around randomly to avoid automatic AFK disconnection\n# /!\ Make sure your server rules do not forbid anti-AFK mechanisms!\n# /!\ Make sure you keep the bot in an enclosure to prevent it wandering off if you're using terrain handling! (Recommended size 5x5x5) -config.ChatBot.AntiAfk.Delay=10 = 1s (Can also be a random number between 2 numbers, example: 50-600) (Default: 600) -config.ChatBot.AntiAfk.Command=Command to send to the server -config.ChatBot.AntiAfk.Use_Terrain_Handling=Use terrain handling to enable the bot to move around +config.ChatBot.AntiAfk.Delay=The time interval for execution. (in seconds) +config.ChatBot.AntiAfk.Command=Command to send to the server. +config.ChatBot.AntiAfk.Use_Terrain_Handling=Use terrain handling to enable the bot to move around. config.ChatBot.AntiAfk.Walk_Range=The range the bot can move around randomly (Note: the bigger the range, the slower the bot will be) -config.ChatBot.AntiAfk.Walk_Retries=How many timec can the bot fail trying to move before using the command method +config.ChatBot.AntiAfk.Walk_Retries=How many times can the bot fail trying to move before using the command method. # ChatBot.AutoAttack config.ChatBot.AutoAttack=Automatically attack hostile mobs around you\n# You need to enable Entity Handling to use this bot\n# /!\ Make sure server rules allow your planned use of AutoAttack\n# /!\ SERVER PLUGINS may consider AutoAttack to be a CHEAT MOD and TAKE ACTION AGAINST YOUR ACCOUNT so DOUBLE CHECK WITH SERVER RULES! -config.ChatBot.AutoAttack.Mode=single or multi. single target one mob per attack. multi target all mobs in range per attack -config.ChatBot.AutoAttack.Priority=health or distance. Only needed when using single mode -config.ChatBot.AutoAttack.Cooldown_Time=How long to wait between each attack. Use auto to let MCC calculate it -config.ChatBot.AutoAttack.Interaction=Possible values: Interact, Attack (default), InteractAt (Interact and Attack) -config.ChatBot.AutoAttack.Attack_Hostile=Allow attacking hostile mobs -config.ChatBot.AutoAttack.Attack_Passive=Allow attacking passive mobs -config.ChatBot.AutoAttack.List_Mode=Wether to treat the entities list as a whitelist or as a blacklist +config.ChatBot.AutoAttack.Mode="single" or "multi". single target one mob per attack. multi target all mobs in range per attack +config.ChatBot.AutoAttack.Priority="health" or "distance". Only needed when using single mode +config.ChatBot.AutoAttack.Cooldown_Time=How long to wait between each attack. Set "Custom = false" to let MCC calculate it. +config.ChatBot.AutoAttack.Interaction=Possible values: "Interact", "Attack" (default), "InteractAt" (Interact and Attack). +config.ChatBot.AutoAttack.Attack_Hostile=Allow attacking hostile mobs. +config.ChatBot.AutoAttack.Attack_Passive=Allow attacking passive mobs. +config.ChatBot.AutoAttack.List_Mode=Wether to treat the entities list as a whitelist or as a blacklist. config.ChatBot.AutoAttack.Entites_List=All entity types can be found here: https://bit.ly/3Rg68lp # ChatBot.AutoCraft @@ -797,8 +798,7 @@ config.ChatBot.AutoCraft.Recipes=Recipes.Name: The name can be whatever you like # ChatBot.AutoDrop config.ChatBot.AutoDrop=Automatically drop items in inventory\n# You need to enable Inventory Handling to use this bot\n# See this file for an up-to-date list of item types you can use with this bot:\n# https://github.com/MCCTeam/Minecraft-Console-Client/blob/master/MinecraftClient/Inventory/ItemType.cs -config.ChatBot.AutoDrop.Mode=include, exclude or everything. Include: drop item IN the list. Exclude: drop item NOT IN the list -config.ChatBot.AutoDrop.Items=separate each item name with a comma ',': "ItemOne", "ItemTwo" +config.ChatBot.AutoDrop.Mode="include", "exclude" or "everything". Include: drop item IN the list. Exclude: drop item NOT IN the list # ChatBot.AutoEat config.ChatBot.AutoEat=Automatically eat food when your Hunger value is low\n# You need to enable Inventory Handling to use this bot @@ -806,7 +806,7 @@ config.ChatBot.AutoEat=Automatically eat food when your Hunger value is low\n# Y # ChatBot.AutoFishing config.ChatBot.AutoFishing=Automatically catch fish using a fishing rod\n# Guide: https://mccteam.github.io/guide/chat-bots.html#auto-fishing\n# /!\ Make sure server rules allow automated farming before using this bot config.ChatBot.AutoFishing.Antidespawn=Keep it as false if you have not changed it before. -config.ChatBot.AutoFishing.Mainhand=Use the main hand or the off hand to hold the rod. +config.ChatBot.AutoFishing.Mainhand=Use the mainhand or the offhand to hold the rod. config.ChatBot.AutoFishing.Auto_Start=Whether to start fishing automatically after entering a world. config.ChatBot.AutoFishing.Cast_Delay=How soon to re-cast after successful fishing. config.ChatBot.AutoFishing.Fishing_Delay=How long after entering the game to start fishing (seconds). @@ -819,12 +819,11 @@ config.ChatBot.AutoFishing.Log_Fish_Bobber=For debugging purposes, you can use t config.ChatBot.AutoFishing.Enable_Move=This allows the player to change position/facing after each fish caught. config.ChatBot.AutoFishing.Movements=It will move in order "1->2->3->4->3->2->1->2->..." and can change position or facing or both each time. It is recommended to change the facing only. - # ChatBot.AutoRelog config.ChatBot.AutoRelog=Automatically relog when disconnected by server, for example because the server is restating\n# Put keywords/strings such as "Server is restarting" in kick messages file to relog when the message is seen\n# /!\ Use ignorekickmessage=true at own risk! Server staff might not appreciate if you auto-relog on manual kicks -config.ChatBot.AutoRelog.Delay=use 10 for 10 seconds, 10-60 for a random delay between 10 and 60 seconds -config.ChatBot.AutoRelog.Retries=retries when failing to relog to the server. use -1 for unlimited retries -config.ChatBot.AutoRelog.Ignore_Kick_Message=when set to true, autorelog will reconnect regardless of kick messages +config.ChatBot.AutoRelog.Delay=The delay time before joining the server. (in seconds) +config.ChatBot.AutoRelog.Retries=Retries when failing to relog to the server. use -1 for unlimited retries. +config.ChatBot.AutoRelog.Ignore_Kick_Message=When set to true, autorelog will reconnect regardless of kick messages. config.ChatBot.AutoRelog.Kick_Messages=If the kickout message matches any of the strings, then autorelog will be triggered. # ChatBot.AutoRespond @@ -836,7 +835,7 @@ config.ChatBot.ChatLog=Logs chat messages in a file on disk. # ChatBot.FollowPlayer config.ChatBot.FollowPlayer=Enabled you to make the bot follow you\n# NOTE: This is an experimental feature, the bot can be slow at times, you need to walk with a normal speed and to sometimes stop for it to be able to keep up with you\n# It's similar to making animals follow you when you're holding food in your hand.\n# This is due to a slow pathfinding algorithm, we're working on getting a better one\n# You can tweak the update limit and find what works best for you. (NOTE: Do not but a very low one, because you might achieve the opposite,\n# this might clog the thread for terain handling) and thus slow the bot even more.\n# /!\ Make sure server rules allow an option like this in the rules of the server before using this bot -config.ChatBot.FollowPlayer.Update_Limit=The rate at which the bot does calculations (10 = 1s) (Default: 5) (You can tweak this if you feel the bot is too slow) +config.ChatBot.FollowPlayer.Update_Limit=The rate at which the bot does calculations (in seconds) (You can tweak this if you feel the bot is too slow) config.ChatBot.FollowPlayer.Stop_At_Distance=Do not follow the player if he is in the range of 3 blocks (prevents the bot from pushing a player in an infinite loop) # ChatBot.HangmanGame @@ -849,20 +848,20 @@ config.ChatBot.Mailer=Relay messages between players and servers, like a mail pl config.ChatBot.Map=Allows you to render maps into .jpg images\n# This is useful for solving captchas which use maps\n# The maps are rendered into Rendered_Maps folder.\n# NOTE:\n# This feature is currently only useful for solving captchas which use maps.\n# If some servers have a very short time for solving captchas, enabe auto_render_on_update and prepare to open the file quickly.\n# On linux you can use FTP to access generated files.\n# In the future it might will be possible to display maps directly in the console with a separate command.\n# /!\ Make sure server rules allow bots to be used on the server, or you risk being punished. config.ChatBot.Map.Should_Resize=Should the map be resized? (Default one is small 128x128) config.ChatBot.Map.Resize_To=The size to resize the map to (Note: the bigger it is, the lower the quallity is) -config.ChatBot.Map.Auto_Render_On_Update=Automatically render the map once it's received or updated from/by the server +config.ChatBot.Map.Auto_Render_On_Update=Automatically render the map once it is received or updated from/by the server config.ChatBot.Map.Delete_All_On_Unload=Delete all rendered maps on unload/reload (Does not delete the images if you exit the client) config.ChatBot.Map.Notify_On_First_Update=Get a notification when you have gotten a map from the server for the first time # ChatBot.PlayerListLogger -config.ChatBot.PlayerListLogger=Log the list of players periodically into a textual file -config.ChatBot.PlayerListLogger.Delay=10 = 1s +config.ChatBot.PlayerListLogger=Log the list of players periodically into a textual file. +config.ChatBot.PlayerListLogger.Delay=(In seconds) # ChatBot.RemoteControl config.ChatBot.RemoteControl=Send MCC console commands to your bot through server PMs (/tell)\n# You need to have ChatFormat working correctly and add yourself in botowners to use the bot\n# /!\ Server admins can spoof PMs (/tellraw, /nick) so enable RemoteControl only if you trust server admins # ChatBot.ReplayCapture config.ChatBot.ReplayCapture=Enable recording of the game (/replay start) and replay it later using the Replay Mod (https://www.replaymod.com/)\n# Please note that due to technical limitations, the client player (you) will not be shown in the replay file\n# /!\ You SHOULD use /replay stop or exit the program gracefully with /quit OR THE REPLAY FILE MAY GET CORRUPT! -config.ChatBot.ReplayCapture.Backup_Interval=How long should replay file be auto-saved, in seconds. Use -1 to disable +config.ChatBot.ReplayCapture.Backup_Interval=How long should replay file be auto-saved, in seconds. Use -1 to disable. # ChatBot.ScriptScheduler config.ChatBot.ScriptScheduler=Schedule commands and scripts to launch on various events such as server join, date/time or time interval\n# See README > 'Using the Script Scheduler' for more info diff --git a/MinecraftClient/Resources/lang/zh-Hans.ini b/MinecraftClient/Resources/lang/zh-Hans.ini index c13d96f1..42938675 100644 --- a/MinecraftClient/Resources/lang/zh-Hans.ini +++ b/MinecraftClient/Resources/lang/zh-Hans.ini @@ -4,8 +4,8 @@ mcc.help_us_translate=帮助我们翻译MCC:{0} mcc.run_with_default_settings=\nMCC正在使用默认配置运行。 mcc.settings_generated=§c配置文件 MinecraftClient.ini 已经生成。 mcc.has_update=§e新版本的MCC已经推出:{0} -mcc.login=账户名: -mcc.login_basic_io=请输入用户名或邮箱。 +mcc.login=登录: +mcc.login_basic_io=请输入。 mcc.password=密码: mcc.password_basic_io=请输入{0}的密码。 mcc.password_hidden=密码:{0} diff --git a/MinecraftClient/Scripting/ChatBot.cs b/MinecraftClient/Scripting/ChatBot.cs index 51f04829..d996af1a 100644 --- a/MinecraftClient/Scripting/ChatBot.cs +++ b/MinecraftClient/Scripting/ChatBot.cs @@ -522,7 +522,7 @@ namespace MinecraftClient text = GetVerbatim(text); //User-defined regex for private chat messages - if (Config.ChatFormat.Private != null) + if (Config.ChatFormat.UserDefined && !string.IsNullOrWhiteSpace(Config.ChatFormat.Private)) { Match regexMatch = new Regex(Config.ChatFormat.Private).Match(text); if (regexMatch.Success && regexMatch.Groups.Count >= 3) @@ -633,7 +633,7 @@ namespace MinecraftClient text = GetVerbatim(text); //User-defined regex for public chat messages - if (Config.ChatFormat.Public != null) + if (Config.ChatFormat.UserDefined && !string.IsNullOrWhiteSpace(Config.ChatFormat.Public)) { Match regexMatch = new Regex(Config.ChatFormat.Public).Match(text); if (regexMatch.Success && regexMatch.Groups.Count >= 3) @@ -736,7 +736,7 @@ namespace MinecraftClient text = GetVerbatim(text); //User-defined regex for teleport requests - if (Config.ChatFormat.TeleportRequest != null) + if (Config.ChatFormat.UserDefined && !string.IsNullOrWhiteSpace(Config.ChatFormat.TeleportRequest)) { Match regexMatch = new Regex(Config.ChatFormat.TeleportRequest).Match(text); if (regexMatch.Success && regexMatch.Groups.Count >= 2) diff --git a/MinecraftClient/Settings.cs b/MinecraftClient/Settings.cs index aabc6833..1cd353c9 100644 --- a/MinecraftClient/Settings.cs +++ b/MinecraftClient/Settings.cs @@ -176,14 +176,14 @@ namespace MinecraftClient } bool needUpdate = true; - string newConfigStr = newConfig.ToString(); + byte[] newConfigByte = Encoding.UTF8.GetBytes(newConfig.ToString()); if (File.Exists(filepath)) { try { - string oldConfigStr = File.ReadAllText(filepath); - if (oldConfigStr == newConfigStr) - needUpdate = false; + if (new FileInfo(filepath).Length == newConfigByte.Length) + if (File.ReadAllBytes(filepath).SequenceEqual(newConfigByte)) + needUpdate = false; } catch { } } @@ -205,7 +205,7 @@ namespace MinecraftClient if (backupSuccessed) { - try { File.WriteAllText(filepath, newConfigStr); } + try { File.WriteAllBytes(filepath, newConfigByte); } catch (Exception ex) { ConsoleIO.WriteLineFormatted(Translations.TryGet("config.write.fail", filepath)); @@ -268,14 +268,14 @@ namespace MinecraftClient public class HeadComment { [TomlProperty("Current Version")] - public string CurrentVersion { get; set; } = Program.BuildInfo ?? Program.MCHighestVersion; + public string CurrentVersion { get; set; } = Program.BuildInfo ?? "Development Build"; [TomlProperty("Latest Version")] public string LatestVersion { get; set; } = "Unknown"; public void OnSettingUpdate() { - CurrentVersion = Program.BuildInfo ?? Program.MCHighestVersion; + CurrentVersion = Program.BuildInfo ?? "Development Build"; LatestVersion ??= "Unknown"; } } @@ -373,10 +373,11 @@ namespace MinecraftClient Advanced.MovementSpeed = 1; Advanced.Language = Regex.Replace(Advanced.Language, @"[^-^_^\w^*\d]", string.Empty).Replace('-', '_'); + Advanced.Language = ToLowerIfNeed(Advanced.Language); if (!AvailableLang.Contains(Advanced.Language)) { Advanced.Language = Translations.GetTranslationPriority().Item1; - ConsoleIO.WriteLogLine("[Settings] " + Translations.GetOrNull("config.Main.Advanced.language.invaild") ?? "The language code is invalid."); + ConsoleIO.WriteLogLine("[Settings] " + (Translations.GetOrNull("config.Main.Advanced.language.invaild") ?? "The language code is invalid.")); } if (!string.IsNullOrWhiteSpace(General.Server.Host)) @@ -418,7 +419,7 @@ namespace MinecraftClient public class AdvancedConfig { [TomlInlineComment("$config.Main.Advanced.language$")] - public string Language = "en_GB"; + public string Language = "en_gb"; // [TomlInlineComment("$config.Main.Advanced.console_title$")] public string ConsoleTitle = "%username%@%serverip% - Minecraft Console Client"; @@ -427,7 +428,7 @@ namespace MinecraftClient public InternalCmdCharType InternalCmdChar = InternalCmdCharType.slash; [TomlInlineComment("$config.Main.Advanced.message_cooldown$")] - public int MessageCooldown = 2; + public double MessageCooldown = 1.0; [TomlInlineComment("$config.Main.Advanced.bot_owners$")] public List BotOwners = new() { "Player1", "Player2" }; @@ -657,7 +658,7 @@ namespace MinecraftClient public string DebugFilterRegex = @".*"; [TomlInlineComment("$config.Logging.FilterMode$")] - public FilterModeEnum FilterMode = FilterModeEnum.whitelist; + public FilterModeEnum FilterMode = FilterModeEnum.disable; [TomlInlineComment("$config.Logging.LogToFile$")] public bool LogToFile = false; @@ -673,7 +674,7 @@ namespace MinecraftClient public void OnSettingUpdate() { } - public enum FilterModeEnum { blacklist, whitelist } + public enum FilterModeEnum { disable, blacklist, whitelist } } } @@ -937,6 +938,9 @@ namespace MinecraftClient [TomlInlineComment("$config.ChatFormat.Builtins$")] public bool Builtins = true; + [TomlInlineComment("$config.ChatFormat.UserDefined$")] + public bool UserDefined = false; + public string Public = @"^<([a-zA-Z0-9_]+)> (.+)$"; public string Private = @"^([a-zA-Z0-9_]+) whispers to you: (.+)$"; @@ -961,7 +965,7 @@ namespace MinecraftClient set { ChatBots.Alerts.Config = value; ChatBots.Alerts.Config.OnSettingUpdate(); } } - [TomlPrecedingComment("$config.ChatBot.AntiAFK$")] + [TomlPrecedingComment("$config.ChatBot.AntiAfk$")] public ChatBots.AntiAFK.Configs AntiAFK { get { return ChatBots.AntiAFK.Config; } From e5c713192e0ec1b57841d2ac9a3f3398b55b02b1 Mon Sep 17 00:00:00 2001 From: BruceChen Date: Thu, 6 Oct 2022 22:14:15 +0800 Subject: [PATCH 14/14] Update translation file --- MinecraftClient/ChatBots/AutoCraft.cs | 17 +- MinecraftClient/Mapping/Location.cs | 18 - MinecraftClient/Program.cs | 6 + MinecraftClient/Resources/lang/de.ini | 374 +++++++++++++++++++- MinecraftClient/Resources/lang/en.ini | 31 +- MinecraftClient/Resources/lang/fr.ini | 375 +++++++++++++++++++- MinecraftClient/Resources/lang/ru.ini | 383 ++++++++++++++++++++- MinecraftClient/Resources/lang/vi.ini | 377 +++++++++++++++++++- MinecraftClient/Resources/lang/zh-Hans.ini | 331 +++++++++++++++++- MinecraftClient/Translations.cs | 62 +++- README.md | 10 +- 11 files changed, 1887 insertions(+), 97 deletions(-) diff --git a/MinecraftClient/ChatBots/AutoCraft.cs b/MinecraftClient/ChatBots/AutoCraft.cs index bf3dac79..c2128ad5 100644 --- a/MinecraftClient/ChatBots/AutoCraft.cs +++ b/MinecraftClient/ChatBots/AutoCraft.cs @@ -53,9 +53,24 @@ namespace MinecraftClient.ChatBots public void OnSettingUpdate() { _Table_Location = new Location(CraftingTable.X, CraftingTable.Y, CraftingTable.Z).ToFloor(); + + List nameList = new(); foreach (RecipeConfig recipe in Recipes) { - recipe.Name ??= string.Empty; + if (string.IsNullOrWhiteSpace(recipe.Name)) + { + recipe.Name = new Random().NextInt64().ToString(); + LogToConsole(BotName, Translations.TryGet("bot.autoCraft.exception.name_miss")); + } + if (nameList.Contains(recipe.Name)) + { + LogToConsole(BotName, Translations.TryGet("bot.autoCraft.exception.duplicate", recipe.Name)); + do + { + recipe.Name = new Random().NextInt64().ToString(); + } while (nameList.Contains(recipe.Name)); + } + nameList.Add(recipe.Name); int fixLength = -1; if (recipe.Type == CraftTypeConfig.player && recipe.Slots.Length != 4) diff --git a/MinecraftClient/Mapping/Location.cs b/MinecraftClient/Mapping/Location.cs index b64ace5e..f535c724 100644 --- a/MinecraftClient/Mapping/Location.cs +++ b/MinecraftClient/Mapping/Location.cs @@ -295,15 +295,6 @@ namespace MinecraftClient.Mapping return loc1.Equals(loc2); } - public static bool operator ==(Location? loc1, Location? loc2) - { - if (loc1 == null && loc2 == null) - return true; - if (loc1 == null || loc2 == null) - return false; - return loc1.Equals(loc2); - } - /// /// Compare two locations. Locations are not equals if the integer part of their coordinates are not equals. /// @@ -315,15 +306,6 @@ namespace MinecraftClient.Mapping return !loc1.Equals(loc2); } - public static bool operator !=(Location? loc1, Location? loc2) - { - if (loc1 == null && loc2 == null) - return false; - if (loc1 == null || loc2 == null) - return true; - return !loc1.Equals(loc2); - } - /// /// Sums two locations and returns the result. /// diff --git a/MinecraftClient/Program.cs b/MinecraftClient/Program.cs index 734fd420..03d898c3 100644 --- a/MinecraftClient/Program.cs +++ b/MinecraftClient/Program.cs @@ -172,6 +172,12 @@ namespace MinecraftClient return; } + if (args.Contains("--trim-translation")) + { + Translations.TrimAllTranslations(); + return; + } + if (args.Contains("--generate")) { string dataGenerator = ""; diff --git a/MinecraftClient/Resources/lang/de.ini b/MinecraftClient/Resources/lang/de.ini index 8f734620..7b0c05c5 100644 --- a/MinecraftClient/Resources/lang/de.ini +++ b/MinecraftClient/Resources/lang/de.ini @@ -1,15 +1,22 @@ [mcc] # Messages from MCC itself +mcc.help_us_translate= +mcc.run_with_default_settings= +mcc.settings_generated= +mcc.has_update= mcc.login=Login : mcc.login_basic_io=Bitte gib einen Nutzernamen oder eine E-Mail deiner Wahl ein. -mcc.password=Passwort : +mcc.password=Passwort : mcc.password_basic_io=Bitte gib das Passwort für {0} ein. mcc.password_hidden=Passwort : {0} mcc.offline=§8Das Programm läuft im Offline-Modus. mcc.session_invalid=§8Gespeicherte Session ungültig oder abgelaufen. mcc.session_valid=§8Gespeicherte Session gültig für {0}. +mcc.profile_key_invalid= +mcc.profile_key_valid= mcc.connecting=Verbinde zu {0}... -mcc.ip=Server-IP : +mcc.fetching_key= +mcc.ip=Server-IP : mcc.use_version=§8Benutze Minecraft-Version {0} (protocol v{1}) mcc.unknown_version=§8Unbekannte oder nicht unterstützte MC-Version {0}.\nWechsele in den Autodetection-Modus. mcc.forge=Prüfe, ob der Server Forge benutzt... @@ -20,7 +27,7 @@ mcc.not_found=§8SRV-Lookup fehlgeschlagen für {0}\n{1}: {2} mcc.retrieve=Erhalte Server-Info... mcc.restart=Starte Minecraft Console Client neu... mcc.restart_delay=Warte {0} Sekunden vor Neustart... -mcc.server_version=Server-Version : +mcc.server_version=Server-Version : mcc.disconnected=Mit keinem Server verbunden. Schreibe '{0}help' für weitere Hilfe. mcc.press_exit=Oder drücke Enter, um den Minecraft Console Client zu verlassen. mcc.version_supported=Version wird unterstützt.\nMelde an... @@ -41,13 +48,16 @@ mcc.with_forge=, mit Forge mcc.handshake=§8Handshake erfolgreich. (Server ID: {0}) mcc.realms_available=Du hast Zugang zu den folgenden Realms-Welten mcc.realms_join=Nutze realms:index als Server-IP, um der Realms-Welt beizutreten - +mcc.generator.generating= +mcc.generator.done= [debug] # Messages from MCC Debug Mode debug.color_test=Farbtest: Dein Terminal sollte {0} anzeigen. debug.session_cache_ok=§8Sitzungsdaten wurden erfolgreich vom Speicher geladen. debug.session_cache_fail=§8Es konnten keine Sitzungsdaten vom Speicher geladen werden. +debug.keys_cache_ok= +debug.keys_cache_fail= debug.session_id=Erfolgreich. (session ID: {0}) debug.crypto=§8Crypto-Schlüssel & -Hash wurden generiert. debug.request=§8Starte Anfrage zu {0} @@ -58,7 +68,7 @@ error.ping=Ping an IP fehlgeschlagen. error.unsupported=Kann nicht zum Server verbinden : Diese Version wird nicht unterstützt ! error.determine=Konnte Server-Version nicht bestimmen. error.forgeforce=Der zwangshafte Forge-Support wird für diese Minecraft-Version nicht unterstützt! -error.login=Minecraft Login fehlgeschlagen : +error.login=Minecraft Login fehlgeschlagen : error.login.migrated=Account wurde migriert, benutze eine E-Mail als Nutzername. error.login.server=Login-Server nicht erreichbar. Bitte versuche es später erneut. error.login.blocked=Falsches Passwort, gesperrte IP oder zu viele Logins. @@ -82,6 +92,9 @@ error.connection_timeout=§8Es gab einen Timeout während des Verbindungsaufbaus error.forge=§8Forge Login Handshake konnte nicht erfolgreich abgeschlossen werden. error.forge_encrypt=§8Forge StartEncryption Handshake konnte nicht erfolgreich abgeschlossen werden. error.setting.str2int=Konnte '{0}' nicht in einen Int umwandeln. Bitte überprüfe die Einstellungen. +error.setting.str2double= +error.setting.str2locationList.convert_fail= +error.setting.str2locationList.format_err= error.setting.argument_syntax={0}: Invalid syntax, expecting --argname=value or --section.argname=value error.setting.unknown_section={0}: Unknown setting section '{1}' error.setting.unknown_or_invalid={0}: Unknown setting or invalid value @@ -92,6 +105,11 @@ error.realms.access_denied=Diese Realms-Welt existiert nicht oder der Zugang wur error.realms.server_unavailable=Der Realms-Server braucht ein wenig Zeit zum starten. Bitte versuche es später erneut. error.realms.server_id=Invalid or unknown Realms server ID. error.realms.disabled=Versuche der Realms-Welt beizutreten, allerdings wurde der Realms-Support in der Config deaktiviert +error.missing.argument= +error.usage= +error.generator.invalid= +error.generator.path= +error.generator.json= [internal command] # MCC internal help command @@ -173,6 +191,14 @@ cache.ignore_line=§8Ignoriere ungültigen Sitzungstoken Zeile: {0} cache.read_fail_plain=§8Konnte Sitzungscache nicht vom Speicher lesen: {0} cache.saving=§8Speichere Sitzungscache auf Festplatte cache.save_fail=§8Konnte Sitzungscache auf keine Festplatte schreiben: {0} +# Profile Key Cache +cache.loading_keys= +cache.loaded_keys= +cache.ignore_string_keys= +cache.ignore_line_keys= +cache.read_fail_plain_keys= +cache.saving_keys= +cache.save_fail_keys= [proxy] proxy.connected=§8Verbunden mit Proxy {0}:{1} @@ -186,6 +212,7 @@ chat.fail=§8Konnte Datei nicht herunterladen. chat.from_dir=§8Nutze en_GB.lang als Standard von deinem Minecraft-Pfad. chat.loaded=§8Übersetzungsdatei geladen. chat.not_found=§8Übersetzungsdatei konnte nicht gefunden werden: '{0}'\nEinige Nachrichten können ohne diese Datei nicht korrekt angezeigt werden. +chat.message_chain_broken= [general] # General message/information (i.e. Done) @@ -201,12 +228,23 @@ general.available_cmd=Verfügbare Befehle: {0} # Animation cmd.animation.desc=Schwinge deinen Arm. +# Bots +cmd.bots.desc= +cmd.bots.list= +cmd.bots.notfound= +cmd.bots.noloaded= +cmd.bots.unloaded= +cmd.bots.unloaded_all= + # ChangeSlot cmd.changeSlot.desc=Ändere deine Hotbar cmd.changeSlot.nan=Konnte Slot nicht ändern: Dies ist keine Nummer. cmd.changeSlot.changed=Slot geändert auf {0} cmd.changeSlot.fail=Konnte Slot nicht ändern. +# Chunk +cmd.chunk.desc= + # Connect cmd.connect.desc=Verbinde zum angegebenen Server. cmd.connect.unknown=Unbekannter Account '{0}'. @@ -248,6 +286,19 @@ cmd.entityCmd.distance=Entfernung cmd.entityCmd.location=Position cmd.entityCmd.type=Typ +# Exec If +cmd.execif.desc= +cmd.execif.executed= +cmd.execif.executed_no_output= +cmd.execif.error_occured= +cmd.execif.error= + +# Exec Multi +cmd.execmulti.desc= +cmd.execmulti.executed= +cmd.execmulti.result= +cmd.execmulti.no_result= + # Exit cmd.exit.desc=Verbindung zum Server verloren. @@ -267,12 +318,15 @@ cmd.inventory.close_fail=Konnte das Inventar #{0} nicht schließen cmd.inventory.not_exist=Inventar #{0} existiert nicht. cmd.inventory.inventory=Inventar cmd.inventory.inventories=Inventare +cmd.inventory.inventories_available= cmd.inventory.hotbar=Deine ausgewählte Hotbar ist {0} cmd.inventory.damage=Schaden cmd.inventory.left=Links cmd.inventory.right=Rechts cmd.inventory.middle=Mittel cmd.inventory.clicking={0} klicke Slote {1} im Fenster #{2} +cmd.inventory.shiftclick= +cmd.inventory.shiftclick_fail= cmd.inventory.no_item=Kein Item im Slot #{0} cmd.inventory.drop=Droppe 1 Item aus Slot #{0} cmd.inventory.drop_stack=Droppe ganzen Item Stack aus Slot #{0} @@ -284,10 +338,29 @@ cmd.inventory.help.usage=Benutzung cmd.inventory.help.list=Liste deine Inventare auf. cmd.inventory.help.close=Schließe einen offenen Container. cmd.inventory.help.click=Klicke auf ein Item. +cmd.inventory.help.shiftclick= cmd.inventory.help.drop=Werfe ein Item aus deinem Inventar. cmd.inventory.help.creativegive=Gebe dir ein Item im Kreativmodus. cmd.inventory.help.creativedelete=Leere Slot im Kreativmodus. -cmd.inventory.help.unknown=Unbekannte Aktion. +cmd.inventory.help.inventories= +cmd.inventory.help.search= +cmd.inventory.help.unknown=Unbekannte Aktion. +cmd.inventory.found_items= +cmd.inventory.no_found_items= + +# Leave bed +cmd.bed.desc= +cmd.bed.leaving= +cmd.bed.trying_to_use= +cmd.bed.in= +cmd.bed.not_in= +cmd.bed.not_a_bed= +cmd.bed.searching= +cmd.bed.bed_not_found= +cmd.bed.found_a_bed_at= +cmd.bed.cant_reach_safely= +cmd.bed.moving= +cmd.bed.failed_to_reach_in_time= # List cmd.list.desc=Liste alle Spieler auf. @@ -301,6 +374,8 @@ cmd.look.desc=Schaue in eine Richtung oder auf Koordinaten. cmd.look.unknown=Unbekannte Richtung '{0}' cmd.look.at=Schaue nach YAW: {0} PITCH: {1} cmd.look.block=Schaue auf {0} +cmd.look.inspection= +cmd.look.noinspection= # Move cmd.move.desc=Laufe oder fange an zu laufen. @@ -313,11 +388,21 @@ cmd.move.fail=Konnte Pfad nach {0} nicht berechnen. cmd.move.suggestforce=Weg nach {0} konnte nicht berechnet werden. Benutze den -f Parameter, um unsichere Wege zu aktivieren. cmd.move.gravity.enabled=Gravitation ist aktiv. cmd.move.gravity.disabled=Gravitation ist deaktiviert. - +cmd.move.chunk_loading_status= +cmd.move.chunk_not_loaded= # Reco cmd.reco.desc=Starte neu und verbinde erneut zum Server. +# Reload +cmd.reload.started= +cmd.reload.warning1= +cmd.reload.warning2= +cmd.reload.warning3= +cmd.reload.warning4= +cmd.reload.finished= +cmd.reload.desc= + # Respawn cmd.respawn.desc=Benutze dies, um nach deinem Tod zu respawnen. cmd.respawn.done=Du wurdest respawned. @@ -353,6 +438,7 @@ cmd.tps.current=Aktuelle TPS # Useblock cmd.useblock.desc=Plaziere einen Block oder öffne eine Kiste +cmd.useblock.use= # Useitem cmd.useitem.desc=Benutze (links klick) ein Item auf der Hand @@ -362,6 +448,20 @@ cmd.useitem.use=Item wurde benutzt. [bot] # ChatBots. Naming style: bot.. +# Alerts +bot.alerts.start_rain= +bot.alerts.end_rain= +bot.alerts.start_thunderstorm= +bot.alerts.end_thunderstorm= + +# Anti AFK +bot.antiafk.not_using_terrain_handling= +bot.antiafk.invalid_range_partial= +bot.antiafk.invalid_range= +bot.antiafk.invalid_value= +bot.antiafk.swapping= +bot.antiafk.invalid_walk_range= + # AutoAttack bot.autoAttack.mode=Unbekannter Angriffsmodus: {0}. Benutze Einfach als Standard. bot.autoAttack.priority=Unbekannte Priorität: {0}. Benutze Entfernung als Standard. @@ -402,6 +502,8 @@ bot.autoCraft.exception.name_miss=Fehlender Rezeptname während der Rezeptüberg bot.autoCraft.exception.slot=Ungültiges Slot-Feld im Rezept: {0} bot.autoCraft.exception.duplicate=Doppelter Rezeptname angegeben: {0} bot.autoCraft.debug.no_config=Keine Config-Datei gefunden. Schreibe eine neue... +bot.autocraft.invaild_slots= +bot.autocraft.invaild_invaild_result= # AutoDrop bot.autoDrop.cmd=AutoDrop ChatBot Befehl @@ -420,9 +522,17 @@ bot.autoDrop.no_mode=Kann drop Modus nicht aus Config Datei lesen. Benutze inclu bot.autoDrop.no_inventory=Konnte Inventar nicht finden {0}! # AutoFish +bot.autoFish.no_inv_handle= +bot.autoFish.start= bot.autoFish.throw=Angel ausgeworfen! bot.autoFish.caught=Fisch gefangen! +bot.autoFish.caught_at= bot.autoFish.no_rod=Keine Angelrute in der Hand. Ist sie kaputt? +bot.autoFish.despawn= +bot.autoFish.fishing_timeout= +bot.autoFish.cast_timeout= +bot.autoFish.update_lookat= +bot.autoFish.switch= # AutoRelog bot.autoRelog.launch=Starte mit {0} reconnect Versuchen @@ -466,7 +576,7 @@ bot.mailer.init_fail.mail_retention=Konnte Mailer nicht aktivieren: Die Auslaufz bot.mailer.create.db=Erstelle neue Datenbank: {0} bot.mailer.create.ignore=Erstelle neue Ignore-Liste: {0} bot.mailer.load.db=Lade Datenbank-Datei: {0} -bot.mailer.load.ignore=Lade Ignore-Liste: +bot.mailer.load.ignore=Lade Ignore-Liste: bot.mailer.cmd=Mailer-Befehl @@ -482,12 +592,43 @@ bot.mailer.cmd.ignore.removed=Entferne {0} von der Ignore Liste! bot.mailer.cmd.ignore.invalid=Fehlender oder ungültiger Name. Benutzung: {0} bot.mailer.cmd.help=Siehe Benutzung +# Maps +bot.map.cmd.desc= +bot.map.cmd.not_found= +bot.map.cmd.invalid_id= +bot.map.received= +bot.map.no_maps= +bot.map.received_map= +bot.map.rendered= +bot.map.failed_to_render= +bot.map.list_item= + # ReplayCapture bot.replayCapture.cmd=replay Befehl bot.replayCapture.created=Replay-Datei erstellt. bot.replayCapture.stopped=Record angehalten. bot.replayCapture.restart=Aufnahme wurde angehalten. Starte das Programm neu um eine neue Aufnahme zu erstellen. +# Follow player +cmd.follow.desc= +cmd.follow.usage= +cmd.follow.already_stopped= +cmd.follow.stopping= +cmd.follow.invalid_name= +cmd.follow.invalid_player= +cmd.follow.cant_reach_player= +cmd.follow.already_following= +cmd.follow.switched= +cmd.follow.started= +cmd.follow.unsafe_enabled= +cmd.follow.note= +cmd.follow.player_came_to_the_range= +cmd.follow.resuming= +cmd.follow.player_left_the_range= +cmd.follow.pausing= +cmd.follow.player_left= +cmd.follow.stopping= + # Script bot.script.not_found=§8[MCC] [{0}] Konnte Skriptdatei nicht finden: {1} bot.script.file_not_found=Datei nicht gefunden: '{0}' @@ -508,3 +649,220 @@ bot.scriptScheduler.task=triggeronfirstlogin: {0}\n triggeronlogin: {1}\n trigge # TestBot bot.testBot.told=Bot: {0} told me : {1} bot.testBot.said=Bot: {0} said : {1} + + +[config] + +config.load= +config.load.fail= +config.write.fail= +config.backup.fail= +config.saving= + +# Head +config.Head= + +# Main.General +config.Main.General.account= +config.Main.General.login= +config.Main.General.server_info= +config.Main.General.method= + +# Main.Advanced +config.Main.Advanced= +config.Main.Advanced.language= +config.Main.Advanced.internal_cmd_char= +config.Main.Advanced.message_cooldown= +config.Main.Advanced.bot_owners= +config.Main.Advanced.mc_version= +config.Main.Advanced.mc_forge= +config.Main.Advanced.brand_info= +config.Main.Advanced.chatbot_log_file= +config.Main.Advanced.private_msgs_cmd_name= +config.Main.Advanced.show_system_messages= +config.Main.Advanced.show_xpbar_messages= +config.Main.Advanced.show_chat_links= +config.Main.Advanced.show_inventory_layout= +config.Main.Advanced.terrain_and_movements= +config.Main.Advanced.inventory_handling= +config.Main.Advanced.entity_handling= +config.Main.Advanced.session_cache= +config.Main.Advanced.profilekey_cache= +config.Main.Advanced.resolve_srv_records= +config.Main.Advanced.account_list= +config.Main.Advanced.server_list= +config.Main.Advanced.player_head_icon= +config.Main.Advanced.exit_on_failure= +config.Main.Advanced.script_cache= +config.Main.Advanced.timestamps= +config.Main.Advanced.auto_respawn= +config.Main.Advanced.minecraft_realms= +config.Main.Advanced.move_head_while_walking= +config.Main.Advanced.timeout= +config.Main.Advanced.enable_emoji= +config.Main.Advanced.movement_speed= +config.Main.Advanced.language.invaild= + +# Signature +config.Signature= +config.Signature.LoginWithSecureProfile= +config.Signature.SignChat= +config.Signature.SignMessageInCommand= +config.Signature.MarkLegallySignedMsg= +config.Signature.MarkModifiedMsg= +config.Signature.MarkIllegallySignedMsg= +config.Signature.MarkSystemMessage= +config.Signature.ShowModifiedChat= +config.Signature.ShowIllegalSignedChat= + +# Logging +config.Logging= +config.Logging.DebugMessages= +config.Logging.ChatMessages= +config.Logging.InfoMessages= +config.Logging.WarningMessages= +config.Logging.ErrorMessages= +config.Logging.ChatFilter= +config.Logging.DebugFilter= +config.Logging.FilterMode= +config.Logging.LogToFile= +config.Logging.LogFile= +config.Logging.PrependTimestamp= +config.Logging.SaveColorCodes= + +# AppVars +config.AppVars.Variables= + +# Proxy +config.Proxy= +config.Proxy.Enabled_Login= +config.Proxy.Enabled_Ingame= +config.Proxy.Server= +config.Proxy.Proxy_Type= +config.Proxy.Username= +config.Proxy.Password= + +# ChatFormat +config.ChatFormat= +config.ChatFormat.Builtins= +config.ChatFormat.UserDefined= + +# MCSettings +config.MCSettings= +config.MCSettings.Enabled= +config.MCSettings.Locale= +config.MCSettings.RenderDistance= +config.MCSettings.Difficulty= +config.MCSettings.ChatMode= +config.MCSettings.ChatColors= +config.MCSettings.MainHand= + +# ChatBot +config.ChatBot= + +# ChatBot.Alerts +config.ChatBot.Alerts= +config.ChatBot.Alerts.Beep_Enabled= +config.ChatBot.Alerts.Trigger_By_Words= +config.ChatBot.Alerts.Trigger_By_Rain= +config.ChatBot.Alerts.Trigger_By_Thunderstorm= +config.ChatBot.Alerts.Matches_File= +config.ChatBot.Alerts.Excludes_File= +config.ChatBot.Alerts.Log_To_File= +config.ChatBot.Alerts.Log_File= + +# ChatBot.AntiAFK +config.ChatBot.AntiAfk= +config.ChatBot.AntiAfk.Delay= +config.ChatBot.AntiAfk.Command= +config.ChatBot.AntiAfk.Use_Terrain_Handling= +config.ChatBot.AntiAfk.Walk_Range= +config.ChatBot.AntiAfk.Walk_Retries= + +# ChatBot.AutoAttack +config.ChatBot.AutoAttack= +config.ChatBot.AutoAttack.Mode= +config.ChatBot.AutoAttack.Priority= +config.ChatBot.AutoAttack.Cooldown_Time= +config.ChatBot.AutoAttack.Interaction= +config.ChatBot.AutoAttack.Attack_Hostile= +config.ChatBot.AutoAttack.Attack_Passive= +config.ChatBot.AutoAttack.List_Mode= +config.ChatBot.AutoAttack.Entites_List= + +# ChatBot.AutoCraft +config.ChatBot.AutoCraft= +config.ChatBot.AutoCraft.CraftingTable= +config.ChatBot.AutoCraft.OnFailure= +config.ChatBot.AutoCraft.Recipes= + +# ChatBot.AutoDrop +config.ChatBot.AutoDrop= +config.ChatBot.AutoDrop.Mode= + +# ChatBot.AutoEat +config.ChatBot.AutoEat= + +# ChatBot.AutoFishing +config.ChatBot.AutoFishing= +config.ChatBot.AutoFishing.Antidespawn= +config.ChatBot.AutoFishing.Mainhand= +config.ChatBot.AutoFishing.Auto_Start= +config.ChatBot.AutoFishing.Cast_Delay= +config.ChatBot.AutoFishing.Fishing_Delay= +config.ChatBot.AutoFishing.Fishing_Timeout= +config.ChatBot.AutoFishing.Durability_Limit= +config.ChatBot.AutoFishing.Auto_Rod_Switch= +config.ChatBot.AutoFishing.Stationary_Threshold= +config.ChatBot.AutoFishing.Hook_Threshold= +config.ChatBot.AutoFishing.Log_Fish_Bobber= +config.ChatBot.AutoFishing.Enable_Move= +config.ChatBot.AutoFishing.Movements= + +# ChatBot.AutoRelog +config.ChatBot.AutoRelog= +config.ChatBot.AutoRelog.Delay= +config.ChatBot.AutoRelog.Retries= +config.ChatBot.AutoRelog.Ignore_Kick_Message= +config.ChatBot.AutoRelog.Kick_Messages= + +# ChatBot.AutoRespond +config.ChatBot.AutoRespond= +config.ChatBot.AutoRespond.Match_Colors= + +# ChatBot.ChatLog +config.ChatBot.ChatLog= + +# ChatBot.FollowPlayer +config.ChatBot.FollowPlayer= +config.ChatBot.FollowPlayer.Update_Limit= +config.ChatBot.FollowPlayer.Stop_At_Distance= + +# ChatBot.HangmanGame +config.ChatBot.HangmanGame= + +# ChatBot.Mailer +config.ChatBot.Mailer= + +# ChatBot.Map +config.ChatBot.Map= +config.ChatBot.Map.Should_Resize= +config.ChatBot.Map.Resize_To= +config.ChatBot.Map.Auto_Render_On_Update= +config.ChatBot.Map.Delete_All_On_Unload= +config.ChatBot.Map.Notify_On_First_Update= + +# ChatBot.PlayerListLogger +config.ChatBot.PlayerListLogger= +config.ChatBot.PlayerListLogger.Delay= + +# ChatBot.RemoteControl +config.ChatBot.RemoteControl= + +# ChatBot.ReplayCapture +config.ChatBot.ReplayCapture= +config.ChatBot.ReplayCapture.Backup_Interval= + +# ChatBot.ScriptScheduler +config.ChatBot.ScriptScheduler= + diff --git a/MinecraftClient/Resources/lang/en.ini b/MinecraftClient/Resources/lang/en.ini index cb617770..f9c2f0d9 100644 --- a/MinecraftClient/Resources/lang/en.ini +++ b/MinecraftClient/Resources/lang/en.ini @@ -91,13 +91,7 @@ error.no_version_report=§8Server does not report its protocol version, autodete error.connection_timeout=§8A timeout occured while attempting to connect to this IP. error.forge=§8Forge Login Handshake did not complete successfully error.forge_encrypt=§8Forge StartEncryption Handshake did not complete successfully -error.setting.str2int=Failed to convert '{0}' into an integer. Please check your settings. -error.setting.str2double=Failed to convert '{0}' to a floating-point number. Please check your settings. -error.setting.str2locationList.convert_fail=Failed to convert '{0}' to a floating point number. Please check your settings. -error.setting.str2locationList.format_err=Wrong format, can't parse '{0}' into position data.. Please check your settings. error.setting.argument_syntax={0}: Invalid syntax, expecting --argname=value or --section.argname=value -error.setting.unknown_section={0}: Unknown setting section '{1}' -error.setting.unknown_or_invalid={0}: Unknown setting or invalid value error.http_code=§8Got error code from server: {0} error.auth=§8Got error code from server while refreshing authentication: {0} error.realms.ip_error=Cannot retrieve the server IP of your Realms world @@ -425,7 +419,7 @@ cmd.setrndstr.format=setrnd variable string1 "\"string2\" string3" # Sneak cmd.sneak.desc=Toggles sneaking cmd.sneak.on=You are sneaking now -cmd.sneak.off=You aren't sneaking anymore +cmd.sneak.off=You are not sneaking anymore # DropItem cmd.dropItem.desc=Drop specified type of items from player inventory or opened container @@ -449,23 +443,18 @@ cmd.useitem.use=Used an item # 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 +bot.alerts.start_rain=§cWeather change: It is raining now.§r +bot.alerts.end_rain=§cWeather change: It is no longer raining.§r +bot.alerts.start_thunderstorm=§cWeather change: It is a thunderstorm.§r +bot.alerts.end_thunderstorm=§cWeather change: It is 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! -bot.antiafk.invalid_range=Invalid time range provided, using default time of 600! -bot.antiafk.invalid_value=Invalid time provided, using default time of 600! bot.antiafk.swapping=The time range begins with a bigger value, swapped them around. bot.antiafk.invalid_walk_range=Invalid walk range provided, must be a positive integer greater than 0, using default value of 5! # AutoAttack -bot.autoAttack.mode=Unknown attack mode: {0}. Using single mode as default. -bot.autoAttack.priority=Unknown priority: {0}. Using distance priority as default. -bot.autoAttack.invalidcooldown=Attack cooldown value cannot be smaller than 0. Using auto as default +bot.autoAttack.invalidcooldown=Attack cooldown value cannot be smaller than 0. # AutoCraft bot.autoCraft.cmd=Auto-crafting ChatBot command @@ -493,13 +482,7 @@ bot.autoCraft.aborted=Crafting aborted! Check your available materials. bot.autoCraft.craft_fail=Crafting failed! Waiting for more materials bot.autoCraft.timeout=Action timeout! Reason: {0} bot.autoCraft.error.config=Error while parsing config: {0} -bot.autoCraft.exception.empty=Empty configuration file: {0} -bot.autoCraft.exception.invalid=Invalid configuration file: {0} -bot.autoCraft.exception.item_miss=Missing item in recipe: {0} -bot.autoCraft.exception.invalid_table=Invalid tablelocation format: {0} -bot.autoCraft.exception.item_name=Invalid item name in recipe {0} at {1} bot.autoCraft.exception.name_miss=Missing recipe name while parsing a recipe -bot.autoCraft.exception.slot=Invalid slot field in recipe: {0} bot.autoCraft.exception.duplicate=Duplicate recipe name specified: {0} bot.autoCraft.debug.no_config=No config found. Writing a new one. bot.autocraft.invaild_slots=The number of slots does not match and has been adjusted automatically. @@ -636,8 +619,6 @@ bot.script.fail=Script '{0}' failed to run ({1}). bot.script.pm.loaded=Script '{0}' loaded. # ScriptScheduler -bot.scriptScheduler.loading=Loading tasks from '{0}' -bot.scriptScheduler.not_found=File not found: '{0}' bot.scriptScheduler.loaded_task=Loaded task:\n{0} bot.scriptScheduler.no_trigger=This task will never trigger:\n{0} bot.scriptScheduler.no_action=No action for task:\n{0} diff --git a/MinecraftClient/Resources/lang/fr.ini b/MinecraftClient/Resources/lang/fr.ini index 3b6e904a..b2af8a9b 100644 --- a/MinecraftClient/Resources/lang/fr.ini +++ b/MinecraftClient/Resources/lang/fr.ini @@ -1,15 +1,22 @@ [mcc] # Messages from MCC itself +mcc.help_us_translate= +mcc.run_with_default_settings= +mcc.settings_generated= +mcc.has_update= mcc.login=Connexion : mcc.login_basic_io=Veuillez saisir un nom d'utilisateur ou une adresse email. -mcc.password=Mot de passe : +mcc.password=Mot de passe : mcc.password_basic_io=Saisissez le mot de passe pour {0}. mcc.password_hidden=Mot de passe : {0} mcc.offline=§8Vous avez choisi d'utiliser le mode hors ligne. mcc.session_invalid=§8Le cache de la session est invalide ou a expiré. mcc.session_valid=§8Le cache de la session est encore valable pendant {0}. +mcc.profile_key_invalid= +mcc.profile_key_valid= mcc.connecting=Connexion à {0}... -mcc.ip=Adresse IP du Serveur : +mcc.fetching_key= +mcc.ip=Adresse IP du Serveur : mcc.use_version=§8Utilisation de la version {0} de Minecraft (protocole v{1}) mcc.unknown_version=§8Version MC non connue ou non supportée. {0}.\nPassage en mode autodétection. mcc.forge=Vérification si le serveur utilise Forge... @@ -20,7 +27,7 @@ mcc.not_found=§8Échec de la résolution SRV pour {0}\n{1} : {2} mcc.retrieve=Récupération des informations du serveur... mcc.restart=Redémarrage de Minecraft Console Client... mcc.restart_delay=Attente de {0} secondes avant de redémarrer... -mcc.server_version=Version du serveur : +mcc.server_version=Version du serveur : mcc.disconnected=Actuellement non connecté à un serveur. Utilisez '{0}help' pour obtenir de l'aide. mcc.press_exit=Ou appuyez sur la touche Entrer pour quitter Minecraft Console Client. mcc.version_supported=La version est prise en charge.\nConnexion... @@ -41,13 +48,16 @@ mcc.with_forge=, avec Forge mcc.handshake=§8Handshake réussi. (ID Serveur : {0}) mcc.realms_available=Vous avez accès aux mondes Realms suivants mcc.realms_join=Utilisez realms: comme ip de serveur pour rejoindre un monde Realms - +mcc.generator.generating= +mcc.generator.done= [debug] # Messages from MCC Debug Mode debug.color_test=Test des couleurs : Votre terminal devrait afficher {0} debug.session_cache_ok=§8Informations de Session chargées depuis le disque avec succès. debug.session_cache_fail=§8Aucune session n'a pu être chargé depuis le disque +debug.keys_cache_ok= +debug.keys_cache_fail= debug.session_id=Succès. (ID de Session : {0}) debug.crypto=§8Clé de chiffrement & hash générés. debug.request=§8Envoi d'une requête à {0} @@ -58,7 +68,7 @@ error.ping=Échec du ping sur l'IP. error.unsupported=Impossible de se connecter au serveur : Cette version n'est pas prise en charge ! error.determine=La version du serveur n'a pas pu être déterminée. error.forgeforce=Impossible de forcer le support de Forge sur cette version de Minecraft ! -error.login=Échec d'authentification : +error.login=Échec d'authentification : error.login.migrated=Compte migré, utiliser l'email à la place du nom d'utilisateur. error.login.server=Serveur d'authentification indisponible. Veuillez réessayer ultérieurement. error.login.blocked=Mot de passe incorrect, IP bannie ou trop de connexions. @@ -82,6 +92,9 @@ error.connection_timeout=§8La connexion à cette adresse IP n'a pas abouti (tim error.forge=§8Le Handshake Forge (Login) n'a pas réussi error.forge_encrypt=§8Le Handshake Forge (StartEncryption) n'a pas réussi error.setting.str2int=Échec de la conversion '{0}' en nombre entier. Veuillez vérifier la configuration. +error.setting.str2double= +error.setting.str2locationList.convert_fail= +error.setting.str2locationList.format_err= error.setting.argument_syntax={0} : Syntaxe invalide, --argname=value ou --section.argname=value attendu error.setting.unknown_section={0} : Section de configuration '{1}' inconnue error.setting.unknown_or_invalid={0} : Paramètre inconnu ou valeur invalide @@ -92,6 +105,11 @@ error.realms.access_denied=Ce monde Realms n'existe pas ou l'accès a été refu error.realms.server_unavailable=Le serveur peut nécessiter un peu de temps pour démarrer. Veuillez réessayer plus tard. error.realms.server_id=ID Realms invalide ou inconnu. error.realms.disabled=Tentative de connexion à un monde Realms mais le support Realms est désactivé dans la configuration +error.missing.argument= +error.usage= +error.generator.invalid= +error.generator.path= +error.generator.json= [internal command] # MCC internal help command @@ -173,6 +191,14 @@ cache.ignore_line=§8Ignoré une ligne de jeton de session invalide : {0} cache.read_fail_plain=§8Échec de la lecture ddu fichier de cache de sessions : {0} cache.saving=§8Sauvegarde du cache de sessions sur le disque cache.save_fail=§8Échec d'écriture du fichier de cache de sessions : {0} +# Profile Key Cache +cache.loading_keys= +cache.loaded_keys= +cache.ignore_string_keys= +cache.ignore_line_keys= +cache.read_fail_plain_keys= +cache.saving_keys= +cache.save_fail_keys= [proxy] proxy.connected=§8Connecté au proxy {0}:{1} @@ -186,6 +212,7 @@ chat.fail=§8Échec de téléchargement du fichier. chat.from_dir=§8Utilisation à la place de en_GB.lang depuis votre jeu Minecraft. chat.loaded=§8Fichier de traductions chargé. chat.not_found=§8Fichier de traductions non trouvé : '{0}'\nCertains messages ne seront pas affichés correctement sans ce fichier. +chat.message_chain_broken= [general] # General message/information (i.e. Done) @@ -201,12 +228,23 @@ general.available_cmd=Commandes disponibles : {0} # Animation cmd.animation.desc=Balancer le bras. +# Bots +cmd.bots.desc= +cmd.bots.list= +cmd.bots.notfound= +cmd.bots.noloaded= +cmd.bots.unloaded= +cmd.bots.unloaded_all= + # ChangeSlot cmd.changeSlot.desc=Changer de slot (emplacement) dans la hotbar cmd.changeSlot.nan=Le slot n'a pas pu être changé : Numéro invalide cmd.changeSlot.changed=Slot sélectionné : {0} cmd.changeSlot.fail=Le slot n'a pas pu être sélectionné +# Chunk +cmd.chunk.desc= + # Connect cmd.connect.desc=Se connecter au serveur spécifié cmd.connect.unknown=Compte '{0}' inconnu. @@ -248,6 +286,19 @@ cmd.entityCmd.distance=Distance cmd.entityCmd.location=Emplacement cmd.entityCmd.type=Type +# Exec If +cmd.execif.desc= +cmd.execif.executed= +cmd.execif.executed_no_output= +cmd.execif.error_occured= +cmd.execif.error= + +# Exec Multi +cmd.execmulti.desc= +cmd.execmulti.executed= +cmd.execmulti.result= +cmd.execmulti.no_result= + # Exit cmd.exit.desc=Se déconnecter du serveur. @@ -267,15 +318,18 @@ cmd.inventory.close_fail=Impossible de fermer l'inventaire #{0} cmd.inventory.not_exist=L'inventaire #{0} n'existe pas cmd.inventory.inventory=Inventaire cmd.inventory.inventories=Inventaires +cmd.inventory.inventories_available= cmd.inventory.hotbar=Votre sélection dans la horbar : {0} cmd.inventory.damage=Dommage cmd.inventory.left=gauche cmd.inventory.right=droit cmd.inventory.middle=du milieu cmd.inventory.clicking=Clic {0} sur le slot {1} dans la fenêtre #{2} +cmd.inventory.shiftclick= +cmd.inventory.shiftclick_fail= cmd.inventory.no_item=Aucun objet dans le slot #{0} cmd.inventory.drop=Lâché 1 objet depuis le slot #{0} -cmd.inventory.drop_stack=Lâché tous les objets du slot #{0} +cmd.inventory.drop_stack=Lâché tous les objets du slot #{0} # Inventory Help cmd.inventory.help.basic=Utilisation de base cmd.inventory.help.available=Actions possibles @@ -284,10 +338,29 @@ cmd.inventory.help.usage=Utilisation cmd.inventory.help.list=Lister votre inventaire. cmd.inventory.help.close=Fermer un conteneur ouvert. cmd.inventory.help.click=Cliquer sur un objet. +cmd.inventory.help.shiftclick= cmd.inventory.help.drop=Lâcher un objet de votre inventaire. cmd.inventory.help.creativegive=Se donner un objet en mode créatif. cmd.inventory.help.creativedelete=Vider un slot en mode créatif. -cmd.inventory.help.unknown=Action inconnue. +cmd.inventory.help.inventories= +cmd.inventory.help.search= +cmd.inventory.help.unknown=Action inconnue. +cmd.inventory.found_items= +cmd.inventory.no_found_items= + +# Leave bed +cmd.bed.desc= +cmd.bed.leaving= +cmd.bed.trying_to_use= +cmd.bed.in= +cmd.bed.not_in= +cmd.bed.not_a_bed= +cmd.bed.searching= +cmd.bed.bed_not_found= +cmd.bed.found_a_bed_at= +cmd.bed.cant_reach_safely= +cmd.bed.moving= +cmd.bed.failed_to_reach_in_time= # List cmd.list.desc=Lister les joueurs connectés. @@ -301,6 +374,8 @@ cmd.look.desc=Regarder dans une direction ou des coordonnées. cmd.look.unknown=Direction inconnue : '{0}' cmd.look.at=Rotation de la tête (YAW:{0}, PITCH:{1}) cmd.look.block=Rotation de la tête vers : {0} +cmd.look.inspection= +cmd.look.noinspection= # Move cmd.move.desc=Marcher ou commencer à marcher. @@ -313,10 +388,21 @@ cmd.move.fail=Échec de calcul du chemin vers {0} cmd.move.suggestforce=Échec de calcul du chemin vers {0}. Utilisez -f pour autoriser les mouvements risqués. cmd.move.gravity.enabled=La gravité est activée. cmd.move.gravity.disabled=La gravité est désactivée. +cmd.move.chunk_loading_status= +cmd.move.chunk_not_loaded= # Reco cmd.reco.desc=Relancer le programme et se reconnecter au serveur +# Reload +cmd.reload.started= +cmd.reload.warning1= +cmd.reload.warning2= +cmd.reload.warning3= +cmd.reload.warning4= +cmd.reload.finished= +cmd.reload.desc= + # Respawn cmd.respawn.desc=Réapparaitre sur le serveur si vous êtes mort. cmd.respawn.done=Vous êtes réapparu. @@ -352,6 +438,7 @@ cmd.tps.current=TPS actuel # Useblock cmd.useblock.desc=Placer un bloc ou ouvrir un coffre +cmd.useblock.use= # Useitem cmd.useitem.desc=Utiliser (clic gauche) un objet dans la main @@ -361,6 +448,20 @@ cmd.useitem.use=Objet utilisé [bot] # ChatBots. Naming style: bot.. +# Alerts +bot.alerts.start_rain= +bot.alerts.end_rain= +bot.alerts.start_thunderstorm= +bot.alerts.end_thunderstorm= + +# Anti AFK +bot.antiafk.not_using_terrain_handling= +bot.antiafk.invalid_range_partial= +bot.antiafk.invalid_range= +bot.antiafk.invalid_value= +bot.antiafk.swapping= +bot.antiafk.invalid_walk_range= + # AutoAttack bot.autoAttack.mode=Mode d'attaque inconnu : {0}. Utilisation du mode par défaut (single). bot.autoAttack.priority=Priorité inconnue : {0}. Utilisation du mode par défaut (privilégier la distance). @@ -401,6 +502,8 @@ bot.autoCraft.exception.name_miss=Nom manquant lors du chargement d'une recette bot.autoCraft.exception.slot=Slot invalide dans la recette : {0} bot.autoCraft.exception.duplicate=Nom de recette spécifié en double : {0} bot.autoCraft.debug.no_config=Fichier de configuration introuvable. Création d'un nouveau fichier. +bot.autocraft.invaild_slots= +bot.autocraft.invaild_invaild_result= # AutoDrop bot.autoDrop.cmd=Commande du ChatBot AutoDrop @@ -419,9 +522,17 @@ bot.autoDrop.no_mode=Impossible de lire le mode de Drop dans la configuration. U bot.autoDrop.no_inventory=Impossible de trouver l'inventaire {0} ! # AutoFish +bot.autoFish.no_inv_handle= +bot.autoFish.start= bot.autoFish.throw=Canne à pêche lancée bot.autoFish.caught=Poisson attrapé ! +bot.autoFish.caught_at= bot.autoFish.no_rod=Pas de canne a pêche dans la main. Peut-être a-t-elle cassé ? +bot.autoFish.despawn= +bot.autoFish.fishing_timeout= +bot.autoFish.cast_timeout= +bot.autoFish.update_lookat= +bot.autoFish.switch= # AutoRelog bot.autoRelog.launch=Lancement avec {0} tentatives de reconnexion @@ -465,7 +576,7 @@ bot.mailer.init_fail.mail_retention=Impossible d'activer le Mailer : La rétenti bot.mailer.create.db=Création d'un nouveau fichier de base de données : {0} bot.mailer.create.ignore=Création d'une nouvelle liste d'exclusions : {0} bot.mailer.load.db=Chargement de la base de données : {0} -bot.mailer.load.ignore=Chargement de la liste d'exclusions : +bot.mailer.load.ignore=Chargement de la liste d'exclusions : bot.mailer.cmd=Commande du Mailer @@ -481,12 +592,43 @@ bot.mailer.cmd.ignore.removed=Retrait de {0} de la liste d'exclusions ! bot.mailer.cmd.ignore.invalid=Nom manquant ou invalide. Utilisation : {0} bot.mailer.cmd.help=Voir l'utilisation +# Maps +bot.map.cmd.desc= +bot.map.cmd.not_found= +bot.map.cmd.invalid_id= +bot.map.received= +bot.map.no_maps= +bot.map.received_map= +bot.map.rendered= +bot.map.failed_to_render= +bot.map.list_item= + # ReplayCapture bot.replayCapture.cmd=Commande de Replay bot.replayCapture.created=Fichier de Replay créé. bot.replayCapture.stopped=Enregistrement arrêté. bot.replayCapture.restart=L'enregistrement a été stoppé. Redémarrez le programme pour commencer un nouvel enregistrement. +# Follow player +cmd.follow.desc= +cmd.follow.usage= +cmd.follow.already_stopped= +cmd.follow.stopping= +cmd.follow.invalid_name= +cmd.follow.invalid_player= +cmd.follow.cant_reach_player= +cmd.follow.already_following= +cmd.follow.switched= +cmd.follow.started= +cmd.follow.unsafe_enabled= +cmd.follow.note= +cmd.follow.player_came_to_the_range= +cmd.follow.resuming= +cmd.follow.player_left_the_range= +cmd.follow.pausing= +cmd.follow.player_left= +cmd.follow.stopping= + # Script bot.script.not_found=§8[MCC] [{0}] Impossible de trouver le fichier de script : {1} bot.script.file_not_found=Fichier non trouvé : '{0}' @@ -507,3 +649,220 @@ bot.scriptScheduler.task=triggeronfirstlogin : {0}\n triggeronlogin : {1}\n trig # TestBot bot.testBot.told=Bot : {0} m'a dit : {1} bot.testBot.said=Bot : {0} a dit : {1} + + +[config] + +config.load= +config.load.fail= +config.write.fail= +config.backup.fail= +config.saving= + +# Head +config.Head= + +# Main.General +config.Main.General.account= +config.Main.General.login= +config.Main.General.server_info= +config.Main.General.method= + +# Main.Advanced +config.Main.Advanced= +config.Main.Advanced.language= +config.Main.Advanced.internal_cmd_char= +config.Main.Advanced.message_cooldown= +config.Main.Advanced.bot_owners= +config.Main.Advanced.mc_version= +config.Main.Advanced.mc_forge= +config.Main.Advanced.brand_info= +config.Main.Advanced.chatbot_log_file= +config.Main.Advanced.private_msgs_cmd_name= +config.Main.Advanced.show_system_messages= +config.Main.Advanced.show_xpbar_messages= +config.Main.Advanced.show_chat_links= +config.Main.Advanced.show_inventory_layout= +config.Main.Advanced.terrain_and_movements= +config.Main.Advanced.inventory_handling= +config.Main.Advanced.entity_handling= +config.Main.Advanced.session_cache= +config.Main.Advanced.profilekey_cache= +config.Main.Advanced.resolve_srv_records= +config.Main.Advanced.account_list= +config.Main.Advanced.server_list= +config.Main.Advanced.player_head_icon= +config.Main.Advanced.exit_on_failure= +config.Main.Advanced.script_cache= +config.Main.Advanced.timestamps= +config.Main.Advanced.auto_respawn= +config.Main.Advanced.minecraft_realms= +config.Main.Advanced.move_head_while_walking= +config.Main.Advanced.timeout= +config.Main.Advanced.enable_emoji= +config.Main.Advanced.movement_speed= +config.Main.Advanced.language.invaild= + +# Signature +config.Signature= +config.Signature.LoginWithSecureProfile= +config.Signature.SignChat= +config.Signature.SignMessageInCommand= +config.Signature.MarkLegallySignedMsg= +config.Signature.MarkModifiedMsg= +config.Signature.MarkIllegallySignedMsg= +config.Signature.MarkSystemMessage= +config.Signature.ShowModifiedChat= +config.Signature.ShowIllegalSignedChat= + +# Logging +config.Logging= +config.Logging.DebugMessages= +config.Logging.ChatMessages= +config.Logging.InfoMessages= +config.Logging.WarningMessages= +config.Logging.ErrorMessages= +config.Logging.ChatFilter= +config.Logging.DebugFilter= +config.Logging.FilterMode= +config.Logging.LogToFile= +config.Logging.LogFile= +config.Logging.PrependTimestamp= +config.Logging.SaveColorCodes= + +# AppVars +config.AppVars.Variables= + +# Proxy +config.Proxy= +config.Proxy.Enabled_Login= +config.Proxy.Enabled_Ingame= +config.Proxy.Server= +config.Proxy.Proxy_Type= +config.Proxy.Username= +config.Proxy.Password= + +# ChatFormat +config.ChatFormat= +config.ChatFormat.Builtins= +config.ChatFormat.UserDefined= + +# MCSettings +config.MCSettings= +config.MCSettings.Enabled= +config.MCSettings.Locale= +config.MCSettings.RenderDistance= +config.MCSettings.Difficulty= +config.MCSettings.ChatMode= +config.MCSettings.ChatColors= +config.MCSettings.MainHand= + +# ChatBot +config.ChatBot= + +# ChatBot.Alerts +config.ChatBot.Alerts= +config.ChatBot.Alerts.Beep_Enabled= +config.ChatBot.Alerts.Trigger_By_Words= +config.ChatBot.Alerts.Trigger_By_Rain= +config.ChatBot.Alerts.Trigger_By_Thunderstorm= +config.ChatBot.Alerts.Matches_File= +config.ChatBot.Alerts.Excludes_File= +config.ChatBot.Alerts.Log_To_File= +config.ChatBot.Alerts.Log_File= + +# ChatBot.AntiAFK +config.ChatBot.AntiAfk= +config.ChatBot.AntiAfk.Delay= +config.ChatBot.AntiAfk.Command= +config.ChatBot.AntiAfk.Use_Terrain_Handling= +config.ChatBot.AntiAfk.Walk_Range= +config.ChatBot.AntiAfk.Walk_Retries= + +# ChatBot.AutoAttack +config.ChatBot.AutoAttack= +config.ChatBot.AutoAttack.Mode= +config.ChatBot.AutoAttack.Priority= +config.ChatBot.AutoAttack.Cooldown_Time= +config.ChatBot.AutoAttack.Interaction= +config.ChatBot.AutoAttack.Attack_Hostile= +config.ChatBot.AutoAttack.Attack_Passive= +config.ChatBot.AutoAttack.List_Mode= +config.ChatBot.AutoAttack.Entites_List= + +# ChatBot.AutoCraft +config.ChatBot.AutoCraft= +config.ChatBot.AutoCraft.CraftingTable= +config.ChatBot.AutoCraft.OnFailure= +config.ChatBot.AutoCraft.Recipes= + +# ChatBot.AutoDrop +config.ChatBot.AutoDrop= +config.ChatBot.AutoDrop.Mode= + +# ChatBot.AutoEat +config.ChatBot.AutoEat= + +# ChatBot.AutoFishing +config.ChatBot.AutoFishing= +config.ChatBot.AutoFishing.Antidespawn= +config.ChatBot.AutoFishing.Mainhand= +config.ChatBot.AutoFishing.Auto_Start= +config.ChatBot.AutoFishing.Cast_Delay= +config.ChatBot.AutoFishing.Fishing_Delay= +config.ChatBot.AutoFishing.Fishing_Timeout= +config.ChatBot.AutoFishing.Durability_Limit= +config.ChatBot.AutoFishing.Auto_Rod_Switch= +config.ChatBot.AutoFishing.Stationary_Threshold= +config.ChatBot.AutoFishing.Hook_Threshold= +config.ChatBot.AutoFishing.Log_Fish_Bobber= +config.ChatBot.AutoFishing.Enable_Move= +config.ChatBot.AutoFishing.Movements= + +# ChatBot.AutoRelog +config.ChatBot.AutoRelog= +config.ChatBot.AutoRelog.Delay= +config.ChatBot.AutoRelog.Retries= +config.ChatBot.AutoRelog.Ignore_Kick_Message= +config.ChatBot.AutoRelog.Kick_Messages= + +# ChatBot.AutoRespond +config.ChatBot.AutoRespond= +config.ChatBot.AutoRespond.Match_Colors= + +# ChatBot.ChatLog +config.ChatBot.ChatLog= + +# ChatBot.FollowPlayer +config.ChatBot.FollowPlayer= +config.ChatBot.FollowPlayer.Update_Limit= +config.ChatBot.FollowPlayer.Stop_At_Distance= + +# ChatBot.HangmanGame +config.ChatBot.HangmanGame= + +# ChatBot.Mailer +config.ChatBot.Mailer= + +# ChatBot.Map +config.ChatBot.Map= +config.ChatBot.Map.Should_Resize= +config.ChatBot.Map.Resize_To= +config.ChatBot.Map.Auto_Render_On_Update= +config.ChatBot.Map.Delete_All_On_Unload= +config.ChatBot.Map.Notify_On_First_Update= + +# ChatBot.PlayerListLogger +config.ChatBot.PlayerListLogger= +config.ChatBot.PlayerListLogger.Delay= + +# ChatBot.RemoteControl +config.ChatBot.RemoteControl= + +# ChatBot.ReplayCapture +config.ChatBot.ReplayCapture= +config.ChatBot.ReplayCapture.Backup_Interval= + +# ChatBot.ScriptScheduler +config.ChatBot.ScriptScheduler= + diff --git a/MinecraftClient/Resources/lang/ru.ini b/MinecraftClient/Resources/lang/ru.ini index 83757a3c..886b1923 100644 --- a/MinecraftClient/Resources/lang/ru.ini +++ b/MinecraftClient/Resources/lang/ru.ini @@ -1,15 +1,22 @@ [mcc] # Messages from MCC itself +mcc.help_us_translate= +mcc.run_with_default_settings= +mcc.settings_generated= +mcc.has_update= mcc.login=Логин : mcc.login_basic_io=Пожалуйста, введите имя пользователя или email по вашему выбору. -mcc.password=Пароль: +mcc.password=Пароль: mcc.password_basic_io=Пожалуйста, введите пароль для {0}. mcc.password_hidden=Пароль: {0} mcc.offline=§8Вы выбрали запуск в автономном режиме. mcc.session_invalid=§8Кэшированная сессия недействительна или истекла. mcc.session_valid=§8Кэшированная сессия все еще действительна для {0}. +mcc.profile_key_invalid= +mcc.profile_key_valid= mcc.connecting=Подключение к {0}... -mcc.ip=IP сервера: +mcc.fetching_key= +mcc.ip=IP сервера: mcc.use_version=§8Используется Minecraft версии {0} (протокол v{1}) mcc.unknown_version=§8Неизвестная или не поддерживаемая версия MC {0}.\nПереключение в режим автоопределения. mcc.forge=Проверка, запущен ли на сервере Forge... @@ -20,7 +27,7 @@ mcc.not_found=§8Failed to perform SRV lookup for {0}\n{1}: {2} mcc.retrieve=Получение информации о сервере... mcc.restart=Перезапуск консольного клиента Minecraft... mcc.restart_delay=Ожидание {0} секунд перед перезапуском... -mcc.server_version=Версия сервера: +mcc.server_version=Версия сервера: mcc.disconnected=Не подключен ни к одному серверу. Используйте '{0}help' для получения справки. mcc.press_exit=Нажмите Enter, чтобы выйти из консольного клиента Minecraft. mcc.version_supported=Версия поддерживается.\nВойти в игру... @@ -41,13 +48,16 @@ mcc.with_forge=, с Forge mcc.handshake=§8Handshake successful. (ID сервера: {0}) mcc.realms_available=У вас есть доступ к следующим мирам Realms mcc.realms_join=Используйте realms:index как IP сервера, чтобы присоединиться к миру Realms - +mcc.generator.generating= +mcc.generator.done= [debug] # Messages from MCC Debug Mode debug.color_test=Цветовой тест: В вашем терминале должно отображаться {0} debug.session_cache_ok=§8Данные сессии успешно загружены с диска. debug.session_cache_fail=§8Ни одна сессия не могла быть загружена с диска +debug.keys_cache_ok= +debug.keys_cache_fail= debug.session_id=Успех. (ID сессии: {0}) debug.crypto=§8Сгенерированы криптографические ключи и хэш. debug.request=§8Выполнение запроса к {0} @@ -58,7 +68,7 @@ error.ping=Не удалось выполнить ping этого IP. error.unsupported=Не удается подключиться к серверу: эта версия не поддерживается! error.determine=Не удалось определить версию сервера. error.forgeforce=Не удается принудительно включить поддержку Forge для этой версии Minecraft! -error.login=Не удалось войти в систему Minecraft : +error.login=Не удалось войти в систему Minecraft : error.login.migrated=Аккаунт перенесен, используйте e-mail в качестве имени пользователя. error.login.server=Серверы входа недоступны. Пожалуйста, повторите попытку позже. error.login.blocked=Неправильный пароль, IP из черного списка или слишком много логинов. @@ -82,6 +92,9 @@ error.connection_timeout=§8При попытке подключения к эт error.forge=§8Forge Login Handshake не завершилось успешно error.forge_encrypt=§8Forge StartEncryption Handshake не завершилось успешно error.setting.str2int=Не удалось преобразовать '{0}' в int. Проверьте свои настройки. +error.setting.str2double= +error.setting.str2locationList.convert_fail= +error.setting.str2locationList.format_err= error.setting.argument_syntax={0}: Неверный синтаксис, ожидается --argname=value или --section.argname=value error.setting.unknown_section={0}: Неизвестный раздел настройки '{1}' error.setting.unknown_or_invalid={0}: Неизвестная настройка или недопустимое значение @@ -92,6 +105,11 @@ error.realms.access_denied=Этот мир Realms не существует ил error.realms.server_unavailable=Серверу Realms может потребоваться некоторое время для запуска. Пожалуйста, повторите попытку позже. error.realms.server_id=Неверный или неизвестный идентификатор сервера Realms. error.realms.disabled=Попытка присоединиться к миру Realms, но поддержка Realms отключена в конфигурации +error.missing.argument= +error.usage= +error.generator.invalid= +error.generator.path= +error.generator.json= [internal command] # MCC internal help command @@ -114,7 +132,7 @@ exception.chatbot.init= Методы ChatBot НЕ должны вызывать exception.csrunner.invalid_head=Предоставленный скрипт не имеет действительного заголовка MCCScript [chatbot] -# API ChatBot +# ChatBot API chatbot.reconnect=[{0}] Отключение и повторное подключение к серверу [filemonitor] @@ -173,6 +191,14 @@ cache.ignore_line=§8Игнорирование недопустимой стр cache.read_fail_plain=§8Не удалось прочитать кэш сессии с диска: {0} cache.saving=§8Сохранение кэша сессии на диск cache.save_fail=§8Не удалось записать кэш сессии на диск: {0} +# Profile Key Cache +cache.loading_keys= +cache.loaded_keys= +cache.ignore_string_keys= +cache.ignore_line_keys= +cache.read_fail_plain_keys= +cache.saving_keys= +cache.save_fail_keys= [proxy] proxy.connected=§8Подключен к прокси {0}:{1} @@ -186,6 +212,7 @@ chat.fail=§8Не удалось загрузить файл. chat.from_dir=§8Дополнительно к en_GB.lang из вашей директории Minecraft. chat.loaded=§8Файл переводов загружен. chat.not_found=§8Файл переводов не найден: '{0}'\nНекоторые сообщения не будут правильно печататься без этого файла. +chat.message_chain_broken= [general] # General message/information (i.e. Done) @@ -201,12 +228,23 @@ general.available_cmd=Доступные команды: {0} # Animation cmd.animation.desc=Взмах руки. +# Bots +cmd.bots.desc= +cmd.bots.list= +cmd.bots.notfound= +cmd.bots.noloaded= +cmd.bots.unloaded= +cmd.bots.unloaded_all= + # ChangeSlot cmd.changeSlot.desc=Изменить горячую панель cmd.changeSlot.nan=Не удалось изменить слот: Not a Number cmd.changeSlot.changed=Изменился на слот {0} cmd.changeSlot.fail=Не удалось изменить слот +# Chunk +cmd.chunk.desc= + # Connect cmd.connect.desc=подключиться к указанному серверу. cmd.connect.unknown=Неизвестная учетная запись '{0}'. @@ -248,6 +286,19 @@ cmd.entityCmd.distance=Дальность cmd.entityCmd.location=Местоположение cmd.entityCmd.type=Type +# Exec If +cmd.execif.desc= +cmd.execif.executed= +cmd.execif.executed_no_output= +cmd.execif.error_occured= +cmd.execif.error= + +# Exec Multi +cmd.execmulti.desc= +cmd.execmulti.executed= +cmd.execmulti.result= +cmd.execmulti.no_result= + # Exit cmd.exit.desc=отключиться от сервера. @@ -267,12 +318,15 @@ cmd.inventory.close_fail=Не удалось закрыть опись #{0} cmd.inventory.not_exist=Инвентаризация #{0} не существует cmd.inventory.inventory=Инвентарь cmd.inventory.inventories=Инвентарь +cmd.inventory.inventories_available= cmd.inventory.hotbar=Выбранная вами горячая панель - {0} cmd.inventory.damage=Ущерб cmd.inventory.left=Левый cmd.inventory.right=Правый cmd.inventory.middle=Середина cmd.inventory.clicking={0} щелчок по слоту {1} в окне #{2} +cmd.inventory.shiftclick= +cmd.inventory.shiftclick_fail= cmd.inventory.no_item=Нет предмета в слоте #{0} cmd.inventory.drop=Сбросил 1 предмет из слота #{0} cmd.inventory.drop_stack=Выбросил всю стопку предметов из слота #{0} @@ -284,10 +338,29 @@ cmd.inventory.help.usage=Применение cmd.inventory.help.list=Список инвентаря. cmd.inventory.help.close=Закрыть открытый контейнер. cmd.inventory.help.click=Нажать на элемент. +cmd.inventory.help.shiftclick= cmd.inventory.help.drop=Убрать предмет из инвентаря. cmd.inventory.help.creativegive=Выдать предмет в творческом режиме. cmd.inventory.help.creativedelete=Очистить слот в творческом режиме. -cmd.inventory.help.unknown=Неизвестное действие. +cmd.inventory.help.inventories= +cmd.inventory.help.search= +cmd.inventory.help.unknown=Неизвестное действие. +cmd.inventory.found_items= +cmd.inventory.no_found_items= + +# Leave bed +cmd.bed.desc= +cmd.bed.leaving= +cmd.bed.trying_to_use= +cmd.bed.in= +cmd.bed.not_in= +cmd.bed.not_a_bed= +cmd.bed.searching= +cmd.bed.bed_not_found= +cmd.bed.found_a_bed_at= +cmd.bed.cant_reach_safely= +cmd.bed.moving= +cmd.bed.failed_to_reach_in_time= # List cmd.list.desc=получить список игроков. @@ -301,6 +374,8 @@ cmd.look.desc=смотреть направление или координат cmd.look.unknown=Неизвестное направление '{0}' cmd.look.at=Посмотреть на YAW: {0} PITCH: {1} cmd.look.block=Посмотреть на {0} +cmd.look.inspection= +cmd.look.noinspection= # Move cmd.move.desc= идти или начать идти. @@ -310,10 +385,24 @@ cmd.move.moving=Перемещение {0} cmd.move.dir_fail=Невозможно двигаться в этом направлении. cmd.move.walk=Путь к {0} cmd.move.fail=Не удалось вычислить путь к {0} +cmd.move.suggestforce= +cmd.move.gravity.enabled= +cmd.move.gravity.disabled= +cmd.move.chunk_loading_status= +cmd.move.chunk_not_loaded= # Reco cmd.reco.desc=перезапустить и заново подключиться к серверу. +# Reload +cmd.reload.started= +cmd.reload.warning1= +cmd.reload.warning2= +cmd.reload.warning3= +cmd.reload.warning4= +cmd.reload.finished= +cmd.reload.desc= + # Respawn cmd.respawn.desc=Используйте это, чтобы возродиться, если вы мертвы. cmd.respawn.done=Вы переродились. @@ -328,6 +417,11 @@ cmd.send.desc=отправить сообщение в чат или коман cmd.set.desc=установить пользовательскую %переменную%. cmd.set.format=имя переменной должно быть A-Za-z0-9. +# SetRnd +cmd.setrnd.desc= +cmd.setrndnum.format= +cmd.setrndstr.format= + # Sneak cmd.sneak.desc=Выключает подкрадывание cmd.sneak.on=Вы сейчас крадетесь @@ -344,6 +438,7 @@ cmd.tps.current=Текущий tps # Useblock cmd.useblock.desc=Поставить блок или открыть сундук +cmd.useblock.use= # Useitem cmd.useitem.desc=Использовать (левый клик) предмет на руке @@ -353,6 +448,20 @@ cmd.useitem.use=Использовать предмет [bot] # ChatBots. Naming style: bot.. +# Alerts +bot.alerts.start_rain= +bot.alerts.end_rain= +bot.alerts.start_thunderstorm= +bot.alerts.end_thunderstorm= + +# Anti AFK +bot.antiafk.not_using_terrain_handling= +bot.antiafk.invalid_range_partial= +bot.antiafk.invalid_range= +bot.antiafk.invalid_value= +bot.antiafk.swapping= +bot.antiafk.invalid_walk_range= + # AutoAttack bot.autoAttack.mode=Неизвестный режим атаки: {0}. По умолчанию используется одиночный режим. bot.autoAttack.priority=Неизвестный приоритет: {0}. По умолчанию используется приоритет расстояния. @@ -393,6 +502,8 @@ bot.autoCraft.exception.name_miss=Пропущено имя рецепта пр bot.autoCraft.exception.slot=Неправильное поле слота в рецепте: {0} bot.autoCraft.exception.duplicate=Дублируется указанное имя рецепта: {0} bot.autoCraft.debug.no_config=Конфигурация не найдена. Записываем новый. +bot.autocraft.invaild_slots= +bot.autocraft.invaild_invaild_result= # AutoDrop bot.autoDrop.cmd=Команда автоудаления ЧатБота @@ -411,9 +522,17 @@ bot.autoDrop.no_mode=Невозможно прочитать режим паде bot.autoDrop.no_inventory=Не удается найти инвентарь {0}! # AutoFish +bot.autoFish.no_inv_handle= +bot.autoFish.start= bot.autoFish.throw=Закинул удочку bot.autoFish.caught=Поймал рыбу! +bot.autoFish.caught_at= bot.autoFish.no_rod=Нет удочки под рукой. Может быть сломана? +bot.autoFish.despawn= +bot.autoFish.fishing_timeout= +bot.autoFish.cast_timeout= +bot.autoFish.update_lookat= +bot.autoFish.switch= # AutoRelog bot.autoRelog.launch=Запуск с {0} попытками повторного подключения @@ -457,7 +576,7 @@ bot.mailer.init_fail.mail_retention=Невозможно включить Mailer bot.mailer.create.db=Создание нового файла базы данных: {0} bot.mailer.create.ignore=Создание нового списка игнорирования: {0} bot.mailer.load.db=Загрузка файла базы данных: {0} -bot.mailer.load.ignore=Загрузка списка игнорирования: +bot.mailer.load.ignore=Загрузка списка игнорирования: bot.mailer.cmd=команда почтового клиента @@ -473,12 +592,43 @@ bot.mailer.cmd.ignore.removed=Удалил {0} из списка игнорир bot.mailer.cmd.ignore.invalid=Пропущено или недопустимое имя. Использование: {0} <имя пользователя bot.mailer.cmd.help=Смотрите использование +# Maps +bot.map.cmd.desc= +bot.map.cmd.not_found= +bot.map.cmd.invalid_id= +bot.map.received= +bot.map.no_maps= +bot.map.received_map= +bot.map.rendered= +bot.map.failed_to_render= +bot.map.list_item= + # ReplayCapture bot.replayCapture.cmd=команда воспроизведения bot.replayCapture.created=Файл воспроизведения создан. bot.replayCapture.stopped=Запись остановлена. bot.replayCapture.restart=Запись была остановлена. Перезапустите программу, чтобы начать другую запись. +# Follow player +cmd.follow.desc= +cmd.follow.usage= +cmd.follow.already_stopped= +cmd.follow.stopping= +cmd.follow.invalid_name= +cmd.follow.invalid_player= +cmd.follow.cant_reach_player= +cmd.follow.already_following= +cmd.follow.switched= +cmd.follow.started= +cmd.follow.unsafe_enabled= +cmd.follow.note= +cmd.follow.player_came_to_the_range= +cmd.follow.resuming= +cmd.follow.player_left_the_range= +cmd.follow.pausing= +cmd.follow.player_left= +cmd.follow.stopping= + # Script bot.script.not_found=§8[MCC] [{0}] Не удается найти файл скрипта: {1} bot.script.file_not_found=Файл не найден: '{0}' @@ -499,3 +649,220 @@ bot.scriptScheduler.task=triggeronfirstlogin: {0}\n triggeronlogin: {1}\n trigge # TestBot bot.testBot.told=Bot: {0} сказал мне : {1} bot.testBot.said=Бот: {0} сказал: {1} + + +[config] + +config.load= +config.load.fail= +config.write.fail= +config.backup.fail= +config.saving= + +# Head +config.Head= + +# Main.General +config.Main.General.account= +config.Main.General.login= +config.Main.General.server_info= +config.Main.General.method= + +# Main.Advanced +config.Main.Advanced= +config.Main.Advanced.language= +config.Main.Advanced.internal_cmd_char= +config.Main.Advanced.message_cooldown= +config.Main.Advanced.bot_owners= +config.Main.Advanced.mc_version= +config.Main.Advanced.mc_forge= +config.Main.Advanced.brand_info= +config.Main.Advanced.chatbot_log_file= +config.Main.Advanced.private_msgs_cmd_name= +config.Main.Advanced.show_system_messages= +config.Main.Advanced.show_xpbar_messages= +config.Main.Advanced.show_chat_links= +config.Main.Advanced.show_inventory_layout= +config.Main.Advanced.terrain_and_movements= +config.Main.Advanced.inventory_handling= +config.Main.Advanced.entity_handling= +config.Main.Advanced.session_cache= +config.Main.Advanced.profilekey_cache= +config.Main.Advanced.resolve_srv_records= +config.Main.Advanced.account_list= +config.Main.Advanced.server_list= +config.Main.Advanced.player_head_icon= +config.Main.Advanced.exit_on_failure= +config.Main.Advanced.script_cache= +config.Main.Advanced.timestamps= +config.Main.Advanced.auto_respawn= +config.Main.Advanced.minecraft_realms= +config.Main.Advanced.move_head_while_walking= +config.Main.Advanced.timeout= +config.Main.Advanced.enable_emoji= +config.Main.Advanced.movement_speed= +config.Main.Advanced.language.invaild= + +# Signature +config.Signature= +config.Signature.LoginWithSecureProfile= +config.Signature.SignChat= +config.Signature.SignMessageInCommand= +config.Signature.MarkLegallySignedMsg= +config.Signature.MarkModifiedMsg= +config.Signature.MarkIllegallySignedMsg= +config.Signature.MarkSystemMessage= +config.Signature.ShowModifiedChat= +config.Signature.ShowIllegalSignedChat= + +# Logging +config.Logging= +config.Logging.DebugMessages= +config.Logging.ChatMessages= +config.Logging.InfoMessages= +config.Logging.WarningMessages= +config.Logging.ErrorMessages= +config.Logging.ChatFilter= +config.Logging.DebugFilter= +config.Logging.FilterMode= +config.Logging.LogToFile= +config.Logging.LogFile= +config.Logging.PrependTimestamp= +config.Logging.SaveColorCodes= + +# AppVars +config.AppVars.Variables= + +# Proxy +config.Proxy= +config.Proxy.Enabled_Login= +config.Proxy.Enabled_Ingame= +config.Proxy.Server= +config.Proxy.Proxy_Type= +config.Proxy.Username= +config.Proxy.Password= + +# ChatFormat +config.ChatFormat= +config.ChatFormat.Builtins= +config.ChatFormat.UserDefined= + +# MCSettings +config.MCSettings= +config.MCSettings.Enabled= +config.MCSettings.Locale= +config.MCSettings.RenderDistance= +config.MCSettings.Difficulty= +config.MCSettings.ChatMode= +config.MCSettings.ChatColors= +config.MCSettings.MainHand= + +# ChatBot +config.ChatBot= + +# ChatBot.Alerts +config.ChatBot.Alerts= +config.ChatBot.Alerts.Beep_Enabled= +config.ChatBot.Alerts.Trigger_By_Words= +config.ChatBot.Alerts.Trigger_By_Rain= +config.ChatBot.Alerts.Trigger_By_Thunderstorm= +config.ChatBot.Alerts.Matches_File= +config.ChatBot.Alerts.Excludes_File= +config.ChatBot.Alerts.Log_To_File= +config.ChatBot.Alerts.Log_File= + +# ChatBot.AntiAFK +config.ChatBot.AntiAfk= +config.ChatBot.AntiAfk.Delay= +config.ChatBot.AntiAfk.Command= +config.ChatBot.AntiAfk.Use_Terrain_Handling= +config.ChatBot.AntiAfk.Walk_Range= +config.ChatBot.AntiAfk.Walk_Retries= + +# ChatBot.AutoAttack +config.ChatBot.AutoAttack= +config.ChatBot.AutoAttack.Mode= +config.ChatBot.AutoAttack.Priority= +config.ChatBot.AutoAttack.Cooldown_Time= +config.ChatBot.AutoAttack.Interaction= +config.ChatBot.AutoAttack.Attack_Hostile= +config.ChatBot.AutoAttack.Attack_Passive= +config.ChatBot.AutoAttack.List_Mode= +config.ChatBot.AutoAttack.Entites_List= + +# ChatBot.AutoCraft +config.ChatBot.AutoCraft= +config.ChatBot.AutoCraft.CraftingTable= +config.ChatBot.AutoCraft.OnFailure= +config.ChatBot.AutoCraft.Recipes= + +# ChatBot.AutoDrop +config.ChatBot.AutoDrop= +config.ChatBot.AutoDrop.Mode= + +# ChatBot.AutoEat +config.ChatBot.AutoEat= + +# ChatBot.AutoFishing +config.ChatBot.AutoFishing= +config.ChatBot.AutoFishing.Antidespawn= +config.ChatBot.AutoFishing.Mainhand= +config.ChatBot.AutoFishing.Auto_Start= +config.ChatBot.AutoFishing.Cast_Delay= +config.ChatBot.AutoFishing.Fishing_Delay= +config.ChatBot.AutoFishing.Fishing_Timeout= +config.ChatBot.AutoFishing.Durability_Limit= +config.ChatBot.AutoFishing.Auto_Rod_Switch= +config.ChatBot.AutoFishing.Stationary_Threshold= +config.ChatBot.AutoFishing.Hook_Threshold= +config.ChatBot.AutoFishing.Log_Fish_Bobber= +config.ChatBot.AutoFishing.Enable_Move= +config.ChatBot.AutoFishing.Movements= + +# ChatBot.AutoRelog +config.ChatBot.AutoRelog= +config.ChatBot.AutoRelog.Delay= +config.ChatBot.AutoRelog.Retries= +config.ChatBot.AutoRelog.Ignore_Kick_Message= +config.ChatBot.AutoRelog.Kick_Messages= + +# ChatBot.AutoRespond +config.ChatBot.AutoRespond= +config.ChatBot.AutoRespond.Match_Colors= + +# ChatBot.ChatLog +config.ChatBot.ChatLog= + +# ChatBot.FollowPlayer +config.ChatBot.FollowPlayer= +config.ChatBot.FollowPlayer.Update_Limit= +config.ChatBot.FollowPlayer.Stop_At_Distance= + +# ChatBot.HangmanGame +config.ChatBot.HangmanGame= + +# ChatBot.Mailer +config.ChatBot.Mailer= + +# ChatBot.Map +config.ChatBot.Map= +config.ChatBot.Map.Should_Resize= +config.ChatBot.Map.Resize_To= +config.ChatBot.Map.Auto_Render_On_Update= +config.ChatBot.Map.Delete_All_On_Unload= +config.ChatBot.Map.Notify_On_First_Update= + +# ChatBot.PlayerListLogger +config.ChatBot.PlayerListLogger= +config.ChatBot.PlayerListLogger.Delay= + +# ChatBot.RemoteControl +config.ChatBot.RemoteControl= + +# ChatBot.ReplayCapture +config.ChatBot.ReplayCapture= +config.ChatBot.ReplayCapture.Backup_Interval= + +# ChatBot.ScriptScheduler +config.ChatBot.ScriptScheduler= + diff --git a/MinecraftClient/Resources/lang/vi.ini b/MinecraftClient/Resources/lang/vi.ini index 23d88967..f85d3355 100644 --- a/MinecraftClient/Resources/lang/vi.ini +++ b/MinecraftClient/Resources/lang/vi.ini @@ -1,5 +1,9 @@ [mcc] # Messages from MCC itself +mcc.help_us_translate= +mcc.run_with_default_settings= +mcc.settings_generated= +mcc.has_update= mcc.login=Đăng nhập: mcc.login_basic_io=Hãy nhập địa chỉ email hoặc tên tài khoản của bạn: mcc.password=Mật khẩu: @@ -8,8 +12,11 @@ mcc.password_hidden=Password : {0} mcc.offline=§8Bạn chọn sử dụng chế độ ngoại tuyến. mcc.session_invalid=§8Phiên không hợp lệ hoặc đã hết hạn. mcc.session_valid=§8Phiên vẫn còn hợp lệ cho {0}. +mcc.profile_key_invalid= +mcc.profile_key_valid= mcc.connecting=Đang kết nối tới {0}... -mcc.ip=Địa chỉ máy chủ: +mcc.fetching_key= +mcc.ip=Địa chỉ máy chủ: mcc.use_version=§8Sử dụng Minecraft phiên bản {0} (protocol v{1}) mcc.unknown_version=§8Phiên bản không hợp lệ {0}.\nChuyển sang chế độ nhận diện tự động. mcc.forge=Đang kiểm tra xem máy chủ có dùng Forge... @@ -20,7 +27,7 @@ mcc.not_found=§8Tìm kiếm SRV thất bại cho {0}\n{1}: {2} mcc.retrieve=Đang nhận thông tin máy chủ... mcc.restart=Đang khởi động lại Minecraft Console Client... mcc.restart_delay=Đang chờ {0} giây trước khi khởi động lại... -mcc.server_version=Phiên bản máy chủ: +mcc.server_version=Phiên bản máy chủ: mcc.disconnected=Chưa kết nối tới máy chủ nào. Dùng '{0}help' để in ra hướng dẫn. mcc.press_exit=Hoặc nhấn Enter để đóng Minecraft Console Client mcc.version_supported=Phiên bản hợp lệ \nĐang đăng nhập @@ -41,13 +48,16 @@ mcc.with_forge=, với Forge mcc.handshake=§8Bắt tay thành công (ID máy chủ: {0}) mcc.realms_available=Bạn có quyền tham gia vào những máy chủ Realm này mcc.realms_join=Dùng realm:[thứ tự] để tham gia máy chủ Realm - +mcc.generator.generating= +mcc.generator.done= [debug] # Messages from MCC Debug Mode debug.color_test=Color test: Màn hình của bạn sẽ hiển thị {0} debug.session_cache_ok=§8Đã load thông tin phiên thành công debug.session_cache_fail=§8Không có phiên nào có thể load. +debug.keys_cache_ok= +debug.keys_cache_fail= debug.session_id=Thành công. (session ID: {0}) debug.crypto=§8Khóa mật mã và hash đã được tạo. debug.request=§8Đang gửi yêu cầu tới {0} @@ -82,6 +92,9 @@ error.connection_timeout=§8A timeout occured while attempting to connect to thi error.forge=§8Forge Login Handshake did not complete successfully error.forge_encrypt=§8Forge StartEncryption Handshake did not complete successfully error.setting.str2int=Failed to convert '{0}' into an int. Please check your settings. +error.setting.str2double= +error.setting.str2locationList.convert_fail= +error.setting.str2locationList.format_err= error.setting.argument_syntax={0}: Invalid syntax, expecting --argname=value or --section.argname=value error.setting.unknown_section={0}: Unknown setting section '{1}' error.setting.unknown_or_invalid={0}: Unknown setting or invalid value @@ -92,6 +105,11 @@ error.realms.access_denied=This Realms world does not exist or access was denied error.realms.server_unavailable=Realms server may require some time to start up. Please retry again later. error.realms.server_id=Invalid or unknown Realms server ID. error.realms.disabled=Trying to join a Realms world but Realms support is disabled in config +error.missing.argument= +error.usage= +error.generator.invalid= +error.generator.path= +error.generator.json= [internal command] # MCC internal help command @@ -173,6 +191,14 @@ cache.ignore_line=§8Ignoring invalid session token line: {0} cache.read_fail_plain=§8Failed to read session cache from disk: {0} cache.saving=§8Saving session cache to disk cache.save_fail=§8Failed to write session cache to disk: {0} +# Profile Key Cache +cache.loading_keys= +cache.loaded_keys= +cache.ignore_string_keys= +cache.ignore_line_keys= +cache.read_fail_plain_keys= +cache.saving_keys= +cache.save_fail_keys= [proxy] proxy.connected=§8Connected to proxy {0}:{1} @@ -186,6 +212,7 @@ chat.fail=§8Failed to download the file. chat.from_dir=§8Defaulting to en_GB.lang from your Minecraft directory. chat.loaded=§8Translations file loaded. chat.not_found=§8Translations file not found: '{0}'\nSome messages won't be properly printed without this file. +chat.message_chain_broken= [general] # General message/information (i.e. Done) @@ -201,12 +228,23 @@ general.available_cmd=Available commands: {0} # Animation cmd.animation.desc=Swing your arm. +# Bots +cmd.bots.desc= +cmd.bots.list= +cmd.bots.notfound= +cmd.bots.noloaded= +cmd.bots.unloaded= +cmd.bots.unloaded_all= + # ChangeSlot cmd.changeSlot.desc=Change hotbar cmd.changeSlot.nan=Could not change slot: Not a Number cmd.changeSlot.changed=Changed to slot {0} cmd.changeSlot.fail=Could not change slot +# Chunk +cmd.chunk.desc= + # Connect cmd.connect.desc=connect to the specified server. cmd.connect.unknown=Unknown account '{0}'. @@ -248,6 +286,19 @@ cmd.entityCmd.distance=Distance cmd.entityCmd.location=Location cmd.entityCmd.type=Type +# Exec If +cmd.execif.desc= +cmd.execif.executed= +cmd.execif.executed_no_output= +cmd.execif.error_occured= +cmd.execif.error= + +# Exec Multi +cmd.execmulti.desc= +cmd.execmulti.executed= +cmd.execmulti.result= +cmd.execmulti.no_result= + # Exit cmd.exit.desc=disconnect from the server. @@ -267,12 +318,15 @@ cmd.inventory.close_fail=Failed to close Inventory #{0} cmd.inventory.not_exist=Inventory #{0} do not exist cmd.inventory.inventory=Inventory cmd.inventory.inventories=Inventories +cmd.inventory.inventories_available= cmd.inventory.hotbar=Your selected hotbar is {0} cmd.inventory.damage=Damage cmd.inventory.left=Left cmd.inventory.right=Right cmd.inventory.middle=Middle cmd.inventory.clicking={0} clicking slot {1} in window #{2} +cmd.inventory.shiftclick= +cmd.inventory.shiftclick_fail= cmd.inventory.no_item=No item in slot #{0} cmd.inventory.drop=Dropped 1 item from slot #{0} cmd.inventory.drop_stack=Dropped whole item stack from slot #{0} @@ -284,10 +338,29 @@ cmd.inventory.help.usage=Usage cmd.inventory.help.list=List your inventory. cmd.inventory.help.close=Close an opened container. cmd.inventory.help.click=Click on an item. +cmd.inventory.help.shiftclick= cmd.inventory.help.drop=Drop an item from inventory. cmd.inventory.help.creativegive=Give item in creative mode. cmd.inventory.help.creativedelete=Clear slot in creative mode. -cmd.inventory.help.unknown=Unknown action. +cmd.inventory.help.inventories= +cmd.inventory.help.search= +cmd.inventory.help.unknown=Unknown action. +cmd.inventory.found_items= +cmd.inventory.no_found_items= + +# Leave bed +cmd.bed.desc= +cmd.bed.leaving= +cmd.bed.trying_to_use= +cmd.bed.in= +cmd.bed.not_in= +cmd.bed.not_a_bed= +cmd.bed.searching= +cmd.bed.bed_not_found= +cmd.bed.found_a_bed_at= +cmd.bed.cant_reach_safely= +cmd.bed.moving= +cmd.bed.failed_to_reach_in_time= # List cmd.list.desc=get the player list. @@ -301,6 +374,8 @@ cmd.look.desc=look at direction or coordinates. cmd.look.unknown=Unknown direction '{0}' cmd.look.at=Looking at YAW: {0} PITCH: {1} cmd.look.block=Looking at {0} +cmd.look.inspection= +cmd.look.noinspection= # Move cmd.move.desc=walk or start walking. @@ -310,10 +385,24 @@ cmd.move.moving=Moving {0} cmd.move.dir_fail=Cannot move in that direction. cmd.move.walk=Walking to {0} cmd.move.fail=Failed to compute path to {0} +cmd.move.suggestforce= +cmd.move.gravity.enabled= +cmd.move.gravity.disabled= +cmd.move.chunk_loading_status= +cmd.move.chunk_not_loaded= # Reco cmd.reco.desc=restart and reconnect to the server. +# Reload +cmd.reload.started= +cmd.reload.warning1= +cmd.reload.warning2= +cmd.reload.warning3= +cmd.reload.warning4= +cmd.reload.finished= +cmd.reload.desc= + # Respawn cmd.respawn.desc=Use this to respawn if you are dead. cmd.respawn.done=You have respawned. @@ -328,6 +417,11 @@ cmd.send.desc=send a chat message or command. cmd.set.desc=set a custom %variable%. cmd.set.format=variable name must be A-Za-z0-9. +# SetRnd +cmd.setrnd.desc= +cmd.setrndnum.format= +cmd.setrndstr.format= + # Sneak cmd.sneak.desc=Toggles sneaking cmd.sneak.on=You are sneaking now @@ -344,6 +438,7 @@ cmd.tps.current=Current tps # Useblock cmd.useblock.desc=Place a block or open chest +cmd.useblock.use= # Useitem cmd.useitem.desc=Use (left click) an item on the hand @@ -353,6 +448,20 @@ cmd.useitem.use=Used an item [bot] # ChatBots. Naming style: bot.. +# Alerts +bot.alerts.start_rain= +bot.alerts.end_rain= +bot.alerts.start_thunderstorm= +bot.alerts.end_thunderstorm= + +# Anti AFK +bot.antiafk.not_using_terrain_handling= +bot.antiafk.invalid_range_partial= +bot.antiafk.invalid_range= +bot.antiafk.invalid_value= +bot.antiafk.swapping= +bot.antiafk.invalid_walk_range= + # AutoAttack bot.autoAttack.mode=Unknown attack mode: {0}. Using single mode as default. bot.autoAttack.priority=Unknown priority: {0}. Using distance priority as default. @@ -393,6 +502,8 @@ bot.autoCraft.exception.name_miss=Missing recipe name while parsing a recipe bot.autoCraft.exception.slot=Invalid slot field in recipe: {0} bot.autoCraft.exception.duplicate=Duplicate recipe name specified: {0} bot.autoCraft.debug.no_config=No config found. Writing a new one. +bot.autocraft.invaild_slots= +bot.autocraft.invaild_invaild_result= # AutoDrop bot.autoDrop.cmd=AutoDrop ChatBot command @@ -411,9 +522,17 @@ bot.autoDrop.no_mode=Cannot read drop mode from config. Using include mode. bot.autoDrop.no_inventory=Cannot find inventory {0}! # AutoFish +bot.autoFish.no_inv_handle= +bot.autoFish.start= bot.autoFish.throw=Threw a fishing rod bot.autoFish.caught=Caught a fish! +bot.autoFish.caught_at= bot.autoFish.no_rod=No Fishing Rod on hand. Maybe broken? +bot.autoFish.despawn= +bot.autoFish.fishing_timeout= +bot.autoFish.cast_timeout= +bot.autoFish.update_lookat= +bot.autoFish.switch= # AutoRelog bot.autoRelog.launch=Launching with {0} reconnection attempts @@ -457,7 +576,7 @@ bot.mailer.init_fail.mail_retention=Cannot enable Mailer: Mail Retention must be bot.mailer.create.db=Creating new database file: {0} bot.mailer.create.ignore=Creating new ignore list: {0} bot.mailer.load.db=Loading database file: {0} -bot.mailer.load.ignore=Loading ignore list: +bot.mailer.load.ignore=Loading ignore list: bot.mailer.cmd=mailer command @@ -473,12 +592,43 @@ bot.mailer.cmd.ignore.removed=Removed {0} from the ignore list! bot.mailer.cmd.ignore.invalid=Missing or invalid name. Usage: {0} bot.mailer.cmd.help=See usage +# Maps +bot.map.cmd.desc= +bot.map.cmd.not_found= +bot.map.cmd.invalid_id= +bot.map.received= +bot.map.no_maps= +bot.map.received_map= +bot.map.rendered= +bot.map.failed_to_render= +bot.map.list_item= + # ReplayCapture bot.replayCapture.cmd=replay command bot.replayCapture.created=Replay file created. bot.replayCapture.stopped=Record stopped. bot.replayCapture.restart=Record was stopped. Restart the program to start another record. +# Follow player +cmd.follow.desc= +cmd.follow.usage= +cmd.follow.already_stopped= +cmd.follow.stopping= +cmd.follow.invalid_name= +cmd.follow.invalid_player= +cmd.follow.cant_reach_player= +cmd.follow.already_following= +cmd.follow.switched= +cmd.follow.started= +cmd.follow.unsafe_enabled= +cmd.follow.note= +cmd.follow.player_came_to_the_range= +cmd.follow.resuming= +cmd.follow.player_left_the_range= +cmd.follow.pausing= +cmd.follow.player_left= +cmd.follow.stopping= + # Script bot.script.not_found=§8[MCC] [{0}] Cannot find script file: {1} bot.script.file_not_found=File not found: '{0}' @@ -499,3 +649,220 @@ bot.scriptScheduler.task=triggeronfirstlogin: {0}\n triggeronlogin: {1}\n trigge # TestBot bot.testBot.told=Bot: {0} told me : {1} bot.testBot.said=Bot: {0} said : {1} + + +[config] + +config.load= +config.load.fail= +config.write.fail= +config.backup.fail= +config.saving= + +# Head +config.Head= + +# Main.General +config.Main.General.account= +config.Main.General.login= +config.Main.General.server_info= +config.Main.General.method= + +# Main.Advanced +config.Main.Advanced= +config.Main.Advanced.language= +config.Main.Advanced.internal_cmd_char= +config.Main.Advanced.message_cooldown= +config.Main.Advanced.bot_owners= +config.Main.Advanced.mc_version= +config.Main.Advanced.mc_forge= +config.Main.Advanced.brand_info= +config.Main.Advanced.chatbot_log_file= +config.Main.Advanced.private_msgs_cmd_name= +config.Main.Advanced.show_system_messages= +config.Main.Advanced.show_xpbar_messages= +config.Main.Advanced.show_chat_links= +config.Main.Advanced.show_inventory_layout= +config.Main.Advanced.terrain_and_movements= +config.Main.Advanced.inventory_handling= +config.Main.Advanced.entity_handling= +config.Main.Advanced.session_cache= +config.Main.Advanced.profilekey_cache= +config.Main.Advanced.resolve_srv_records= +config.Main.Advanced.account_list= +config.Main.Advanced.server_list= +config.Main.Advanced.player_head_icon= +config.Main.Advanced.exit_on_failure= +config.Main.Advanced.script_cache= +config.Main.Advanced.timestamps= +config.Main.Advanced.auto_respawn= +config.Main.Advanced.minecraft_realms= +config.Main.Advanced.move_head_while_walking= +config.Main.Advanced.timeout= +config.Main.Advanced.enable_emoji= +config.Main.Advanced.movement_speed= +config.Main.Advanced.language.invaild= + +# Signature +config.Signature= +config.Signature.LoginWithSecureProfile= +config.Signature.SignChat= +config.Signature.SignMessageInCommand= +config.Signature.MarkLegallySignedMsg= +config.Signature.MarkModifiedMsg= +config.Signature.MarkIllegallySignedMsg= +config.Signature.MarkSystemMessage= +config.Signature.ShowModifiedChat= +config.Signature.ShowIllegalSignedChat= + +# Logging +config.Logging= +config.Logging.DebugMessages= +config.Logging.ChatMessages= +config.Logging.InfoMessages= +config.Logging.WarningMessages= +config.Logging.ErrorMessages= +config.Logging.ChatFilter= +config.Logging.DebugFilter= +config.Logging.FilterMode= +config.Logging.LogToFile= +config.Logging.LogFile= +config.Logging.PrependTimestamp= +config.Logging.SaveColorCodes= + +# AppVars +config.AppVars.Variables= + +# Proxy +config.Proxy= +config.Proxy.Enabled_Login= +config.Proxy.Enabled_Ingame= +config.Proxy.Server= +config.Proxy.Proxy_Type= +config.Proxy.Username= +config.Proxy.Password= + +# ChatFormat +config.ChatFormat= +config.ChatFormat.Builtins= +config.ChatFormat.UserDefined= + +# MCSettings +config.MCSettings= +config.MCSettings.Enabled= +config.MCSettings.Locale= +config.MCSettings.RenderDistance= +config.MCSettings.Difficulty= +config.MCSettings.ChatMode= +config.MCSettings.ChatColors= +config.MCSettings.MainHand= + +# ChatBot +config.ChatBot= + +# ChatBot.Alerts +config.ChatBot.Alerts= +config.ChatBot.Alerts.Beep_Enabled= +config.ChatBot.Alerts.Trigger_By_Words= +config.ChatBot.Alerts.Trigger_By_Rain= +config.ChatBot.Alerts.Trigger_By_Thunderstorm= +config.ChatBot.Alerts.Matches_File= +config.ChatBot.Alerts.Excludes_File= +config.ChatBot.Alerts.Log_To_File= +config.ChatBot.Alerts.Log_File= + +# ChatBot.AntiAFK +config.ChatBot.AntiAfk= +config.ChatBot.AntiAfk.Delay= +config.ChatBot.AntiAfk.Command= +config.ChatBot.AntiAfk.Use_Terrain_Handling= +config.ChatBot.AntiAfk.Walk_Range= +config.ChatBot.AntiAfk.Walk_Retries= + +# ChatBot.AutoAttack +config.ChatBot.AutoAttack= +config.ChatBot.AutoAttack.Mode= +config.ChatBot.AutoAttack.Priority= +config.ChatBot.AutoAttack.Cooldown_Time= +config.ChatBot.AutoAttack.Interaction= +config.ChatBot.AutoAttack.Attack_Hostile= +config.ChatBot.AutoAttack.Attack_Passive= +config.ChatBot.AutoAttack.List_Mode= +config.ChatBot.AutoAttack.Entites_List= + +# ChatBot.AutoCraft +config.ChatBot.AutoCraft= +config.ChatBot.AutoCraft.CraftingTable= +config.ChatBot.AutoCraft.OnFailure= +config.ChatBot.AutoCraft.Recipes= + +# ChatBot.AutoDrop +config.ChatBot.AutoDrop= +config.ChatBot.AutoDrop.Mode= + +# ChatBot.AutoEat +config.ChatBot.AutoEat= + +# ChatBot.AutoFishing +config.ChatBot.AutoFishing= +config.ChatBot.AutoFishing.Antidespawn= +config.ChatBot.AutoFishing.Mainhand= +config.ChatBot.AutoFishing.Auto_Start= +config.ChatBot.AutoFishing.Cast_Delay= +config.ChatBot.AutoFishing.Fishing_Delay= +config.ChatBot.AutoFishing.Fishing_Timeout= +config.ChatBot.AutoFishing.Durability_Limit= +config.ChatBot.AutoFishing.Auto_Rod_Switch= +config.ChatBot.AutoFishing.Stationary_Threshold= +config.ChatBot.AutoFishing.Hook_Threshold= +config.ChatBot.AutoFishing.Log_Fish_Bobber= +config.ChatBot.AutoFishing.Enable_Move= +config.ChatBot.AutoFishing.Movements= + +# ChatBot.AutoRelog +config.ChatBot.AutoRelog= +config.ChatBot.AutoRelog.Delay= +config.ChatBot.AutoRelog.Retries= +config.ChatBot.AutoRelog.Ignore_Kick_Message= +config.ChatBot.AutoRelog.Kick_Messages= + +# ChatBot.AutoRespond +config.ChatBot.AutoRespond= +config.ChatBot.AutoRespond.Match_Colors= + +# ChatBot.ChatLog +config.ChatBot.ChatLog= + +# ChatBot.FollowPlayer +config.ChatBot.FollowPlayer= +config.ChatBot.FollowPlayer.Update_Limit= +config.ChatBot.FollowPlayer.Stop_At_Distance= + +# ChatBot.HangmanGame +config.ChatBot.HangmanGame= + +# ChatBot.Mailer +config.ChatBot.Mailer= + +# ChatBot.Map +config.ChatBot.Map= +config.ChatBot.Map.Should_Resize= +config.ChatBot.Map.Resize_To= +config.ChatBot.Map.Auto_Render_On_Update= +config.ChatBot.Map.Delete_All_On_Unload= +config.ChatBot.Map.Notify_On_First_Update= + +# ChatBot.PlayerListLogger +config.ChatBot.PlayerListLogger= +config.ChatBot.PlayerListLogger.Delay= + +# ChatBot.RemoteControl +config.ChatBot.RemoteControl= + +# ChatBot.ReplayCapture +config.ChatBot.ReplayCapture= +config.ChatBot.ReplayCapture.Backup_Interval= + +# ChatBot.ScriptScheduler +config.ChatBot.ScriptScheduler= + diff --git a/MinecraftClient/Resources/lang/zh-Hans.ini b/MinecraftClient/Resources/lang/zh-Hans.ini index 42938675..723be3d0 100644 --- a/MinecraftClient/Resources/lang/zh-Hans.ini +++ b/MinecraftClient/Resources/lang/zh-Hans.ini @@ -4,8 +4,8 @@ mcc.help_us_translate=帮助我们翻译MCC:{0} mcc.run_with_default_settings=\nMCC正在使用默认配置运行。 mcc.settings_generated=§c配置文件 MinecraftClient.ini 已经生成。 mcc.has_update=§e新版本的MCC已经推出:{0} -mcc.login=登录: -mcc.login_basic_io=请输入。 +mcc.login=账户名: +mcc.login_basic_io=请输入用户名或邮箱。 mcc.password=密码: mcc.password_basic_io=请输入{0}的密码。 mcc.password_hidden=密码:{0} @@ -15,6 +15,7 @@ mcc.session_valid=§8{0}的缓存仍然有效。 mcc.profile_key_invalid=§8缓存的聊天签名密钥需要刷新。 mcc.profile_key_valid=§8{0}的聊天签名密钥缓存仍然有效. mcc.connecting=正在连接至{0}... +mcc.fetching_key= mcc.ip=服务器IP: mcc.use_version=§8正在运行Minecraft版本{0} (v{1}协议) mcc.unknown_version=§8未知或不受支持的Minecraft版本{0}。\n正在切换至自动检测模式。 @@ -47,7 +48,8 @@ mcc.with_forge=, 带有Forge mcc.handshake=§8握手成功。 (服务器ID:{0}) mcc.realms_available==您可以访问以下Realms世界 mcc.realms_join=请使用realms:<序号>作为服务器IP加入Realms世界 - +mcc.generator.generating= +mcc.generator.done= [debug] # Messages from MCC Debug Mode @@ -61,7 +63,7 @@ debug.crypto=§8密钥和哈希值已生成: debug.request=§8正在请求{0} [error] -# Error messages from MCC +# Error messages from MCC error.ping=ping此IP失败。 error.unsupported=无法连接到服务器:不支持此版本! error.determine=无法确定服务器版本。 @@ -91,6 +93,8 @@ error.forge=§8Forge登录握手未成功完成 error.forge_encrypt=§8Forge StartEncryption握手未成功完成 error.setting.str2int=无法将'{0}'转换为一个整数。请检查设置。 error.setting.str2double=无法将'{0}'转换为一个浮点数。请检查设置。 +error.setting.str2locationList.convert_fail= +error.setting.str2locationList.format_err= error.setting.argument_syntax={0}:无效语法,应为 --argname=value 或 --section.argname=value error.setting.unknown_section={0}:未知设置部分'{1}' error.setting.unknown_or_invalid={0}:未知设置或无效值 @@ -101,6 +105,11 @@ error.realms.access_denied=此Realms世界不存在或访问被拒绝 error.realms.server_unavailable=Realms服务器可能需要一些时间来启动。请稍后再试。 error.realms.server_id=Realms服务器ID无效或未知。 error.realms.disabled=正在尝试加入Realms世界,但配置中禁用了Realms支持 +error.missing.argument= +error.usage= +error.generator.invalid= +error.generator.path= +error.generator.json= [internal command] # MCC internal help command @@ -203,6 +212,7 @@ chat.fail=§8下载文件失败。 chat.from_dir=§8默认为你的Minecraft目录中的en_GB.lang chat.loaded=§8已加载翻译文件。 chat.not_found=§8找不到翻译文件:'{0}'\n如果没有此文件,某些信息将无法正确打印。 +chat.message_chain_broken= [general] # General message/information (i.e. Done) @@ -218,12 +228,23 @@ general.available_cmd=可用命令:{0} # Animation cmd.animation.desc=挥动你的手臂。 +# Bots +cmd.bots.desc= +cmd.bots.list= +cmd.bots.notfound= +cmd.bots.noloaded= +cmd.bots.unloaded= +cmd.bots.unloaded_all= + # ChangeSlot cmd.changeSlot.desc=变更快捷栏栏位 cmd.changeSlot.nan=无法变更栏位:不是数字 cmd.changeSlot.changed=已变更为栏位{0} cmd.changeSlot.fail=无法变更栏位 +# Chunk +cmd.chunk.desc= + # Connect cmd.connect.desc=连接到指定的服务器。 cmd.connect.unknown=未知帐户 '{0}'。 @@ -265,6 +286,19 @@ cmd.entityCmd.distance=距离 cmd.entityCmd.location=位置 cmd.entityCmd.type=类型 +# Exec If +cmd.execif.desc= +cmd.execif.executed= +cmd.execif.executed_no_output= +cmd.execif.error_occured= +cmd.execif.error= + +# Exec Multi +cmd.execmulti.desc= +cmd.execmulti.executed= +cmd.execmulti.result= +cmd.execmulti.no_result= + # Exit cmd.exit.desc=断开与服务器的连接。 @@ -284,12 +318,15 @@ cmd.inventory.close_fail=关闭物品栏失败 #{0} cmd.inventory.not_exist=物品栏#{0}不存在 cmd.inventory.inventory=物品栏 cmd.inventory.inventories=物品栏集 +cmd.inventory.inventories_available= cmd.inventory.hotbar=您选择的快捷栏是{0} cmd.inventory.damage=武器伤害值 cmd.inventory.left=左 cmd.inventory.right=右 cmd.inventory.middle=中间 cmd.inventory.clicking={0}正在点击窗口#{2}中的栏位{1} +cmd.inventory.shiftclick= +cmd.inventory.shiftclick_fail= cmd.inventory.no_item=栏位#{0}中没有物品 cmd.inventory.drop=从栏位#{0}中丢弃了1个物品 cmd.inventory.drop_stack=从栏位#{0}中丢弃了所有堆叠的物品 @@ -301,12 +338,31 @@ cmd.inventory.help.usage=用法 cmd.inventory.help.list=列出你的物品栏。 cmd.inventory.help.close=关闭打开的容器。 cmd.inventory.help.click=单击物品。 +cmd.inventory.help.shiftclick= cmd.inventory.help.drop=从物品栏中丢弃物品。 cmd.inventory.help.creativegive=在创造模式中给予物品。 cmd.inventory.help.creativedelete=在创造性模式中清除栏位。 +cmd.inventory.help.inventories= +cmd.inventory.help.search= cmd.inventory.help.unknown=未知操作。 +cmd.inventory.found_items= +cmd.inventory.no_found_items= -# List 列表设置 +# Leave bed +cmd.bed.desc= +cmd.bed.leaving= +cmd.bed.trying_to_use= +cmd.bed.in= +cmd.bed.not_in= +cmd.bed.not_a_bed= +cmd.bed.searching= +cmd.bed.bed_not_found= +cmd.bed.found_a_bed_at= +cmd.bed.cant_reach_safely= +cmd.bed.moving= +cmd.bed.failed_to_reach_in_time= + +# List cmd.list.desc=获取玩家列表。 cmd.list.players=玩家列表:{0} @@ -332,10 +388,21 @@ cmd.move.fail=无法计算到达{0}的路径。 cmd.move.suggestforce=无法计算安全到达{0}的路径. 请使用 -f 参数允许不安全移动。 cmd.move.gravity.enabled=重力已开启。 cmd.move.gravity.disabled=重力已关闭。 +cmd.move.chunk_loading_status= +cmd.move.chunk_not_loaded= # Reco cmd.reco.desc=重新启动并重新连接到服务器。 +# Reload +cmd.reload.started= +cmd.reload.warning1= +cmd.reload.warning2= +cmd.reload.warning3= +cmd.reload.warning4= +cmd.reload.finished= +cmd.reload.desc= + # Respawn cmd.respawn.desc=如果你死亡了,请用这个来重生。 cmd.respawn.done=你重生了。 @@ -371,6 +438,7 @@ cmd.tps.current=当前TPS # Useblock cmd.useblock.desc=放置一个方块或打开箱子 +cmd.useblock.use= # Useitem cmd.useitem.desc=使用(左键单击)手上的物品 @@ -386,6 +454,14 @@ bot.alerts.end_rain=§c天气变化:雨停了。§r bot.alerts.start_thunderstorm=§c天气变化:现在是雷雨天。§r bot.alerts.end_thunderstorm=§c天气变化:现在不再是雷雨天了。§r +# Anti AFK +bot.antiafk.not_using_terrain_handling= +bot.antiafk.invalid_range_partial= +bot.antiafk.invalid_range= +bot.antiafk.invalid_value= +bot.antiafk.swapping= +bot.antiafk.invalid_walk_range= + # AutoAttack bot.autoAttack.mode=未知的攻击模式:{0},使用单一模式作为默认值。 bot.autoAttack.priority=未知优先模式:{0},使用距离优先作为默认值。 @@ -404,7 +480,7 @@ bot.autoCraft.help.load=加载配置文件。 bot.autoCraft.help.list=列出可用配方。 bot.autoCraft.help.reload=重新加载配置文件。 bot.autoCraft.help.resetcfg=将默认示例配置写入默认位置。 -bot.autoCraft.help.start=开始制作。用法:/autocraft start <配方名称> +bot.autoCraft.help.start=开始制作。用法:/autocraft start <配方名称> bot.autoCraft.help.stop=停止当前正在进行的制作过程 bot.autoCraft.help.help=获取命令描述。用法: /autocraft help <命令名> bot.autoCraft.loaded=已成功加载 @@ -426,6 +502,8 @@ bot.autoCraft.exception.name_miss=解析配方时缺少配方名称 bot.autoCraft.exception.slot=配方中的栏位字段无效:{0} bot.autoCraft.exception.duplicate=指定了重复的配方名称:{0} bot.autoCraft.debug.no_config=找不到配置。请新建一个。 +bot.autocraft.invaild_slots= +bot.autocraft.invaild_invaild_result= # AutoDrop bot.autoDrop.cmd=AutoDrop ChatBot命令 @@ -444,9 +522,17 @@ bot.autoDrop.no_mode=无法从配置中读取丢弃模式(drop mode)。使 bot.autoDrop.no_inventory=找不到物品栏{0}! # AutoFish +bot.autoFish.no_inv_handle= +bot.autoFish.start= bot.autoFish.throw=抛竿 bot.autoFish.caught=钓到鱼了! +bot.autoFish.caught_at= bot.autoFish.no_rod=手上没有鱼竿,可能用坏了? +bot.autoFish.despawn= +bot.autoFish.fishing_timeout= +bot.autoFish.cast_timeout= +bot.autoFish.update_lookat= +bot.autoFish.switch= # AutoRelog bot.autoRelog.launch=已启动,尝试了{0}次重新连接 @@ -474,7 +560,7 @@ bot.autoRespond.match=match: {0}\nregex: {1}\naction: {2}\nactionPrivate: {3}\na # ChatLog bot.chatLog.invalid_file=路径'{0}'包含无效字符。 -# Mailer +# Mailer bot.mailer.init=使用设置初始化Mailer: bot.mailer.init.db= - 数据库文件:{0} bot.mailer.init.ignore= - 忽略列表:{0} @@ -506,12 +592,43 @@ bot.mailer.cmd.ignore.removed={0}已从忽略列表中删除! bot.mailer.cmd.ignore.invalid=丢失或无效的名称。用法:{0}<用户名> bot.mailer.cmd.help=查看用法 +# Maps +bot.map.cmd.desc= +bot.map.cmd.not_found= +bot.map.cmd.invalid_id= +bot.map.received= +bot.map.no_maps= +bot.map.received_map= +bot.map.rendered= +bot.map.failed_to_render= +bot.map.list_item= + # ReplayCapture bot.replayCapture.cmd=replay 命令 bot.replayCapture.created=已创建重播文件。 bot.replayCapture.stopped=录制已停止。 bot.replayCapture.restart=录制已停止。请重新启动程序以进行另一段录制。 +# Follow player +cmd.follow.desc= +cmd.follow.usage= +cmd.follow.already_stopped= +cmd.follow.stopping= +cmd.follow.invalid_name= +cmd.follow.invalid_player= +cmd.follow.cant_reach_player= +cmd.follow.already_following= +cmd.follow.switched= +cmd.follow.started= +cmd.follow.unsafe_enabled= +cmd.follow.note= +cmd.follow.player_came_to_the_range= +cmd.follow.resuming= +cmd.follow.player_left_the_range= +cmd.follow.pausing= +cmd.follow.player_left= +cmd.follow.stopping= + # Script bot.script.not_found=§8[MCC] [{0}] 找不到脚本文件:{1} bot.script.file_not_found=找不到文件:'{0}' @@ -533,6 +650,7 @@ bot.scriptScheduler.task=triggeronfirstlogin: {0}\n triggeronlogin: {1}\n trigge bot.testBot.told=Bot:{0}对我说:{1} bot.testBot.said=Bot:{0}说:{1} + [config] config.load=已从 {0} 加载设置。 @@ -549,3 +667,202 @@ config.Main.General.account=Login请填写邮箱或玩家名称。若要以离 config.Main.General.login=游戏服务器的地址和端口,可填入域名或IP地址。(可删除端口字段,会自动解析SRV记录) config.Main.General.server_info=帐户类型:mojang 或是 microsoft。此项设置也会影响交互式登录。 config.Main.General.method=微软账户的登录方式:mcc 或是 browser(手动在网页上登录)。 + +# Main.Advanced +config.Main.Advanced= +config.Main.Advanced.language= +config.Main.Advanced.internal_cmd_char= +config.Main.Advanced.message_cooldown= +config.Main.Advanced.bot_owners= +config.Main.Advanced.mc_version= +config.Main.Advanced.mc_forge= +config.Main.Advanced.brand_info= +config.Main.Advanced.chatbot_log_file= +config.Main.Advanced.private_msgs_cmd_name= +config.Main.Advanced.show_system_messages= +config.Main.Advanced.show_xpbar_messages= +config.Main.Advanced.show_chat_links= +config.Main.Advanced.show_inventory_layout= +config.Main.Advanced.terrain_and_movements= +config.Main.Advanced.inventory_handling= +config.Main.Advanced.entity_handling= +config.Main.Advanced.session_cache= +config.Main.Advanced.profilekey_cache= +config.Main.Advanced.resolve_srv_records= +config.Main.Advanced.account_list= +config.Main.Advanced.server_list= +config.Main.Advanced.player_head_icon= +config.Main.Advanced.exit_on_failure= +config.Main.Advanced.script_cache= +config.Main.Advanced.timestamps= +config.Main.Advanced.auto_respawn= +config.Main.Advanced.minecraft_realms= +config.Main.Advanced.move_head_while_walking= +config.Main.Advanced.timeout= +config.Main.Advanced.enable_emoji= +config.Main.Advanced.movement_speed= +config.Main.Advanced.language.invaild= + +# Signature +config.Signature= +config.Signature.LoginWithSecureProfile= +config.Signature.SignChat= +config.Signature.SignMessageInCommand= +config.Signature.MarkLegallySignedMsg= +config.Signature.MarkModifiedMsg= +config.Signature.MarkIllegallySignedMsg= +config.Signature.MarkSystemMessage= +config.Signature.ShowModifiedChat= +config.Signature.ShowIllegalSignedChat= + +# Logging +config.Logging= +config.Logging.DebugMessages= +config.Logging.ChatMessages= +config.Logging.InfoMessages= +config.Logging.WarningMessages= +config.Logging.ErrorMessages= +config.Logging.ChatFilter= +config.Logging.DebugFilter= +config.Logging.FilterMode= +config.Logging.LogToFile= +config.Logging.LogFile= +config.Logging.PrependTimestamp= +config.Logging.SaveColorCodes= + +# AppVars +config.AppVars.Variables= + +# Proxy +config.Proxy= +config.Proxy.Enabled_Login= +config.Proxy.Enabled_Ingame= +config.Proxy.Server= +config.Proxy.Proxy_Type= +config.Proxy.Username= +config.Proxy.Password= + +# ChatFormat +config.ChatFormat= +config.ChatFormat.Builtins= +config.ChatFormat.UserDefined= + +# MCSettings +config.MCSettings= +config.MCSettings.Enabled= +config.MCSettings.Locale= +config.MCSettings.RenderDistance= +config.MCSettings.Difficulty= +config.MCSettings.ChatMode= +config.MCSettings.ChatColors= +config.MCSettings.MainHand= + +# ChatBot +config.ChatBot= + +# ChatBot.Alerts +config.ChatBot.Alerts= +config.ChatBot.Alerts.Beep_Enabled= +config.ChatBot.Alerts.Trigger_By_Words= +config.ChatBot.Alerts.Trigger_By_Rain= +config.ChatBot.Alerts.Trigger_By_Thunderstorm= +config.ChatBot.Alerts.Matches_File= +config.ChatBot.Alerts.Excludes_File= +config.ChatBot.Alerts.Log_To_File= +config.ChatBot.Alerts.Log_File= + +# ChatBot.AntiAFK +config.ChatBot.AntiAfk= +config.ChatBot.AntiAfk.Delay= +config.ChatBot.AntiAfk.Command= +config.ChatBot.AntiAfk.Use_Terrain_Handling= +config.ChatBot.AntiAfk.Walk_Range= +config.ChatBot.AntiAfk.Walk_Retries= + +# ChatBot.AutoAttack +config.ChatBot.AutoAttack= +config.ChatBot.AutoAttack.Mode= +config.ChatBot.AutoAttack.Priority= +config.ChatBot.AutoAttack.Cooldown_Time= +config.ChatBot.AutoAttack.Interaction= +config.ChatBot.AutoAttack.Attack_Hostile= +config.ChatBot.AutoAttack.Attack_Passive= +config.ChatBot.AutoAttack.List_Mode= +config.ChatBot.AutoAttack.Entites_List= + +# ChatBot.AutoCraft +config.ChatBot.AutoCraft= +config.ChatBot.AutoCraft.CraftingTable= +config.ChatBot.AutoCraft.OnFailure= +config.ChatBot.AutoCraft.Recipes= + +# ChatBot.AutoDrop +config.ChatBot.AutoDrop= +config.ChatBot.AutoDrop.Mode= + +# ChatBot.AutoEat +config.ChatBot.AutoEat= + +# ChatBot.AutoFishing +config.ChatBot.AutoFishing= +config.ChatBot.AutoFishing.Antidespawn= +config.ChatBot.AutoFishing.Mainhand= +config.ChatBot.AutoFishing.Auto_Start= +config.ChatBot.AutoFishing.Cast_Delay= +config.ChatBot.AutoFishing.Fishing_Delay= +config.ChatBot.AutoFishing.Fishing_Timeout= +config.ChatBot.AutoFishing.Durability_Limit= +config.ChatBot.AutoFishing.Auto_Rod_Switch= +config.ChatBot.AutoFishing.Stationary_Threshold= +config.ChatBot.AutoFishing.Hook_Threshold= +config.ChatBot.AutoFishing.Log_Fish_Bobber= +config.ChatBot.AutoFishing.Enable_Move= +config.ChatBot.AutoFishing.Movements= + +# ChatBot.AutoRelog +config.ChatBot.AutoRelog= +config.ChatBot.AutoRelog.Delay= +config.ChatBot.AutoRelog.Retries= +config.ChatBot.AutoRelog.Ignore_Kick_Message= +config.ChatBot.AutoRelog.Kick_Messages= + +# ChatBot.AutoRespond +config.ChatBot.AutoRespond= +config.ChatBot.AutoRespond.Match_Colors= + +# ChatBot.ChatLog +config.ChatBot.ChatLog= + +# ChatBot.FollowPlayer +config.ChatBot.FollowPlayer= +config.ChatBot.FollowPlayer.Update_Limit= +config.ChatBot.FollowPlayer.Stop_At_Distance= + +# ChatBot.HangmanGame +config.ChatBot.HangmanGame= + +# ChatBot.Mailer +config.ChatBot.Mailer= + +# ChatBot.Map +config.ChatBot.Map= +config.ChatBot.Map.Should_Resize= +config.ChatBot.Map.Resize_To= +config.ChatBot.Map.Auto_Render_On_Update= +config.ChatBot.Map.Delete_All_On_Unload= +config.ChatBot.Map.Notify_On_First_Update= + +# ChatBot.PlayerListLogger +config.ChatBot.PlayerListLogger= +config.ChatBot.PlayerListLogger.Delay= + +# ChatBot.RemoteControl +config.ChatBot.RemoteControl= + +# ChatBot.ReplayCapture +config.ChatBot.ReplayCapture= +config.ChatBot.ReplayCapture.Backup_Interval= + +# ChatBot.ScriptScheduler +config.ChatBot.ScriptScheduler= + diff --git a/MinecraftClient/Translations.cs b/MinecraftClient/Translations.cs index 3d79003e..8e257882 100644 --- a/MinecraftClient/Translations.cs +++ b/MinecraftClient/Translations.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Drawing.Drawing2D; using System.Globalization; using System.IO; using System.Text; @@ -632,19 +633,14 @@ namespace MinecraftClient foreach (string lineRaw in content) { string line = lineRaw.Trim(); - if (line.Length <= 0) + if (line.Length < 3) continue; - if (line.StartsWith("#")) // ignore comment line started with # - continue; - if (line[0] == '[' && line[^1] == ']') // ignore section + if (!char.IsLetterOrDigit(line[0])) // ignore comment line started with # continue; - string translationName = line.Split('=')[0]; - if (line.Length > (translationName.Length + 1)) - { - string translationValue = line[(translationName.Length + 1)..].Replace("\\n", "\n"); - translations[translationName] = translationValue; - } + int index = line.IndexOf('='); + if (line.Length > (index + 1)) + translations[line[..index]] = line[(index + 1)..].Replace("\\n", "\n"); } return translations; } @@ -657,12 +653,54 @@ namespace MinecraftClient string defaultPath = AppDomain.CurrentDomain.BaseDirectory + Path.DirectorySeparatorChar + translationFilePath + Path.DirectorySeparatorChar + defaultTranslation; if (!Directory.Exists(translationFilePath)) - { Directory.CreateDirectory(translationFilePath); - } File.WriteAllText(defaultPath, DefaultConfigResource.Translation_en, Encoding.UTF8); } + public static void TrimAllTranslations() + { + string[] transEn = DefaultConfigResource.ResourceManager.GetString("Translation_en")! + .Split(new[] { "\r\n", "\r", "\n" }, StringSplitOptions.None); + + foreach (string lang in new string[] { "de", "fr", "ru", "vi", "zh_Hans" }) + { + Dictionary trans = ParseTranslationContent( + DefaultConfigResource.ResourceManager.GetString("Translation_" + lang)! + .Split(new[] { "\r\n", "\r", "\n" }, StringSplitOptions.None) + ); + using FileStream file = File.OpenWrite(AppDomain.CurrentDomain.BaseDirectory + + Path.DirectorySeparatorChar + translationFilePath + Path.DirectorySeparatorChar + lang + ".ini"); + int total = 0, translated = 0; + for (int i = 0; i < transEn.Length; ++i) + { + string line = transEn[i].Trim(); + int index = transEn[i].IndexOf('='); + if (line.Length < 3 || !char.IsLetterOrDigit(line[0]) || index == -1 || line.Length <= (index + 1)) + { + file.Write(Encoding.UTF8.GetBytes(line)); + } + else + { + string key = line[..index]; + file.Write(Encoding.UTF8.GetBytes(key)); + file.Write(Encoding.UTF8.GetBytes("=")); + if (trans.TryGetValue(key, out string? value)) + { + file.Write(Encoding.UTF8.GetBytes(value.Replace("\n", "\\n"))); + ++total; + ++translated; + } + else + { + ++total; + } + } + file.Write(Encoding.UTF8.GetBytes(Environment.NewLine)); + } + ConsoleIO.WriteLine(string.Format("Language {0}: Translated {1} of {2}, {3:0.00}%", lang, translated, total, 100.0 * (double)translated / total)); + } + } + #region Console writing method wrapper /// diff --git a/README.md b/README.md index 39a969a7..dd59e00d 100644 --- a/README.md +++ b/README.md @@ -50,12 +50,12 @@ If you'd like to contribute to Minecraft Console Client, great, just fork the re Check out: [How to update or add translations for MCC](https://mccteam.github.io/guide/contibuting.html#translations). MCC now supports the following languages (Alphabetical order) : - * `de.ini` : Deutsch - German + * `de.ini` (57.69% translated) : Deutsch - German * `en.ini` : English - English - * `fr.ini` : Français (France) - French - * `ru.ini` : Русский (Russkiy) - Russian - * `vi.ini` : Tiếng Việt (Việt Nam) - Vietnamese - * `zh-Hans.ini` : 简体中文(中国大陆) - Chinese Simplified (China; Mandarin) + * `fr.ini` (57.69% translated) : Français (France) - French + * `ru.ini` (56.77% translated) : Русский (Russkiy) - Russian + * `vi.ini` (56.77% translated) : Tiếng Việt (Việt Nam) - Vietnamese + * `zh-Hans.ini` (62.56% translated) : 简体中文(中国大陆) - Chinese Simplified (China; Mandarin) ## Building from the source 🏗️