Switching to TOML

Refactoring Settings.cs & Switch to use TOML
This commit is contained in:
BruceChen 2022-10-06 22:28:14 +08:00 committed by GitHub
commit 453914a740
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
75 changed files with 5766 additions and 3168 deletions

View file

@ -1,5 +1,6 @@
using System;
using System.Linq;
using Tomlet.Attributes;
namespace MinecraftClient.ChatBots
{
@ -8,53 +9,103 @@ namespace MinecraftClient.ChatBots
/// </summary>
public class Alerts : ChatBot
{
private string[] dictionary = Array.Empty<string>();
private string[] excludelist = Array.Empty<string>();
private bool logToFile = false;
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.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()
{
Log_File ??= string.Empty;
if (!Enabled) return;
bool checkSuccessed = true;
if (Trigger_By_Words)
{
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(Log_File));
}
}
}
if (!checkSuccessed)
{
LogToConsole(BotName, Translations.TryGet("general.bot_unload"));
Enabled = false;
}
}
}
float curRainLevel = 0;
float curThunderLevel = 0;
const float threshold = 0.2f;
/// <summary>
/// Intitialize the Alerts bot
/// </summary>
public override void Initialize()
{
if (Settings.Alerts_Trigger_By_Words)
{
dictionary = LoadDistinctEntriesFromFile(Settings.Alerts_MatchesFile);
excludelist = LoadDistinctEntriesFromFile(Settings.Alerts_ExcludesFile);
logToFile = Settings.Alerts_File_Logging;
}
}
/// <summary>
/// Process text received from the server to display alerts
/// </summary>
/// <param name="text">Received text</param>
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();
//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 (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 +116,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 +128,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 +144,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 +156,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();
}

View file

@ -1,6 +1,6 @@
using System;
using System.Globalization;
using MinecraftClient.Mapping;
using Tomlet.Attributes;
namespace MinecraftClient.ChatBots
{
@ -10,94 +10,105 @@ 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(60);
[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;
[NonSerialized]
public int _DelayMin, _DelayMax;
public void OnSettingUpdate()
{
if (Walk_Range <= 0)
{
Walk_Range = 5;
LogToConsole(BotName, Translations.TryGet("bot.antiafk.invalid_walk_range"));
}
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)
{
(Delay.min, Delay.max) = (Delay.max, Delay.min);
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 double min, max;
public Range(int value)
{
min = max = value;
}
public Range(int min, int max)
{
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();
/// <summary>
/// This bot sends a /ping command every X seconds in order to stay non-afk.
/// </summary>
/// <param name="pingparam">Time amount between each ping (10 = 1s, 600 = 1 minute, etc.) Can be a range of numbers eg. 10-600</param>
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._DelayMin, Config._DelayMax))
{
DoAntiAfkStuff();
count = 0;
@ -107,7 +118,7 @@ namespace MinecraftClient.ChatBots
private void DoAntiAfkStuff()
{
if (useTerrainHandling)
if (Config.Use_Terrain_Handling && GetTerrainEnabled())
{
Location currentLocation = GetCurrentLocation();
Location goal;
@ -118,19 +129,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 +162,7 @@ namespace MinecraftClient.ChatBots
}
}
SendText(Settings.AntiAFK_Command);
SendText(Config.Command);
Sneak(previousSneakState);
previousSneakState = !previousSneakState;
count = 0;

View file

@ -1,15 +1,89 @@
using System;
using System.Collections.Generic;
using System.IO;
using MinecraftClient.Mapping;
using Tomlet.Attributes;
namespace MinecraftClient.ChatBots
{
/// <summary>
/// The AutoAttack bot will automatically attack any hostile mob close to the player
/// </summary>
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<EntityType> 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<int, Entity> entitiesToAttack = new(); // mobs within attack range
private int attackCooldown = 6;
private int attackCooldownCounter = 6;
@ -19,73 +93,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<EntityType> 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 +129,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 +163,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 +175,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 +227,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;

View file

@ -1,14 +1,141 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using MinecraftClient.Inventory;
using MinecraftClient.Mapping;
using Tomlet.Attributes;
using static MinecraftClient.ChatBots.AutoCraft.Configs;
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;
[TomlInlineComment("$config.ChatBot.AutoCraft.CraftingTable$")]
public LocationConfig CraftingTable = new(123, 65, 456);
[TomlInlineComment("$config.ChatBot.AutoCraft.OnFailure$")]
public OnFailConfig OnFailure = 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()
{
_Table_Location = new Location(CraftingTable.X, CraftingTable.Y, CraftingTable.Z).ToFloor();
List<string> nameList = new();
foreach (RecipeConfig recipe in Recipes)
{
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)
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;
private bool waitingForUpdate = false;
private bool waitingForTable = false;
@ -18,19 +145,12 @@ namespace MinecraftClient.ChatBots
private Recipe? recipeInUse;
private readonly List<ActionStep> 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 readonly string configPath = @"autocraft\config.ini";
private string lastRecipe = ""; // Used in parsing recipe config
private readonly Dictionary<string, Recipe> recipes = new();
private void ResetVar()
{
craftingFailed = false;
@ -158,11 +278,6 @@ namespace MinecraftClient.ChatBots
}
}
public AutoCraft(string configPath = @"autocraft\config.ini")
{
this.configPath = configPath;
}
public override void Initialize()
{
if (!GetInventoryEnabled())
@ -174,7 +289,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)
@ -183,32 +297,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");
@ -243,220 +362,6 @@ namespace MinecraftClient.ChatBots
};
}
#region Config handling
public void LoadConfig()
{
if (!File.Exists(configPath))
{
if (!Directory.Exists(configPath))
{
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(configPath, content);
}
private void ParseConfig()
{
string[] content = File.ReadAllLines(configPath);
if (content.Length <= 0)
{
throw new Exception(Translations.Get("bot.autoCraft.exception.empty", configPath));
}
if (content[0].ToLower() != "[autocraft]")
{
throw new Exception(Translations.Get("bot.autoCraft.exception.invalid", configPath));
}
// local variable for use in parsing config
string section = "";
Dictionary<string, Recipe> 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<int, ItemType>? materials = recipes[lastRecipe].Materials;
if (materials != null && materials.Count > 0)
{
materials.Add(slot, itemType);
}
else
{
recipes[lastRecipe].Materials = new Dictionary<int, ItemType>()
{
{ 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)
@ -525,9 +430,19 @@ namespace MinecraftClient.ChatBots
/// Prepare the crafting action steps by the given recipe name and start crafting
/// </summary>
/// <param name="recipe">Name of the recipe to craft</param>
private void PrepareCrafting(string name)
private void PrepareCrafting(RecipeConfig recipeConfig)
{
PrepareCrafting(recipes[name]);
Dictionary<int, ItemType> 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));
}
/// <summary>
@ -548,7 +463,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;
@ -698,7 +613,7 @@ namespace MinecraftClient.ChatBots
// Inform user the missing meterial name
LogToConsoleTranslated("bot.autoCraft.missing_material", actionSteps[index - 1].ItemType.ToString());
}
if (abortOnFailure)
if (Config.OnFailure == OnFailConfig.abort)
{
StopCrafting();
LogToConsoleTranslated("bot.autoCraft.aborted");

View file

@ -2,51 +2,42 @@
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;
public List<ItemType> 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<ItemType> 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();
}
/// <summary>
/// Convert an item type string to item type array
/// </summary>
/// <param name="itemList">String to convert</param>
/// <returns>Item type array</returns>
private ItemType[] ItemListParser(string itemList)
{
string trimed = new(itemList.Where(c => !char.IsWhiteSpace(c)).ToArray());
List<ItemType> 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 +45,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 +74,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 +94,9 @@ namespace MinecraftClient.ChatBots
return Translations.Get("cmd.inventory.help.usage") + ": remove <item name>";
}
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 +108,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 +169,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 +190,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);

View file

@ -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)

View file

@ -1,6 +1,8 @@
using System;
using MinecraftClient.Inventory;
using MinecraftClient.Mapping;
using Tomlet.Attributes;
using static MinecraftClient.ChatBots.AutoFishing.Configs;
namespace MinecraftClient.ChatBots
{
@ -8,8 +10,130 @@ 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.
/// </summary>
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.Enable_Move$")]
public bool Enable_Move = false;
[TomlPrecedingComment("$config.ChatBot.AutoFishing.Movements$")]
public LocationConfig[] Movements = new LocationConfig[]
{
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),
};
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(double yaw, double 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, double yaw, double 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 double yaw, pitch;
public Facing(double yaw, double pitch)
{
this.yaw = yaw; this.pitch = pitch;
}
}
}
}
private int fishCount = 0;
private bool inventoryEnabled;
private int castTimeout = 12;
@ -54,9 +178,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 +208,7 @@ namespace MinecraftClient.ChatBots
private void UseFishRod()
{
if (Settings.AutoFishing_Mainhand)
if (Config.Mainhand)
UseItemInHand();
else
UseItemInLeftHand();
@ -100,7 +224,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 +240,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.Enable_Move && Config.Movements.Length > 0)
{
if (GetTerrainEnabled())
{
UpdateLocation(locationList);
UpdateLocation(Config.Movements);
state = FishingState.WaitingMovement;
}
else
@ -148,7 +271,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 +290,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 +304,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 +325,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 +356,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 +406,7 @@ namespace MinecraftClient.ChatBots
public void OnCaughtFish()
{
++fishCount;
if (Settings.AutoFishing_Location != null)
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
@ -298,47 +421,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) = ((float)curConfig.facing.Value.yaw, (float)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 +459,7 @@ namespace MinecraftClient.ChatBots
if (!isMoveSuccessed)
{
nextYaw = GetYaw();
nextPitch = GetPitch();
(nextYaw, nextPitch) = (GetYaw(), GetPitch());
LogToConsole(Translations.Get("cmd.move.fail", goal));
}
else
@ -365,13 +476,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 +492,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);

View file

@ -1,5 +1,5 @@
using System;
using System.Text;
using Tomlet.Attributes;
namespace MinecraftClient.ChatBots
{
@ -8,11 +8,71 @@ namespace MinecraftClient.ChatBots
/// </summary>
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(3);
[TomlInlineComment("$config.ChatBot.AutoRelog.Retries$")]
public int Retries = 3;
[TomlInlineComment("$config.ChatBot.AutoRelog.Ignore_Kick_Message$")]
public bool Ignore_Kick_Message = false;
[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(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;
if (Enabled)
for (int i = 0; i < Kick_Messages.Length; i++)
Kick_Messages[i] = Kick_Messages[i].ToLower();
}
public struct Range
{
public double min, max;
public Range(int value)
{
min = max = value;
}
public Range(int min, int max)
{
this.min = min;
this.max = max;
}
}
}
private static readonly Random random = new();
private string[] dictionary = Array.Empty<string>();
private readonly int attempts;
private readonly int delayMin;
private readonly int delayMax;
/// <summary>
/// This bot automatically re-join the server if kick message contains predefined string
@ -20,48 +80,18 @@ namespace MinecraftClient.ChatBots
/// <param name="DelayBeforeRelogMin">Minimum delay before re-joining the server (in seconds)</param>
/// <param name="DelayBeforeRelogMax">Maximum delay before re-joining the server (in seconds)</param>
/// <param name="retries">Number of retries if connection fails (-1 = infinite)</param>
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))
{
LogDebugToConsoleTranslated("bot.autoRelog.loading", System.IO.Path.GetFullPath(Settings.AutoRelog_KickMessagesFile));
dictionary = System.IO.File.ReadAllLines(Settings.AutoRelog_KickMessagesFile, 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(Settings.AutoRelog_KickMessagesFile));
LogDebugToConsoleTranslated("bot.autoRelog.curr_dir", System.IO.Directory.GetCurrentDirectory());
}
}
}
public override bool OnDisconnect(DisconnectReason reason, string message)
@ -77,13 +107,13 @@ namespace MinecraftClient.ChatBots
LogDebugToConsoleTranslated("bot.autoRelog.disconnect_msg", message);
if (Settings.AutoRelog_IgnoreKickMessage)
if (Config.Ignore_Kick_Message)
{
LaunchDelayedReconnection(null);
return true;
}
foreach (string msg in dictionary)
foreach (string msg in Config.Kick_Messages)
{
if (comp.Contains(msg))
{
@ -100,7 +130,7 @@ namespace MinecraftClient.ChatBots
private void LaunchDelayedReconnection(string? msg)
{
int delay = random.Next(delayMin, delayMax);
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);
@ -109,9 +139,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);
}

View file

@ -1,31 +1,52 @@
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
{
/// <summary>
/// This bot automatically runs actions when a user sends a message matching a specified rule
/// </summary>
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()
{
Matches_File ??= string.Empty;
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<RespondRule>? respondRules;
private enum MessageType { Public, Private, Other };
/// <summary>
/// Create a new AutoRespond bot
/// </summary>
/// <param name="matchesFile">INI File to load matches from</param>
public AutoRespond(string matchesFile, bool matchColors)
{
this.matchesFile = matchesFile;
this.matchColors = matchColors;
}
/// <summary>
/// Describe a respond rule based on a simple match or a regex
/// </summary>
@ -96,7 +117,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 +185,7 @@ namespace MinecraftClient.ChatBots
/// </summary>
public override void Initialize()
{
if (File.Exists(matchesFile))
if (File.Exists(Config.Matches_File))
{
Regex? matchRegex = null;
string? matchString = null;
@ -175,9 +196,9 @@ namespace MinecraftClient.ChatBots
TimeSpan cooldown = TimeSpan.Zero;
respondRules = new List<RespondRule>();
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 +232,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 +243,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 +285,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 +298,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!)
{

View file

@ -1,5 +1,6 @@
using System;
using System.IO;
using Tomlet.Attributes;
namespace MinecraftClient.ChatBots
{
@ -9,13 +10,44 @@ 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()
{
Log_File ??= string.Empty;
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();
/// <summary>
@ -25,59 +57,42 @@ namespace MinecraftClient.ChatBots
/// <param name="filter">The kind of messages to save</param>
/// <param name="AddDateAndTime">Add a date and time before each message</param>
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 +125,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);

View file

@ -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 double Update_Limit = 1;
[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 < (int)(Config.Update_Limit * 10))
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);

View file

@ -1,5 +1,6 @@
using System;
using System.Text;
using Tomlet.Attributes;
namespace MinecraftClient.ChatBots
{
@ -9,26 +10,37 @@ 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()
{
FileWords_EN ??= string.Empty;
FileWords_FR ??= string.Empty;
}
}
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<bool>();
private string word = "";
private string letters = "";
private readonly bool English;
/// <summary>
/// Le jeu du Pendu / Hangman Game
/// </summary>
/// <param name="english">if true, the game will be in english. If false, the game will be in french.</param>
public HangmanGame(bool english)
{
English = english;
discovered = Array.Empty<bool>();
}
public override void Update()
{
@ -40,8 +52,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 +67,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 +93,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 +103,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 +144,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";
}
}

View file

@ -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,63 @@ namespace MinecraftClient.ChatBots
/// </summary>
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()
{
DatabaseFile ??= string.Empty;
IgnoreListFile ??= string.Empty;
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;
}
}
}
/// <summary>
/// Holds the list of ignored players
/// </summary>
@ -161,58 +219,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 <getmails|addignored|getignored|removeignored>", ProcessInternalCommand);
}
@ -224,7 +261,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
}
/// <summary>
@ -236,7 +273,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 +284,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<string> args = new(Command.GetArgs(message));
if (args.Count >= 2)
@ -266,7 +303,7 @@ namespace MinecraftClient.ChatBots
lock (readWriteLock)
{
mailDatabase.Add(mail);
mailDatabase.SaveToFile(Settings.Mailer_DatabaseFile);
mailDatabase.SaveToFile(Config.DatabaseFile);
}
SendPrivateMessage(username, "Message saved!");
}
@ -307,8 +344,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 +361,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 +394,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 +406,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]);

View file

@ -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<int, McMap> 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 <id> or maps l|r <id>", 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));

View file

@ -1,6 +1,6 @@
using System;
using System.Linq;
using System.Text;
using Tomlet.Attributes;
namespace MinecraftClient.ChatBots
{
@ -10,28 +10,36 @@ namespace MinecraftClient.ChatBots
public class PlayerListLogger : ChatBot
{
private int count;
private readonly int timeping;
private readonly string file;
public static Configs Config = new();
/// <summary>
/// This bot sends a /list command every X seconds and save the result.
/// </summary>
/// <param name="pingparam">Time amount between each list ping (10 = 1s, 600 = 1 minute, etc.)</param>
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 double Delay = 60;
public void OnSettingUpdate()
{
File ??= string.Empty;
if (Delay < 1.0)
Delay = 1.0;
}
}
private int count = 0;
public override void Update()
{
count++;
if (count == timeping)
if (count == (int)(Config.Delay * 10))
{
DateTime now = DateTime.Now;
@ -40,7 +48,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;
}

View file

@ -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");
}

View file

@ -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
/// </summary>
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 <save|stop>", 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--;
}

View file

@ -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())
{

View file

@ -1,7 +1,6 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Text;
using Tomlet.Attributes;
using static MinecraftClient.ChatBots.ScriptScheduler.Configs;
namespace MinecraftClient.ChatBots
{
@ -11,143 +10,164 @@ namespace MinecraftClient.ChatBots
public class ScriptScheduler : ChatBot
{
private class TaskDesc
public static Configs Config = new();
[TomlDoNotInlineObject]
public class Configs
{
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<DateTime> triggerOnTime_Times = new();
public bool triggerOnTime_alreadyTriggered = false;
}
[NonSerialized]
private const string BotName = "ScriptScheduler";
private static bool firstlogin_done = false;
public bool Enabled = false;
private readonly string tasksfile;
private bool serverlogin_done;
private readonly List<TaskDesc> tasks = new();
private int verifytasks_timeleft = 10;
private readonly int verifytasks_delay = 10;
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<TimeSpan>() ),
Trigger_On_Interval: new(false, 1, 10),
Action: "send /login pass"
),
};
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))
public void OnSettingUpdate()
{
LogDebugToConsoleTranslated("bot.scriptScheduler.loading", System.IO.Path.GetFullPath(tasksfile));
TaskDesc? current_task = null;
string[] lines = System.IO.File.ReadAllLines(tasksfile, Encoding.UTF8);
foreach (string lineRAW in lines)
foreach (TaskConfig task in TaskList)
{
string line = lineRAW.Split('#')[0].Trim();
if (line.Length > 0)
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))
{
if (line[0] == '[' && line[^1] == ']')
//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))
{
switch (line[1..^1].ToLower())
{
case "task":
CheckAddTask(current_task);
current_task = new TaskDesc(); //Create a blank task
break;
}
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 (current_task != null)
else
{
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 = 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 "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;
}
}
if (Settings.Config.Logging.DebugMessages)
LogToConsole(BotName, Translations.TryGet("bot.scriptScheduler.no_trigger", Task2String(task)));
}
}
}
CheckAddTask(current_task);
}
else
{
LogToConsoleTranslated("bot.scriptScheduler.not_found", System.IO.Path.GetFullPath(tasksfile));
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));
task.Action ??= string.Empty;
if (Settings.Config.Logging.DebugMessages)
LogToConsole(BotName, Translations.TryGet("bot.scriptScheduler.no_action", Task2String(task)));
}
}
else
if (Enabled && TaskList.Length == 0)
{
LogDebugToConsoleTranslated("bot.scriptScheduler.no_action", Task2String(current_task));
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 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;
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;
MinTime = MaxTime = value;
}
public TriggerOnIntervalConfig(bool Enable, int value)
{
this.Enable = Enable;
MinTime = MaxTime = value;
}
public TriggerOnIntervalConfig(int min, int max)
{
this.MinTime = min;
this.MaxTime = max;
}
public TriggerOnIntervalConfig(bool Enable, int min, int max)
{
this.Enable = Enable;
this.MinTime = min;
this.MaxTime = max;
}
}
}
}
private Random random = new();
private static bool firstlogin_done = false;
private bool serverlogin_done = false;
private int verifytasks_timeleft = 10;
private readonly int verifytasks_delay = 10;
public override void Update()
{
if (verifytasks_timeleft <= 0)
@ -155,55 +175,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);
}
}
@ -220,17 +235,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
);
}
}

View file

@ -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

View file

@ -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 "";

View file

@ -11,11 +11,10 @@ namespace MinecraftClient.Commands
public override string Run(McClient handler, string command, Dictionary<string, object>? 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");
}
}
}

View file

@ -36,7 +36,7 @@ namespace MinecraftClient.Commands
var interpreter = new Interpreter();
interpreter.SetVariable("MCC", handler);
foreach (KeyValuePair<string, object> entry in Settings.GetVariables())
foreach (KeyValuePair<string, object> entry in Settings.Config.AppVar.GetVariables())
interpreter.SetVariable(entry.Key, entry.Value);
var result = interpreter.Eval<bool>(expressionText);

View file

@ -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;

View file

@ -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");
}

View file

@ -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]);
}

View file

@ -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();
}
}
}

View file

@ -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<string> 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");
}

View file

@ -8,11 +8,10 @@
// </auto-generated>
//------------------------------------------------------------------------------
namespace MinecraftClient
{
namespace MinecraftClient {
using System;
/// <summary>
/// A strongly-typed resource class, for looking up localized strings, etc.
/// </summary>
@ -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
{
internal 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() {
}
/// <summary>
/// Returns the cached ResourceManager instance used by this class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
public static global::System.Resources.ResourceManager ResourceManager
{
get
{
if (object.ReferenceEquals(resourceMan, null))
{
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);
resourceMan = temp;
}
return resourceMan;
}
}
/// <summary>
/// Overrides the current thread's CurrentUICulture property for all
/// resource lookups using this strongly typed resource class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
public static global::System.Globalization.CultureInfo Culture
{
get
{
internal static global::System.Globalization.CultureInfo Culture {
get {
return resourceCulture;
}
set
{
set {
resourceCulture = value;
}
}
/// <summary>
/// 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]&quot;;.
///║╠═══╬═══╬═══╬═══╬══ [rest of string was truncated]&quot;;.
/// </summary>
public static string ContainerType_BrewingStand
{
get
{
internal static string ContainerType_BrewingStand {
get {
return ResourceManager.GetString("ContainerType_BrewingStand", resourceCulture);
}
}
/// <summary>
/// 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]&quot;;.
///║╠═══╬═══╬═══╬═══╬══ [rest of string was truncated]&quot;;.
/// </summary>
public static string ContainerType_Crafting
{
get
{
internal static string ContainerType_Crafting {
get {
return ResourceManager.GetString("ContainerType_Crafting", resourceCulture);
}
}
public static string ContainerType_Furnace
{
get
{
/// <summary>
/// Looks up a localized string similar to ╔═════════════════════════════════════╗
///║ Container ║
///║ ╔═══╗ ║
///║ ║ 0 ║ ║
///║ ╚═══╝ ╔═══╗ ║
///║ ⠂⡠⢂ ━━▶ ║ 2 ║ ║
///║ ⠂⡠⢂ ╚═══╝ ║
///║ ╔═══╗ ║
///║ ║ 1 ║ ║
///║ ╚═══╝ ║
///║ Inventory ║
///║╔═══╦═══╦═══╦═══╦═══╦═══╦═══╦═══╦═══╗║
///║║ 3 ║ 4 ║ 5 ║ 6 ║ 7 [rest of string was truncated]&quot;;.
/// </summary>
internal static string ContainerType_Furnace {
get {
return ResourceManager.GetString("ContainerType_Furnace", resourceCulture);
}
}
/// <summary>
/// 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]&quot;;.
///║╠═══╬═══╬═══╬═══╬══ [rest of string was truncated]&quot;;.
/// </summary>
public static string ContainerType_Generic_3x3
{
get
{
internal static string ContainerType_Generic_3x3 {
get {
return ResourceManager.GetString("ContainerType_Generic_3x3", resourceCulture);
}
}
/// <summary>
/// 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]&quot;;.
///║╠═══╬═══╬═══╬═══╬══ [rest of string was truncated]&quot;;.
/// </summary>
public static string ContainerType_Generic_9x3
{
get
{
internal static string ContainerType_Generic_9x3 {
get {
return ResourceManager.GetString("ContainerType_Generic_9x3", resourceCulture);
}
}
/// <summary>
/// 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]&quot;;.
///║╠═══╬═══╬═══╬═══╬══ [rest of string was truncated]&quot;;.
/// </summary>
public static string ContainerType_Generic_9x6
{
get
{
internal static string ContainerType_Generic_9x6 {
get {
return ResourceManager.GetString("ContainerType_Generic_9x6", resourceCulture);
}
}
public static string ContainerType_Grindstone
{
get
{
/// <summary>
/// Looks up a localized string similar to ╔═════════════════════════════════════╗
///║ Repair &amp; Disenchant ║
///║ ╔═════════╗ ║
///║ ║ ╔═══╗ ║ ║
///║ ╔══║ ║ 0 ║ ║══╗ ║
///║ ║ ║ ╚═══╝ ║ ║ ║
///║ ║ ║ ╔═══╗ ║ ║ ╔═══╗ ║
///║ ║ ║ ║ 1 ║ ║ ║ ━━▶ ║ 2 ║ ║
///║ ║ ║ ╚═══╝ ║ ║ ╚═══╝ ║
///║ ║ ╠═════════╣ ║ ║
///║ ║ ║ ║ ║ ║
///║ ╚══╝ ╚══╝ ║
///║ [rest of string was truncated]&quot;;.
/// </summary>
internal static string ContainerType_Grindstone {
get {
return ResourceManager.GetString("ContainerType_Grindstone", resourceCulture);
}
}
public static string ContainerType_Hopper
{
get
{
/// <summary>
/// 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]&quot;;.
/// </summary>
internal static string ContainerType_Hopper {
get {
return ResourceManager.GetString("ContainerType_Hopper", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to ╔═════════════════════════════════════╗
///║╔═══╦═══════════╗ ║
@ -221,66 +241,138 @@ namespace MinecraftClient
///║╚═══╩═══════════╩═══╝ ║
///║╔═══╦═══╦═══╦═══╦═══╦═══╦═══╦═══╦═══╗║
///║║ 9 ║10 ║11 ║12 ║13 ║14 ║15 ║16 ║17 ║║
///║╠═══╬═══╬═══╬═══╬═══╬═══╬═══╬══ [rest of string was truncated]&quot;;.
///║╠═══╬═══╬═══╬═══╬══ [rest of string was truncated]&quot;;.
/// </summary>
public static string ContainerType_PlayerInventory
{
get
{
internal static string ContainerType_PlayerInventory {
get {
return ResourceManager.GetString("ContainerType_PlayerInventory", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to # Startup Config File
///
///[Main]
///
///# General settings
///# Leave blank to prompt user on startup
///# Use &quot;-&quot; 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 &apos;none&apos;, &apos;slash&apos; or &apos;backslash&apos;
///messagec [rest of string was truncated]&quot;;.
/// </summary>
public static string MinecraftClient
{
get
{
return ResourceManager.GetString("MinecraftClient", resourceCulture);
}
}
/// <summary>
/// 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]&quot;;.
/// </summary>
internal static string Translation_de {
get {
return ResourceManager.GetString("Translation_de", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to [mcc]
///# Messages from MCC itself
///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 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]&quot;;.
///mcc.offline=§8Yo [rest of string was truncated]&quot;;.
/// </summary>
public static string TranslationEnglish
{
get
{
return ResourceManager.GetString("TranslationEnglish", resourceCulture);
internal static string Translation_en {
get {
return ResourceManager.GetString("Translation_en", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to [mcc]
///# Messages from MCC itself
///mcc.login=Connexion :
///mcc.login_basic_io=Veuillez saisir un nom d&apos;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&apos;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]&quot;;.
/// </summary>
internal static string Translation_fr {
get {
return ResourceManager.GetString("Translation_fr", resourceCulture);
}
}
/// <summary>
/// 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]&quot;;.
/// </summary>
internal static string Translation_ru {
get {
return ResourceManager.GetString("Translation_ru", resourceCulture);
}
}
/// <summary>
/// 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]&quot;;.
/// </summary>
internal static string Translation_vi {
get {
return ResourceManager.GetString("Translation_vi", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to [mcc]
///# Messages from MCC itself
///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.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]&quot;;.
/// </summary>
internal static string Translation_zh_Hans {
get {
return ResourceManager.GetString("Translation_zh_Hans", resourceCulture);
}
}
}

View file

@ -145,10 +145,22 @@
<data name="ContainerType_PlayerInventory" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>Resources\containers\ContainerType.PlayerInventory.txt;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8</value>
</data>
<data name="MinecraftClient" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>Resources\config\MinecraftClient.ini;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8</value>
<data name="Translation_de" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>resources\lang\de.ini;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8</value>
</data>
<data name="TranslationEnglish" type="System.Resources.ResXFileRef, System.Windows.Forms">
<data name="Translation_en" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>Resources\lang\en.ini;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8</value>
</data>
<data name="Translation_fr" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>resources\lang\fr.ini;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8</value>
</data>
<data name="Translation_ru" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>resources\lang\ru.ini;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8</value>
</data>
<data name="Translation_vi" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>resources\lang\vi.ini;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8</value>
</data>
<data name="Translation_zh_Hans" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>resources\lang\zh-hans.ini;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8</value>
</data>
</root>

View file

@ -22,7 +22,7 @@ namespace MinecraftClient
/// <param name="handler">Callback for file changes</param>
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));

View file

@ -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
{

View file

@ -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;

View file

@ -1,4 +1,5 @@
using System.Text.RegularExpressions;
using static MinecraftClient.Settings;
namespace MinecraftClient.Logger
{
@ -8,19 +9,38 @@ 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 = Settings.FilterMode == Settings.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)
{
// 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;
}

View file

@ -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);
}
/// <summary>
/// Compare two locations. Locations are not equals if the integer part of their coordinates are not equals.
/// </summary>
@ -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);
}
/// <summary>
/// Sums two locations and returns the result.
/// </summary>

View file

@ -21,7 +21,7 @@ namespace MinecraftClient.Mapping
/// <returns>Updated location after applying gravity</returns>
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);

View file

@ -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
{

View file

@ -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
/// <param name="port">The server port to use</param>
/// <param name="protocolversion">Minecraft protocol version to use</param>
/// <param name="forgeInfo">ForgeInfo item stating that Forge is enabled</param>
/// <param name="command">The text or command to send. Will only be sent if singlecommand is set to true.</param>
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
/// </summary>
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;
@ -471,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;
}
@ -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 = "";
}
/// <summary>
@ -2395,18 +2375,19 @@ namespace MinecraftClient
/// </summary>
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());
}

View file

@ -36,9 +36,10 @@
<PackageReference Include="DnsClient" Version="1.6.1" />
<PackageReference Include="DotNetZip" Version="1.16.0" />
<PackageReference Include="DynamicExpresso.Core" Version="2.13.0" />
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="4.3.0" />
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="4.3.1" />
<PackageReference Include="Microsoft.CSharp" Version="4.7.0" />
<PackageReference Include="Microsoft.Windows.Compatibility" Version="5.0.2" />
<PackageReference Include="Microsoft.Windows.Compatibility" Version="6.0.0" />
<PackageReference Include="Samboy063.Tomlet" Version="5.0.0" />
<PackageReference Include="SingleFileExtractor.Core" Version="1.0.1" />
<PackageReference Include="starksoft.aspen" Version="1.1.8">
<NoWarn>NU1701</NoWarn>
@ -72,4 +73,9 @@
<ItemGroup>
<ProjectReference Include="..\ConsoleInteractive\ConsoleInteractive\ConsoleInteractive\ConsoleInteractive.csproj" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Update="DefaultConfigResource.resx">
<Generator></Generator>
</EmbeddedResource>
</ItemGroup>
</Project>

View file

@ -3,9 +3,11 @@ 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;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
using MinecraftClient.Inventory.ItemPalettes;
@ -16,6 +18,10 @@ using MinecraftClient.Protocol.Handlers.Forge;
using MinecraftClient.Protocol.Keys;
using MinecraftClient.Protocol.Session;
using MinecraftClient.WinAPI;
using Tomlet;
using static MinecraftClient.Settings;
using static MinecraftClient.Settings.MainConfigHealper.MainConfig.AdvancedConfig;
using static MinecraftClient.Settings.MainConfigHealper.MainConfig.GeneralConfig;
namespace MinecraftClient
{
@ -45,15 +51,18 @@ namespace MinecraftClient
private static Tuple<Thread, CancellationTokenSource>? offlinePrompt = null;
private static bool useMcVersionOnce = false;
private static string? settingsIniPath = null;
private static string settingsIniPath = "MinecraftClient.ini";
/// <summary>
/// The main entry point of Minecraft Console Client
/// </summary>
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))
{
@ -69,10 +78,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] ";
@ -104,12 +110,11 @@ 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;
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 +122,41 @@ 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;
WriteBackSettings(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.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
if (args.Length >= 1)
@ -140,6 +172,12 @@ namespace MinecraftClient
return;
}
if (args.Contains("--trim-translation"))
{
Translations.TrimAllTranslations();
return;
}
if (args.Contains("--generate"))
{
string dataGenerator = "";
@ -222,55 +260,92 @@ namespace MinecraftClient
}
catch (ArgumentException e)
{
Settings.interactiveMode = false;
InternalConfig.InteractiveMode = false;
HandleFailure(e.Message);
return;
}
}
if (Settings.ConsoleTitle != "")
// Check for updates
Task.Run(() =>
{
Settings.Username = "New Window";
Console.Title = Settings.ExpandVars(Settings.ConsoleTitle);
HttpClientHandler httpClientHandler = new() { AllowAutoRedirect = false };
HttpClient httpClient = new(httpClientHandler);
Task<HttpResponseMessage>? 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";
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)
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))))
{
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 +356,10 @@ namespace MinecraftClient
/// </summary>
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;
}
/// <summary>
@ -292,23 +367,25 @@ namespace MinecraftClient
/// </summary>
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 = InternalConfig.Username;
}
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 +407,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,30 +416,30 @@ 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 && 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 && Settings.SessionCaching != CacheType.None)
SessionCache.Store(loginLower, session);
if (result == ProtocolHandler.LoginResult.Success)
session.SessionPreCheckTask = Task.Factory.StartNew(() => session.SessionPreCheck());
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 +452,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<string> 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 +493,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 +518,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 +556,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 +576,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)
{
@ -542,8 +618,16 @@ namespace MinecraftClient
/// </summary>
public static void ReloadSettings()
{
if (settingsIniPath != null)
Settings.LoadFile(settingsIniPath);
if(Settings.LoadFromFile(settingsIniPath))
ConsoleIO.WriteLine(Translations.TryGet("config.loading", settingsIniPath));
}
/// <summary>
/// Write-back settings
/// </summary>
public static void WriteBackSettings(bool enableBackup = true)
{
Settings.WriteToFile(settingsIniPath, enableBackup);
}
/// <summary>
@ -563,22 +647,28 @@ namespace MinecraftClient
System.Threading.Thread.Sleep(delaySeconds * 1000);
}
Translations.WriteLine("mcc.restart");
ReloadSettings();
InitializeClient();
})).Start();
}
public static void DoExit(int exitcode = 0)
{
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(); }
Environment.Exit(exitcode);
}
/// <summary>
/// Disconnect the current client from the server and exit the app
/// </summary>
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();
}
/// <summary>
@ -595,7 +685,7 @@ namespace MinecraftClient
ConsoleIO.Reset();
while (Console.KeyAvailable)
Console.ReadKey(true);
Console.WriteLine(errorMessage);
ConsoleIO.WriteLine(errorMessage);
if (disconnectReason.HasValue)
{
@ -604,13 +694,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 +717,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 +736,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 +751,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 +760,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);
}
}

View file

@ -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;
}

View file

@ -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;

View file

@ -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
/// <returns> List< Argument Name, Argument Value > </returns>
private List<Tuple<string, string>>? CollectCommandArguments(string command)
{
if (!isOnlineMode || !Settings.SignMessageInCommand)
if (!isOnlineMode || !Config.Signature.SignMessageInCommand)
return null;
List<Tuple<string, string>> 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

View file

@ -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<string> 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)

View file

@ -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
{
/// <summary>
/// This class parses JSON chat data from MC 1.6+ and returns the appropriate string to be printed.
/// </summary>
static class ChatParser
{
public enum MessageType
@ -47,7 +47,7 @@ namespace MinecraftClient.Protocol
/// <returns>Returns the translated text</returns>
public static string ParseSignedChat(ChatMessage message, List<string>? 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<string> 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.

View file

@ -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());
}

View file

@ -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);
}

View file

@ -3,7 +3,8 @@ 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;
namespace MinecraftClient.Protocol.Keys
{
@ -46,11 +47,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<string, PlayerKeyPair>(login, playerKeyPair));
}
else if (Settings.ProfileKeyCaching == CacheType.Disk)
else if (Config.Main.Advanced.ProfileKeyCache == CacheType.disk)
{
SaveToDisk();
}
@ -114,7 +115,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 +134,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 +175,7 @@ namespace MinecraftClient.Protocol.Keys
/// </summary>
private static void SaveToDisk()
{
if (Settings.DebugMessages)
if (Config.Logging.DebugMessages)
Translations.WriteLineFormatted("cache.saving_keys");
List<string> KeysCacheLines = new()

View file

@ -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
/// <param name="pass">Password</param>
/// <param name="session">In case of successful login, will contain session information for multiplayer</param>
/// <returns>Returns the status of the login (Success, Failure, etc.)</returns>
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
}

View file

@ -109,7 +109,7 @@ namespace MinecraftClient.Protocol
requestMessage.Add(body);
}
else requestMessage.Add(""); // <CR><LF>
if (Settings.DebugMessages)
if (Settings.Config.Logging.DebugMessages)
{
foreach (string l in requestMessage)
{

View file

@ -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);
}

View file

@ -1,20 +0,0 @@
namespace MinecraftClient.Protocol.Session
{
public enum CacheType
{
/// <summary>
/// Do not perform any session caching, always perform login requests from scratch.
/// </summary>
None,
/// <summary>
/// Cache session information in memory to reuse session tokens across server joins.
/// </summary>
Memory,
/// <summary>
/// Cache session information in a SessionCache file to share session tokens between different MCC instances.
/// </summary>
Disk
};
}

View file

@ -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<string, SessionToken>(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<string, SessionToken> 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
/// </summary>
private static void SaveToDisk()
{
if (Settings.DebugMessages)
if (Config.Logging.DebugMessages)
Translations.WriteLineFormatted("cache.saving");
List<string> sessionCacheLines = new()

View file

@ -1,5 +1,6 @@
using System.Net.Sockets;
using Starksoft.Aspen.Proxy;
using Tomlet.Attributes;
namespace MinecraftClient.Proxy
{
@ -11,7 +12,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 +67,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;
}

View file

@ -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. "<Yourname>"
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 <bot username> 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

View file

@ -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.<className>.<msg...>
# 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} <username>
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=

View file

@ -1,5 +1,9 @@
[mcc]
# Messages from MCC itself
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 :
@ -67,7 +71,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.
@ -87,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
@ -421,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
@ -445,23 +443,18 @@ cmd.useitem.use=Used an item
# ChatBots. Naming style: bot.<className>.<msg...>
# 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
@ -489,15 +482,11 @@ 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.
bot.autocraft.invaild_invaild_result=Invalid result item!
# AutoDrop
bot.autoDrop.cmd=AutoDrop ChatBot command
@ -610,7 +599,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}!
@ -630,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}
@ -643,3 +630,219 @@ 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.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# 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=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, 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 <mybot> reco Player2", "/connect <serverip> 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 <mybot> 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=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 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"
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=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="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.
# 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.
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.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.
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=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 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. 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
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.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
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
# 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 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).
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.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=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
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 (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
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 <bot username> 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 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=(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.
# 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

View file

@ -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:<index> 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.<className>.<msg...>
# 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} <pseudo>
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=

View file

@ -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.<className>.<msg...>
# 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=

View file

@ -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.<className>.<msg...>
# 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} <username>
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=

View file

@ -1,6 +1,10 @@
[mcc]
# Messages from MCC itself
mcc.login=登录:
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.password=密码:
mcc.password_basic_io=请输入{0}的密码。
@ -11,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正在切换至自动检测模式。
@ -30,7 +35,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秒后自动重生。
@ -43,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
@ -57,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=无法确定服务器版本。
@ -65,7 +71,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=网络错误。
@ -87,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}:未知设置或无效值
@ -97,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
@ -199,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)
@ -214,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}'。
@ -261,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=断开与服务器的连接。
@ -280,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}中丢弃了所有堆叠的物品
@ -297,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}
@ -328,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=你重生了。
@ -367,6 +438,7 @@ cmd.tps.current=当前TPS
# Useblock
cmd.useblock.desc=放置一个方块或打开箱子
cmd.useblock.use=
# Useitem
cmd.useitem.desc=使用(左键单击)手上的物品
@ -382,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},使用距离优先作为默认值。
@ -400,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=已成功加载
@ -422,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命令
@ -440,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}次重新连接
@ -470,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}
@ -502,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}'
@ -528,3 +649,220 @@ 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.write.fail=§保存备份文件({0}时出错§r
config.backup.fail=§c写入设置文件{0}时出错§r
config.saving=§a当前设置已保存至 {0}
# Head
config.Head=启动配置文件\n\n# 对 MCCMinecraft 命令行客户端不熟悉请看这个文档https://mccteam.github.io/guide/configuration.html\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手动在网页上登录
# 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=

View file

@ -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);
}
/// <summary>
@ -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);
}
/// <summary>
@ -347,7 +348,7 @@ namespace MinecraftClient
/// <returns>True if the account was found and loaded</returns>
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
/// <returns>True if the server IP was valid and loaded, false otherwise</returns>
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;

View file

@ -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.UserDefined && !string.IsNullOrWhiteSpace(Config.ChatFormat.Private))
{
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.UserDefined && !string.IsNullOrWhiteSpace(Config.ChatFormat.Public))
{
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.UserDefined && !string.IsNullOrWhiteSpace(Config.ChatFormat.TeleportRequest))
{
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
/// <param name="text">Debug log text to write</param>
protected void LogDebugToConsole(object text)
{
if (Settings.DebugMessages)
if (Settings.Config.Logging.DebugMessages)
LogToConsole(text);
}
@ -840,7 +860,7 @@ namespace MinecraftClient
/// <param name="delaySeconds">Optional delay, in seconds, before restarting</param>
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
/// <param name="message">Message</param>
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));
}
/// <summary>

File diff suppressed because it is too large Load diff

View file

@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Drawing.Drawing2D;
using System.Globalization;
using System.IO;
using System.Text;
@ -15,7 +16,7 @@ namespace MinecraftClient
/// </remarks>
public static class Translations
{
private static readonly Dictionary<string, string> translations;
private static readonly Dictionary<string, string> 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;
}
/// <summary>
/// Return a tranlation for the requested text. Support string formatting. If not found, return the original text
/// </summary>
/// <param name="msgName">text identifier</param>
/// <param name="args"></param>
/// <returns>Translated text or original text if not found</returns>
/// <remarks>Useful when not sure msgName is a translation mapping key or a normal text</remarks>
public static string? GetOrNull(string msgName, params object?[] args)
{
if (translations.ContainsKey(msgName))
return Get(msgName, args);
else
return null;
}
/// <summary>
/// Replace the translation key inside a sentence to translated text. Wrap the key in ([translation.key])
/// </summary>
@ -75,32 +91,495 @@ namespace MinecraftClient
return Get(m.Groups[1].Value);
}
/// <summary>
/// Initialize translations depending on system language.
/// English is the default for all unknown system languages.
/// </summary>
static Translations()
public static Tuple<string, string[]> GetTranslationPriority()
{
translations = new Dictionary<string, string>();
LoadDefaultTranslationsFile();
string gameLanguage = "en_gb";
List<string> 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<string> 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();
}
/// <summary>
/// Load default translation file (English)
/// Load translation files
/// </summary>
/// <remarks>
/// This will be loaded during program start up.
/// </remarks>
private static void LoadDefaultTranslationsFile()
{
string[] engLang = DefaultConfigResource.TranslationEnglish.Split(new[] { "\r\n", "\r", "\n" }, StringSplitOptions.None); // use embedded translations
ParseTranslationContent(engLang);
}
/// <summary>
/// Load translation file depends on system language or by giving a file path. Default to English if translation file does not exist
/// </summary>
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<string, string> 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<string, string> 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,25 +627,22 @@ namespace MinecraftClient
/// Parse the given array to translation map
/// </summary>
/// <param name="content">Content of the translation file (in ini format)</param>
private static void ParseTranslationContent(string[] content)
private static Dictionary<string, string> ParseTranslationContent(string[] content)
{
Dictionary<string, string> translations = new();
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;
}
/// <summary>
@ -182,10 +653,52 @@ 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<string, string> 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));
}
File.WriteAllText(defaultPath, DefaultConfigResource.TranslationEnglish, Encoding.UTF8);
}
#region Console writing method wrapper

View file

@ -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();

View file

@ -79,9 +79,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
{

View file

@ -1,8 +0,0 @@
myserver.com
Yourname>:
Player Yourname
Yourname joined
Yourname left
[Lockette] (Admin)
Yourname:
Yourname is

View file

@ -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

View file

@ -1,4 +0,0 @@
Connection has been lost
Server is restarting
Server is full
Too Many people

View file

@ -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 <mybot> reco Player2
# /connect <serverip> Player1
Player1,playerone@email.com,thepassword
Player2,TestBot,-

View file

@ -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 <mybot> connect Server1
# /connect Server2
Server1,localhost
Server2,mc.awesomeserver.com:25567
Server3,192.168.1.27:1348 # Example of LAN server

View file

@ -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 <numer>-<number>, 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

View file

@ -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)
## 从源码构建 🏗️

View file

@ -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) <a href="https://discord.gg/sfBv4TtpC9"><img src="https://img.shields.io/discord/1018553894831403028?color=5865F2&logo=discord&logoColor=white" alt="Discord server" /></a>
</div>
@ -45,11 +47,15 @@ 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 supports the following languages (Alphabetical order) :
* `de.ini` (57.69% translated) : Deutsch - German
* `en.ini` : English - English
* `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 🏗️