mirror of
https://github.com/MCCTeam/Minecraft-Console-Client
synced 2025-10-14 21:22:49 +00:00
Refactoring Settings.cs
This commit is contained in:
parent
f16b1c118b
commit
16c1d1fd77
59 changed files with 3425 additions and 2180 deletions
|
|
@ -1,5 +1,6 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using Tomlet.Attributes;
|
||||||
|
|
||||||
namespace MinecraftClient.ChatBots
|
namespace MinecraftClient.ChatBots
|
||||||
{
|
{
|
||||||
|
|
@ -8,9 +9,85 @@ namespace MinecraftClient.ChatBots
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class Alerts : ChatBot
|
public class Alerts : ChatBot
|
||||||
{
|
{
|
||||||
|
public static Configs Config = new();
|
||||||
|
|
||||||
|
[TomlDoNotInlineObject]
|
||||||
|
public class Configs
|
||||||
|
{
|
||||||
|
[NonSerialized]
|
||||||
|
private const string BotName = "Alerts";
|
||||||
|
|
||||||
|
public bool Enabled = false;
|
||||||
|
|
||||||
|
[TomlInlineComment("$config.ChatBot.Alerts.Beep_Enabled$")]
|
||||||
|
public bool Beep_Enabled = true;
|
||||||
|
|
||||||
|
[TomlInlineComment("$config.ChatBot.Alerts.Trigger_By_Words$")]
|
||||||
|
public bool Trigger_By_Words = false;
|
||||||
|
|
||||||
|
[TomlInlineComment("$config.ChatBot.Alerts.Trigger_By_Rain$")]
|
||||||
|
public bool Trigger_By_Rain = false;
|
||||||
|
|
||||||
|
[TomlInlineComment("$config.ChatBot.Alerts.Trigger_By_Thunderstorm$")]
|
||||||
|
public bool Trigger_By_Thunderstorm = false;
|
||||||
|
|
||||||
|
[TomlInlineComment("$config.ChatBot.Alerts.Matches_File$")]
|
||||||
|
public string Matches_File = @"alerts.txt";
|
||||||
|
|
||||||
|
[TomlInlineComment("$config.ChatBot.Alerts.Excludes_File$")]
|
||||||
|
public string Excludes_File = @"alerts-exclude.txt";
|
||||||
|
|
||||||
|
[TomlInlineComment("$config.ChatBot.Alerts.Log_To_File$")]
|
||||||
|
public bool Log_To_File = false;
|
||||||
|
|
||||||
|
[TomlInlineComment("$config.ChatBot.Alerts.Log_File$")]
|
||||||
|
public string Log_File = @"alerts-log.txt";
|
||||||
|
|
||||||
|
public void OnSettingUpdate()
|
||||||
|
{
|
||||||
|
if (!Enabled) return;
|
||||||
|
|
||||||
|
bool checkSuccessed = true;
|
||||||
|
|
||||||
|
if (Trigger_By_Words)
|
||||||
|
{
|
||||||
|
if (!System.IO.File.Exists(Matches_File))
|
||||||
|
{
|
||||||
|
checkSuccessed = false;
|
||||||
|
LogToConsole(BotName, "File not found: " + System.IO.Path.GetFullPath(Matches_File));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!System.IO.File.Exists(Excludes_File))
|
||||||
|
{
|
||||||
|
checkSuccessed = false;
|
||||||
|
LogToConsole(BotName, "File not found: " + System.IO.Path.GetFullPath(Excludes_File));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Log_To_File)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
System.IO.File.AppendAllText(Log_File, string.Empty);
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
checkSuccessed = false;
|
||||||
|
LogToConsole(BotName, "Can't write logs to " + System.IO.Path.GetFullPath(Excludes_File));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!checkSuccessed)
|
||||||
|
{
|
||||||
|
LogToConsole(BotName, Translations.TryGet("general.bot_unload"));
|
||||||
|
Enabled = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private string[] dictionary = Array.Empty<string>();
|
private string[] dictionary = Array.Empty<string>();
|
||||||
private string[] excludelist = Array.Empty<string>();
|
private string[] excludelist = Array.Empty<string>();
|
||||||
private bool logToFile = false;
|
|
||||||
float curRainLevel = 0;
|
float curRainLevel = 0;
|
||||||
float curThunderLevel = 0;
|
float curThunderLevel = 0;
|
||||||
const float threshold = 0.2f;
|
const float threshold = 0.2f;
|
||||||
|
|
@ -20,11 +97,10 @@ namespace MinecraftClient.ChatBots
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public override void Initialize()
|
public override void Initialize()
|
||||||
{
|
{
|
||||||
if (Settings.Alerts_Trigger_By_Words)
|
if (Config.Trigger_By_Words)
|
||||||
{
|
{
|
||||||
dictionary = LoadDistinctEntriesFromFile(Settings.Alerts_MatchesFile);
|
dictionary = LoadDistinctEntriesFromFile(Config.Matches_File);
|
||||||
excludelist = LoadDistinctEntriesFromFile(Settings.Alerts_ExcludesFile);
|
excludelist = LoadDistinctEntriesFromFile(Config.Excludes_File);
|
||||||
logToFile = Settings.Alerts_File_Logging;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -34,7 +110,7 @@ namespace MinecraftClient.ChatBots
|
||||||
/// <param name="text">Received text</param>
|
/// <param name="text">Received text</param>
|
||||||
public override void GetText(string text)
|
public override void GetText(string text)
|
||||||
{
|
{
|
||||||
if (Settings.Alerts_Trigger_By_Words)
|
if (Config.Trigger_By_Words)
|
||||||
{
|
{
|
||||||
//Remove color codes and convert to lowercase
|
//Remove color codes and convert to lowercase
|
||||||
text = GetVerbatim(text).ToLower();
|
text = GetVerbatim(text).ToLower();
|
||||||
|
|
@ -45,16 +121,16 @@ namespace MinecraftClient.ChatBots
|
||||||
//Show an alert for each alert item found in text, if any
|
//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 dictionary.Where(alert => text.Contains(alert)))
|
||||||
{
|
{
|
||||||
if (Settings.Alerts_Beep_Enabled)
|
if (Config.Beep_Enabled)
|
||||||
Console.Beep(); //Text found !
|
Console.Beep(); //Text found !
|
||||||
|
|
||||||
ConsoleIO.WriteLine(text.Replace(alert, "§c" + alert + "§r"));
|
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;
|
DateTime now = DateTime.Now;
|
||||||
string TimeStamp = "[" + now.Year + '/' + now.Month + '/' + now.Day + ' ' + now.Hour + ':' + now.Minute + ']';
|
string TimeStamp = "[" + now.Year + '/' + now.Month + '/' + now.Day + ' ' + now.Hour + ':' + now.Minute + ']';
|
||||||
System.IO.File.AppendAllText(Settings.Alerts_LogFile, TimeStamp + " " + GetVerbatim(text) + "\n");
|
System.IO.File.AppendAllText(Config.Log_File, TimeStamp + " " + GetVerbatim(text) + "\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -65,9 +141,9 @@ namespace MinecraftClient.ChatBots
|
||||||
{
|
{
|
||||||
if (curRainLevel < threshold && level >= threshold)
|
if (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();
|
||||||
Console.Beep();
|
Console.Beep();
|
||||||
|
|
@ -77,9 +153,9 @@ namespace MinecraftClient.ChatBots
|
||||||
}
|
}
|
||||||
else if (curRainLevel >= threshold && level < threshold)
|
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();
|
Console.Beep();
|
||||||
}
|
}
|
||||||
|
|
@ -93,9 +169,9 @@ namespace MinecraftClient.ChatBots
|
||||||
{
|
{
|
||||||
if (curThunderLevel < threshold && level >= threshold)
|
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();
|
||||||
Console.Beep();
|
Console.Beep();
|
||||||
|
|
@ -105,9 +181,9 @@ namespace MinecraftClient.ChatBots
|
||||||
}
|
}
|
||||||
else if (curThunderLevel >= threshold && level < threshold)
|
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();
|
Console.Beep();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Globalization;
|
|
||||||
using MinecraftClient.Mapping;
|
using MinecraftClient.Mapping;
|
||||||
|
using Tomlet.Attributes;
|
||||||
|
|
||||||
namespace MinecraftClient.ChatBots
|
namespace MinecraftClient.ChatBots
|
||||||
{
|
{
|
||||||
|
|
@ -10,94 +10,94 @@ namespace MinecraftClient.ChatBots
|
||||||
|
|
||||||
public class AntiAFK : ChatBot
|
public class AntiAFK : ChatBot
|
||||||
{
|
{
|
||||||
|
public static Configs Config = new();
|
||||||
|
|
||||||
|
[TomlDoNotInlineObject]
|
||||||
|
public class Configs
|
||||||
|
{
|
||||||
|
[NonSerialized]
|
||||||
|
private const string BotName = "AntiAFK";
|
||||||
|
|
||||||
|
public bool Enabled = false;
|
||||||
|
|
||||||
|
[TomlInlineComment("$config.ChatBot.AntiAfk.Delay$")]
|
||||||
|
public Range Delay = new(600);
|
||||||
|
|
||||||
|
[TomlInlineComment("$config.ChatBot.AntiAfk.Command$")]
|
||||||
|
public string Command = "/ping";
|
||||||
|
|
||||||
|
[TomlInlineComment("$config.ChatBot.AntiAfk.Use_Terrain_Handling$")]
|
||||||
|
public bool Use_Terrain_Handling = false;
|
||||||
|
|
||||||
|
[TomlInlineComment("$config.ChatBot.AntiAfk.Walk_Range$")]
|
||||||
|
public int Walk_Range = 5;
|
||||||
|
|
||||||
|
[TomlInlineComment("$config.ChatBot.AntiAfk.Walk_Retries$")]
|
||||||
|
public int Walk_Retries = 20;
|
||||||
|
|
||||||
|
public void OnSettingUpdate()
|
||||||
|
{
|
||||||
|
if (Walk_Range <= 0)
|
||||||
|
{
|
||||||
|
Walk_Range = 5;
|
||||||
|
LogToConsole(BotName, Translations.TryGet("bot.antiafk.invalid_walk_range"));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Delay.min > Delay.max)
|
||||||
|
{
|
||||||
|
(Delay.min, Delay.max) = (Delay.max, Delay.min);
|
||||||
|
LogToConsole(BotName, Translations.TryGet("bot.antiafk.swapping"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public struct Range
|
||||||
|
{
|
||||||
|
public int min, max;
|
||||||
|
|
||||||
|
public Range(int value)
|
||||||
|
{
|
||||||
|
value = Math.Max(value, 10);
|
||||||
|
min = max = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Range(int min, int max)
|
||||||
|
{
|
||||||
|
min = Math.Max(min, 10);
|
||||||
|
max = Math.Max(max, 10);
|
||||||
|
this.min = min;
|
||||||
|
this.max = max;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private int count;
|
private int count;
|
||||||
private readonly string pingparam;
|
|
||||||
private int timeping = 600;
|
|
||||||
private int timepingMax = -1;
|
|
||||||
private bool useTerrainHandling = false;
|
|
||||||
private bool previousSneakState = false;
|
private bool previousSneakState = false;
|
||||||
private int walkRange = 5;
|
|
||||||
private readonly int walkRetries = 10;
|
|
||||||
private readonly Random random = new();
|
private readonly Random random = new();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// This bot sends a /ping command every X seconds in order to stay non-afk.
|
/// This bot sends a /ping command every X seconds in order to stay non-afk.
|
||||||
/// </summary>
|
/// </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()
|
||||||
|
|
||||||
public AntiAFK(string pingparam, bool useTerrainHandling, int walkRange, int walkRetries)
|
|
||||||
{
|
{
|
||||||
count = 0;
|
count = 0;
|
||||||
this.pingparam = pingparam;
|
|
||||||
this.useTerrainHandling = useTerrainHandling;
|
|
||||||
this.walkRange = walkRange;
|
|
||||||
this.walkRetries = walkRetries;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void Initialize()
|
public override void Initialize()
|
||||||
{
|
{
|
||||||
if (useTerrainHandling)
|
if (Config.Use_Terrain_Handling)
|
||||||
{
|
{
|
||||||
if (!GetTerrainEnabled())
|
if (!GetTerrainEnabled())
|
||||||
{
|
{
|
||||||
useTerrainHandling = false;
|
|
||||||
LogToConsole(Translations.TryGet("bot.antiafk.not_using_terrain_handling"));
|
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()
|
public override void Update()
|
||||||
{
|
{
|
||||||
count++;
|
count++;
|
||||||
|
|
||||||
if ((timepingMax != -1 && count == random.Next(timeping, timepingMax)) || count == timeping)
|
if (count == random.Next(Config.Delay.min, Config.Delay.max))
|
||||||
{
|
{
|
||||||
DoAntiAfkStuff();
|
DoAntiAfkStuff();
|
||||||
count = 0;
|
count = 0;
|
||||||
|
|
@ -107,7 +107,7 @@ namespace MinecraftClient.ChatBots
|
||||||
|
|
||||||
private void DoAntiAfkStuff()
|
private void DoAntiAfkStuff()
|
||||||
{
|
{
|
||||||
if (useTerrainHandling)
|
if (Config.Use_Terrain_Handling && GetTerrainEnabled())
|
||||||
{
|
{
|
||||||
Location currentLocation = GetCurrentLocation();
|
Location currentLocation = GetCurrentLocation();
|
||||||
Location goal;
|
Location goal;
|
||||||
|
|
@ -118,19 +118,19 @@ namespace MinecraftClient.ChatBots
|
||||||
|
|
||||||
while (!moved)
|
while (!moved)
|
||||||
{
|
{
|
||||||
if (triesCounter++ >= walkRetries)
|
if (triesCounter++ >= Config.Walk_Retries)
|
||||||
{
|
{
|
||||||
useAlternativeMethod = true;
|
useAlternativeMethod = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
goal = GetRandomLocationWithinRangeXZ(currentLocation, walkRange);
|
goal = GetRandomLocationWithinRangeXZ(currentLocation, Config.Walk_Range);
|
||||||
|
|
||||||
// Prevent getting the same location
|
// Prevent getting the same location
|
||||||
while ((currentLocation.X == goal.X) && (currentLocation.Y == goal.Y) && (currentLocation.Z == goal.Z))
|
while ((currentLocation.X == goal.X) && (currentLocation.Y == goal.Y) && (currentLocation.Z == goal.Z))
|
||||||
{
|
{
|
||||||
LogToConsole("Same location!, generating new one");
|
LogToConsole("Same location!, generating new one");
|
||||||
goal = GetRandomLocationWithinRangeXZ(currentLocation, walkRange);
|
goal = GetRandomLocationWithinRangeXZ(currentLocation, Config.Walk_Range);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!Movement.CheckChunkLoading(GetWorld(), currentLocation, goal))
|
if (!Movement.CheckChunkLoading(GetWorld(), currentLocation, goal))
|
||||||
|
|
@ -151,7 +151,7 @@ namespace MinecraftClient.ChatBots
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SendText(Settings.AntiAFK_Command);
|
SendText(Config.Command);
|
||||||
Sneak(previousSneakState);
|
Sneak(previousSneakState);
|
||||||
previousSneakState = !previousSneakState;
|
previousSneakState = !previousSneakState;
|
||||||
count = 0;
|
count = 0;
|
||||||
|
|
|
||||||
|
|
@ -2,14 +2,89 @@
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using MinecraftClient.Mapping;
|
using MinecraftClient.Mapping;
|
||||||
|
using Tomlet.Attributes;
|
||||||
|
|
||||||
namespace MinecraftClient.ChatBots
|
namespace MinecraftClient.ChatBots
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The AutoAttack bot will automatically attack any hostile mob close to the player
|
/// The AutoAttack bot will automatically attack any hostile mob close to the player
|
||||||
/// </summary>
|
/// </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 readonly Dictionary<int, Entity> entitiesToAttack = new(); // mobs within attack range
|
||||||
private int attackCooldown = 6;
|
private int attackCooldown = 6;
|
||||||
private int attackCooldownCounter = 6;
|
private int attackCooldownCounter = 6;
|
||||||
|
|
@ -19,73 +94,20 @@ namespace MinecraftClient.ChatBots
|
||||||
private readonly int attackRange = 4;
|
private readonly int attackRange = 4;
|
||||||
private Double serverTPS;
|
private Double serverTPS;
|
||||||
private float health = 100;
|
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 attackHostile = true;
|
||||||
private readonly bool attackPassive = false;
|
private readonly bool attackPassive = false;
|
||||||
private readonly string listMode = "blacklist";
|
|
||||||
private readonly List<EntityType> listedEntites = new();
|
|
||||||
|
|
||||||
public AutoAttack(
|
public AutoAttack()
|
||||||
string mode, string priority, bool overrideAttackSpeed = false, double cooldownSeconds = 1, InteractType interaction = InteractType.Attack)
|
|
||||||
{
|
{
|
||||||
if (mode == "single")
|
overrideAttackSpeed = Config.Cooldown_Time.Custom;
|
||||||
singleMode = true;
|
if (Config.Cooldown_Time.Custom)
|
||||||
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)
|
|
||||||
{
|
{
|
||||||
if (cooldownSeconds <= 0)
|
attackCooldownSeconds = Config.Cooldown_Time.value;
|
||||||
{
|
attackCooldown = Convert.ToInt32(Math.Truncate(attackCooldownSeconds / 0.1) + 1);
|
||||||
LogToConsoleTranslated("bot.autoAttack.invalidcooldown");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
this.overrideAttackSpeed = overrideAttackSpeed;
|
|
||||||
attackCooldownSeconds = cooldownSeconds;
|
|
||||||
attackCooldown = Convert.ToInt32(Math.Truncate(attackCooldownSeconds / 0.1) + 1);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
attackHostile = Settings.AutoAttack_Attack_Hostile;
|
attackHostile = Config.Attack_Hostile;
|
||||||
attackPassive = Settings.AutoAttack_Attack_Passive;
|
attackPassive = Config.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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void Initialize()
|
public override void Initialize()
|
||||||
|
|
@ -108,10 +130,10 @@ namespace MinecraftClient.ChatBots
|
||||||
attackCooldownCounter = attackCooldown;
|
attackCooldownCounter = attackCooldown;
|
||||||
if (entitiesToAttack.Count > 0)
|
if (entitiesToAttack.Count > 0)
|
||||||
{
|
{
|
||||||
if (singleMode)
|
if (Config.Mode == Configs.AttackMode.single)
|
||||||
{
|
{
|
||||||
int priorityEntity = 0;
|
int priorityEntity = 0;
|
||||||
if (priorityDistance) // closest distance priority
|
if (Config.Priority == Configs.PriorityType.distance) // closest distance priority
|
||||||
{
|
{
|
||||||
double distance = 5;
|
double distance = 5;
|
||||||
foreach (var entity in entitiesToAttack)
|
foreach (var entity in entitiesToAttack)
|
||||||
|
|
@ -142,7 +164,7 @@ namespace MinecraftClient.ChatBots
|
||||||
// check entity distance and health again
|
// check entity distance and health again
|
||||||
if (ShouldAttackEntity(entitiesToAttack[priorityEntity]))
|
if (ShouldAttackEntity(entitiesToAttack[priorityEntity]))
|
||||||
{
|
{
|
||||||
InteractEntity(priorityEntity, interactMode); // hit the entity!
|
InteractEntity(priorityEntity, Config.Interaction); // hit the entity!
|
||||||
SendAnimation(Inventory.Hand.MainHand); // Arm animation
|
SendAnimation(Inventory.Hand.MainHand); // Arm animation
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -154,7 +176,7 @@ namespace MinecraftClient.ChatBots
|
||||||
// check that we are in range once again.
|
// check that we are in range once again.
|
||||||
if (ShouldAttackEntity(entity.Value))
|
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
|
SendAnimation(Inventory.Hand.MainHand); // Arm animation
|
||||||
|
|
@ -206,10 +228,13 @@ namespace MinecraftClient.ChatBots
|
||||||
if (attackPassive && entity.Type.IsPassive())
|
if (attackPassive && entity.Type.IsPassive())
|
||||||
result = true;
|
result = true;
|
||||||
|
|
||||||
if (listedEntites.Count > 0)
|
if (Config.Entites_List.Count > 0)
|
||||||
{
|
{
|
||||||
bool inList = listedEntites.Contains(entity.Type);
|
bool inList = Config.Entites_List.Contains(entity.Type);
|
||||||
result = listMode.Equals("blacklist") ? (!inList && result) : (inList);
|
if (Config.List_Mode == Configs.ListType.blacklist)
|
||||||
|
result = !inList && result;
|
||||||
|
else
|
||||||
|
result = inList;
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
|
|
||||||
|
|
@ -4,11 +4,27 @@ using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using MinecraftClient.Inventory;
|
using MinecraftClient.Inventory;
|
||||||
using MinecraftClient.Mapping;
|
using MinecraftClient.Mapping;
|
||||||
|
using Tomlet.Attributes;
|
||||||
|
|
||||||
namespace MinecraftClient.ChatBots
|
namespace MinecraftClient.ChatBots
|
||||||
{
|
{
|
||||||
class AutoCraft : ChatBot
|
public class AutoCraft : ChatBot
|
||||||
{
|
{
|
||||||
|
public static Configs Config = new();
|
||||||
|
|
||||||
|
[TomlDoNotInlineObject]
|
||||||
|
public class Configs
|
||||||
|
{
|
||||||
|
[NonSerialized]
|
||||||
|
private const string BotName = "AutoCraft";
|
||||||
|
|
||||||
|
public bool Enabled = false;
|
||||||
|
|
||||||
|
public string configFile = @"autocraft\config.ini";
|
||||||
|
|
||||||
|
public void OnSettingUpdate() { }
|
||||||
|
}
|
||||||
|
|
||||||
private bool waitingForMaterials = false;
|
private bool waitingForMaterials = false;
|
||||||
private bool waitingForUpdate = false;
|
private bool waitingForUpdate = false;
|
||||||
private bool waitingForTable = false;
|
private bool waitingForTable = false;
|
||||||
|
|
@ -26,7 +42,6 @@ namespace MinecraftClient.ChatBots
|
||||||
private int updateTimeout = 0;
|
private int updateTimeout = 0;
|
||||||
private string timeoutAction = "unspecified";
|
private string timeoutAction = "unspecified";
|
||||||
|
|
||||||
private readonly string configPath = @"autocraft\config.ini";
|
|
||||||
private string lastRecipe = ""; // Used in parsing recipe config
|
private string lastRecipe = ""; // Used in parsing recipe config
|
||||||
|
|
||||||
private readonly Dictionary<string, Recipe> recipes = new();
|
private readonly Dictionary<string, Recipe> recipes = new();
|
||||||
|
|
@ -158,11 +173,6 @@ namespace MinecraftClient.ChatBots
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public AutoCraft(string configPath = @"autocraft\config.ini")
|
|
||||||
{
|
|
||||||
this.configPath = configPath;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void Initialize()
|
public override void Initialize()
|
||||||
{
|
{
|
||||||
if (!GetInventoryEnabled())
|
if (!GetInventoryEnabled())
|
||||||
|
|
@ -247,9 +257,9 @@ namespace MinecraftClient.ChatBots
|
||||||
|
|
||||||
public void LoadConfig()
|
public void LoadConfig()
|
||||||
{
|
{
|
||||||
if (!File.Exists(configPath))
|
if (!File.Exists(Config.configFile))
|
||||||
{
|
{
|
||||||
if (!Directory.Exists(configPath))
|
if (!Directory.Exists(Config.configFile))
|
||||||
{
|
{
|
||||||
Directory.CreateDirectory(@"autocraft");
|
Directory.CreateDirectory(@"autocraft");
|
||||||
}
|
}
|
||||||
|
|
@ -289,19 +299,19 @@ namespace MinecraftClient.ChatBots
|
||||||
"# For the naming of the items, please see",
|
"# For the naming of the items, please see",
|
||||||
"# https://github.com/MCCTeam/Minecraft-Console-Client/blob/master/MinecraftClient/Inventory/ItemType.cs"
|
"# https://github.com/MCCTeam/Minecraft-Console-Client/blob/master/MinecraftClient/Inventory/ItemType.cs"
|
||||||
};
|
};
|
||||||
File.WriteAllLines(configPath, content);
|
File.WriteAllLines(Config.configFile, content);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ParseConfig()
|
private void ParseConfig()
|
||||||
{
|
{
|
||||||
string[] content = File.ReadAllLines(configPath);
|
string[] content = File.ReadAllLines(Config.configFile);
|
||||||
if (content.Length <= 0)
|
if (content.Length <= 0)
|
||||||
{
|
{
|
||||||
throw new Exception(Translations.Get("bot.autoCraft.exception.empty", configPath));
|
throw new Exception(Translations.Get("bot.autoCraft.exception.empty", Config.configFile));
|
||||||
}
|
}
|
||||||
if (content[0].ToLower() != "[autocraft]")
|
if (content[0].ToLower() != "[autocraft]")
|
||||||
{
|
{
|
||||||
throw new Exception(Translations.Get("bot.autoCraft.exception.invalid", configPath));
|
throw new Exception(Translations.Get("bot.autoCraft.exception.invalid", Config.configFile));
|
||||||
}
|
}
|
||||||
|
|
||||||
// local variable for use in parsing config
|
// local variable for use in parsing config
|
||||||
|
|
|
||||||
|
|
@ -2,51 +2,43 @@
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using MinecraftClient.Inventory;
|
using MinecraftClient.Inventory;
|
||||||
|
using Tomlet.Attributes;
|
||||||
|
using static MinecraftClient.ChatBots.AutoDrop.Configs;
|
||||||
|
|
||||||
namespace MinecraftClient.ChatBots
|
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
|
[NonSerialized]
|
||||||
Exclude, // Items in list will be kept
|
private const string BotName = "AutoDrop";
|
||||||
Everything // Everything will be dropped
|
|
||||||
|
public bool Enabled = false;
|
||||||
|
|
||||||
|
[TomlInlineComment("$config.ChatBot.AutoDrop.Mode$")]
|
||||||
|
public DropMode Mode = DropMode.include;
|
||||||
|
|
||||||
|
[TomlInlineComment("$config.ChatBot.AutoDrop.Items$")]
|
||||||
|
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 int updateDebounce = 0;
|
||||||
private readonly int updateDebounceValue = 2;
|
private readonly int updateDebounceValue = 2;
|
||||||
private int inventoryUpdated = -1;
|
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)
|
public string CommandHandler(string cmd, string[] args)
|
||||||
{
|
{
|
||||||
if (args.Length > 0)
|
if (args.Length > 0)
|
||||||
|
|
@ -54,19 +46,19 @@ namespace MinecraftClient.ChatBots
|
||||||
switch (args[0].ToLower())
|
switch (args[0].ToLower())
|
||||||
{
|
{
|
||||||
case "on":
|
case "on":
|
||||||
enable = true;
|
Config.Enabled = true;
|
||||||
inventoryUpdated = 0;
|
inventoryUpdated = 0;
|
||||||
OnUpdateFinish();
|
OnUpdateFinish();
|
||||||
return Translations.Get("bot.autoDrop.on");
|
return Translations.Get("bot.autoDrop.on");
|
||||||
case "off":
|
case "off":
|
||||||
enable = false;
|
Config.Enabled = false;
|
||||||
return Translations.Get("bot.autoDrop.off");
|
return Translations.Get("bot.autoDrop.off");
|
||||||
case "add":
|
case "add":
|
||||||
if (args.Length >= 2)
|
if (args.Length >= 2)
|
||||||
{
|
{
|
||||||
if (Enum.TryParse(args[1], true, out ItemType item))
|
if (Enum.TryParse(args[1], true, out ItemType item))
|
||||||
{
|
{
|
||||||
itemList.Add(item);
|
Config.Items.Add(item);
|
||||||
return Translations.Get("bot.autoDrop.added", item.ToString());
|
return Translations.Get("bot.autoDrop.added", item.ToString());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
@ -83,9 +75,9 @@ namespace MinecraftClient.ChatBots
|
||||||
{
|
{
|
||||||
if (Enum.TryParse(args[1], true, out ItemType item))
|
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());
|
return Translations.Get("bot.autoDrop.removed", item.ToString());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
@ -103,9 +95,9 @@ namespace MinecraftClient.ChatBots
|
||||||
return Translations.Get("cmd.inventory.help.usage") + ": remove <item name>";
|
return Translations.Get("cmd.inventory.help.usage") + ": remove <item name>";
|
||||||
}
|
}
|
||||||
case "list":
|
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
|
else
|
||||||
{
|
{
|
||||||
|
|
@ -117,20 +109,20 @@ namespace MinecraftClient.ChatBots
|
||||||
switch (args[1].ToLower())
|
switch (args[1].ToLower())
|
||||||
{
|
{
|
||||||
case "include":
|
case "include":
|
||||||
dropMode = Mode.Include;
|
Config.Mode = DropMode.include;
|
||||||
break;
|
break;
|
||||||
case "exclude":
|
case "exclude":
|
||||||
dropMode = Mode.Exclude;
|
Config.Mode = DropMode.exclude;
|
||||||
break;
|
break;
|
||||||
case "everything":
|
case "everything":
|
||||||
dropMode = Mode.Everything;
|
Config.Mode = DropMode.everything;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return Translations.Get("bot.autoDrop.unknown_mode"); // Unknwon mode. Available modes: Include, Exclude, Everything
|
return Translations.Get("bot.autoDrop.unknown_mode"); // Unknwon mode. Available modes: Include, Exclude, Everything
|
||||||
}
|
}
|
||||||
inventoryUpdated = 0;
|
inventoryUpdated = 0;
|
||||||
OnUpdateFinish();
|
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
|
else
|
||||||
{
|
{
|
||||||
|
|
@ -178,7 +170,7 @@ namespace MinecraftClient.ChatBots
|
||||||
|
|
||||||
public override void OnInventoryUpdate(int inventoryId)
|
public override void OnInventoryUpdate(int inventoryId)
|
||||||
{
|
{
|
||||||
if (enable)
|
if (Config.Enabled)
|
||||||
{
|
{
|
||||||
updateDebounce = updateDebounceValue;
|
updateDebounce = updateDebounceValue;
|
||||||
// Always interact container if available (larger ID) because they included player inventory (ID 0)
|
// Always interact container if available (larger ID) because they included player inventory (ID 0)
|
||||||
|
|
@ -199,28 +191,28 @@ namespace MinecraftClient.ChatBots
|
||||||
}
|
}
|
||||||
var inventory = GetInventories()[inventoryUpdated];
|
var inventory = GetInventories()[inventoryUpdated];
|
||||||
var items = inventory.Items.ToDictionary(entry => entry.Key, entry => entry.Value);
|
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)
|
foreach (var item in items)
|
||||||
{
|
{
|
||||||
// Ingore crafting result slot
|
// Ingore crafting result slot
|
||||||
if (item.Key == 0)
|
if (item.Key == 0)
|
||||||
continue;
|
continue;
|
||||||
if (itemList.Contains(item.Value.Type))
|
if (Config.Items.Contains(item.Value.Type))
|
||||||
{
|
{
|
||||||
// Drop it !!
|
// Drop it !!
|
||||||
WindowAction(inventoryUpdated, item.Key, WindowActionType.DropItemStack);
|
WindowAction(inventoryUpdated, item.Key, WindowActionType.DropItemStack);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (dropMode == Mode.Exclude)
|
else if (Config.Mode == DropMode.exclude)
|
||||||
{
|
{
|
||||||
foreach (var item in items)
|
foreach (var item in items)
|
||||||
{
|
{
|
||||||
// Ingore crafting result slot
|
// Ingore crafting result slot
|
||||||
if (item.Key == 0)
|
if (item.Key == 0)
|
||||||
continue;
|
continue;
|
||||||
if (!itemList.Contains(item.Value.Type))
|
if (!Config.Items.Contains(item.Value.Type))
|
||||||
{
|
{
|
||||||
// Drop it !!
|
// Drop it !!
|
||||||
WindowAction(inventoryUpdated, item.Key, WindowActionType.DropItemStack);
|
WindowAction(inventoryUpdated, item.Key, WindowActionType.DropItemStack);
|
||||||
|
|
|
||||||
|
|
@ -1,19 +1,36 @@
|
||||||
using MinecraftClient.Inventory;
|
using System;
|
||||||
|
using MinecraftClient.Inventory;
|
||||||
|
using Tomlet.Attributes;
|
||||||
|
|
||||||
namespace MinecraftClient.ChatBots
|
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;
|
byte LastSlot = 0;
|
||||||
public static bool Eating = false;
|
public static bool Eating = false;
|
||||||
private readonly int HungerThreshold = 6;
|
|
||||||
private int DelayCounter = 0;
|
private int DelayCounter = 0;
|
||||||
|
|
||||||
public AutoEat(int Threshold)
|
|
||||||
{
|
|
||||||
HungerThreshold = Threshold;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void Update()
|
public override void Update()
|
||||||
{
|
{
|
||||||
if (DelayCounter > 0)
|
if (DelayCounter > 0)
|
||||||
|
|
@ -31,7 +48,7 @@ namespace MinecraftClient.ChatBots
|
||||||
public override void OnHealthUpdate(float health, int food)
|
public override void OnHealthUpdate(float health, int food)
|
||||||
{
|
{
|
||||||
if (health <= 0) return; // player dead
|
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();
|
Eating = FindFoodAndEat();
|
||||||
if (!Eating)
|
if (!Eating)
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,9 @@
|
||||||
using System;
|
using System;
|
||||||
using MinecraftClient.Inventory;
|
using MinecraftClient.Inventory;
|
||||||
using MinecraftClient.Mapping;
|
using MinecraftClient.Mapping;
|
||||||
|
using Tomlet.Attributes;
|
||||||
|
using static MinecraftClient.ChatBots.AutoFishing.Configs;
|
||||||
|
using static MinecraftClient.ChatBots.AutoFishing.Configs.LocationConfig;
|
||||||
|
|
||||||
namespace MinecraftClient.ChatBots
|
namespace MinecraftClient.ChatBots
|
||||||
{
|
{
|
||||||
|
|
@ -8,8 +11,122 @@ namespace MinecraftClient.ChatBots
|
||||||
/// The AutoFishing bot semi-automates fishing.
|
/// The AutoFishing bot semi-automates fishing.
|
||||||
/// The player needs to have a fishing rod in hand, then manually send it using the UseItem command.
|
/// The player needs to have a fishing rod in hand, then manually send it using the UseItem command.
|
||||||
/// </summary>
|
/// </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.Movements$")]
|
||||||
|
public LocationConfig[] Movements = Array.Empty<LocationConfig>();
|
||||||
|
|
||||||
|
public void OnSettingUpdate()
|
||||||
|
{
|
||||||
|
if (Cast_Delay < 0)
|
||||||
|
Cast_Delay = 0;
|
||||||
|
|
||||||
|
if (Fishing_Delay < 0)
|
||||||
|
Fishing_Delay = 0;
|
||||||
|
|
||||||
|
if (Fishing_Timeout < 0)
|
||||||
|
Fishing_Timeout = 0;
|
||||||
|
|
||||||
|
if (Durability_Limit < 0)
|
||||||
|
Durability_Limit = 0;
|
||||||
|
else if (Durability_Limit > 64)
|
||||||
|
Durability_Limit = 64;
|
||||||
|
|
||||||
|
if (Stationary_Threshold < 0)
|
||||||
|
Stationary_Threshold = -Stationary_Threshold;
|
||||||
|
|
||||||
|
if (Hook_Threshold < 0)
|
||||||
|
Hook_Threshold = -Hook_Threshold;
|
||||||
|
}
|
||||||
|
|
||||||
|
public struct LocationConfig
|
||||||
|
{
|
||||||
|
public Coordination? XYZ;
|
||||||
|
public Facing? facing;
|
||||||
|
|
||||||
|
public LocationConfig(float yaw, float pitch)
|
||||||
|
{
|
||||||
|
this.XYZ = null;
|
||||||
|
this.facing = new(yaw, pitch);
|
||||||
|
}
|
||||||
|
|
||||||
|
public LocationConfig(double x, double y, double z)
|
||||||
|
{
|
||||||
|
this.XYZ = new(x, y, z);
|
||||||
|
this.facing = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public LocationConfig(double x, double y, double z, float yaw, float pitch)
|
||||||
|
{
|
||||||
|
this.XYZ = new(x, y, z);
|
||||||
|
this.facing = new(yaw, pitch);
|
||||||
|
}
|
||||||
|
|
||||||
|
public struct Coordination
|
||||||
|
{
|
||||||
|
public double x, y, z;
|
||||||
|
|
||||||
|
public Coordination(double x, double y, double z)
|
||||||
|
{
|
||||||
|
this.x = x; this.y = y; this.z = z;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public struct Facing
|
||||||
|
{
|
||||||
|
public float yaw, pitch;
|
||||||
|
|
||||||
|
public Facing(float yaw, float pitch)
|
||||||
|
{
|
||||||
|
this.yaw = yaw; this.pitch = pitch;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private int fishCount = 0;
|
private int fishCount = 0;
|
||||||
private bool inventoryEnabled;
|
private bool inventoryEnabled;
|
||||||
private int castTimeout = 12;
|
private int castTimeout = 12;
|
||||||
|
|
@ -54,9 +171,9 @@ namespace MinecraftClient.ChatBots
|
||||||
private void StartFishing()
|
private void StartFishing()
|
||||||
{
|
{
|
||||||
isFishing = false;
|
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));
|
LogToConsole(Translations.Get("bot.autoFish.start", delay));
|
||||||
lock (stateLock)
|
lock (stateLock)
|
||||||
{
|
{
|
||||||
|
|
@ -84,7 +201,7 @@ namespace MinecraftClient.ChatBots
|
||||||
|
|
||||||
private void UseFishRod()
|
private void UseFishRod()
|
||||||
{
|
{
|
||||||
if (Settings.AutoFishing_Mainhand)
|
if (Config.Mainhand)
|
||||||
UseItemInHand();
|
UseItemInHand();
|
||||||
else
|
else
|
||||||
UseItemInLeftHand();
|
UseItemInLeftHand();
|
||||||
|
|
@ -100,7 +217,7 @@ namespace MinecraftClient.ChatBots
|
||||||
break;
|
break;
|
||||||
case FishingState.WaitingToCast:
|
case FishingState.WaitingToCast:
|
||||||
if (AutoEat.Eating)
|
if (AutoEat.Eating)
|
||||||
counter = (int)(Settings.AutoFishing_CastDelay * 10);
|
counter = (int)(Config.Cast_Delay * 10);
|
||||||
else if (--counter < 0)
|
else if (--counter < 0)
|
||||||
state = FishingState.CastingRod;
|
state = FishingState.CastingRod;
|
||||||
break;
|
break;
|
||||||
|
|
@ -116,28 +233,27 @@ namespace MinecraftClient.ChatBots
|
||||||
castTimeout *= 2; // Exponential backoff
|
castTimeout *= 2; // Exponential backoff
|
||||||
LogToConsole(GetTimestamp() + ": " + Translations.Get("bot.autoFish.cast_timeout", castTimeout / 10.0));
|
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;
|
state = FishingState.WaitingToCast;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case FishingState.WaitingFishToBite:
|
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"));
|
LogToConsole(GetTimestamp() + ": " + Translations.Get("bot.autoFish.fishing_timeout"));
|
||||||
|
|
||||||
counter = (int)(Settings.AutoFishing_CastDelay * 10);
|
counter = (int)(Config.Cast_Delay * 10);
|
||||||
state = FishingState.WaitingToCast;
|
state = FishingState.WaitingToCast;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case FishingState.StartMove:
|
case FishingState.StartMove:
|
||||||
if (--counter < 0)
|
if (--counter < 0)
|
||||||
{
|
{
|
||||||
double[,]? locationList = Settings.AutoFishing_Location;
|
if (Config.Movements.Length > 0)
|
||||||
if (locationList != null)
|
|
||||||
{
|
{
|
||||||
if (GetTerrainEnabled())
|
if (GetTerrainEnabled())
|
||||||
{
|
{
|
||||||
UpdateLocation(locationList);
|
UpdateLocation(Config.Movements);
|
||||||
state = FishingState.WaitingMovement;
|
state = FishingState.WaitingMovement;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
@ -148,7 +264,7 @@ namespace MinecraftClient.ChatBots
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
counter = (int)(Settings.AutoFishing_CastDelay * 10);
|
counter = (int)(Config.Cast_Delay * 10);
|
||||||
state = FishingState.DurabilityCheck;
|
state = FishingState.DurabilityCheck;
|
||||||
goto case FishingState.DurabilityCheck;
|
goto case FishingState.DurabilityCheck;
|
||||||
}
|
}
|
||||||
|
|
@ -167,7 +283,7 @@ namespace MinecraftClient.ChatBots
|
||||||
case FishingState.DurabilityCheck:
|
case FishingState.DurabilityCheck:
|
||||||
if (DurabilityCheck())
|
if (DurabilityCheck())
|
||||||
{
|
{
|
||||||
counter = (int)(Settings.AutoFishing_CastDelay * 10);
|
counter = (int)(Config.Cast_Delay * 10);
|
||||||
state = FishingState.WaitingToCast;
|
state = FishingState.WaitingToCast;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
@ -181,7 +297,7 @@ namespace MinecraftClient.ChatBots
|
||||||
{
|
{
|
||||||
if (entity.Type == EntityType.FishingBobber && entity.ObjectData == GetPlayerEntityID())
|
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(string.Format("FishingBobber spawn at {0}, distance = {1:0.00}", entity.Location, GetCurrentLocation().Distance(entity.Location)));
|
||||||
|
|
||||||
LogToConsole(GetTimestamp() + ": " + Translations.Get("bot.autoFish.throw"));
|
LogToConsole(GetTimestamp() + ": " + Translations.Get("bot.autoFish.throw"));
|
||||||
|
|
@ -202,20 +318,20 @@ namespace MinecraftClient.ChatBots
|
||||||
{
|
{
|
||||||
if (entity != null && entity.Type == EntityType.FishingBobber && entity.ID == fishingBobber!.ID)
|
if (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));
|
LogToConsole(string.Format("FishingBobber despawn at {0}", entity.Location));
|
||||||
|
|
||||||
if (isFishing)
|
if (isFishing)
|
||||||
{
|
{
|
||||||
isFishing = false;
|
isFishing = false;
|
||||||
|
|
||||||
if (Settings.AutoFishing_Antidespawn)
|
if (Config.Antidespawn)
|
||||||
{
|
{
|
||||||
LogToConsoleTranslated("bot.autoFish.despawn");
|
LogToConsoleTranslated("bot.autoFish.despawn");
|
||||||
|
|
||||||
lock (stateLock)
|
lock (stateLock)
|
||||||
{
|
{
|
||||||
counter = (int)(Settings.AutoFishing_CastDelay * 10);
|
counter = (int)(Config.Cast_Delay * 10);
|
||||||
state = FishingState.WaitingToCast;
|
state = FishingState.WaitingToCast;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -233,12 +349,12 @@ namespace MinecraftClient.ChatBots
|
||||||
double Dz = LastPos.Z - Pos.Z;
|
double Dz = LastPos.Z - Pos.Z;
|
||||||
LastPos = Pos;
|
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));
|
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) &&
|
if (Math.Abs(Dx) < Math.Abs(Config.Stationary_Threshold) &&
|
||||||
Math.Abs(Dz) < Math.Abs(Settings.AutoFishing_StationaryThreshold) &&
|
Math.Abs(Dz) < Math.Abs(Config.Stationary_Threshold) &&
|
||||||
Math.Abs(Dy) > Math.Abs(Settings.AutoFishing_HookThreshold))
|
Math.Abs(Dy) > Math.Abs(Config.Hook_Threshold))
|
||||||
{
|
{
|
||||||
// prevent triggering multiple time
|
// prevent triggering multiple time
|
||||||
if ((DateTime.Now - CaughtTime).TotalSeconds > 1)
|
if ((DateTime.Now - CaughtTime).TotalSeconds > 1)
|
||||||
|
|
@ -283,7 +399,7 @@ namespace MinecraftClient.ChatBots
|
||||||
public void OnCaughtFish()
|
public void OnCaughtFish()
|
||||||
{
|
{
|
||||||
++fishCount;
|
++fishCount;
|
||||||
if (Settings.AutoFishing_Location != null)
|
if (Config.Movements.Length > 0)
|
||||||
LogToConsole(GetTimestamp() + ": " + Translations.Get("bot.autoFish.caught_at",
|
LogToConsole(GetTimestamp() + ": " + Translations.Get("bot.autoFish.caught_at",
|
||||||
fishingBobber!.Location.X, fishingBobber!.Location.Y, fishingBobber!.Location.Z, fishCount));
|
fishingBobber!.Location.X, fishingBobber!.Location.Y, fishingBobber!.Location.Z, fishCount));
|
||||||
else
|
else
|
||||||
|
|
@ -298,47 +414,36 @@ namespace MinecraftClient.ChatBots
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void UpdateLocation(double[,] locationList)
|
private void UpdateLocation(LocationConfig[] locationList)
|
||||||
{
|
{
|
||||||
if (curLocationIdx >= locationList.GetLength(0))
|
if (curLocationIdx >= locationList.Length)
|
||||||
{
|
{
|
||||||
curLocationIdx = Math.Max(0, locationList.GetLength(0) - 2);
|
curLocationIdx = Math.Max(0, locationList.Length - 2);
|
||||||
moveDir = -1;
|
moveDir = -1;
|
||||||
}
|
}
|
||||||
else if (curLocationIdx < 0)
|
else if (curLocationIdx < 0)
|
||||||
{
|
{
|
||||||
curLocationIdx = Math.Min(locationList.GetLength(0) - 1, 1);
|
curLocationIdx = Math.Min(locationList.Length - 1, 1);
|
||||||
moveDir = 1;
|
moveDir = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int locationType = locationList.GetLength(1);
|
LocationConfig curConfig = locationList[curLocationIdx];
|
||||||
|
|
||||||
if (locationType == 2)
|
if (curConfig.facing != null)
|
||||||
{
|
(nextYaw, nextPitch) = (curConfig.facing.Value.yaw, curConfig.facing.Value.pitch);
|
||||||
nextYaw = (float)locationList[curLocationIdx, 0];
|
else
|
||||||
nextPitch = (float)locationList[curLocationIdx, 1];
|
(nextYaw, nextPitch) = (GetYaw(), GetPitch());
|
||||||
}
|
|
||||||
else if (locationType == 3)
|
|
||||||
{
|
|
||||||
nextYaw = GetYaw();
|
|
||||||
nextPitch = GetPitch();
|
|
||||||
}
|
|
||||||
else if (locationType == 5)
|
|
||||||
{
|
|
||||||
nextYaw = (float)locationList[curLocationIdx, 3];
|
|
||||||
nextPitch = (float)locationList[curLocationIdx, 4];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (locationType == 3 || locationType == 5)
|
if (curConfig.XYZ != null)
|
||||||
{
|
{
|
||||||
Location current = GetCurrentLocation();
|
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;
|
bool isMoveSuccessed;
|
||||||
if (!Movement.CheckChunkLoading(GetWorld(), current, goal))
|
if (!Movement.CheckChunkLoading(GetWorld(), current, goal))
|
||||||
{
|
{
|
||||||
LogToConsole(Translations.Get("cmd.move.chunk_not_loaded", goal.X, goal.Y, goal.Z));
|
|
||||||
isMoveSuccessed = false;
|
isMoveSuccessed = false;
|
||||||
|
LogToConsole(Translations.Get("cmd.move.chunk_not_loaded", goal.X, goal.Y, goal.Z));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
@ -347,8 +452,7 @@ namespace MinecraftClient.ChatBots
|
||||||
|
|
||||||
if (!isMoveSuccessed)
|
if (!isMoveSuccessed)
|
||||||
{
|
{
|
||||||
nextYaw = GetYaw();
|
(nextYaw, nextPitch) = (GetYaw(), GetPitch());
|
||||||
nextPitch = GetPitch();
|
|
||||||
LogToConsole(Translations.Get("cmd.move.fail", goal));
|
LogToConsole(Translations.Get("cmd.move.fail", goal));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
@ -365,13 +469,13 @@ namespace MinecraftClient.ChatBots
|
||||||
if (!inventoryEnabled)
|
if (!inventoryEnabled)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
bool useMainHand = Settings.AutoFishing_Mainhand;
|
bool useMainHand = Config.Mainhand;
|
||||||
Container container = GetPlayerInventory();
|
Container container = GetPlayerInventory();
|
||||||
|
|
||||||
int itemSolt = useMainHand ? GetCurrentSlot() + 36 : 45;
|
int itemSolt = useMainHand ? GetCurrentSlot() + 36 : 45;
|
||||||
|
|
||||||
if (container.Items.TryGetValue(itemSolt, out Item? handItem) &&
|
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;
|
isWaitingRod = false;
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -381,11 +485,11 @@ namespace MinecraftClient.ChatBots
|
||||||
if (!isWaitingRod)
|
if (!isWaitingRod)
|
||||||
LogToConsole(GetTimestamp() + ": " + Translations.Get("bot.autoFish.no_rod"));
|
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)
|
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, slot, WindowActionType.LeftClick);
|
||||||
WindowAction(0, itemSolt, WindowActionType.LeftClick);
|
WindowAction(0, itemSolt, WindowActionType.LeftClick);
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
using Tomlet.Attributes;
|
||||||
|
|
||||||
namespace MinecraftClient.ChatBots
|
namespace MinecraftClient.ChatBots
|
||||||
{
|
{
|
||||||
|
|
@ -8,11 +9,59 @@ namespace MinecraftClient.ChatBots
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class AutoRelog : ChatBot
|
public class AutoRelog : ChatBot
|
||||||
{
|
{
|
||||||
|
public static Configs Config = new();
|
||||||
|
|
||||||
|
[TomlDoNotInlineObject]
|
||||||
|
public class Configs
|
||||||
|
{
|
||||||
|
[NonSerialized]
|
||||||
|
private const string BotName = "AutoRelog";
|
||||||
|
|
||||||
|
public bool Enabled = false;
|
||||||
|
|
||||||
|
[TomlInlineComment("$config.ChatBot.AutoRelog.Delay$")]
|
||||||
|
public Range Delay = new(10);
|
||||||
|
|
||||||
|
[TomlInlineComment("$config.ChatBot.AutoRelog.Retries$")]
|
||||||
|
public int Retries = 3;
|
||||||
|
|
||||||
|
[TomlInlineComment("$config.ChatBot.AutoRelog.Ignore_Kick_Message$")]
|
||||||
|
public bool Ignore_Kick_Message = false;
|
||||||
|
|
||||||
|
[TomlInlineComment("$config.ChatBot.AutoRelog.Kick_Messages_File$")]
|
||||||
|
public string Kick_Messages_File = @"kickmessages.txt";
|
||||||
|
|
||||||
|
public void OnSettingUpdate()
|
||||||
|
{
|
||||||
|
if (Delay.min > Delay.max)
|
||||||
|
(Delay.min, Delay.max) = (Delay.max, Delay.min);
|
||||||
|
|
||||||
|
if (Retries == -1)
|
||||||
|
Retries = int.MaxValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
public struct Range
|
||||||
|
{
|
||||||
|
public int min, max;
|
||||||
|
|
||||||
|
public Range(int value)
|
||||||
|
{
|
||||||
|
value = Math.Max(value, 1);
|
||||||
|
min = max = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Range(int min, int max)
|
||||||
|
{
|
||||||
|
min = Math.Max(min, 1);
|
||||||
|
max = Math.Max(max, 1);
|
||||||
|
this.min = min;
|
||||||
|
this.max = max;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private static readonly Random random = new();
|
private static readonly Random random = new();
|
||||||
private string[] dictionary = Array.Empty<string>();
|
private string[] dictionary = Array.Empty<string>();
|
||||||
private readonly int attempts;
|
|
||||||
private readonly int delayMin;
|
|
||||||
private readonly int delayMax;
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// This bot automatically re-join the server if kick message contains predefined string
|
/// This bot automatically re-join the server if kick message contains predefined string
|
||||||
|
|
@ -20,34 +69,25 @@ namespace MinecraftClient.ChatBots
|
||||||
/// <param name="DelayBeforeRelogMin">Minimum delay before re-joining the server (in seconds)</param>
|
/// <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="DelayBeforeRelogMax">Maximum delay before re-joining the server (in seconds)</param>
|
||||||
/// <param name="retries">Number of retries if connection fails (-1 = infinite)</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;
|
LogDebugToConsoleTranslated("bot.autoRelog.launch", Config.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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void Initialize()
|
public override void Initialize()
|
||||||
{
|
{
|
||||||
McClient.ReconnectionAttemptsLeft = attempts;
|
McClient.ReconnectionAttemptsLeft = Config.Retries;
|
||||||
if (Settings.AutoRelog_IgnoreKickMessage)
|
if (Config.Ignore_Kick_Message)
|
||||||
{
|
{
|
||||||
LogDebugToConsoleTranslated("bot.autoRelog.no_kick_msg");
|
LogDebugToConsoleTranslated("bot.autoRelog.no_kick_msg");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (System.IO.File.Exists(Settings.AutoRelog_KickMessagesFile))
|
if (System.IO.File.Exists(Config.Kick_Messages_File))
|
||||||
{
|
{
|
||||||
LogDebugToConsoleTranslated("bot.autoRelog.loading", System.IO.Path.GetFullPath(Settings.AutoRelog_KickMessagesFile));
|
LogDebugToConsoleTranslated("bot.autoRelog.loading", System.IO.Path.GetFullPath(Config.Kick_Messages_File));
|
||||||
|
|
||||||
dictionary = System.IO.File.ReadAllLines(Settings.AutoRelog_KickMessagesFile, Encoding.UTF8);
|
dictionary = System.IO.File.ReadAllLines(Config.Kick_Messages_File, Encoding.UTF8);
|
||||||
|
|
||||||
for (int i = 0; i < dictionary.Length; i++)
|
for (int i = 0; i < dictionary.Length; i++)
|
||||||
{
|
{
|
||||||
|
|
@ -57,7 +97,7 @@ namespace MinecraftClient.ChatBots
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
LogToConsoleTranslated("bot.autoRelog.not_found", System.IO.Path.GetFullPath(Settings.AutoRelog_KickMessagesFile));
|
LogToConsoleTranslated("bot.autoRelog.not_found", System.IO.Path.GetFullPath(Config.Kick_Messages_File));
|
||||||
|
|
||||||
LogDebugToConsoleTranslated("bot.autoRelog.curr_dir", System.IO.Directory.GetCurrentDirectory());
|
LogDebugToConsoleTranslated("bot.autoRelog.curr_dir", System.IO.Directory.GetCurrentDirectory());
|
||||||
}
|
}
|
||||||
|
|
@ -77,7 +117,7 @@ namespace MinecraftClient.ChatBots
|
||||||
|
|
||||||
LogDebugToConsoleTranslated("bot.autoRelog.disconnect_msg", message);
|
LogDebugToConsoleTranslated("bot.autoRelog.disconnect_msg", message);
|
||||||
|
|
||||||
if (Settings.AutoRelog_IgnoreKickMessage)
|
if (Config.Ignore_Kick_Message)
|
||||||
{
|
{
|
||||||
LaunchDelayedReconnection(null);
|
LaunchDelayedReconnection(null);
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -100,7 +140,7 @@ namespace MinecraftClient.ChatBots
|
||||||
|
|
||||||
private void LaunchDelayedReconnection(string? msg)
|
private void LaunchDelayedReconnection(string? msg)
|
||||||
{
|
{
|
||||||
int delay = random.Next(delayMin, delayMax);
|
int delay = random.Next(Config.Delay.min, Config.Delay.max);
|
||||||
LogDebugToConsoleTranslated(String.IsNullOrEmpty(msg) ? "bot.autoRelog.reconnect_always" : "bot.autoRelog.reconnect", msg);
|
LogDebugToConsoleTranslated(String.IsNullOrEmpty(msg) ? "bot.autoRelog.reconnect_always" : "bot.autoRelog.reconnect", msg);
|
||||||
LogToConsoleTranslated("bot.autoRelog.wait", delay);
|
LogToConsoleTranslated("bot.autoRelog.wait", delay);
|
||||||
System.Threading.Thread.Sleep(delay * 1000);
|
System.Threading.Thread.Sleep(delay * 1000);
|
||||||
|
|
@ -109,9 +149,9 @@ namespace MinecraftClient.ChatBots
|
||||||
|
|
||||||
public static bool OnDisconnectStatic(DisconnectReason reason, string message)
|
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();
|
bot.Initialize();
|
||||||
return bot.OnDisconnect(reason, message);
|
return bot.OnDisconnect(reason, message);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,31 +1,50 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Globalization;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
|
using Tomlet.Attributes;
|
||||||
|
using static MinecraftClient.Settings;
|
||||||
|
|
||||||
namespace MinecraftClient.ChatBots
|
namespace MinecraftClient.ChatBots
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// This bot automatically runs actions when a user sends a message matching a specified rule
|
/// This bot automatically runs actions when a user sends a message matching a specified rule
|
||||||
/// </summary>
|
/// </summary>
|
||||||
class AutoRespond : ChatBot
|
public class AutoRespond : ChatBot
|
||||||
{
|
{
|
||||||
private readonly string matchesFile;
|
public static Configs Config = new();
|
||||||
private readonly bool matchColors;
|
|
||||||
|
[TomlDoNotInlineObject]
|
||||||
|
public class Configs
|
||||||
|
{
|
||||||
|
[NonSerialized]
|
||||||
|
private const string BotName = "AutoRespond";
|
||||||
|
|
||||||
|
public bool Enabled = false;
|
||||||
|
|
||||||
|
public string Matches_File = @"matches.ini";
|
||||||
|
|
||||||
|
[TomlInlineComment("$config.ChatBot.AutoRespond.Match_Colors$")]
|
||||||
|
public bool Match_Colors = false;
|
||||||
|
|
||||||
|
public void OnSettingUpdate()
|
||||||
|
{
|
||||||
|
if (!Enabled) return;
|
||||||
|
|
||||||
|
if (!File.Exists(Matches_File))
|
||||||
|
{
|
||||||
|
LogToConsole(BotName, Translations.TryGet("bot.autoRespond.file_not_found", Path.GetFullPath(Matches_File)));
|
||||||
|
LogToConsole(BotName, Translations.TryGet("general.bot_unload"));
|
||||||
|
Enabled = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private List<RespondRule>? respondRules;
|
private List<RespondRule>? respondRules;
|
||||||
private enum MessageType { Public, Private, Other };
|
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>
|
/// <summary>
|
||||||
/// Describe a respond rule based on a simple match or a regex
|
/// Describe a respond rule based on a simple match or a regex
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
@ -96,7 +115,7 @@ namespace MinecraftClient.ChatBots
|
||||||
|
|
||||||
string? toSend = null;
|
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;
|
return null;
|
||||||
|
|
||||||
switch (msgType)
|
switch (msgType)
|
||||||
|
|
@ -164,7 +183,7 @@ namespace MinecraftClient.ChatBots
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public override void Initialize()
|
public override void Initialize()
|
||||||
{
|
{
|
||||||
if (File.Exists(matchesFile))
|
if (File.Exists(Config.Matches_File))
|
||||||
{
|
{
|
||||||
Regex? matchRegex = null;
|
Regex? matchRegex = null;
|
||||||
string? matchString = null;
|
string? matchString = null;
|
||||||
|
|
@ -175,9 +194,9 @@ namespace MinecraftClient.ChatBots
|
||||||
TimeSpan cooldown = TimeSpan.Zero;
|
TimeSpan cooldown = TimeSpan.Zero;
|
||||||
respondRules = new List<RespondRule>();
|
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();
|
string line = lineRAW.Split('#')[0].Trim();
|
||||||
if (line.Length > 0)
|
if (line.Length > 0)
|
||||||
|
|
@ -211,8 +230,8 @@ namespace MinecraftClient.ChatBots
|
||||||
case "action": matchAction = argValue; break;
|
case "action": matchAction = argValue; break;
|
||||||
case "actionprivate": matchActionPrivate = argValue; break;
|
case "actionprivate": matchActionPrivate = argValue; break;
|
||||||
case "actionother": matchActionOther = argValue; break;
|
case "actionother": matchActionOther = argValue; break;
|
||||||
case "ownersonly": ownersOnly = Settings.str2bool(argValue); break;
|
case "ownersonly": ownersOnly = bool.Parse(argValue); break;
|
||||||
case "cooldown": cooldown = TimeSpan.FromSeconds(Settings.str2int(argValue)); break;
|
case "cooldown": cooldown = TimeSpan.FromSeconds(int.Parse(argValue, NumberStyles.Any, CultureInfo.CurrentCulture)); break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -222,7 +241,7 @@ namespace MinecraftClient.ChatBots
|
||||||
}
|
}
|
||||||
else
|
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
|
UnloadBot(); //No need to keep the bot active
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -264,7 +283,7 @@ namespace MinecraftClient.ChatBots
|
||||||
public override void GetText(string text)
|
public override void GetText(string text)
|
||||||
{
|
{
|
||||||
//Remove colour codes
|
//Remove colour codes
|
||||||
if (!matchColors)
|
if (!Config.Match_Colors)
|
||||||
text = GetVerbatim(text);
|
text = GetVerbatim(text);
|
||||||
|
|
||||||
//Get Message type
|
//Get Message type
|
||||||
|
|
@ -277,7 +296,7 @@ namespace MinecraftClient.ChatBots
|
||||||
else message = text;
|
else message = text;
|
||||||
|
|
||||||
//Do not process messages sent by the bot itself
|
//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!)
|
foreach (RespondRule rule in respondRules!)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
using System;
|
using System;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
using Tomlet.Attributes;
|
||||||
|
using static System.Net.WebRequestMethods;
|
||||||
|
|
||||||
namespace MinecraftClient.ChatBots
|
namespace MinecraftClient.ChatBots
|
||||||
{
|
{
|
||||||
|
|
@ -9,13 +11,42 @@ namespace MinecraftClient.ChatBots
|
||||||
|
|
||||||
public class ChatLog : ChatBot
|
public class ChatLog : ChatBot
|
||||||
{
|
{
|
||||||
public enum MessageFilter { AllText, AllMessages, OnlyChat, OnlyWhispers, OnlyInternalCommands };
|
public static Configs Config = new();
|
||||||
private readonly bool dateandtime;
|
|
||||||
private readonly bool saveOther = true;
|
[TomlDoNotInlineObject]
|
||||||
private readonly bool saveChat = true;
|
public class Configs
|
||||||
private readonly bool savePrivate = true;
|
{
|
||||||
private readonly bool saveInternal = true;
|
[NonSerialized]
|
||||||
private readonly string logfile;
|
private const string BotName = "ChatLog";
|
||||||
|
|
||||||
|
public bool Enabled = false;
|
||||||
|
|
||||||
|
public bool Add_DateTime = true;
|
||||||
|
|
||||||
|
public string Log_File = @"chatlog-%username%-%serverip%.txt";
|
||||||
|
|
||||||
|
public MessageFilter Filter = MessageFilter.messages;
|
||||||
|
|
||||||
|
public void OnSettingUpdate()
|
||||||
|
{
|
||||||
|
if (!Enabled) return;
|
||||||
|
|
||||||
|
string Log_File_Full = Settings.Config.AppVar.ExpandVars(Log_File);
|
||||||
|
if (String.IsNullOrEmpty(Log_File_Full) || Log_File_Full.IndexOfAny(Path.GetInvalidPathChars()) >= 0)
|
||||||
|
{
|
||||||
|
LogToConsole(BotName, Translations.TryGet("bot.chatLog.invalid_file", Log_File_Full));
|
||||||
|
LogToConsole(BotName, Translations.TryGet("general.bot_unload"));
|
||||||
|
Enabled = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum MessageFilter { all, messages, chat, private_chat, internal_msg };
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool saveOther = true;
|
||||||
|
private bool saveChat = true;
|
||||||
|
private bool savePrivate = true;
|
||||||
|
private bool saveInternal = true;
|
||||||
private readonly object logfileLock = new();
|
private readonly object logfileLock = new();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
@ -25,59 +56,42 @@ namespace MinecraftClient.ChatBots
|
||||||
/// <param name="filter">The kind of messages to save</param>
|
/// <param name="filter">The kind of messages to save</param>
|
||||||
/// <param name="AddDateAndTime">Add a date and time before each message</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)
|
switch (filter)
|
||||||
{
|
{
|
||||||
case MessageFilter.AllText:
|
case Configs.MessageFilter.all:
|
||||||
saveOther = true;
|
saveOther = true;
|
||||||
savePrivate = true;
|
savePrivate = true;
|
||||||
saveChat = true;
|
saveChat = true;
|
||||||
break;
|
break;
|
||||||
case MessageFilter.AllMessages:
|
case Configs.MessageFilter.messages:
|
||||||
saveOther = false;
|
saveOther = false;
|
||||||
savePrivate = true;
|
savePrivate = true;
|
||||||
saveChat = true;
|
saveChat = true;
|
||||||
break;
|
break;
|
||||||
case MessageFilter.OnlyChat:
|
case Configs.MessageFilter.chat:
|
||||||
saveOther = false;
|
saveOther = false;
|
||||||
savePrivate = false;
|
savePrivate = false;
|
||||||
saveChat = true;
|
saveChat = true;
|
||||||
break;
|
break;
|
||||||
case MessageFilter.OnlyWhispers:
|
case Configs.MessageFilter.private_chat:
|
||||||
saveOther = false;
|
saveOther = false;
|
||||||
savePrivate = true;
|
savePrivate = true;
|
||||||
saveChat = false;
|
saveChat = false;
|
||||||
break;
|
break;
|
||||||
case MessageFilter.OnlyInternalCommands:
|
case Configs.MessageFilter.internal_msg:
|
||||||
saveOther = false;
|
saveOther = false;
|
||||||
savePrivate = false;
|
savePrivate = false;
|
||||||
saveChat = false;
|
saveChat = false;
|
||||||
saveInternal = true;
|
saveInternal = true;
|
||||||
break;
|
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)
|
public override void GetText(string text)
|
||||||
|
|
@ -110,14 +124,15 @@ namespace MinecraftClient.ChatBots
|
||||||
|
|
||||||
private void Save(string tosave)
|
private void Save(string tosave)
|
||||||
{
|
{
|
||||||
if (dateandtime)
|
if (Config.Add_DateTime)
|
||||||
tosave = GetTimestamp() + ' ' + tosave;
|
tosave = GetTimestamp() + ' ' + tosave;
|
||||||
|
string Log_File_Full = Settings.Config.AppVar.ExpandVars(Config.Log_File);
|
||||||
lock (logfileLock)
|
lock (logfileLock)
|
||||||
{
|
{
|
||||||
string? directory = Path.GetDirectoryName(logfile);
|
string? directory = Path.GetDirectoryName(Log_File_Full);
|
||||||
if (!String.IsNullOrEmpty(directory) && !Directory.Exists(directory))
|
if (!String.IsNullOrEmpty(directory) && !Directory.Exists(directory))
|
||||||
Directory.CreateDirectory(directory);
|
Directory.CreateDirectory(directory);
|
||||||
FileStream stream = new(logfile, FileMode.OpenOrCreate);
|
FileStream stream = new(Log_File_Full, FileMode.OpenOrCreate);
|
||||||
StreamWriter writer = new(stream);
|
StreamWriter writer = new(stream);
|
||||||
stream.Seek(0, SeekOrigin.End);
|
stream.Seek(0, SeekOrigin.End);
|
||||||
writer.WriteLine(tosave);
|
writer.WriteLine(tosave);
|
||||||
|
|
|
||||||
|
|
@ -1,23 +1,42 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using MinecraftClient.Mapping;
|
using MinecraftClient.Mapping;
|
||||||
|
using Tomlet.Attributes;
|
||||||
|
|
||||||
namespace MinecraftClient.ChatBots
|
namespace MinecraftClient.ChatBots
|
||||||
{
|
{
|
||||||
public class FollowPlayer : ChatBot
|
public class FollowPlayer : ChatBot
|
||||||
{
|
{
|
||||||
|
public static Configs Config = new();
|
||||||
|
|
||||||
|
[TomlDoNotInlineObject]
|
||||||
|
public class Configs
|
||||||
|
{
|
||||||
|
[NonSerialized]
|
||||||
|
private const string BotName = "FollowPlayer";
|
||||||
|
|
||||||
|
public bool Enabled = false;
|
||||||
|
|
||||||
|
[TomlInlineComment("$config.ChatBot.FollowPlayer.Update_Limit$")]
|
||||||
|
public int Update_Limit = 10;
|
||||||
|
|
||||||
|
[TomlInlineComment("$config.ChatBot.FollowPlayer.Stop_At_Distance$")]
|
||||||
|
public double Stop_At_Distance = 3.0;
|
||||||
|
|
||||||
|
public void OnSettingUpdate()
|
||||||
|
{
|
||||||
|
if (Update_Limit < 0)
|
||||||
|
Update_Limit = 0;
|
||||||
|
|
||||||
|
if (Stop_At_Distance < 0)
|
||||||
|
Stop_At_Distance = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private string? _playerToFollow = null;
|
private string? _playerToFollow = null;
|
||||||
private int _updateCounter = 0;
|
private int _updateCounter = 0;
|
||||||
private readonly int _updateLimit;
|
|
||||||
private readonly int _stopAtDistance;
|
|
||||||
private bool _unsafeEnabled = false;
|
private bool _unsafeEnabled = false;
|
||||||
|
|
||||||
public FollowPlayer(int updateLimit = 15, int stopAtDistance = 3)
|
|
||||||
{
|
|
||||||
_updateLimit = updateLimit;
|
|
||||||
_stopAtDistance = stopAtDistance;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void Initialize()
|
public override void Initialize()
|
||||||
{
|
{
|
||||||
if (!GetEntityHandlingEnabled())
|
if (!GetEntityHandlingEnabled())
|
||||||
|
|
@ -94,7 +113,7 @@ namespace MinecraftClient.ChatBots
|
||||||
public override void OnEntityMove(Entity entity)
|
public override void OnEntityMove(Entity entity)
|
||||||
{
|
{
|
||||||
|
|
||||||
if (_updateCounter < _updateLimit)
|
if (_updateCounter < Config.Update_Limit)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
_updateCounter = 0;
|
_updateCounter = 0;
|
||||||
|
|
@ -114,7 +133,7 @@ namespace MinecraftClient.ChatBots
|
||||||
// Stop at specified distance from plater (prevents pushing player around)
|
// Stop at specified distance from plater (prevents pushing player around)
|
||||||
double distance = entity.Location.Distance(GetCurrentLocation());
|
double distance = entity.Location.Distance(GetCurrentLocation());
|
||||||
|
|
||||||
if (distance < _stopAtDistance)
|
if (distance < Config.Stop_At_Distance)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
MoveToLocation(entity.Location, _unsafeEnabled);
|
MoveToLocation(entity.Location, _unsafeEnabled);
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
using Tomlet.Attributes;
|
||||||
|
|
||||||
namespace MinecraftClient.ChatBots
|
namespace MinecraftClient.ChatBots
|
||||||
{
|
{
|
||||||
|
|
@ -9,26 +10,33 @@ namespace MinecraftClient.ChatBots
|
||||||
|
|
||||||
public class HangmanGame : ChatBot
|
public class HangmanGame : ChatBot
|
||||||
{
|
{
|
||||||
|
public static Configs Config = new();
|
||||||
|
|
||||||
|
[TomlDoNotInlineObject]
|
||||||
|
public class Configs
|
||||||
|
{
|
||||||
|
[NonSerialized]
|
||||||
|
private const string BotName = "HangmanGame";
|
||||||
|
|
||||||
|
public bool Enabled = false;
|
||||||
|
|
||||||
|
public bool English = true;
|
||||||
|
|
||||||
|
public string FileWords_EN = "hangman-en.txt";
|
||||||
|
|
||||||
|
public string FileWords_FR = "hangman-fr.txt";
|
||||||
|
|
||||||
|
public void OnSettingUpdate() { }
|
||||||
|
}
|
||||||
|
|
||||||
private int vie = 0;
|
private int vie = 0;
|
||||||
private readonly int vie_param = 10;
|
private readonly int vie_param = 10;
|
||||||
private int compteur = 0;
|
private int compteur = 0;
|
||||||
private readonly int compteur_param = 3000; //5 minutes
|
private readonly int compteur_param = 3000; //5 minutes
|
||||||
private bool running = false;
|
private bool running = false;
|
||||||
private bool[] discovered;
|
private bool[] discovered = Array.Empty<bool>();
|
||||||
private string word = "";
|
private string word = "";
|
||||||
private string letters = "";
|
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()
|
public override void Update()
|
||||||
{
|
{
|
||||||
|
|
@ -40,8 +48,8 @@ namespace MinecraftClient.ChatBots
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
SendText(English ? "You took too long to try a letter." : "Temps imparti écoulé !");
|
SendText(Config.English ? "You took too long to try a letter." : "Temps imparti écoulé !");
|
||||||
SendText(English ? "Game canceled." : "Partie annulée.");
|
SendText(Config.English ? "Game canceled." : "Partie annulée.");
|
||||||
running = false;
|
running = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -55,7 +63,7 @@ namespace MinecraftClient.ChatBots
|
||||||
|
|
||||||
if (IsPrivateMessage(text, ref message, ref username))
|
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)
|
switch (message)
|
||||||
{
|
{
|
||||||
|
|
@ -81,7 +89,7 @@ namespace MinecraftClient.ChatBots
|
||||||
{
|
{
|
||||||
if (letters.Contains(letter))
|
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
|
else
|
||||||
{
|
{
|
||||||
|
|
@ -91,29 +99,29 @@ namespace MinecraftClient.ChatBots
|
||||||
if (word.Contains(letter))
|
if (word.Contains(letter))
|
||||||
{
|
{
|
||||||
for (int i = 0; i < word.Length; i++) { if (word[i] == letter) { discovered[i] = true; } }
|
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
|
else
|
||||||
{
|
{
|
||||||
vie--;
|
vie--;
|
||||||
if (vie == 0)
|
if (vie == 0)
|
||||||
{
|
{
|
||||||
SendText(English ? "Game Over! :]" : "Perdu ! Partie terminée :]");
|
SendText(Config.English ? "Game Over! :]" : "Perdu ! Partie terminée :]");
|
||||||
SendText(English ? ("The word was: " + word) : ("Le mot était : " + word));
|
SendText(Config.English ? ("The word was: " + word) : ("Le mot était : " + word));
|
||||||
running = false;
|
running = false;
|
||||||
}
|
}
|
||||||
else SendText(English ? ("The " + letter + "? No.") : ("Le " + letter + " ? Non."));
|
else SendText(Config.English ? ("The " + letter + "? No.") : ("Le " + letter + " ? Non."));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (running)
|
if (running)
|
||||||
{
|
{
|
||||||
SendText(English ? ("Mysterious word: " + WordCached + " (lives : " + vie + ")")
|
SendText(Config.English ? ("Mysterious word: " + WordCached + " (lives : " + vie + ")")
|
||||||
: ("Mot mystère : " + WordCached + " (vie : " + vie + ")"));
|
: ("Mot mystère : " + WordCached + " (vie : " + vie + ")"));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Winner)
|
if (Winner)
|
||||||
{
|
{
|
||||||
SendText(English ? ("Congrats, " + username + '!') : ("Félicitations, " + username + " !"));
|
SendText(Config.English ? ("Congrats, " + username + '!') : ("Félicitations, " + username + " !"));
|
||||||
running = false;
|
running = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -132,23 +140,23 @@ namespace MinecraftClient.ChatBots
|
||||||
compteur = compteur_param;
|
compteur = compteur_param;
|
||||||
discovered = new bool[word.Length];
|
discovered = new bool[word.Length];
|
||||||
|
|
||||||
SendText(English ? "Hangman v1.0 - By ORelio" : "Pendu v1.0 - Par ORelio");
|
SendText(Config.English ? "Hangman v1.0 - By ORelio" : "Pendu v1.0 - Par ORelio");
|
||||||
SendText(English ? ("Mysterious word: " + WordCached + " (lives : " + vie + ")")
|
SendText(Config.English ? ("Mysterious word: " + WordCached + " (lives : " + vie + ")")
|
||||||
: ("Mot mystère : " + WordCached + " (vie : " + 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()
|
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)];
|
return dico[new Random().Next(dico.Length)];
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
LogToConsole(English ? "File not found: " + Settings.Hangman_FileWords_EN : "Fichier introuvable : " + Settings.Hangman_FileWords_FR);
|
LogToConsole(Config.English ? "File not found: " + Config.FileWords_EN : "Fichier introuvable : " + Config.FileWords_FR);
|
||||||
return English ? "WORDSAREMISSING" : "DICOMANQUANT";
|
return Config.English ? "WORDSAREMISSING" : "DICOMANQUANT";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@ using System.Collections.Generic;
|
||||||
using System.Data;
|
using System.Data;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using Tomlet.Attributes;
|
||||||
|
|
||||||
namespace MinecraftClient.ChatBots
|
namespace MinecraftClient.ChatBots
|
||||||
{
|
{
|
||||||
|
|
@ -11,6 +12,60 @@ namespace MinecraftClient.ChatBots
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class Mailer : ChatBot
|
public class Mailer : ChatBot
|
||||||
{
|
{
|
||||||
|
public static Configs Config = new();
|
||||||
|
|
||||||
|
[TomlDoNotInlineObject]
|
||||||
|
public class Configs
|
||||||
|
{
|
||||||
|
[NonSerialized]
|
||||||
|
private const string BotName = "Mailer";
|
||||||
|
|
||||||
|
public bool Enabled = false;
|
||||||
|
|
||||||
|
public string DatabaseFile = "MailerDatabase.ini";
|
||||||
|
|
||||||
|
public string IgnoreListFile = "MailerIgnoreList.ini";
|
||||||
|
|
||||||
|
public bool PublicInteractions = false;
|
||||||
|
|
||||||
|
public int MaxMailsPerPlayer = 10;
|
||||||
|
|
||||||
|
public int MaxDatabaseSize = 10000;
|
||||||
|
|
||||||
|
public int MailRetentionDays = 30;
|
||||||
|
|
||||||
|
public void OnSettingUpdate()
|
||||||
|
{
|
||||||
|
if (!Enabled) return;
|
||||||
|
|
||||||
|
bool checkSuccessed = true;
|
||||||
|
|
||||||
|
if (Config.MaxDatabaseSize <= 0)
|
||||||
|
{
|
||||||
|
LogToConsole(BotName, Translations.TryGet("bot.mailer.init_fail.db_size"));
|
||||||
|
checkSuccessed = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Config.MaxMailsPerPlayer <= 0)
|
||||||
|
{
|
||||||
|
LogToConsole(BotName, Translations.TryGet("bot.mailer.init_fail.max_mails"));
|
||||||
|
checkSuccessed = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Config.MailRetentionDays <= 0)
|
||||||
|
{
|
||||||
|
LogToConsole(BotName, Translations.TryGet("bot.mailer.init_fail.mail_retention"));
|
||||||
|
checkSuccessed = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!checkSuccessed)
|
||||||
|
{
|
||||||
|
LogToConsole(BotName, Translations.TryGet("general.bot_unload"));
|
||||||
|
Enabled = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Holds the list of ignored players
|
/// Holds the list of ignored players
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
@ -161,58 +216,37 @@ namespace MinecraftClient.ChatBots
|
||||||
public override void Initialize()
|
public override void Initialize()
|
||||||
{
|
{
|
||||||
LogDebugToConsoleTranslated("bot.mailer.init");
|
LogDebugToConsoleTranslated("bot.mailer.init");
|
||||||
LogDebugToConsoleTranslated("bot.mailer.init.db" + Settings.Mailer_DatabaseFile);
|
LogDebugToConsoleTranslated("bot.mailer.init.db" + Config.DatabaseFile);
|
||||||
LogDebugToConsoleTranslated("bot.mailer.init.ignore" + Settings.Mailer_IgnoreListFile);
|
LogDebugToConsoleTranslated("bot.mailer.init.ignore" + Config.IgnoreListFile);
|
||||||
LogDebugToConsoleTranslated("bot.mailer.init.public" + Settings.Mailer_PublicInteractions);
|
LogDebugToConsoleTranslated("bot.mailer.init.public" + Config.PublicInteractions);
|
||||||
LogDebugToConsoleTranslated("bot.mailer.init.max_mails" + Settings.Mailer_MaxMailsPerPlayer);
|
LogDebugToConsoleTranslated("bot.mailer.init.max_mails" + Config.MaxMailsPerPlayer);
|
||||||
LogDebugToConsoleTranslated("bot.mailer.init.db_size" + Settings.Mailer_MaxDatabaseSize);
|
LogDebugToConsoleTranslated("bot.mailer.init.db_size" + Config.MaxDatabaseSize);
|
||||||
LogDebugToConsoleTranslated("bot.mailer.init.mail_retention" + Settings.Mailer_MailRetentionDays + " days");
|
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");
|
LogToConsoleTranslated("bot.mailer.create.db", Path.GetFullPath(Config.DatabaseFile));
|
||||||
UnloadBot();
|
new MailDatabase().SaveToFile(Config.DatabaseFile);
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Settings.Mailer_MaxMailsPerPlayer <= 0)
|
if (!File.Exists(Config.IgnoreListFile))
|
||||||
{
|
{
|
||||||
LogToConsoleTranslated("bot.mailer.init_fail.max_mails");
|
LogToConsoleTranslated("bot.mailer.create.ignore", Path.GetFullPath(Config.IgnoreListFile));
|
||||||
UnloadBot();
|
new IgnoreList().SaveToFile(Config.IgnoreListFile);
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
lock (readWriteLock)
|
lock (readWriteLock)
|
||||||
{
|
{
|
||||||
LogDebugToConsoleTranslated("bot.mailer.load.db", Path.GetFullPath(Settings.Mailer_DatabaseFile));
|
LogDebugToConsoleTranslated("bot.mailer.load.db", Path.GetFullPath(Config.DatabaseFile));
|
||||||
mailDatabase = MailDatabase.FromFile(Settings.Mailer_DatabaseFile);
|
mailDatabase = MailDatabase.FromFile(Config.DatabaseFile);
|
||||||
|
|
||||||
LogDebugToConsoleTranslated("bot.mailer.load.ignore", Path.GetFullPath(Settings.Mailer_IgnoreListFile));
|
LogDebugToConsoleTranslated("bot.mailer.load.ignore", Path.GetFullPath(Config.IgnoreListFile));
|
||||||
ignoreList = IgnoreList.FromFile(Settings.Mailer_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
|
//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);
|
mailDbFileMonitor = new FileMonitor(Path.GetDirectoryName(Config.DatabaseFile)!, Path.GetFileName(Config.DatabaseFile), FileMonitorCallback);
|
||||||
ignoreListFileMonitor = new FileMonitor(Path.GetDirectoryName(Settings.Mailer_IgnoreListFile)!, Path.GetFileName(Settings.Mailer_IgnoreListFile), 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);
|
RegisterChatBotCommand("mailer", Translations.Get("bot.mailer.cmd"), "mailer <getmails|addignored|getignored|removeignored>", ProcessInternalCommand);
|
||||||
}
|
}
|
||||||
|
|
@ -224,7 +258,7 @@ namespace MinecraftClient.ChatBots
|
||||||
{
|
{
|
||||||
maxMessageLength = GetMaxChatMessageLength()
|
maxMessageLength = GetMaxChatMessageLength()
|
||||||
- 44 // Deduct length of "/ 16CharPlayerName 16CharPlayerName mailed: "
|
- 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>
|
/// <summary>
|
||||||
|
|
@ -236,7 +270,7 @@ namespace MinecraftClient.ChatBots
|
||||||
string username = "";
|
string username = "";
|
||||||
text = GetVerbatim(text);
|
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();
|
string usernameLower = username.ToLower();
|
||||||
if (!ignoreList.Contains(usernameLower))
|
if (!ignoreList.Contains(usernameLower))
|
||||||
|
|
@ -247,8 +281,8 @@ namespace MinecraftClient.ChatBots
|
||||||
case "mail":
|
case "mail":
|
||||||
case "tellonym":
|
case "tellonym":
|
||||||
if (usernameLower != GetUsername().ToLower()
|
if (usernameLower != GetUsername().ToLower()
|
||||||
&& mailDatabase.Count < Settings.Mailer_MaxDatabaseSize
|
&& mailDatabase.Count < Config.MaxDatabaseSize
|
||||||
&& mailDatabase.Where(mail => mail.SenderLowercase == usernameLower).Count() < Settings.Mailer_MaxMailsPerPlayer)
|
&& mailDatabase.Where(mail => mail.SenderLowercase == usernameLower).Count() < Config.MaxMailsPerPlayer)
|
||||||
{
|
{
|
||||||
Queue<string> args = new(Command.GetArgs(message));
|
Queue<string> args = new(Command.GetArgs(message));
|
||||||
if (args.Count >= 2)
|
if (args.Count >= 2)
|
||||||
|
|
@ -266,7 +300,7 @@ namespace MinecraftClient.ChatBots
|
||||||
lock (readWriteLock)
|
lock (readWriteLock)
|
||||||
{
|
{
|
||||||
mailDatabase.Add(mail);
|
mailDatabase.Add(mail);
|
||||||
mailDatabase.SaveToFile(Settings.Mailer_DatabaseFile);
|
mailDatabase.SaveToFile(Config.DatabaseFile);
|
||||||
}
|
}
|
||||||
SendPrivateMessage(username, "Message saved!");
|
SendPrivateMessage(username, "Message saved!");
|
||||||
}
|
}
|
||||||
|
|
@ -307,8 +341,8 @@ namespace MinecraftClient.ChatBots
|
||||||
lock (readWriteLock)
|
lock (readWriteLock)
|
||||||
{
|
{
|
||||||
mailDatabase.RemoveAll(mail => mail.Delivered);
|
mailDatabase.RemoveAll(mail => mail.Delivered);
|
||||||
mailDatabase.RemoveAll(mail => mail.DateSent.AddDays(Settings.Mailer_MailRetentionDays) < DateTime.Now);
|
mailDatabase.RemoveAll(mail => mail.DateSent.AddDays(Config.MailRetentionDays) < DateTime.Now);
|
||||||
mailDatabase.SaveToFile(Settings.Mailer_DatabaseFile);
|
mailDatabase.SaveToFile(Config.DatabaseFile);
|
||||||
}
|
}
|
||||||
|
|
||||||
nextMailSend = dateNow.AddSeconds(10);
|
nextMailSend = dateNow.AddSeconds(10);
|
||||||
|
|
@ -324,8 +358,8 @@ namespace MinecraftClient.ChatBots
|
||||||
{
|
{
|
||||||
lock (readWriteLock)
|
lock (readWriteLock)
|
||||||
{
|
{
|
||||||
mailDatabase = MailDatabase.FromFile(Settings.Mailer_DatabaseFile);
|
mailDatabase = MailDatabase.FromFile(Config.DatabaseFile);
|
||||||
ignoreList = IgnoreList.FromFile(Settings.Mailer_IgnoreListFile);
|
ignoreList = IgnoreList.FromFile(Config.IgnoreListFile);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -357,7 +391,7 @@ namespace MinecraftClient.ChatBots
|
||||||
if (!ignoreList.Contains(username))
|
if (!ignoreList.Contains(username))
|
||||||
{
|
{
|
||||||
ignoreList.Add(username);
|
ignoreList.Add(username);
|
||||||
ignoreList.SaveToFile(Settings.Mailer_IgnoreListFile);
|
ignoreList.SaveToFile(Config.IgnoreListFile);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return Translations.Get("bot.mailer.cmd.ignore.added", args[1]);
|
return Translations.Get("bot.mailer.cmd.ignore.added", args[1]);
|
||||||
|
|
@ -369,7 +403,7 @@ namespace MinecraftClient.ChatBots
|
||||||
if (ignoreList.Contains(username))
|
if (ignoreList.Contains(username))
|
||||||
{
|
{
|
||||||
ignoreList.Remove(username);
|
ignoreList.Remove(username);
|
||||||
ignoreList.SaveToFile(Settings.Mailer_IgnoreListFile);
|
ignoreList.SaveToFile(Config.IgnoreListFile);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return Translations.Get("bot.mailer.cmd.ignore.removed", args[1]);
|
return Translations.Get("bot.mailer.cmd.ignore.removed", args[1]);
|
||||||
|
|
|
||||||
|
|
@ -5,41 +5,59 @@ using System.Globalization;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using MinecraftClient.Mapping;
|
using MinecraftClient.Mapping;
|
||||||
using MinecraftClient.Protocol.Handlers;
|
using MinecraftClient.Protocol.Handlers;
|
||||||
|
using Tomlet.Attributes;
|
||||||
|
|
||||||
namespace MinecraftClient.ChatBots
|
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 string baseDirectory = @"Rendered_Maps";
|
||||||
|
|
||||||
private readonly Dictionary<int, McMap> cachedMaps = new();
|
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()
|
public override void Initialize()
|
||||||
{
|
{
|
||||||
if (!Directory.Exists(baseDirectory))
|
if (!Directory.Exists(baseDirectory))
|
||||||
Directory.CreateDirectory(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);
|
RegisterChatBotCommand("maps", "bot.map.cmd.desc", "maps list|render <id> or maps l|r <id>", OnMapCommand);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void OnUnload()
|
public override void OnUnload()
|
||||||
{
|
{
|
||||||
if (deleteAllOnExit)
|
if (Config.Delete_All_On_Unload)
|
||||||
{
|
{
|
||||||
DirectoryInfo di = new(baseDirectory);
|
DirectoryInfo di = new(baseDirectory);
|
||||||
FileInfo[] files = di.GetFiles();
|
FileInfo[] files = di.GetFiles();
|
||||||
|
|
@ -124,7 +142,7 @@ namespace MinecraftClient.ChatBots
|
||||||
{
|
{
|
||||||
cachedMaps.Add(mapid, map);
|
cachedMaps.Add(mapid, map);
|
||||||
|
|
||||||
if (notifyOnFirstUpdate)
|
if (Config.Notify_On_First_Update)
|
||||||
LogToConsoleTranslated("bot.map.received_map", map.MapId);
|
LogToConsoleTranslated("bot.map.received_map", map.MapId);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
@ -133,7 +151,7 @@ namespace MinecraftClient.ChatBots
|
||||||
cachedMaps.Add(mapid, map);
|
cachedMaps.Add(mapid, map);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (autoRenderOnUpdate)
|
if (Config.Auto_Render_On_Update)
|
||||||
GenerateMapImage(map);
|
GenerateMapImage(map);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -165,8 +183,8 @@ namespace MinecraftClient.ChatBots
|
||||||
|
|
||||||
// Resize, double the image
|
// Resize, double the image
|
||||||
|
|
||||||
if (shouldResize)
|
if (Config.Should_Resize)
|
||||||
image = ResizeBitmap(image, resizeTo, resizeTo);
|
image = ResizeBitmap(image, Config.Resize_To, Config.Resize_To);
|
||||||
|
|
||||||
image.Save(fileName);
|
image.Save(fileName);
|
||||||
LogToConsole(Translations.TryGet("bot.map.rendered", map.MapId, fileName));
|
LogToConsole(Translations.TryGet("bot.map.rendered", map.MapId, fileName));
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
using Tomlet.Attributes;
|
||||||
|
|
||||||
namespace MinecraftClient.ChatBots
|
namespace MinecraftClient.ChatBots
|
||||||
{
|
{
|
||||||
|
|
@ -10,28 +11,34 @@ namespace MinecraftClient.ChatBots
|
||||||
|
|
||||||
public class PlayerListLogger : ChatBot
|
public class PlayerListLogger : ChatBot
|
||||||
{
|
{
|
||||||
private int count;
|
public static Configs Config = new();
|
||||||
private readonly int timeping;
|
|
||||||
private readonly string file;
|
|
||||||
|
|
||||||
/// <summary>
|
[TomlDoNotInlineObject]
|
||||||
/// This bot sends a /list command every X seconds and save the result.
|
public class Configs
|
||||||
/// </summary>
|
|
||||||
/// <param name="pingparam">Time amount between each list ping (10 = 1s, 600 = 1 minute, etc.)</param>
|
|
||||||
|
|
||||||
public PlayerListLogger(int pingparam, string filetosavein)
|
|
||||||
{
|
{
|
||||||
count = 0;
|
[NonSerialized]
|
||||||
file = filetosavein;
|
private const string BotName = "PlayerListLogger";
|
||||||
timeping = pingparam;
|
|
||||||
if (timeping < 10) { timeping = 10; } //To avoid flooding
|
|
||||||
|
|
||||||
|
public bool Enabled = false;
|
||||||
|
|
||||||
|
public string File = "playerlog.txt";
|
||||||
|
|
||||||
|
[TomlInlineComment("$config.ChatBot.PlayerListLogger.Delay$")]
|
||||||
|
public int Delay = 600;
|
||||||
|
|
||||||
|
public void OnSettingUpdate()
|
||||||
|
{
|
||||||
|
if (Delay < 10)
|
||||||
|
Delay = 10;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private int count = 0;
|
||||||
|
|
||||||
public override void Update()
|
public override void Update()
|
||||||
{
|
{
|
||||||
count++;
|
count++;
|
||||||
if (count == timeping)
|
if (count == Config.Delay)
|
||||||
{
|
{
|
||||||
DateTime now = DateTime.Now;
|
DateTime now = DateTime.Now;
|
||||||
|
|
||||||
|
|
@ -40,7 +47,7 @@ namespace MinecraftClient.ChatBots
|
||||||
StringBuilder sb = new();
|
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.Format("[{0}/{1}/{2} {3}:{4}]", now.Year, now.Month, now.Day, now.Hour, now.Minute));
|
||||||
sb.AppendLine(string.Join(", ", GetOnlinePlayers())).AppendLine();
|
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;
|
count = 0;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
using System;
|
using System;
|
||||||
|
using Tomlet.Attributes;
|
||||||
|
|
||||||
namespace MinecraftClient.ChatBots
|
namespace MinecraftClient.ChatBots
|
||||||
{
|
{
|
||||||
|
|
@ -8,11 +9,28 @@ namespace MinecraftClient.ChatBots
|
||||||
|
|
||||||
public class RemoteControl : ChatBot
|
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)
|
public override void GetText(string text)
|
||||||
{
|
{
|
||||||
text = GetVerbatim(text).Trim();
|
text = GetVerbatim(text).Trim();
|
||||||
string command = "", sender = "";
|
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 = "";
|
string? response = "";
|
||||||
PerformInternalCommand(command, ref response);
|
PerformInternalCommand(command, ref response);
|
||||||
|
|
@ -26,9 +44,9 @@ namespace MinecraftClient.ChatBots
|
||||||
SendPrivateMessage(sender, response);
|
SendPrivateMessage(sender, response);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (Settings.RemoteCtrl_AutoTpaccept
|
else if (Config.AutoTpaccept
|
||||||
&& IsTeleportRequest(text, ref sender)
|
&& 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");
|
SendText("/tpaccept");
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using MinecraftClient.Protocol;
|
using MinecraftClient.Protocol;
|
||||||
|
using Tomlet.Attributes;
|
||||||
|
|
||||||
namespace MinecraftClient.ChatBots
|
namespace MinecraftClient.ChatBots
|
||||||
{
|
{
|
||||||
|
|
@ -9,24 +10,35 @@ namespace MinecraftClient.ChatBots
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class ReplayCapture : ChatBot
|
public class ReplayCapture : ChatBot
|
||||||
{
|
{
|
||||||
private ReplayHandler? replay;
|
public static Configs Config = new();
|
||||||
private readonly int backupInterval = 3000; // Unit: second * 10
|
|
||||||
private int backupCounter = -1;
|
|
||||||
|
|
||||||
public ReplayCapture(int backupInterval)
|
[TomlDoNotInlineObject]
|
||||||
|
public class Configs
|
||||||
{
|
{
|
||||||
if (backupInterval != -1)
|
[NonSerialized]
|
||||||
this.backupInterval = backupInterval * 10;
|
private const string BotName = "ReplayCapture";
|
||||||
else
|
|
||||||
this.backupInterval = -1;
|
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()
|
public override void Initialize()
|
||||||
{
|
{
|
||||||
SetNetworkPacketEventEnabled(true);
|
SetNetworkPacketEventEnabled(true);
|
||||||
replay = new ReplayHandler(GetProtocolVersion());
|
replay = new ReplayHandler(GetProtocolVersion());
|
||||||
replay.MetaData.serverName = GetServerHost() + GetServerPort();
|
replay.MetaData.serverName = GetServerHost() + GetServerPort();
|
||||||
backupCounter = backupInterval;
|
backupCounter = Config.Backup_Interval * 10;
|
||||||
|
|
||||||
RegisterChatBotCommand("replay", Translations.Get("bot.replayCapture.cmd"), "replay <save|stop>", Command);
|
RegisterChatBotCommand("replay", Translations.Get("bot.replayCapture.cmd"), "replay <save|stop>", Command);
|
||||||
}
|
}
|
||||||
|
|
@ -38,12 +50,12 @@ namespace MinecraftClient.ChatBots
|
||||||
|
|
||||||
public override void Update()
|
public override void Update()
|
||||||
{
|
{
|
||||||
if (backupInterval > 0 && replay!.RecordRunning)
|
if (Config.Backup_Interval > 0 && replay!.RecordRunning)
|
||||||
{
|
{
|
||||||
if (backupCounter <= 0)
|
if (backupCounter <= 0)
|
||||||
{
|
{
|
||||||
replay.CreateBackupReplay(@"recording_cache\REPLAY_BACKUP.mcpr");
|
replay.CreateBackupReplay(@"recording_cache\REPLAY_BACKUP.mcpr");
|
||||||
backupCounter = backupInterval;
|
backupCounter = Config.Backup_Interval * 10;
|
||||||
}
|
}
|
||||||
else backupCounter--;
|
else backupCounter--;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -107,7 +107,7 @@ namespace MinecraftClient.ChatBots
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Settings.DebugMessages)
|
if (Settings.Config.Logging.DebugMessages)
|
||||||
{
|
{
|
||||||
string caller = "Script";
|
string caller = "Script";
|
||||||
try
|
try
|
||||||
|
|
@ -195,7 +195,7 @@ namespace MinecraftClient.ChatBots
|
||||||
{
|
{
|
||||||
if (instruction_line[0] != '#' && instruction_line[0] != '/' && instruction_line[1] != '/')
|
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];
|
string instruction_name = instruction_line.Split(' ')[0];
|
||||||
switch (instruction_name.ToLower())
|
switch (instruction_name.ToLower())
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,9 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
|
using System.IO;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
using Tomlet.Attributes;
|
||||||
|
|
||||||
namespace MinecraftClient.ChatBots
|
namespace MinecraftClient.ChatBots
|
||||||
{
|
{
|
||||||
|
|
@ -11,6 +13,32 @@ namespace MinecraftClient.ChatBots
|
||||||
|
|
||||||
public class ScriptScheduler : ChatBot
|
public class ScriptScheduler : ChatBot
|
||||||
{
|
{
|
||||||
|
public static Configs Config = new();
|
||||||
|
|
||||||
|
[TomlDoNotInlineObject]
|
||||||
|
public class Configs
|
||||||
|
{
|
||||||
|
[NonSerialized]
|
||||||
|
private const string BotName = "ScriptScheduler";
|
||||||
|
|
||||||
|
public bool Enabled = false;
|
||||||
|
|
||||||
|
public string Tasks_File = @"tasks.ini";
|
||||||
|
|
||||||
|
public void OnSettingUpdate()
|
||||||
|
{
|
||||||
|
if (!Enabled) return;
|
||||||
|
|
||||||
|
string Tasks_File_Full = Settings.Config.AppVar.ExpandVars(Tasks_File);
|
||||||
|
if (!File.Exists(Tasks_File_Full))
|
||||||
|
{
|
||||||
|
LogToConsole(BotName, Translations.TryGet("bot.scriptScheduler.not_found", Path.GetFullPath(Tasks_File_Full)));
|
||||||
|
LogToConsole(BotName, Translations.TryGet("general.bot_unload"));
|
||||||
|
Enabled = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private class TaskDesc
|
private class TaskDesc
|
||||||
{
|
{
|
||||||
public string? action = null;
|
public string? action = null;
|
||||||
|
|
@ -27,26 +55,20 @@ namespace MinecraftClient.ChatBots
|
||||||
|
|
||||||
private static bool firstlogin_done = false;
|
private static bool firstlogin_done = false;
|
||||||
|
|
||||||
private readonly string tasksfile;
|
private bool serverlogin_done = false;
|
||||||
private bool serverlogin_done;
|
|
||||||
private readonly List<TaskDesc> tasks = new();
|
private readonly List<TaskDesc> tasks = new();
|
||||||
private int verifytasks_timeleft = 10;
|
private int verifytasks_timeleft = 10;
|
||||||
private readonly int verifytasks_delay = 10;
|
private readonly int verifytasks_delay = 10;
|
||||||
|
|
||||||
public ScriptScheduler(string tasksfile)
|
|
||||||
{
|
|
||||||
this.tasksfile = tasksfile;
|
|
||||||
serverlogin_done = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void Initialize()
|
public override void Initialize()
|
||||||
{
|
{
|
||||||
//Load the given file from the startup parameters
|
//Load the given file from the startup parameters
|
||||||
if (System.IO.File.Exists(tasksfile))
|
string Tasks_File_Full = Settings.Config.AppVar.ExpandVars(Config.Tasks_File);
|
||||||
|
if (File.Exists(Tasks_File_Full))
|
||||||
{
|
{
|
||||||
LogDebugToConsoleTranslated("bot.scriptScheduler.loading", System.IO.Path.GetFullPath(tasksfile));
|
LogDebugToConsoleTranslated("bot.scriptScheduler.loading", System.IO.Path.GetFullPath(Tasks_File_Full));
|
||||||
TaskDesc? current_task = null;
|
TaskDesc? current_task = null;
|
||||||
string[] lines = System.IO.File.ReadAllLines(tasksfile, Encoding.UTF8);
|
string[] lines = System.IO.File.ReadAllLines(Tasks_File_Full, Encoding.UTF8);
|
||||||
foreach (string lineRAW in lines)
|
foreach (string lineRAW in lines)
|
||||||
{
|
{
|
||||||
string line = lineRAW.Split('#')[0].Trim();
|
string line = lineRAW.Split('#')[0].Trim();
|
||||||
|
|
@ -70,10 +92,10 @@ namespace MinecraftClient.ChatBots
|
||||||
string argValue = line[(argName.Length + 1)..];
|
string argValue = line[(argName.Length + 1)..];
|
||||||
switch (argName.ToLower())
|
switch (argName.ToLower())
|
||||||
{
|
{
|
||||||
case "triggeronfirstlogin": current_task.triggerOnFirstLogin = Settings.str2bool(argValue); break;
|
case "triggeronfirstlogin": current_task.triggerOnFirstLogin = bool.Parse(argValue); break;
|
||||||
case "triggeronlogin": current_task.triggerOnLogin = Settings.str2bool(argValue); break;
|
case "triggeronlogin": current_task.triggerOnLogin = bool.Parse(argValue); break;
|
||||||
case "triggerontime": current_task.triggerOnTime = Settings.str2bool(argValue); break;
|
case "triggerontime": current_task.triggerOnTime = bool.Parse(argValue); break;
|
||||||
case "triggeroninterval": current_task.triggerOnInterval = Settings.str2bool(argValue); break;
|
case "triggeroninterval": current_task.triggerOnInterval = bool.Parse(argValue); break;
|
||||||
case "timevalue": try { current_task.triggerOnTime_Times.Add(DateTime.ParseExact(argValue, "HH:mm", CultureInfo.InvariantCulture)); } catch { } break;
|
case "timevalue": try { current_task.triggerOnTime_Times.Add(DateTime.ParseExact(argValue, "HH:mm", CultureInfo.InvariantCulture)); } catch { } break;
|
||||||
case "timeinterval":
|
case "timeinterval":
|
||||||
int interval;
|
int interval;
|
||||||
|
|
@ -112,7 +134,7 @@ namespace MinecraftClient.ChatBots
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
LogToConsoleTranslated("bot.scriptScheduler.not_found", System.IO.Path.GetFullPath(tasksfile));
|
LogToConsoleTranslated("bot.scriptScheduler.not_found", Path.GetFullPath(Tasks_File_Full));
|
||||||
UnloadBot(); //No need to keep the bot active
|
UnloadBot(); //No need to keep the bot active
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -138,7 +138,7 @@ namespace MinecraftClient.Commands
|
||||||
|
|
||||||
|
|
||||||
// \ud83d\udd33: 🔳, \ud83d\udfe8: 🟨, \ud83d\udfe9: 🟩, \u25A1: □, \u25A3: ▣, \u25A0: ■
|
// \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" };
|
new string[] { "\ud83d\udd33", "\ud83d\udfe8", "\ud83d\udfe9" } : new string[] { "\u25A1", "\u25A3", "\u25A0" };
|
||||||
|
|
||||||
// Output
|
// Output
|
||||||
|
|
|
||||||
|
|
@ -15,13 +15,13 @@ namespace MinecraftClient.Commands
|
||||||
string[] args = GetArgs(command);
|
string[] args = GetArgs(command);
|
||||||
if (args.Length > 1)
|
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]);
|
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();
|
Program.Restart();
|
||||||
return "";
|
return "";
|
||||||
|
|
|
||||||
|
|
@ -11,11 +11,10 @@ namespace MinecraftClient.Commands
|
||||||
public override string Run(McClient handler, string command, Dictionary<string, object>? localVars)
|
public override string Run(McClient handler, string command, Dictionary<string, object>? localVars)
|
||||||
{
|
{
|
||||||
if (HasArg(command))
|
if (HasArg(command))
|
||||||
{
|
Settings.Config.Logging.DebugMessages = (GetArg(command).ToLower() == "on");
|
||||||
Settings.DebugMessages = (GetArg(command).ToLower() == "on");
|
else
|
||||||
}
|
Settings.Config.Logging.DebugMessages = !Settings.Config.Logging.DebugMessages;
|
||||||
else Settings.DebugMessages = !Settings.DebugMessages;
|
return Translations.Get(Settings.Config.Logging.DebugMessages ? "cmd.debug.state_on" : "cmd.debug.state_off");
|
||||||
return Translations.Get(Settings.DebugMessages ? "cmd.debug.state_on" : "cmd.debug.state_off");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -36,7 +36,7 @@ namespace MinecraftClient.Commands
|
||||||
var interpreter = new Interpreter();
|
var interpreter = new Interpreter();
|
||||||
interpreter.SetVariable("MCC", handler);
|
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);
|
interpreter.SetVariable(entry.Key, entry.Value);
|
||||||
|
|
||||||
var result = interpreter.Eval<bool>(expressionText);
|
var result = interpreter.Eval<bool>(expressionText);
|
||||||
|
|
|
||||||
|
|
@ -185,7 +185,7 @@ namespace MinecraftClient.Commands
|
||||||
response.AppendLine(String.Format(" #{0} - {1}§8", inventoryId, inventory.Title));
|
response.AppendLine(String.Format(" #{0} - {1}§8", inventoryId, inventory.Title));
|
||||||
|
|
||||||
string? asciiArt = inventory.Type.GetAsciiArt();
|
string? asciiArt = inventory.Type.GetAsciiArt();
|
||||||
if (asciiArt != null && Settings.DisplayInventoryLayout)
|
if (asciiArt != null && Settings.Config.Main.Advanced.ShowInventoryLayout)
|
||||||
response.AppendLine(asciiArt);
|
response.AppendLine(asciiArt);
|
||||||
|
|
||||||
int selectedHotbar = handler.GetCurrentSlot() + 1;
|
int selectedHotbar = handler.GetCurrentSlot() + 1;
|
||||||
|
|
|
||||||
|
|
@ -45,8 +45,8 @@ namespace MinecraftClient.Commands
|
||||||
else if (args[0] == "gravity")
|
else if (args[0] == "gravity")
|
||||||
{
|
{
|
||||||
if (args.Count >= 2)
|
if (args.Count >= 2)
|
||||||
Settings.GravityEnabled = (args[1] == "on");
|
Settings.InternalConfig.GravityEnabled = (args[1] == "on");
|
||||||
if (Settings.GravityEnabled)
|
if (Settings.InternalConfig.GravityEnabled)
|
||||||
return Translations.Get("cmd.move.gravity.enabled");
|
return Translations.Get("cmd.move.gravity.enabled");
|
||||||
else return Translations.Get("cmd.move.gravity.disabled");
|
else return Translations.Get("cmd.move.gravity.disabled");
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@ namespace MinecraftClient.Commands
|
||||||
string[] args = GetArgs(command);
|
string[] args = GetArgs(command);
|
||||||
if (args.Length > 0)
|
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]);
|
return Translations.Get("cmd.connect.unknown", args[0]);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -15,15 +15,16 @@ namespace MinecraftClient.Commands
|
||||||
string[] temp = GetArg(command).Split('=');
|
string[] temp = GetArg(command).Split('=');
|
||||||
if (temp.Length > 1)
|
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
|
return ""; //Success
|
||||||
}
|
else
|
||||||
else return Translations.Get("cmd.set.format");
|
return Translations.Get("cmd.set.format");
|
||||||
}
|
}
|
||||||
else return GetCmdDescTranslated();
|
else
|
||||||
|
return GetCmdDescTranslated();
|
||||||
}
|
}
|
||||||
else return GetCmdDescTranslated();
|
else
|
||||||
|
return GetCmdDescTranslated();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -40,9 +40,9 @@ namespace MinecraftClient.Commands
|
||||||
(num2, num1) = (num1, num2);
|
(num2, num1) = (num1, num2);
|
||||||
|
|
||||||
// create a variable or set it to num1 <= varlue < 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");
|
else return Translations.Get("cmd.setrndnum.format");
|
||||||
}
|
}
|
||||||
|
|
@ -55,9 +55,9 @@ namespace MinecraftClient.Commands
|
||||||
List<string> values = ParseCommandLine(argString);
|
List<string> values = ParseCommandLine(argString);
|
||||||
|
|
||||||
// create a variable or set it to one of the values
|
// 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");
|
else return Translations.Get("cmd.setrndstr.format");
|
||||||
}
|
}
|
||||||
|
|
|
||||||
332
MinecraftClient/DefaultConfigResource.Designer.cs
generated
332
MinecraftClient/DefaultConfigResource.Designer.cs
generated
|
|
@ -8,11 +8,10 @@
|
||||||
// </auto-generated>
|
// </auto-generated>
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
namespace MinecraftClient
|
namespace MinecraftClient {
|
||||||
{
|
|
||||||
using System;
|
using System;
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A strongly-typed resource class, for looking up localized strings, etc.
|
/// A strongly-typed resource class, for looking up localized strings, etc.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
@ -20,55 +19,47 @@ namespace MinecraftClient
|
||||||
// class via a tool like ResGen or Visual Studio.
|
// class via a tool like ResGen or Visual Studio.
|
||||||
// To add or remove a member, edit your .ResX file then rerun ResGen
|
// To add or remove a member, edit your .ResX file then rerun ResGen
|
||||||
// with the /str option, or rebuild your VS project.
|
// 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.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||||
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
||||||
public class DefaultConfigResource
|
public class DefaultConfigResource {
|
||||||
{
|
|
||||||
|
|
||||||
private static global::System.Resources.ResourceManager resourceMan;
|
private static global::System.Resources.ResourceManager resourceMan;
|
||||||
|
|
||||||
private static global::System.Globalization.CultureInfo resourceCulture;
|
private static global::System.Globalization.CultureInfo resourceCulture;
|
||||||
|
|
||||||
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
|
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
|
||||||
internal DefaultConfigResource()
|
internal DefaultConfigResource() {
|
||||||
{
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Returns the cached ResourceManager instance used by this class.
|
/// Returns the cached ResourceManager instance used by this class.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||||
public static global::System.Resources.ResourceManager ResourceManager
|
public static global::System.Resources.ResourceManager ResourceManager {
|
||||||
{
|
get {
|
||||||
get
|
if (object.ReferenceEquals(resourceMan, null)) {
|
||||||
{
|
|
||||||
if (object.ReferenceEquals(resourceMan, null))
|
|
||||||
{
|
|
||||||
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("MinecraftClient.DefaultConfigResource", typeof(DefaultConfigResource).Assembly);
|
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("MinecraftClient.DefaultConfigResource", typeof(DefaultConfigResource).Assembly);
|
||||||
resourceMan = temp;
|
resourceMan = temp;
|
||||||
}
|
}
|
||||||
return resourceMan;
|
return resourceMan;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Overrides the current thread's CurrentUICulture property for all
|
/// Overrides the current thread's CurrentUICulture property for all
|
||||||
/// resource lookups using this strongly typed resource class.
|
/// resource lookups using this strongly typed resource class.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||||
public static global::System.Globalization.CultureInfo Culture
|
public static global::System.Globalization.CultureInfo Culture {
|
||||||
{
|
get {
|
||||||
get
|
|
||||||
{
|
|
||||||
return resourceCulture;
|
return resourceCulture;
|
||||||
}
|
}
|
||||||
set
|
set {
|
||||||
{
|
|
||||||
resourceCulture = value;
|
resourceCulture = value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Looks up a localized string similar to ╔═════════════════════════════════════╗
|
/// Looks up a localized string similar to ╔═════════════════════════════════════╗
|
||||||
///║ Brewing Stand ║
|
///║ Brewing Stand ║
|
||||||
|
|
@ -82,16 +73,14 @@ namespace MinecraftClient
|
||||||
///║ Inventory ╚═══╝ ║
|
///║ Inventory ╚═══╝ ║
|
||||||
///║╔═══╦═══╦═══╦═══╦═══╦═══╦═══╦═══╦═══╗║
|
///║╔═══╦═══╦═══╦═══╦═══╦═══╦═══╦═══╦═══╗║
|
||||||
///║║ 5 ║ 6 ║ 7 ║ 8 ║ 9 ║10 ║11 ║12 ║13 ║║
|
///║║ 5 ║ 6 ║ 7 ║ 8 ║ 9 ║10 ║11 ║12 ║13 ║║
|
||||||
///║╠═══╬═══╬═══╬═══╬═══╬═══╬═══╬══ [rest of string was truncated]";.
|
///║╠═══╬═══╬═══╬═══╬══ [rest of string was truncated]";.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static string ContainerType_BrewingStand
|
public static string ContainerType_BrewingStand {
|
||||||
{
|
get {
|
||||||
get
|
|
||||||
{
|
|
||||||
return ResourceManager.GetString("ContainerType_BrewingStand", resourceCulture);
|
return ResourceManager.GetString("ContainerType_BrewingStand", resourceCulture);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Looks up a localized string similar to ╔═════════════════════════════════════╗
|
/// Looks up a localized string similar to ╔═════════════════════════════════════╗
|
||||||
///║ Crafting ║
|
///║ Crafting ║
|
||||||
|
|
@ -105,24 +94,35 @@ namespace MinecraftClient
|
||||||
///║ Inventory ║
|
///║ Inventory ║
|
||||||
///║╔═══╦═══╦═══╦═══╦═══╦═══╦═══╦═══╦═══╗║
|
///║╔═══╦═══╦═══╦═══╦═══╦═══╦═══╦═══╦═══╗║
|
||||||
///║║10 ║11 ║12 ║13 ║14 ║15 ║16 ║17 ║18 ║║
|
///║║10 ║11 ║12 ║13 ║14 ║15 ║16 ║17 ║18 ║║
|
||||||
///║╠═══╬═══╬═══╬═══╬═══╬═══╬═══╬══ [rest of string was truncated]";.
|
///║╠═══╬═══╬═══╬═══╬══ [rest of string was truncated]";.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static string ContainerType_Crafting
|
public static string ContainerType_Crafting {
|
||||||
{
|
get {
|
||||||
get
|
|
||||||
{
|
|
||||||
return ResourceManager.GetString("ContainerType_Crafting", resourceCulture);
|
return ResourceManager.GetString("ContainerType_Crafting", resourceCulture);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static string ContainerType_Furnace
|
/// <summary>
|
||||||
{
|
/// Looks up a localized string similar to ╔═════════════════════════════════════╗
|
||||||
get
|
///║ Container ║
|
||||||
{
|
///║ ╔═══╗ ║
|
||||||
|
///║ ║ 0 ║ ║
|
||||||
|
///║ ╚═══╝ ╔═══╗ ║
|
||||||
|
///║ ⠂⡠⢂ ━━▶ ║ 2 ║ ║
|
||||||
|
///║ ⠂⡠⢂ ╚═══╝ ║
|
||||||
|
///║ ╔═══╗ ║
|
||||||
|
///║ ║ 1 ║ ║
|
||||||
|
///║ ╚═══╝ ║
|
||||||
|
///║ Inventory ║
|
||||||
|
///║╔═══╦═══╦═══╦═══╦═══╦═══╦═══╦═══╦═══╗║
|
||||||
|
///║║ 3 ║ 4 ║ 5 ║ 6 ║ 7 [rest of string was truncated]";.
|
||||||
|
/// </summary>
|
||||||
|
public static string ContainerType_Furnace {
|
||||||
|
get {
|
||||||
return ResourceManager.GetString("ContainerType_Furnace", resourceCulture);
|
return ResourceManager.GetString("ContainerType_Furnace", resourceCulture);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Looks up a localized string similar to ╔═════════════════════════════════════╗
|
/// Looks up a localized string similar to ╔═════════════════════════════════════╗
|
||||||
///║ Container ║
|
///║ Container ║
|
||||||
|
|
@ -136,19 +136,17 @@ namespace MinecraftClient
|
||||||
///║ Inventory ║
|
///║ Inventory ║
|
||||||
///║╔═══╦═══╦═══╦═══╦═══╦═══╦═══╦═══╦═══╗║
|
///║╔═══╦═══╦═══╦═══╦═══╦═══╦═══╦═══╦═══╗║
|
||||||
///║║ 9 ║10 ║11 ║12 ║13 ║14 ║15 ║16 ║17 ║║
|
///║║ 9 ║10 ║11 ║12 ║13 ║14 ║15 ║16 ║17 ║║
|
||||||
///║╠═══╬═══╬═══╬═══╬═══╬═══╬═══╬══ [rest of string was truncated]";.
|
///║╠═══╬═══╬═══╬═══╬══ [rest of string was truncated]";.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static string ContainerType_Generic_3x3
|
public static string ContainerType_Generic_3x3 {
|
||||||
{
|
get {
|
||||||
get
|
|
||||||
{
|
|
||||||
return ResourceManager.GetString("ContainerType_Generic_3x3", resourceCulture);
|
return ResourceManager.GetString("ContainerType_Generic_3x3", resourceCulture);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Looks up a localized string similar to ╔═════════════════════════════════════╗
|
/// Looks up a localized string similar to ╔═════════════════════════════════════╗
|
||||||
///║ Chest ║
|
///║ Container ║
|
||||||
///║╔═══╦═══╦═══╦═══╦═══╦═══╦═══╦═══╦═══╗║
|
///║╔═══╦═══╦═══╦═══╦═══╦═══╦═══╦═══╦═══╗║
|
||||||
///║║ 0 ║ 1 ║ 2 ║ 3 ║ 4 ║ 5 ║ 6 ║ 7 ║ 8 ║║
|
///║║ 0 ║ 1 ║ 2 ║ 3 ║ 4 ║ 5 ║ 6 ║ 7 ║ 8 ║║
|
||||||
///║╠═══╬═══╬═══╬═══╬═══╬═══╬═══╬═══╬═══╣║
|
///║╠═══╬═══╬═══╬═══╬═══╬═══╬═══╬═══╬═══╣║
|
||||||
|
|
@ -159,19 +157,17 @@ namespace MinecraftClient
|
||||||
///║ Inventory ║
|
///║ Inventory ║
|
||||||
///║╔═══╦═══╦═══╦═══╦═══╦═══╦═══╦═══╦═══╗║
|
///║╔═══╦═══╦═══╦═══╦═══╦═══╦═══╦═══╦═══╗║
|
||||||
///║║27 ║28 ║29 ║30 ║31 ║32 ║33 ║34 ║35 ║║
|
///║║27 ║28 ║29 ║30 ║31 ║32 ║33 ║34 ║35 ║║
|
||||||
///║╠═══╬═══╬═══╬═══╬═══╬═══╬═══╬══ [rest of string was truncated]";.
|
///║╠═══╬═══╬═══╬═══╬══ [rest of string was truncated]";.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static string ContainerType_Generic_9x3
|
public static string ContainerType_Generic_9x3 {
|
||||||
{
|
get {
|
||||||
get
|
|
||||||
{
|
|
||||||
return ResourceManager.GetString("ContainerType_Generic_9x3", resourceCulture);
|
return ResourceManager.GetString("ContainerType_Generic_9x3", resourceCulture);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Looks up a localized string similar to ╔═════════════════════════════════════╗
|
/// Looks up a localized string similar to ╔═════════════════════════════════════╗
|
||||||
///║ Large Container ║
|
///║ Container ║
|
||||||
///║╔═══╦═══╦═══╦═══╦═══╦═══╦═══╦═══╦═══╗║
|
///║╔═══╦═══╦═══╦═══╦═══╦═══╦═══╦═══╦═══╗║
|
||||||
///║║ 0 ║ 1 ║ 2 ║ 3 ║ 4 ║ 5 ║ 6 ║ 7 ║ 8 ║║
|
///║║ 0 ║ 1 ║ 2 ║ 3 ║ 4 ║ 5 ║ 6 ║ 7 ║ 8 ║║
|
||||||
///║╠═══╬═══╬═══╬═══╬═══╬═══╬═══╬═══╬═══╣║
|
///║╠═══╬═══╬═══╬═══╬═══╬═══╬═══╬═══╬═══╣║
|
||||||
|
|
@ -182,32 +178,56 @@ namespace MinecraftClient
|
||||||
///║║27 ║28 ║29 ║30 ║31 ║32 ║33 ║34 ║35 ║║
|
///║║27 ║28 ║29 ║30 ║31 ║32 ║33 ║34 ║35 ║║
|
||||||
///║╠═══╬═══╬═══╬═══╬═══╬═══╬═══╬═══╬═══╣║
|
///║╠═══╬═══╬═══╬═══╬═══╬═══╬═══╬═══╬═══╣║
|
||||||
///║║36 ║37 ║38 ║39 ║40 ║41 ║42 ║43 ║44 ║║
|
///║║36 ║37 ║38 ║39 ║40 ║41 ║42 ║43 ║44 ║║
|
||||||
///║╠═══╬═══╬═══╬═══╬═══╬═══╬═══╬══ [rest of string was truncated]";.
|
///║╠═══╬═══╬═══╬═══╬══ [rest of string was truncated]";.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static string ContainerType_Generic_9x6
|
public static string ContainerType_Generic_9x6 {
|
||||||
{
|
get {
|
||||||
get
|
|
||||||
{
|
|
||||||
return ResourceManager.GetString("ContainerType_Generic_9x6", resourceCulture);
|
return ResourceManager.GetString("ContainerType_Generic_9x6", resourceCulture);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static string ContainerType_Grindstone
|
/// <summary>
|
||||||
{
|
/// Looks up a localized string similar to ╔═════════════════════════════════════╗
|
||||||
get
|
///║ Repair & Disenchant ║
|
||||||
{
|
///║ ╔═════════╗ ║
|
||||||
|
///║ ║ ╔═══╗ ║ ║
|
||||||
|
///║ ╔══║ ║ 0 ║ ║══╗ ║
|
||||||
|
///║ ║ ║ ╚═══╝ ║ ║ ║
|
||||||
|
///║ ║ ║ ╔═══╗ ║ ║ ╔═══╗ ║
|
||||||
|
///║ ║ ║ ║ 1 ║ ║ ║ ━━▶ ║ 2 ║ ║
|
||||||
|
///║ ║ ║ ╚═══╝ ║ ║ ╚═══╝ ║
|
||||||
|
///║ ║ ╠═════════╣ ║ ║
|
||||||
|
///║ ║ ║ ║ ║ ║
|
||||||
|
///║ ╚══╝ ╚══╝ ║
|
||||||
|
///║ [rest of string was truncated]";.
|
||||||
|
/// </summary>
|
||||||
|
public static string ContainerType_Grindstone {
|
||||||
|
get {
|
||||||
return ResourceManager.GetString("ContainerType_Grindstone", resourceCulture);
|
return ResourceManager.GetString("ContainerType_Grindstone", resourceCulture);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static string ContainerType_Hopper
|
/// <summary>
|
||||||
{
|
/// Looks up a localized string similar to ╔═════════════════════════════════════╗
|
||||||
get
|
///║ 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]";.
|
||||||
|
/// </summary>
|
||||||
|
public static string ContainerType_Hopper {
|
||||||
|
get {
|
||||||
return ResourceManager.GetString("ContainerType_Hopper", resourceCulture);
|
return ResourceManager.GetString("ContainerType_Hopper", resourceCulture);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Looks up a localized string similar to ╔═════════════════════════════════════╗
|
/// Looks up a localized string similar to ╔═════════════════════════════════════╗
|
||||||
///║╔═══╦═══════════╗ ║
|
///║╔═══╦═══════════╗ ║
|
||||||
|
|
@ -221,66 +241,156 @@ namespace MinecraftClient
|
||||||
///║╚═══╩═══════════╩═══╝ ║
|
///║╚═══╩═══════════╩═══╝ ║
|
||||||
///║╔═══╦═══╦═══╦═══╦═══╦═══╦═══╦═══╦═══╗║
|
///║╔═══╦═══╦═══╦═══╦═══╦═══╦═══╦═══╦═══╗║
|
||||||
///║║ 9 ║10 ║11 ║12 ║13 ║14 ║15 ║16 ║17 ║║
|
///║║ 9 ║10 ║11 ║12 ║13 ║14 ║15 ║16 ║17 ║║
|
||||||
///║╠═══╬═══╬═══╬═══╬═══╬═══╬═══╬══ [rest of string was truncated]";.
|
///║╠═══╬═══╬═══╬═══╬══ [rest of string was truncated]";.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static string ContainerType_PlayerInventory
|
public static string ContainerType_PlayerInventory {
|
||||||
{
|
get {
|
||||||
get
|
|
||||||
{
|
|
||||||
return ResourceManager.GetString("ContainerType_PlayerInventory", resourceCulture);
|
return ResourceManager.GetString("ContainerType_PlayerInventory", resourceCulture);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Looks up a localized string similar to # Startup Config File
|
/// Looks up a localized string similar to # Startup Config File
|
||||||
///
|
///
|
||||||
///[Main]
|
///# New to Minecraft Console Client? See README and sample configuration files here:
|
||||||
|
///# https://github.com/MCCTeam/Minecraft-Console-Client/tree/master/MinecraftClient/config
|
||||||
///
|
///
|
||||||
|
///# Want to upgrade to a newer version? See https://github.com/MCCTeam/Minecraft-Console-Client/#download
|
||||||
|
///# Some settings missing here after an upgrade? Try to delete this file and relaunch MCC to generate a new one
|
||||||
|
///
|
||||||
|
///[Main]
|
||||||
///# General settings
|
///# General settings
|
||||||
///# Leave blank to prompt user on startup
|
///# Leave blank to prompt user on startup
|
||||||
///# Use "-" as password for offline mode
|
///# Use "-" as password fo [rest of string was truncated]";.
|
||||||
///
|
|
||||||
///login=
|
|
||||||
///password=
|
|
||||||
///serverip=
|
|
||||||
///type=mojang # Account type. mojang or microsoft
|
|
||||||
///method=mcc # Microsoft Account sign-in method. mcc OR browser
|
|
||||||
///
|
|
||||||
///# Advanced settings
|
|
||||||
///
|
|
||||||
///language=en_GB
|
|
||||||
///consoletitle=%username%@%serverip% - Minecraft Console Client
|
|
||||||
///internalcmdchar=slash # Use 'none', 'slash' or 'backslash'
|
|
||||||
///messagec [rest of string was truncated]";.
|
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static string MinecraftClient
|
public static string MinecraftClient {
|
||||||
{
|
get {
|
||||||
get
|
|
||||||
{
|
|
||||||
return ResourceManager.GetString("MinecraftClient", resourceCulture);
|
return ResourceManager.GetString("MinecraftClient", resourceCulture);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Looks up a localized string similar to [mcc]
|
/// Looks up a localized string similar to [mcc]
|
||||||
///# Messages from MCC itself
|
///# Messages from MCC itself
|
||||||
///mcc.login=Login :
|
///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]";.
|
||||||
|
/// </summary>
|
||||||
|
public 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: https://mccteam.github.io/guide/translation.html
|
||||||
|
///mcc.run_with_default_settings=\nMCC is running with default settings.
|
||||||
|
///mcc.settings_generated=§cSettings file MinecraftClient.ini has been generated.
|
||||||
|
///mcc.login=Login :
|
||||||
///mcc.login_basic_io=Please type the username or email of your choice.
|
///mcc.login_basic_io=Please type the username or email of your choice.
|
||||||
///mcc.password=Password :
|
///mcc.password=Password :
|
||||||
///mcc.password_basic_io=Please type the password for {0}.
|
///mcc.password_basic_io=Please type the password for {0}.
|
||||||
///mcc.password_hidden=Password : {0}
|
///mcc.password_hidden=Password : {0}
|
||||||
///mcc.offline=§8You chose to run in offline mode.
|
///mcc.offline=§8You chose [rest of string was truncated]";.
|
||||||
///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]";.
|
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static string TranslationEnglish
|
public static string Translation_en {
|
||||||
{
|
get {
|
||||||
get
|
return ResourceManager.GetString("Translation_en", resourceCulture);
|
||||||
{
|
}
|
||||||
return ResourceManager.GetString("TranslationEnglish", 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'utilisateur ou une adresse email.
|
||||||
|
///mcc.password=Mot de passe :
|
||||||
|
///mcc.password_basic_io=Saisissez le mot de passe pour {0}.
|
||||||
|
///mcc.password_hidden=Mot de passe : {0}
|
||||||
|
///mcc.offline=§8Vous avez choisi d'utiliser le mode hors ligne.
|
||||||
|
///mcc.session_invalid=§8Le cache de la session est invalide ou a expiré.
|
||||||
|
///mcc.session_valid=§8Le cache de la session est encore valable pendant {0}.
|
||||||
|
///mcc.connecting=Connexion à {0}...
|
||||||
|
/// [rest of string was truncated]";.
|
||||||
|
/// </summary>
|
||||||
|
public 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]";.
|
||||||
|
/// </summary>
|
||||||
|
public 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]";.
|
||||||
|
/// </summary>
|
||||||
|
public 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:https://mccteam.github.io/guide/translation.html
|
||||||
|
///mcc.run_with_default_settings=\nMCC正在使用默认配置运行。
|
||||||
|
///mcc.settings_generated=§c配置文件 MinecraftClient.ini 已经生成。
|
||||||
|
///mcc.login=登录:
|
||||||
|
///mcc.login_basic_io=请输入用户名或邮箱。
|
||||||
|
///mcc.password=密码:
|
||||||
|
///mcc.password_basic_io=请输入{0}的密码。
|
||||||
|
///mcc.password_hidden=密码:{0}
|
||||||
|
///mcc.offline=§8您正在使用离线模式。
|
||||||
|
///mcc.session_invalid=§8缓存无效或已过期。
|
||||||
|
///mcc.session_valid=§8{0}的缓存仍然有效。
|
||||||
|
///mcc.profile_key_invalid=§8缓存的聊天签名密钥需要刷新。
|
||||||
|
///mcc.profile_key_valid=§8{0}的聊天 [rest of string was truncated]";.
|
||||||
|
/// </summary>
|
||||||
|
public static string Translation_zh_Hans {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("Translation_zh_Hans", resourceCulture);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -148,7 +148,22 @@
|
||||||
<data name="MinecraftClient" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
<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>
|
<value>Resources\config\MinecraftClient.ini;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TranslationEnglish" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
<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="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>
|
<value>Resources\lang\en.ini;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8</value>
|
||||||
</data>
|
</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>
|
</root>
|
||||||
|
|
@ -22,7 +22,7 @@ namespace MinecraftClient
|
||||||
/// <param name="handler">Callback for file changes</param>
|
/// <param name="handler">Callback for file changes</param>
|
||||||
public FileMonitor(string folder, string filename, FileSystemEventHandler handler)
|
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;
|
string callerClass = new System.Diagnostics.StackFrame(1).GetMethod()!.DeclaringType!.Name;
|
||||||
ConsoleIO.WriteLineFormatted(Translations.Get("filemonitor.init", callerClass, Path.Combine(folder, filename)));
|
ConsoleIO.WriteLineFormatted(Translations.Get("filemonitor.init", callerClass, Path.Combine(folder, filename)));
|
||||||
|
|
@ -40,7 +40,7 @@ namespace MinecraftClient
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
if (Settings.DebugMessages)
|
if (Settings.Config.Logging.DebugMessages)
|
||||||
{
|
{
|
||||||
string callerClass = new System.Diagnostics.StackFrame(1).GetMethod()!.DeclaringType!.Name;
|
string callerClass = new System.Diagnostics.StackFrame(1).GetMethod()!.DeclaringType!.Name;
|
||||||
ConsoleIO.WriteLineFormatted(Translations.Get("filemonitor.fail", callerClass));
|
ConsoleIO.WriteLineFormatted(Translations.Get("filemonitor.fail", callerClass));
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,7 @@ namespace MinecraftClient.Logger
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (!Settings.SaveColorCodes)
|
if (!Settings.Config.Logging.SaveColorCodes)
|
||||||
msg = ChatBot.GetVerbatim(msg);
|
msg = ChatBot.GetVerbatim(msg);
|
||||||
if (prependTimestamp)
|
if (prependTimestamp)
|
||||||
msg = GetTimestamp() + ' ' + msg;
|
msg = GetTimestamp() + ' ' + msg;
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
|
using static MinecraftClient.Settings;
|
||||||
|
|
||||||
namespace MinecraftClient.Logger
|
namespace MinecraftClient.Logger
|
||||||
{
|
{
|
||||||
|
|
@ -10,11 +11,23 @@ namespace MinecraftClient.Logger
|
||||||
{
|
{
|
||||||
Regex? regexToUse = null;
|
Regex? regexToUse = null;
|
||||||
// Convert to bool for XOR later. Whitelist = 0, Blacklist = 1
|
// Convert to bool for XOR later. Whitelist = 0, Blacklist = 1
|
||||||
bool filterMode = Settings.FilterMode == Settings.FilterModeEnum.Blacklist;
|
bool filterMode = Config.Logging.FilterMode == LoggingConfigHealper.LoggingConfig.FilterModeEnum.blacklist;
|
||||||
switch (channel)
|
switch (channel)
|
||||||
{
|
{
|
||||||
case FilterChannel.Chat: regexToUse = Settings.ChatFilter; break;
|
case FilterChannel.Chat:
|
||||||
case FilterChannel.Debug: regexToUse = Settings.DebugFilter; break;
|
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)
|
if (regexToUse != null)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,7 @@ namespace MinecraftClient.Mapping
|
||||||
/// <returns>Updated location after applying gravity</returns>
|
/// <returns>Updated location after applying gravity</returns>
|
||||||
public static Location HandleGravity(World world, Location location, ref double motionY)
|
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 onFoots = new(location.X, Math.Floor(location.Y), location.Z);
|
||||||
Location belowFoots = Move(location, Direction.Down);
|
Location belowFoots = Move(location, Direction.Down);
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,7 @@ using MinecraftClient.Protocol.Keys;
|
||||||
using MinecraftClient.Protocol.Message;
|
using MinecraftClient.Protocol.Message;
|
||||||
using MinecraftClient.Protocol.Session;
|
using MinecraftClient.Protocol.Session;
|
||||||
using MinecraftClient.Proxy;
|
using MinecraftClient.Proxy;
|
||||||
|
using static MinecraftClient.Settings;
|
||||||
|
|
||||||
namespace MinecraftClient
|
namespace MinecraftClient
|
||||||
{
|
{
|
||||||
|
|
@ -142,12 +143,11 @@ namespace MinecraftClient
|
||||||
/// <param name="port">The server port to use</param>
|
/// <param name="port">The server port to use</param>
|
||||||
/// <param name="protocolversion">Minecraft protocol version 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="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)
|
||||||
public McClient(SessionToken session, PlayerKeyPair? playerKeyPair, string server_ip, ushort port, int protocolversion, ForgeInfo? forgeInfo, string? command)
|
|
||||||
{
|
{
|
||||||
terrainAndMovementsEnabled = Settings.TerrainAndMovements;
|
terrainAndMovementsEnabled = Config.Main.Advanced.TerrainAndMovements;
|
||||||
inventoryHandlingEnabled = Settings.InventoryHandling;
|
inventoryHandlingEnabled = Config.Main.Advanced.InventoryHandling;
|
||||||
entityHandlingEnabled = Settings.EntityHandling;
|
entityHandlingEnabled = Config.Main.Advanced.EntityHandling;
|
||||||
|
|
||||||
sessionid = session.ID;
|
sessionid = session.ID;
|
||||||
if (!Guid.TryParse(session.PlayerID, out uuid))
|
if (!Guid.TryParse(session.PlayerID, out uuid))
|
||||||
|
|
@ -159,64 +159,47 @@ namespace MinecraftClient
|
||||||
this.protocolversion = protocolversion;
|
this.protocolversion = protocolversion;
|
||||||
this.playerKeyPair = playerKeyPair;
|
this.playerKeyPair = playerKeyPair;
|
||||||
|
|
||||||
Log = Settings.LogToFile
|
Log = Settings.Config.Logging.LogToFile
|
||||||
? new FileLogLogger(Settings.ExpandVars(Settings.LogFile), Settings.PrependTimestamp)
|
? new FileLogLogger(Config.AppVar.ExpandVars(Settings.Config.Logging.LogFile), Settings.Config.Logging.PrependTimestamp)
|
||||||
: new FilteredLogger();
|
: new FilteredLogger();
|
||||||
Log.DebugEnabled = Settings.DebugMessages;
|
Log.DebugEnabled = Config.Logging.DebugMessages;
|
||||||
Log.InfoEnabled = Settings.InfoMessages;
|
Log.InfoEnabled = Config.Logging.InfoMessages;
|
||||||
Log.ChatEnabled = Settings.ChatMessages;
|
Log.ChatEnabled = Config.Logging.ChatMessages;
|
||||||
Log.WarnEnabled = Settings.WarningMessages;
|
Log.WarnEnabled = Config.Logging.WarningMessages;
|
||||||
Log.ErrorEnabled = Settings.ErrorMessages;
|
Log.ErrorEnabled = Config.Logging.ErrorMessages;
|
||||||
|
|
||||||
if (command == null)
|
/* Load commands from Commands namespace */
|
||||||
{
|
LoadCommands();
|
||||||
/* Load commands from Commands namespace */
|
|
||||||
LoadCommands();
|
|
||||||
|
|
||||||
if (botsOnHold.Count == 0)
|
if (botsOnHold.Count == 0)
|
||||||
RegisterBots();
|
RegisterBots();
|
||||||
}
|
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
client = ProxyHandler.NewTcpClient(host, port);
|
client = ProxyHandler.NewTcpClient(host, port);
|
||||||
client.ReceiveBufferSize = 1024 * 1024;
|
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);
|
handler = Protocol.ProtocolHandler.GetProtocolHandler(client, protocolversion, forgeInfo, this);
|
||||||
Log.Info(Translations.Get("mcc.version_supported"));
|
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 = new(new Thread(new ParameterizedThreadStart(TimeoutDetector)), new CancellationTokenSource());
|
timeoutdetector.Item1.Start(timeoutdetector.Item2.Token);
|
||||||
timeoutdetector.Item1.Name = "MCC Connection timeout detector";
|
|
||||||
timeoutdetector.Item1.Start(timeoutdetector.Item2.Token);
|
|
||||||
}
|
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (handler.Login(this.playerKeyPair, session))
|
if (handler.Login(this.playerKeyPair, session))
|
||||||
{
|
{
|
||||||
if (command != null)
|
foreach (ChatBot bot in botsOnHold)
|
||||||
{
|
BotLoad(bot, false);
|
||||||
handler.SendChatMessage(command, playerKeyPair);
|
botsOnHold.Clear();
|
||||||
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();
|
|
||||||
|
|
||||||
Log.Info(Translations.Get("mcc.joined", (Settings.internalCmdChar == ' ' ? "" : "" + Settings.internalCmdChar)));
|
Log.Info(Translations.Get("mcc.joined", Config.Main.Advanced.InternalCmdChar.ToLogString()));
|
||||||
|
|
||||||
cmdprompt = new CancellationTokenSource();
|
cmdprompt = new CancellationTokenSource();
|
||||||
ConsoleInteractive.ConsoleReader.BeginReadThread(cmdprompt);
|
ConsoleInteractive.ConsoleReader.BeginReadThread(cmdprompt);
|
||||||
ConsoleInteractive.ConsoleReader.MessageReceived += ConsoleReaderOnMessageReceived;
|
ConsoleInteractive.ConsoleReader.MessageReceived += ConsoleReaderOnMessageReceived;
|
||||||
ConsoleInteractive.ConsoleReader.OnKeyInput += ConsoleIO.AutocompleteHandler;
|
ConsoleInteractive.ConsoleReader.OnKeyInput += ConsoleIO.AutocompleteHandler;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
@ -253,7 +236,7 @@ namespace MinecraftClient
|
||||||
ReconnectionAttemptsLeft--;
|
ReconnectionAttemptsLeft--;
|
||||||
Program.Restart();
|
Program.Restart();
|
||||||
}
|
}
|
||||||
else if (command == null && Settings.interactiveMode)
|
else if (InternalConfig.InteractiveMode)
|
||||||
{
|
{
|
||||||
ConsoleInteractive.ConsoleReader.StopReadThread();
|
ConsoleInteractive.ConsoleReader.StopReadThread();
|
||||||
ConsoleInteractive.ConsoleReader.MessageReceived -= ConsoleReaderOnMessageReceived;
|
ConsoleInteractive.ConsoleReader.MessageReceived -= ConsoleReaderOnMessageReceived;
|
||||||
|
|
@ -269,24 +252,24 @@ namespace MinecraftClient
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private void RegisterBots(bool reload = false)
|
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 (Config.ChatBot.AntiAFK.Enabled) { BotLoad(new AntiAFK()); }
|
||||||
if (Settings.Hangman_Enabled) { BotLoad(new HangmanGame(Settings.Hangman_English)); }
|
if (Config.ChatBot.HangmanGame.Enabled) { BotLoad(new HangmanGame()); }
|
||||||
if (Settings.Alerts_Enabled) { BotLoad(new Alerts()); }
|
if (Config.ChatBot.Alerts.Enabled) { BotLoad(new Alerts()); }
|
||||||
if (Settings.ChatLog_Enabled) { BotLoad(new ChatLog(Settings.ExpandVars(Settings.ChatLog_File), Settings.ChatLog_Filter, Settings.ChatLog_DateTime)); }
|
if (Config.ChatBot.ChatLog.Enabled) { BotLoad(new ChatLog()); }
|
||||||
if (Settings.PlayerLog_Enabled) { BotLoad(new PlayerListLogger(Settings.PlayerLog_Delay, Settings.ExpandVars(Settings.PlayerLog_File))); }
|
if (Config.ChatBot.PlayerListLogger.Enabled) { BotLoad(new PlayerListLogger()); }
|
||||||
if (Settings.AutoRelog_Enabled) { BotLoad(new AutoRelog(Settings.AutoRelog_Delay_Min, Settings.AutoRelog_Delay_Max, Settings.AutoRelog_Retries)); }
|
if (Config.ChatBot.AutoRelog.Enabled) { BotLoad(new AutoRelog()); }
|
||||||
if (Settings.ScriptScheduler_Enabled) { BotLoad(new ScriptScheduler(Settings.ExpandVars(Settings.ScriptScheduler_TasksFile))); }
|
if (Config.ChatBot.ScriptScheduler.Enabled) { BotLoad(new ScriptScheduler()); }
|
||||||
if (Settings.RemoteCtrl_Enabled) { BotLoad(new RemoteControl()); }
|
if (Config.ChatBot.RemoteControl.Enabled) { BotLoad(new RemoteControl()); }
|
||||||
if (Settings.AutoRespond_Enabled) { BotLoad(new AutoRespond(Settings.AutoRespond_Matches, Settings.AutoRespond_MatchColors)); }
|
if (Config.ChatBot.AutoRespond.Enabled) { BotLoad(new AutoRespond()); }
|
||||||
if (Settings.AutoAttack_Enabled) { BotLoad(new AutoAttack(Settings.AutoAttack_Mode, Settings.AutoAttack_Priority, Settings.AutoAttack_OverrideAttackSpeed, Settings.AutoAttack_CooldownSeconds, Settings.AutoAttack_Interaction)); }
|
if (Config.ChatBot.AutoAttack.Enabled) { BotLoad(new AutoAttack()); }
|
||||||
if (Settings.AutoFishing_Enabled) { BotLoad(new AutoFishing()); }
|
if (Config.ChatBot.AutoFishing.Enabled) { BotLoad(new AutoFishing()); }
|
||||||
if (Settings.AutoEat_Enabled) { BotLoad(new AutoEat(Settings.AutoEat_hungerThreshold)); }
|
if (Config.ChatBot.AutoEat.Enabled) { BotLoad(new AutoEat()); }
|
||||||
if (Settings.Mailer_Enabled) { BotLoad(new Mailer()); }
|
if (Config.ChatBot.Mailer.Enabled) { BotLoad(new Mailer()); }
|
||||||
if (Settings.AutoCraft_Enabled) { BotLoad(new AutoCraft(Settings.AutoCraft_configFile)); }
|
if (Config.ChatBot.AutoCraft.Enabled) { BotLoad(new AutoCraft()); }
|
||||||
if (Settings.AutoDrop_Enabled) { BotLoad(new AutoDrop(Settings.AutoDrop_Mode, Settings.AutoDrop_items)); }
|
if (Config.ChatBot.AutoDrop.Enabled) { BotLoad(new AutoDrop()); }
|
||||||
if (Settings.ReplayMod_Enabled && reload) { BotLoad(new ReplayCapture(Settings.ReplayMod_BackupInterval)); }
|
if (Config.ChatBot.ReplayCapture.Enabled && reload) { BotLoad(new ReplayCapture()); }
|
||||||
if (Settings.FollowPlayer_Enabled) { BotLoad(new FollowPlayer(Settings.FollowPlayer_UpdateLimit, Settings.FollowPlayer_UpdateLimit)); }
|
if (Config.ChatBot.FollowPlayer.Enabled) { BotLoad(new FollowPlayer()); }
|
||||||
if (Settings.Map_Enabled) { BotLoad(new Map()); }
|
if (Config.ChatBot.Map.Enabled) { BotLoad(new Map()); }
|
||||||
|
|
||||||
//Add your ChatBot here by uncommenting and adapting
|
//Add your ChatBot here by uncommenting and adapting
|
||||||
//BotLoad(new ChatBots.YourBot());
|
//BotLoad(new ChatBots.YourBot());
|
||||||
|
|
@ -302,7 +285,7 @@ namespace MinecraftClient
|
||||||
{
|
{
|
||||||
string text = chatQueue.Dequeue();
|
string text = chatQueue.Dequeue();
|
||||||
handler.SendChatMessage(text, playerKeyPair);
|
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)
|
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)
|
if (_yaw == null || _pitch == null)
|
||||||
{
|
{
|
||||||
|
|
@ -349,10 +332,8 @@ namespace MinecraftClient
|
||||||
Location next = path.Dequeue();
|
Location next = path.Dequeue();
|
||||||
steps = Movement.Move2Steps(location, next, ref motionY);
|
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
|
UpdateLocation(location, next + new Location(0, 1, 0)); // Update yaw and pitch to look at next step
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
@ -370,7 +351,7 @@ namespace MinecraftClient
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Settings.AutoRespawn && respawnTicks > 0)
|
if (Config.Main.Advanced.AutoRespawn && respawnTicks > 0)
|
||||||
{
|
{
|
||||||
respawnTicks--;
|
respawnTicks--;
|
||||||
if (respawnTicks == 0)
|
if (respawnTicks == 0)
|
||||||
|
|
@ -404,7 +385,7 @@ namespace MinecraftClient
|
||||||
|
|
||||||
lock (lastKeepAliveLock)
|
lock (lastKeepAliveLock)
|
||||||
{
|
{
|
||||||
if (lastKeepAlive.AddSeconds(Settings.Timeout) < DateTime.Now)
|
if (lastKeepAlive.AddSeconds(Config.Main.Advanced.TcpTimeout) < DateTime.Now)
|
||||||
{
|
{
|
||||||
if (((CancellationToken)o!).IsCancellationRequested)
|
if (((CancellationToken)o!).IsCancellationRequested)
|
||||||
return;
|
return;
|
||||||
|
|
@ -572,11 +553,11 @@ namespace MinecraftClient
|
||||||
text = text.Trim();
|
text = text.Trim();
|
||||||
if (text.Length > 0)
|
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? response_msg = "";
|
||||||
string command = Settings.internalCmdChar == ' ' ? text : text[1..];
|
string command = Config.Main.Advanced.InternalCmdChar.ToChar() == ' ' ? text : text[1..];
|
||||||
if (!PerformInternalCommand(Settings.ExpandVars(command), ref response_msg, Settings.GetVariables()) && Settings.internalCmdChar == '/')
|
if (!PerformInternalCommand(Config.AppVar.ExpandVars(command), ref response_msg, Settings.Config.AppVar.GetVariables()) && Config.Main.Advanced.InternalCmdChar.ToChar() == '/')
|
||||||
{
|
{
|
||||||
SendText(text);
|
SendText(text);
|
||||||
}
|
}
|
||||||
|
|
@ -659,7 +640,7 @@ namespace MinecraftClient
|
||||||
}
|
}
|
||||||
else response_msg = Translations.Get("icmd.unknown", command_name);
|
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))
|
else if (cmds.ContainsKey(command_name))
|
||||||
{
|
{
|
||||||
|
|
@ -845,7 +826,6 @@ namespace MinecraftClient
|
||||||
DispatchBotEvent(bot => bot.Initialize(), new ChatBot[] { b });
|
DispatchBotEvent(bot => bot.Initialize(), new ChatBot[] { b });
|
||||||
if (handler != null)
|
if (handler != null)
|
||||||
DispatchBotEvent(bot => bot.AfterGameJoined(), new ChatBot[] { b });
|
DispatchBotEvent(bot => bot.AfterGameJoined(), new ChatBot[] { b });
|
||||||
Settings.SingleCommand = "";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
@ -2395,18 +2375,19 @@ namespace MinecraftClient
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void OnGameJoined()
|
public void OnGameJoined()
|
||||||
{
|
{
|
||||||
if (!String.IsNullOrWhiteSpace(Settings.BrandInfo))
|
string? bandString = Config.Main.Advanced.BrandInfo.ToBrandString();
|
||||||
handler.SendBrandInfo(Settings.BrandInfo.Trim());
|
if (!String.IsNullOrWhiteSpace(bandString))
|
||||||
|
handler.SendBrandInfo(bandString.Trim());
|
||||||
|
|
||||||
if (Settings.MCSettings_Enabled)
|
if (Config.MCSettings.Enabled)
|
||||||
handler.SendClientSettings(
|
handler.SendClientSettings(
|
||||||
Settings.MCSettings_Locale,
|
Config.MCSettings.Locale,
|
||||||
Settings.MCSettings_RenderDistance,
|
Config.MCSettings.RenderDistance,
|
||||||
Settings.MCSettings_Difficulty,
|
(byte)Config.MCSettings.Difficulty,
|
||||||
Settings.MCSettings_ChatMode,
|
(byte)Config.MCSettings.ChatMode,
|
||||||
Settings.MCSettings_ChatColors,
|
Config.MCSettings.ChatColors,
|
||||||
Settings.MCSettings_Skin_All,
|
Config.MCSettings.Skin.GetByte(),
|
||||||
Settings.MCSettings_MainHand);
|
(byte)Config.MCSettings.MainHand);
|
||||||
|
|
||||||
|
|
||||||
if (inventoryHandlingRequested)
|
if (inventoryHandlingRequested)
|
||||||
|
|
@ -2484,15 +2465,15 @@ namespace MinecraftClient
|
||||||
{
|
{
|
||||||
case MovementType.Sneak:
|
case MovementType.Sneak:
|
||||||
// https://minecraft.fandom.com/wiki/Sneaking#Effects - Sneaking 1.31m/s
|
// https://minecraft.fandom.com/wiki/Sneaking#Effects - Sneaking 1.31m/s
|
||||||
Settings.MovementSpeed = 2;
|
Config.Main.Advanced.MovementSpeed = 2;
|
||||||
break;
|
break;
|
||||||
case MovementType.Walk:
|
case MovementType.Walk:
|
||||||
// https://minecraft.fandom.com/wiki/Walking#Usage - Walking 4.317 m/s
|
// https://minecraft.fandom.com/wiki/Walking#Usage - Walking 4.317 m/s
|
||||||
Settings.MovementSpeed = 4;
|
Config.Main.Advanced.MovementSpeed = 4;
|
||||||
break;
|
break;
|
||||||
case MovementType.Sprint:
|
case MovementType.Sprint:
|
||||||
// https://minecraft.fandom.com/wiki/Sprinting#Usage - Sprinting 5.612 m/s
|
// https://minecraft.fandom.com/wiki/Sprinting#Usage - Sprinting 5.612 m/s
|
||||||
Settings.MovementSpeed = 5;
|
Config.Main.Advanced.MovementSpeed = 5;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -2601,7 +2582,7 @@ namespace MinecraftClient
|
||||||
|
|
||||||
if (message.isSignedChat)
|
if (message.isSignedChat)
|
||||||
{
|
{
|
||||||
if (!Settings.ShowIllegalSignedChat && !message.isSystemChat && !(bool)message.isSignatureLegal!)
|
if (!Config.Signature.ShowIllegalSignedChat && !message.isSystemChat && !(bool)message.isSignatureLegal!)
|
||||||
return;
|
return;
|
||||||
messageText = ChatParser.ParseSignedChat(message, links);
|
messageText = ChatParser.ParseSignedChat(message, links);
|
||||||
}
|
}
|
||||||
|
|
@ -2615,7 +2596,7 @@ namespace MinecraftClient
|
||||||
|
|
||||||
Log.Chat(messageText);
|
Log.Chat(messageText);
|
||||||
|
|
||||||
if (Settings.DisplayChatLinks)
|
if (Config.Main.Advanced.ShowChatLinks)
|
||||||
foreach (string link in links)
|
foreach (string link in links)
|
||||||
Log.Chat(Translations.Get("mcc.link", link));
|
Log.Chat(Translations.Get("mcc.link", link));
|
||||||
|
|
||||||
|
|
@ -3024,14 +3005,14 @@ namespace MinecraftClient
|
||||||
|
|
||||||
if (health <= 0)
|
if (health <= 0)
|
||||||
{
|
{
|
||||||
if (Settings.AutoRespawn)
|
if (Config.Main.Advanced.AutoRespawn)
|
||||||
{
|
{
|
||||||
Log.Info(Translations.Get("mcc.player_dead_respawn"));
|
Log.Info(Translations.Get("mcc.player_dead_respawn"));
|
||||||
respawnTicks = 10;
|
respawnTicks = 10;
|
||||||
}
|
}
|
||||||
else
|
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());
|
DispatchBotEvent(bot => bot.OnDeath());
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -36,9 +36,10 @@
|
||||||
<PackageReference Include="DnsClient" Version="1.6.1" />
|
<PackageReference Include="DnsClient" Version="1.6.1" />
|
||||||
<PackageReference Include="DotNetZip" Version="1.16.0" />
|
<PackageReference Include="DotNetZip" Version="1.16.0" />
|
||||||
<PackageReference Include="DynamicExpresso.Core" Version="2.13.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.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="SingleFileExtractor.Core" Version="1.0.1" />
|
||||||
<PackageReference Include="starksoft.aspen" Version="1.1.8">
|
<PackageReference Include="starksoft.aspen" Version="1.1.8">
|
||||||
<NoWarn>NU1701</NoWarn>
|
<NoWarn>NU1701</NoWarn>
|
||||||
|
|
@ -72,4 +73,9 @@
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\ConsoleInteractive\ConsoleInteractive\ConsoleInteractive\ConsoleInteractive.csproj" />
|
<ProjectReference Include="..\ConsoleInteractive\ConsoleInteractive\ConsoleInteractive\ConsoleInteractive.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<EmbeddedResource Update="DefaultConfigResource.resx">
|
||||||
|
<Generator></Generator>
|
||||||
|
</EmbeddedResource>
|
||||||
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ using System.Linq;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using MinecraftClient.Inventory.ItemPalettes;
|
using MinecraftClient.Inventory.ItemPalettes;
|
||||||
|
|
@ -16,6 +17,12 @@ using MinecraftClient.Protocol.Handlers.Forge;
|
||||||
using MinecraftClient.Protocol.Keys;
|
using MinecraftClient.Protocol.Keys;
|
||||||
using MinecraftClient.Protocol.Session;
|
using MinecraftClient.Protocol.Session;
|
||||||
using MinecraftClient.WinAPI;
|
using MinecraftClient.WinAPI;
|
||||||
|
using Tomlet;
|
||||||
|
using Tomlet.Models;
|
||||||
|
using static MinecraftClient.Settings;
|
||||||
|
using static MinecraftClient.Settings.MainConfigHealper.MainConfig.GeneralConfig;
|
||||||
|
using static MinecraftClient.Settings.MainConfigHealper.MainConfig.AdvancedConfig;
|
||||||
|
using static System.Net.Mime.MediaTypeNames;
|
||||||
|
|
||||||
namespace MinecraftClient
|
namespace MinecraftClient
|
||||||
{
|
{
|
||||||
|
|
@ -104,12 +111,12 @@ namespace MinecraftClient
|
||||||
ConsoleIO.DebugReadInput();
|
ConsoleIO.DebugReadInput();
|
||||||
}
|
}
|
||||||
|
|
||||||
settingsIniPath = "MinecraftClient.ini";
|
|
||||||
|
|
||||||
//Process ini configuration file
|
//Process ini configuration file
|
||||||
if (args.Length >= 1 && System.IO.File.Exists(args[0]) && Settings.ToLowerIfNeed(Path.GetExtension(args[0])) == ".ini")
|
bool needWriteDefaultSetting, newlyGenerated = false;
|
||||||
|
settingsIniPath = "MinecraftClient.ini";
|
||||||
|
if (args.Length >= 1 && File.Exists(args[0]) && Settings.ToLowerIfNeed(Path.GetExtension(args[0])) == ".ini")
|
||||||
{
|
{
|
||||||
Settings.LoadFile(args[0]);
|
needWriteDefaultSetting = Settings.LoadFromFile(args[0]);
|
||||||
settingsIniPath = args[0];
|
settingsIniPath = args[0];
|
||||||
|
|
||||||
//remove ini configuration file from arguments array
|
//remove ini configuration file from arguments array
|
||||||
|
|
@ -117,14 +124,34 @@ namespace MinecraftClient
|
||||||
args_tmp.RemoveAt(0);
|
args_tmp.RemoveAt(0);
|
||||||
args = args_tmp.ToArray();
|
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
|
if (needWriteDefaultSetting)
|
||||||
Translations.LoadExternalTranslationFile(Settings.Language);
|
{
|
||||||
|
(string gameLanguage, string[] langList) = Translations.GetTranslationPriority();
|
||||||
|
Translations.LoadTranslationFile(langList);
|
||||||
|
Config.Main.Advanced.Language = gameLanguage;
|
||||||
|
Settings.WriteToFile("MinecraftClient.ini", false);
|
||||||
|
if (newlyGenerated)
|
||||||
|
ConsoleIO.WriteLineFormatted(Translations.TryGet("mcc.settings_generated"));
|
||||||
|
ConsoleIO.WriteLine(Translations.TryGet("mcc.run_with_default_settings"));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//Load external translation file. Should be called AFTER settings loaded
|
||||||
|
Translations.LoadTranslationFile(Translations.GetTranslationPriority(Config.Main.Advanced.Language));
|
||||||
|
if (!Config.Main.Advanced.Language.StartsWith("en"))
|
||||||
|
ConsoleIO.WriteLine(Translations.TryGet("mcc.help_us_translate"));
|
||||||
|
Settings.WriteToFile("MinecraftClient.ini", true); // format
|
||||||
|
}
|
||||||
|
|
||||||
//Other command-line arguments
|
//Other command-line arguments
|
||||||
if (args.Length >= 1)
|
if (args.Length >= 1)
|
||||||
|
|
@ -222,55 +249,56 @@ namespace MinecraftClient
|
||||||
}
|
}
|
||||||
catch (ArgumentException e)
|
catch (ArgumentException e)
|
||||||
{
|
{
|
||||||
Settings.interactiveMode = false;
|
InternalConfig.InteractiveMode = false;
|
||||||
HandleFailure(e.Message);
|
HandleFailure(e.Message);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Settings.ConsoleTitle != "")
|
if (Config.Main.Advanced.ConsoleTitle != "")
|
||||||
{
|
{
|
||||||
Settings.Username = "New Window";
|
InternalConfig.Username = "New Window";
|
||||||
Console.Title = Settings.ExpandVars(Settings.ConsoleTitle);
|
Console.Title = Config.AppVar.ExpandVars(Config.Main.Advanced.ConsoleTitle);
|
||||||
}
|
}
|
||||||
|
|
||||||
//Test line to troubleshoot invisible colors
|
//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]"));
|
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
|
//Load cached sessions from disk if necessary
|
||||||
if (Settings.SessionCaching == CacheType.Disk)
|
if (Config.Main.Advanced.SessionCache == CacheType.disk)
|
||||||
{
|
{
|
||||||
bool cacheLoaded = SessionCache.InitializeDiskCache();
|
bool cacheLoaded = SessionCache.InitializeDiskCache();
|
||||||
if (Settings.DebugMessages)
|
if (Config.Logging.DebugMessages)
|
||||||
Translations.WriteLineFormatted(cacheLoaded ? "debug.session_cache_ok" : "debug.session_cache_fail");
|
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
|
//Asking the user to type in missing data such as Username and Password
|
||||||
bool useBrowser = Settings.AccountType == ProtocolHandler.AccountType.Microsoft && Settings.LoginMethod == "browser";
|
bool useBrowser = Config.Main.General.AccountType == LoginType.microsoft && Config.Main.General.Method == LoginMethod.browser;
|
||||||
if (Settings.Login == "" && !useBrowser)
|
if (string.IsNullOrEmpty(Config.Main.General.Account.Login) && !useBrowser)
|
||||||
{
|
{
|
||||||
ConsoleIO.WriteLine(ConsoleIO.BasicIO ? Translations.Get("mcc.login_basic_io") : Translations.Get("mcc.login"));
|
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 == ""
|
if (string.IsNullOrEmpty(Config.Main.General.Account.Password) && !useBrowser &&
|
||||||
&& (Settings.SessionCaching == CacheType.None || !SessionCache.Contains(Settings.ToLowerIfNeed(Settings.Login)))
|
(Config.Main.Advanced.SessionCache == CacheType.none || !SessionCache.Contains(Settings.ToLowerIfNeed(Config.Main.General.Account.Login))))
|
||||||
&& !useBrowser)
|
|
||||||
{
|
{
|
||||||
RequestPassword();
|
RequestPassword();
|
||||||
}
|
}
|
||||||
|
else
|
||||||
// Setup exit cleaning code
|
|
||||||
ExitCleanUp.Add(delegate ()
|
|
||||||
{
|
{
|
||||||
// Do NOT use Program.Exit() as creating new Thread cause program to freeze
|
InternalConfig.Password = Config.Main.General.Account.Password;
|
||||||
if (client != null) { client.Disconnect(); ConsoleIO.Reset(); }
|
}
|
||||||
if (offlinePrompt != null) { offlinePrompt.Item2.Cancel(); offlinePrompt = null; ConsoleIO.Reset(); }
|
|
||||||
if (Settings.playerHeadAsIcon) { ConsoleIcon.RevertToMCCIcon(); }
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
startupargs = args;
|
startupargs = args;
|
||||||
InitializeClient();
|
InitializeClient();
|
||||||
|
|
@ -281,10 +309,10 @@ namespace MinecraftClient
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private static void RequestPassword()
|
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();
|
string? password = ConsoleIO.BasicIO ? Console.ReadLine() : ConsoleIO.ReadPassword();
|
||||||
if (password == null || password == string.Empty) { password = "-"; }
|
if (password == null || password == string.Empty) { password = "-"; }
|
||||||
Settings.Password = password;
|
InternalConfig.Password = password;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
@ -292,23 +320,25 @@ namespace MinecraftClient
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private static void InitializeClient()
|
private static void InitializeClient()
|
||||||
{
|
{
|
||||||
|
InternalConfig.MinecraftVersion = Config.Main.Advanced.MinecraftVersion;
|
||||||
|
|
||||||
SessionToken session = new();
|
SessionToken session = new();
|
||||||
PlayerKeyPair? playerKeyPair = null;
|
PlayerKeyPair? playerKeyPair = null;
|
||||||
|
|
||||||
ProtocolHandler.LoginResult result = ProtocolHandler.LoginResult.LoginRequired;
|
ProtocolHandler.LoginResult result = ProtocolHandler.LoginResult.LoginRequired;
|
||||||
|
|
||||||
string loginLower = Settings.ToLowerIfNeed(Settings.Login);
|
string loginLower = Settings.ToLowerIfNeed(Config.Main.General.Account.Login);
|
||||||
if (Settings.Password == "-")
|
if (InternalConfig.Password == "-")
|
||||||
{
|
{
|
||||||
Translations.WriteLineFormatted("mcc.offline");
|
Translations.WriteLineFormatted("mcc.offline");
|
||||||
result = ProtocolHandler.LoginResult.Success;
|
result = ProtocolHandler.LoginResult.Success;
|
||||||
session.PlayerID = "0";
|
session.PlayerID = "0";
|
||||||
session.PlayerName = Settings.Login;
|
session.PlayerName = Config.Main.General.Account.Login;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Validate cached session or login new session.
|
// 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);
|
session = SessionCache.Get(loginLower);
|
||||||
result = ProtocolHandler.GetTokenValidation(session);
|
result = ProtocolHandler.GetTokenValidation(session);
|
||||||
|
|
@ -330,8 +360,8 @@ namespace MinecraftClient
|
||||||
}
|
}
|
||||||
|
|
||||||
if (result != ProtocolHandler.LoginResult.Success
|
if (result != ProtocolHandler.LoginResult.Success
|
||||||
&& Settings.Password == ""
|
&& InternalConfig.Password == ""
|
||||||
&& Settings.AccountType == ProtocolHandler.AccountType.Mojang)
|
&& Config.Main.General.AccountType == LoginType.mojang)
|
||||||
RequestPassword();
|
RequestPassword();
|
||||||
}
|
}
|
||||||
else ConsoleIO.WriteLineFormatted(Translations.Get("mcc.session_valid", session.PlayerName));
|
else ConsoleIO.WriteLineFormatted(Translations.Get("mcc.session_valid", session.PlayerName));
|
||||||
|
|
@ -339,12 +369,12 @@ namespace MinecraftClient
|
||||||
|
|
||||||
if (result != ProtocolHandler.LoginResult.Success)
|
if (result != ProtocolHandler.LoginResult.Success)
|
||||||
{
|
{
|
||||||
Translations.WriteLine("mcc.connecting", Settings.AccountType == ProtocolHandler.AccountType.Mojang ? "Minecraft.net" : "Microsoft");
|
Translations.WriteLine("mcc.connecting", Config.Main.General.AccountType == LoginType.mojang ? "Minecraft.net" : "Microsoft");
|
||||||
result = ProtocolHandler.GetLogin(Settings.Login, Settings.Password, Settings.AccountType, out session);
|
result = ProtocolHandler.GetLogin(Config.Main.General.Account.Login, InternalConfig.Password, Config.Main.General.AccountType, out session);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (result == ProtocolHandler.LoginResult.Success && Settings.SessionCaching != CacheType.None)
|
if (result == ProtocolHandler.LoginResult.Success && Config.Main.Advanced.SessionCache != CacheType.none)
|
||||||
SessionCache.Store(loginLower, session);
|
SessionCache.Store(loginLower, session);
|
||||||
|
|
||||||
if (result == ProtocolHandler.LoginResult.Success)
|
if (result == ProtocolHandler.LoginResult.Success)
|
||||||
|
|
@ -352,17 +382,17 @@ namespace MinecraftClient
|
||||||
|
|
||||||
if (result == ProtocolHandler.LoginResult.Success)
|
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
|
// Load cached profile key from disk if necessary
|
||||||
if (Settings.ProfileKeyCaching == CacheType.Disk)
|
if (Config.Main.Advanced.ProfileKeyCache == CacheType.disk)
|
||||||
{
|
{
|
||||||
bool cacheKeyLoaded = KeysCache.InitializeDiskCache();
|
bool cacheKeyLoaded = KeysCache.InitializeDiskCache();
|
||||||
if (Settings.DebugMessages)
|
if (Config.Logging.DebugMessages)
|
||||||
Translations.WriteLineFormatted(cacheKeyLoaded ? "debug.keys_cache_ok" : "debug.keys_cache_fail");
|
Translations.WriteLineFormatted(cacheKeyLoaded ? "debug.keys_cache_ok" : "debug.keys_cache_fail");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Settings.ProfileKeyCaching != CacheType.None && KeysCache.Contains(loginLower))
|
if (Config.Main.Advanced.ProfileKeyCache != CacheType.none && KeysCache.Contains(loginLower))
|
||||||
{
|
{
|
||||||
playerKeyPair = KeysCache.Get(loginLower);
|
playerKeyPair = KeysCache.Get(loginLower);
|
||||||
if (playerKeyPair.NeedRefresh())
|
if (playerKeyPair.NeedRefresh())
|
||||||
|
|
@ -375,36 +405,36 @@ namespace MinecraftClient
|
||||||
{
|
{
|
||||||
Translations.WriteLineFormatted("mcc.fetching_key");
|
Translations.WriteLineFormatted("mcc.fetching_key");
|
||||||
playerKeyPair = KeyUtils.GetNewProfileKeys(session.ID);
|
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);
|
KeysCache.Store(loginLower, playerKeyPair);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Settings.Username = session.PlayerName;
|
InternalConfig.Username = session.PlayerName;
|
||||||
bool isRealms = false;
|
bool isRealms = false;
|
||||||
|
|
||||||
if (Settings.ConsoleTitle != "")
|
if (Config.Main.Advanced.ConsoleTitle != "")
|
||||||
Console.Title = Settings.ExpandVars(Settings.ConsoleTitle);
|
Console.Title = Config.AppVar.ExpandVars(Config.Main.Advanced.ConsoleTitle);
|
||||||
|
|
||||||
if (Settings.playerHeadAsIcon)
|
if (Config.Main.Advanced.PlayerHeadAsIcon)
|
||||||
ConsoleIcon.SetPlayerIconAsync(Settings.Username);
|
ConsoleIcon.SetPlayerIconAsync(InternalConfig.Username);
|
||||||
|
|
||||||
if (Settings.DebugMessages)
|
if (Config.Logging.DebugMessages)
|
||||||
Translations.WriteLine("debug.session_id", session.ID);
|
Translations.WriteLine("debug.session_id", session.ID);
|
||||||
|
|
||||||
List<string> availableWorlds = new();
|
List<string> availableWorlds = new();
|
||||||
if (Settings.MinecraftRealmsEnabled && !String.IsNullOrEmpty(session.ID))
|
if (Config.Main.Advanced.MinecraftRealms && !String.IsNullOrEmpty(session.ID))
|
||||||
availableWorlds = ProtocolHandler.RealmsListWorlds(Settings.Username, session.PlayerID, session.ID);
|
availableWorlds = ProtocolHandler.RealmsListWorlds(InternalConfig.Username, session.PlayerID, session.ID);
|
||||||
|
|
||||||
if (Settings.ServerIP == "")
|
if (InternalConfig.ServerIP == string.Empty)
|
||||||
{
|
{
|
||||||
Translations.Write("mcc.ip");
|
Translations.Write("mcc.ip");
|
||||||
string addressInput = ConsoleIO.ReadLine();
|
string addressInput = ConsoleIO.ReadLine();
|
||||||
if (addressInput.StartsWith("realms:"))
|
if (addressInput.StartsWith("realms:"))
|
||||||
{
|
{
|
||||||
if (Settings.MinecraftRealmsEnabled)
|
if (Config.Main.Advanced.MinecraftRealms)
|
||||||
{
|
{
|
||||||
if (availableWorlds.Count == 0)
|
if (availableWorlds.Count == 0)
|
||||||
{
|
{
|
||||||
|
|
@ -416,12 +446,12 @@ namespace MinecraftClient
|
||||||
worldId = availableWorlds[worldIndex];
|
worldId = availableWorlds[worldIndex];
|
||||||
if (availableWorlds.Contains(worldId))
|
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 != "")
|
if (RealmsAddress != "")
|
||||||
{
|
{
|
||||||
addressInput = RealmsAddress;
|
addressInput = RealmsAddress;
|
||||||
isRealms = true;
|
isRealms = true;
|
||||||
Settings.ServerVersion = MCHighestVersion;
|
InternalConfig.MinecraftVersion = MCHighestVersion;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
@ -441,37 +471,37 @@ namespace MinecraftClient
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Settings.SetServerIP(addressInput);
|
Config.Main.SetServerIP(new MainConfigHealper.MainConfig.ServerInfoConfig(addressInput), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
//Get server version
|
//Get server version
|
||||||
int protocolversion = 0;
|
int protocolversion = 0;
|
||||||
ForgeInfo? forgeInfo = null;
|
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)
|
if (protocolversion != 0)
|
||||||
{
|
ConsoleIO.WriteLineFormatted(Translations.Get("mcc.use_version", InternalConfig.MinecraftVersion, protocolversion));
|
||||||
ConsoleIO.WriteLineFormatted(Translations.Get("mcc.use_version", Settings.ServerVersion, protocolversion));
|
else
|
||||||
}
|
ConsoleIO.WriteLineFormatted(Translations.Get("mcc.unknown_version", InternalConfig.MinecraftVersion));
|
||||||
else ConsoleIO.WriteLineFormatted(Translations.Get("mcc.unknown_version", Settings.ServerVersion));
|
|
||||||
|
|
||||||
if (useMcVersionOnce)
|
if (useMcVersionOnce)
|
||||||
{
|
{
|
||||||
useMcVersionOnce = false;
|
useMcVersionOnce = false;
|
||||||
Settings.ServerVersion = "";
|
InternalConfig.MinecraftVersion = "";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//Retrieve server info if version is not manually set OR if need to retrieve Forge information
|
//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)
|
if (protocolversion != 0)
|
||||||
Translations.WriteLine("mcc.forge");
|
Translations.WriteLine("mcc.forge");
|
||||||
else Translations.WriteLine("mcc.retrieve");
|
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);
|
HandleFailure(Translations.Get("error.ping"), true, ChatBots.AutoRelog.DisconnectReason.ConnectionLost);
|
||||||
return;
|
return;
|
||||||
|
|
@ -479,7 +509,7 @@ namespace MinecraftClient
|
||||||
}
|
}
|
||||||
|
|
||||||
//Force-enable Forge support?
|
//Force-enable Forge support?
|
||||||
if (!isRealms && Settings.ServerForceForge && forgeInfo == null)
|
if (!isRealms && (Config.Main.Advanced.EnableForge == ForgeConfigType.force) && forgeInfo == null)
|
||||||
{
|
{
|
||||||
if (ProtocolHandler.ProtocolMayForceForge(protocolversion))
|
if (ProtocolHandler.ProtocolMayForceForge(protocolversion))
|
||||||
{
|
{
|
||||||
|
|
@ -499,12 +529,11 @@ namespace MinecraftClient
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
//Start the main TCP client
|
//Start the main TCP client
|
||||||
string? command = String.IsNullOrEmpty(Settings.SingleCommand) ? null : Settings.SingleCommand;
|
client = new McClient(session, playerKeyPair, InternalConfig.ServerIP, InternalConfig.ServerPort, protocolversion, forgeInfo);
|
||||||
client = new McClient(session, playerKeyPair, Settings.ServerIP, Settings.ServerPort, protocolversion, forgeInfo, command);
|
|
||||||
|
|
||||||
//Update console title
|
//Update console title
|
||||||
if (Settings.ConsoleTitle != "")
|
if (Config.Main.Advanced.ConsoleTitle != "")
|
||||||
Console.Title = Settings.ExpandVars(Settings.ConsoleTitle);
|
Console.Title = Config.AppVar.ExpandVars(Config.Main.Advanced.ConsoleTitle);
|
||||||
}
|
}
|
||||||
catch (NotSupportedException)
|
catch (NotSupportedException)
|
||||||
{
|
{
|
||||||
|
|
@ -543,7 +572,8 @@ namespace MinecraftClient
|
||||||
public static void ReloadSettings()
|
public static void ReloadSettings()
|
||||||
{
|
{
|
||||||
if (settingsIniPath != null)
|
if (settingsIniPath != null)
|
||||||
Settings.LoadFile(settingsIniPath);
|
if(Settings.LoadFromFile(settingsIniPath))
|
||||||
|
ConsoleIO.WriteLine(Translations.TryGet("config.loading", settingsIniPath));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
@ -563,22 +593,30 @@ namespace MinecraftClient
|
||||||
System.Threading.Thread.Sleep(delaySeconds * 1000);
|
System.Threading.Thread.Sleep(delaySeconds * 1000);
|
||||||
}
|
}
|
||||||
Translations.WriteLine("mcc.restart");
|
Translations.WriteLine("mcc.restart");
|
||||||
|
ReloadSettings();
|
||||||
InitializeClient();
|
InitializeClient();
|
||||||
})).Start();
|
})).Start();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void DoExit(int exitcode = 0)
|
||||||
|
{
|
||||||
|
if (settingsIniPath != null)
|
||||||
|
{
|
||||||
|
Settings.WriteToFile(settingsIniPath, true);
|
||||||
|
ConsoleIO.WriteLineFormatted(Translations.TryGet("config.saving", settingsIniPath));
|
||||||
|
}
|
||||||
|
if (client != null) { client.Disconnect(); ConsoleIO.Reset(); }
|
||||||
|
if (offlinePrompt != null) { offlinePrompt.Item2.Cancel(); offlinePrompt.Item1.Join(); offlinePrompt = null; ConsoleIO.Reset(); }
|
||||||
|
if (Config.Main.Advanced.PlayerHeadAsIcon) { ConsoleIcon.RevertToMCCIcon(); }
|
||||||
|
Environment.Exit(exitcode);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Disconnect the current client from the server and exit the app
|
/// Disconnect the current client from the server and exit the app
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static void Exit(int exitcode = 0)
|
public static void Exit(int exitcode = 0)
|
||||||
{
|
{
|
||||||
new Thread(new ThreadStart(delegate
|
new Thread(new ThreadStart(() => { DoExit(exitcode); })).Start();
|
||||||
{
|
|
||||||
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();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
@ -595,7 +633,7 @@ namespace MinecraftClient
|
||||||
ConsoleIO.Reset();
|
ConsoleIO.Reset();
|
||||||
while (Console.KeyAvailable)
|
while (Console.KeyAvailable)
|
||||||
Console.ReadKey(true);
|
Console.ReadKey(true);
|
||||||
Console.WriteLine(errorMessage);
|
ConsoleIO.WriteLine(errorMessage);
|
||||||
|
|
||||||
if (disconnectReason.HasValue)
|
if (disconnectReason.HasValue)
|
||||||
{
|
{
|
||||||
|
|
@ -604,13 +642,13 @@ namespace MinecraftClient
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Settings.interactiveMode)
|
if (InternalConfig.InteractiveMode)
|
||||||
{
|
{
|
||||||
if (versionError)
|
if (versionError)
|
||||||
{
|
{
|
||||||
Translations.Write("mcc.server_version");
|
Translations.Write("mcc.server_version");
|
||||||
Settings.ServerVersion = ConsoleInteractive.ConsoleReader.RequestImmediateInput();
|
InternalConfig.MinecraftVersion = ConsoleInteractive.ConsoleReader.RequestImmediateInput();
|
||||||
if (Settings.ServerVersion != "")
|
if (InternalConfig.MinecraftVersion != "")
|
||||||
{
|
{
|
||||||
useMcVersionOnce = true;
|
useMcVersionOnce = true;
|
||||||
Restart();
|
Restart();
|
||||||
|
|
@ -627,7 +665,8 @@ namespace MinecraftClient
|
||||||
{
|
{
|
||||||
bool exitThread = false;
|
bool exitThread = false;
|
||||||
string command = " ";
|
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");
|
Translations.WriteLineFormatted("mcc.press_exit");
|
||||||
|
|
||||||
while (!cancellationTokenSource.IsCancellationRequested)
|
while (!cancellationTokenSource.IsCancellationRequested)
|
||||||
|
|
@ -645,13 +684,13 @@ namespace MinecraftClient
|
||||||
{
|
{
|
||||||
string message = "";
|
string message = "";
|
||||||
|
|
||||||
if (Settings.internalCmdChar != ' '
|
if (Config.Main.Advanced.InternalCmdChar.ToChar() != ' '
|
||||||
&& command[0] == Settings.internalCmdChar)
|
&& command[0] == Config.Main.Advanced.InternalCmdChar.ToChar())
|
||||||
command = command[1..];
|
command = command[1..];
|
||||||
|
|
||||||
if (command.StartsWith("reco"))
|
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 == "")
|
if (message == "")
|
||||||
{
|
{
|
||||||
exitThread = true;
|
exitThread = true;
|
||||||
|
|
@ -660,7 +699,7 @@ namespace MinecraftClient
|
||||||
}
|
}
|
||||||
else if (command.StartsWith("connect"))
|
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 == "")
|
if (message == "")
|
||||||
{
|
{
|
||||||
exitThread = true;
|
exitThread = true;
|
||||||
|
|
@ -669,31 +708,26 @@ namespace MinecraftClient
|
||||||
}
|
}
|
||||||
else if (command.StartsWith("exit") || command.StartsWith("quit"))
|
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"))
|
else if (command.StartsWith("help"))
|
||||||
{
|
{
|
||||||
ConsoleIO.WriteLineFormatted("§8MCC: " +
|
ConsoleIO.WriteLineFormatted("§8MCC: " +
|
||||||
(Settings.internalCmdChar == ' '
|
Config.Main.Advanced.InternalCmdChar.ToLogString() +
|
||||||
? ""
|
|
||||||
: "" + Settings.internalCmdChar) +
|
|
||||||
new Commands.Reco().GetCmdDescTranslated());
|
new Commands.Reco().GetCmdDescTranslated());
|
||||||
ConsoleIO.WriteLineFormatted("§8MCC: " +
|
ConsoleIO.WriteLineFormatted("§8MCC: " +
|
||||||
(Settings.internalCmdChar == ' '
|
Config.Main.Advanced.InternalCmdChar.ToLogString() +
|
||||||
? ""
|
|
||||||
: "" + Settings.internalCmdChar) +
|
|
||||||
new Commands.Connect().GetCmdDescTranslated());
|
new Commands.Connect().GetCmdDescTranslated());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
ConsoleIO.WriteLineFormatted(Translations.Get("icmd.unknown",
|
ConsoleIO.WriteLineFormatted(Translations.Get("icmd.unknown", command.Split(' ')[0]));
|
||||||
command.Split(' ')[0]));
|
|
||||||
|
|
||||||
if (message != "")
|
if (message != "")
|
||||||
ConsoleIO.WriteLineFormatted("§8MCC: " + message);
|
ConsoleIO.WriteLineFormatted("§8MCC: " + message);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_ = new Commands.Exit().Run(null, Settings.ExpandVars(command), null);
|
_ = new Commands.Exit().Run(null, Config.AppVar.ExpandVars(command), null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -61,7 +61,7 @@ namespace MinecraftClient.Protocol.Handlers.PacketPalettes
|
||||||
}
|
}
|
||||||
else if (forgeEnabled)
|
else if (forgeEnabled)
|
||||||
{
|
{
|
||||||
if (Settings.DebugMessages)
|
if (Settings.Config.Logging.DebugMessages)
|
||||||
ConsoleIO.WriteLogLine("Ignoring unknown packet ID of 0x" + packetId.ToString("X2"));
|
ConsoleIO.WriteLogLine("Ignoring unknown packet ID of 0x" + packetId.ToString("X2"));
|
||||||
return PacketTypesIn.Unknown;
|
return PacketTypesIn.Unknown;
|
||||||
}
|
}
|
||||||
|
|
@ -92,7 +92,7 @@ namespace MinecraftClient.Protocol.Handlers.PacketPalettes
|
||||||
}
|
}
|
||||||
else if (forgeEnabled)
|
else if (forgeEnabled)
|
||||||
{
|
{
|
||||||
if (Settings.DebugMessages)
|
if (Settings.Config.Logging.DebugMessages)
|
||||||
ConsoleIO.WriteLogLine("Ignoring unknown packet ID of 0x" + packetId.ToString("X2"));
|
ConsoleIO.WriteLogLine("Ignoring unknown packet ID of 0x" + packetId.ToString("X2"));
|
||||||
return PacketTypesOut.Unknown;
|
return PacketTypesOut.Unknown;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,7 @@ using MinecraftClient.Protocol.Keys;
|
||||||
using MinecraftClient.Protocol.Message;
|
using MinecraftClient.Protocol.Message;
|
||||||
using MinecraftClient.Protocol.Session;
|
using MinecraftClient.Protocol.Session;
|
||||||
using MinecraftClient.Proxy;
|
using MinecraftClient.Proxy;
|
||||||
|
using static MinecraftClient.Settings;
|
||||||
|
|
||||||
namespace MinecraftClient.Protocol.Handlers
|
namespace MinecraftClient.Protocol.Handlers
|
||||||
{
|
{
|
||||||
|
|
@ -494,7 +495,7 @@ namespace MinecraftClient.Protocol.Handlers
|
||||||
|
|
||||||
if (serverID == "-")
|
if (serverID == "-")
|
||||||
Translations.WriteLineFormatted("mcc.server_offline");
|
Translations.WriteLineFormatted("mcc.server_offline");
|
||||||
else if (Settings.DebugMessages)
|
else if (Settings.Config.Logging.DebugMessages)
|
||||||
ConsoleIO.WriteLineFormatted(Translations.Get("mcc.handshake", serverID));
|
ConsoleIO.WriteLineFormatted(Translations.Get("mcc.handshake", serverID));
|
||||||
|
|
||||||
return StartEncryption(uuid, username, sessionID, token, serverID, PublicServerkey, session);
|
return StartEncryption(uuid, username, sessionID, token, serverID, PublicServerkey, session);
|
||||||
|
|
@ -511,7 +512,7 @@ namespace MinecraftClient.Protocol.Handlers
|
||||||
RSACryptoServiceProvider RSAService = CryptoHandler.DecodeRSAPublicKey(serverPublicKey)!;
|
RSACryptoServiceProvider RSAService = CryptoHandler.DecodeRSAPublicKey(serverPublicKey)!;
|
||||||
byte[] secretKey = CryptoHandler.ClientAESPrivateKey ?? CryptoHandler.GenerateAESPrivateKey();
|
byte[] secretKey = CryptoHandler.ClientAESPrivateKey ?? CryptoHandler.GenerateAESPrivateKey();
|
||||||
|
|
||||||
if (Settings.DebugMessages)
|
if (Settings.Config.Logging.DebugMessages)
|
||||||
Translations.WriteLineFormatted("debug.crypto");
|
Translations.WriteLineFormatted("debug.crypto");
|
||||||
|
|
||||||
if (serverIDhash != "-")
|
if (serverIDhash != "-")
|
||||||
|
|
@ -534,7 +535,7 @@ namespace MinecraftClient.Protocol.Handlers
|
||||||
{
|
{
|
||||||
session.ServerIDhash = serverIDhash;
|
session.ServerIDhash = serverIDhash;
|
||||||
session.ServerPublicKey = serverPublicKey;
|
session.ServerPublicKey = serverPublicKey;
|
||||||
SessionCache.Store(Settings.Login.ToLower(), session);
|
SessionCache.Store(Config.Main.General.Account.Login.ToLower(), session);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
@ -862,7 +863,7 @@ namespace MinecraftClient.Protocol.Handlers
|
||||||
Protocol16Handler ComTmp = new(tcp);
|
Protocol16Handler ComTmp = new(tcp);
|
||||||
string result = ComTmp.ReadNextString();
|
string result = ComTmp.ReadNextString();
|
||||||
|
|
||||||
if (Settings.DebugMessages)
|
if (Settings.Config.Logging.DebugMessages)
|
||||||
{
|
{
|
||||||
// May contain formatting codes, cannot use WriteLineFormatted
|
// May contain formatting codes, cannot use WriteLineFormatted
|
||||||
Console.ForegroundColor = ConsoleColor.DarkGray;
|
Console.ForegroundColor = ConsoleColor.DarkGray;
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,7 @@ using MinecraftClient.Protocol.Keys;
|
||||||
using MinecraftClient.Protocol.Message;
|
using MinecraftClient.Protocol.Message;
|
||||||
using MinecraftClient.Protocol.Session;
|
using MinecraftClient.Protocol.Session;
|
||||||
using MinecraftClient.Proxy;
|
using MinecraftClient.Proxy;
|
||||||
|
using static MinecraftClient.Settings;
|
||||||
|
|
||||||
namespace MinecraftClient.Protocol.Handlers
|
namespace MinecraftClient.Protocol.Handlers
|
||||||
{
|
{
|
||||||
|
|
@ -461,8 +462,8 @@ namespace MinecraftClient.Protocol.Handlers
|
||||||
{
|
{
|
||||||
//Hide system messages or xp bar messages?
|
//Hide system messages or xp bar messages?
|
||||||
messageType = dataTypes.ReadNextByte(packetData);
|
messageType = dataTypes.ReadNextByte(packetData);
|
||||||
if ((messageType == 1 && !Settings.DisplaySystemMessages)
|
if ((messageType == 1 && !Config.Main.Advanced.ShowSystemMessages)
|
||||||
|| (messageType == 2 && !Settings.DisplayXPBarMessages))
|
|| (messageType == 2 && !Config.Main.Advanced.ShowSystemMessages))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (protocolVersion >= MC_1_16_5_Version)
|
if (protocolVersion >= MC_1_16_5_Version)
|
||||||
|
|
@ -482,8 +483,8 @@ namespace MinecraftClient.Protocol.Handlers
|
||||||
string? unsignedChatContent = hasUnsignedChatContent ? dataTypes.ReadNextString(packetData) : null;
|
string? unsignedChatContent = hasUnsignedChatContent ? dataTypes.ReadNextString(packetData) : null;
|
||||||
|
|
||||||
messageType = dataTypes.ReadNextVarInt(packetData);
|
messageType = dataTypes.ReadNextVarInt(packetData);
|
||||||
if ((messageType == 1 && !Settings.DisplaySystemMessages)
|
if ((messageType == 1 && !Config.Main.Advanced.ShowSystemMessages)
|
||||||
|| (messageType == 2 && !Settings.DisplayXPBarMessages))
|
|| (messageType == 2 && !Config.Main.Advanced.ShowXPBarMessages))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
Guid senderUUID = dataTypes.ReadNextUUID(packetData);
|
Guid senderUUID = dataTypes.ReadNextUUID(packetData);
|
||||||
|
|
@ -1603,7 +1604,7 @@ namespace MinecraftClient.Protocol.Handlers
|
||||||
case PacketTypesIn.SystemChat:
|
case PacketTypesIn.SystemChat:
|
||||||
string systemMessage = dataTypes.ReadNextString(packetData);
|
string systemMessage = dataTypes.ReadNextString(packetData);
|
||||||
int msgType = dataTypes.ReadNextVarInt(packetData);
|
int msgType = dataTypes.ReadNextVarInt(packetData);
|
||||||
if ((msgType == 1 && !Settings.DisplaySystemMessages))
|
if ((msgType == 1 && !Config.Main.Advanced.ShowSystemMessages))
|
||||||
break;
|
break;
|
||||||
handler.OnTextReceived(new(systemMessage, true, msgType, Guid.Empty, true));
|
handler.OnTextReceived(new(systemMessage, true, msgType, Guid.Empty, true));
|
||||||
break;
|
break;
|
||||||
|
|
@ -1925,7 +1926,7 @@ namespace MinecraftClient.Protocol.Handlers
|
||||||
{
|
{
|
||||||
session.ServerIDhash = serverIDhash;
|
session.ServerIDhash = serverIDhash;
|
||||||
session.ServerPublicKey = serverPublicKey;
|
session.ServerPublicKey = serverPublicKey;
|
||||||
SessionCache.Store(Settings.Login.ToLower(), session);
|
SessionCache.Store(Config.Main.General.Account.Login.ToLower(), session);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
@ -2119,7 +2120,7 @@ namespace MinecraftClient.Protocol.Handlers
|
||||||
{
|
{
|
||||||
string result = dataTypes.ReadNextString(packetData); //Get the Json data
|
string result = dataTypes.ReadNextString(packetData); //Get the Json data
|
||||||
|
|
||||||
if (Settings.DebugMessages)
|
if (Config.Logging.DebugMessages)
|
||||||
{
|
{
|
||||||
// May contain formatting codes, cannot use WriteLineFormatted
|
// May contain formatting codes, cannot use WriteLineFormatted
|
||||||
Console.ForegroundColor = ConsoleColor.DarkGray;
|
Console.ForegroundColor = ConsoleColor.DarkGray;
|
||||||
|
|
@ -2230,7 +2231,7 @@ namespace MinecraftClient.Protocol.Handlers
|
||||||
/// <returns> List< Argument Name, Argument Value > </returns>
|
/// <returns> List< Argument Name, Argument Value > </returns>
|
||||||
private List<Tuple<string, string>>? CollectCommandArguments(string command)
|
private List<Tuple<string, string>>? CollectCommandArguments(string command)
|
||||||
{
|
{
|
||||||
if (!isOnlineMode || !Settings.SignMessageInCommand)
|
if (!isOnlineMode || !Config.Signature.SignMessageInCommand)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
List<Tuple<string, string>> needSigned = new();
|
List<Tuple<string, string>> needSigned = new();
|
||||||
|
|
@ -2371,7 +2372,7 @@ namespace MinecraftClient.Protocol.Handlers
|
||||||
DateTimeOffset timeNow = DateTimeOffset.UtcNow;
|
DateTimeOffset timeNow = DateTimeOffset.UtcNow;
|
||||||
fields.AddRange(dataTypes.GetLong(timeNow.ToUnixTimeMilliseconds()));
|
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.GetLong(0)); // Salt: Long
|
||||||
fields.AddRange(dataTypes.GetVarInt(0)); // Signature Length: VarInt
|
fields.AddRange(dataTypes.GetVarInt(0)); // Signature Length: VarInt
|
||||||
|
|
|
||||||
|
|
@ -130,7 +130,7 @@ namespace MinecraftClient.Protocol.Handlers
|
||||||
|
|
||||||
byte fmlProtocolVersion = dataTypes.ReadNextByte(packetData);
|
byte fmlProtocolVersion = dataTypes.ReadNextByte(packetData);
|
||||||
|
|
||||||
if (Settings.DebugMessages)
|
if (Settings.Config.Logging.DebugMessages)
|
||||||
ConsoleIO.WriteLineFormatted(Translations.Get("forge.version", fmlProtocolVersion));
|
ConsoleIO.WriteLineFormatted(Translations.Get("forge.version", fmlProtocolVersion));
|
||||||
|
|
||||||
if (fmlProtocolVersion >= 1)
|
if (fmlProtocolVersion >= 1)
|
||||||
|
|
@ -140,7 +140,7 @@ namespace MinecraftClient.Protocol.Handlers
|
||||||
SendForgeHandshakePacket(FMLHandshakeDiscriminator.ClientHello, new byte[] { fmlProtocolVersion });
|
SendForgeHandshakePacket(FMLHandshakeDiscriminator.ClientHello, new byte[] { fmlProtocolVersion });
|
||||||
|
|
||||||
// Then tell the server that we're running the same mods.
|
// Then tell the server that we're running the same mods.
|
||||||
if (Settings.DebugMessages)
|
if (Settings.Config.Logging.DebugMessages)
|
||||||
Translations.WriteLineFormatted("forge.send_mod");
|
Translations.WriteLineFormatted("forge.send_mod");
|
||||||
byte[][] mods = new byte[forgeInfo.Mods.Count][];
|
byte[][] mods = new byte[forgeInfo.Mods.Count][];
|
||||||
for (int i = 0; i < forgeInfo.Mods.Count; i++)
|
for (int i = 0; i < forgeInfo.Mods.Count; i++)
|
||||||
|
|
@ -160,7 +160,7 @@ namespace MinecraftClient.Protocol.Handlers
|
||||||
|
|
||||||
Thread.Sleep(2000);
|
Thread.Sleep(2000);
|
||||||
|
|
||||||
if (Settings.DebugMessages)
|
if (Settings.Config.Logging.DebugMessages)
|
||||||
Translations.WriteLineFormatted("forge.accept");
|
Translations.WriteLineFormatted("forge.accept");
|
||||||
// Tell the server that yes, we are OK with the mods it has
|
// Tell the server that yes, we are OK with the mods it has
|
||||||
// even though we don't actually care what 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.
|
// with blocks and items.
|
||||||
int registrySize = dataTypes.ReadNextVarInt(packetData);
|
int registrySize = dataTypes.ReadNextVarInt(packetData);
|
||||||
|
|
||||||
if (Settings.DebugMessages)
|
if (Settings.Config.Logging.DebugMessages)
|
||||||
ConsoleIO.WriteLineFormatted(Translations.Get("forge.registry", registrySize));
|
ConsoleIO.WriteLineFormatted(Translations.Get("forge.registry", registrySize));
|
||||||
|
|
||||||
fmlHandshakeState = FMLHandshakeClientState.PENDINGCOMPLETE;
|
fmlHandshakeState = FMLHandshakeClientState.PENDINGCOMPLETE;
|
||||||
|
|
@ -194,7 +194,7 @@ namespace MinecraftClient.Protocol.Handlers
|
||||||
bool hasNextRegistry = dataTypes.ReadNextBool(packetData);
|
bool hasNextRegistry = dataTypes.ReadNextBool(packetData);
|
||||||
string registryName = dataTypes.ReadNextString(packetData);
|
string registryName = dataTypes.ReadNextString(packetData);
|
||||||
int registrySize = dataTypes.ReadNextVarInt(packetData);
|
int registrySize = dataTypes.ReadNextVarInt(packetData);
|
||||||
if (Settings.DebugMessages)
|
if (Settings.Config.Logging.DebugMessages)
|
||||||
ConsoleIO.WriteLineFormatted(Translations.Get("forge.registry_2", registryName, registrySize));
|
ConsoleIO.WriteLineFormatted(Translations.Get("forge.registry_2", registryName, registrySize));
|
||||||
if (!hasNextRegistry)
|
if (!hasNextRegistry)
|
||||||
fmlHandshakeState = FMLHandshakeClientState.PENDINGCOMPLETE;
|
fmlHandshakeState = FMLHandshakeClientState.PENDINGCOMPLETE;
|
||||||
|
|
@ -206,7 +206,7 @@ namespace MinecraftClient.Protocol.Handlers
|
||||||
// Just say yes.
|
// Just say yes.
|
||||||
if (discriminator != FMLHandshakeDiscriminator.HandshakeAck)
|
if (discriminator != FMLHandshakeDiscriminator.HandshakeAck)
|
||||||
return false;
|
return false;
|
||||||
if (Settings.DebugMessages)
|
if (Settings.Config.Logging.DebugMessages)
|
||||||
Translations.WriteLineFormatted("forge.accept_registry");
|
Translations.WriteLineFormatted("forge.accept_registry");
|
||||||
SendForgeHandshakePacket(FMLHandshakeDiscriminator.HandshakeAck,
|
SendForgeHandshakePacket(FMLHandshakeDiscriminator.HandshakeAck,
|
||||||
new byte[] { (byte)FMLHandshakeClientState.PENDINGCOMPLETE });
|
new byte[] { (byte)FMLHandshakeClientState.PENDINGCOMPLETE });
|
||||||
|
|
@ -220,7 +220,7 @@ namespace MinecraftClient.Protocol.Handlers
|
||||||
|
|
||||||
SendForgeHandshakePacket(FMLHandshakeDiscriminator.HandshakeAck,
|
SendForgeHandshakePacket(FMLHandshakeDiscriminator.HandshakeAck,
|
||||||
new byte[] { (byte)FMLHandshakeClientState.COMPLETE });
|
new byte[] { (byte)FMLHandshakeClientState.COMPLETE });
|
||||||
if (Settings.DebugMessages)
|
if (Settings.Config.Logging.DebugMessages)
|
||||||
Translations.WriteLine("forge.complete");
|
Translations.WriteLine("forge.complete");
|
||||||
fmlHandshakeState = FMLHandshakeClientState.DONE;
|
fmlHandshakeState = FMLHandshakeClientState.DONE;
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -300,7 +300,7 @@ namespace MinecraftClient.Protocol.Handlers
|
||||||
//
|
//
|
||||||
// [1]: Version is usually set to "FML2" for FML stuff and "1" for mods
|
// [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");
|
Translations.WriteLineFormatted("forge.fml2.mod");
|
||||||
|
|
||||||
List<string> mods = new();
|
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
|
// 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.
|
// 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");
|
Translations.WriteLineFormatted("forge.fml2.mod_send");
|
||||||
|
|
||||||
// Packet ID 2: Client to Server Mod List
|
// Packet ID 2: Client to Server Mod List
|
||||||
|
|
@ -368,7 +368,7 @@ namespace MinecraftClient.Protocol.Handlers
|
||||||
// Registry Snapshot: ForgeRegistry.java > Snapshot > read(PacketBuffer)
|
// Registry Snapshot: ForgeRegistry.java > Snapshot > read(PacketBuffer)
|
||||||
// Not documented yet. We're ignoring this packet in MCC
|
// Not documented yet. We're ignoring this packet in MCC
|
||||||
|
|
||||||
if (Settings.DebugMessages)
|
if (Settings.Config.Logging.DebugMessages)
|
||||||
{
|
{
|
||||||
string registryName = dataTypes.ReadNextString(packetData);
|
string registryName = dataTypes.ReadNextString(packetData);
|
||||||
ConsoleIO.WriteLineFormatted(Translations.Get("forge.fml2.registry", registryName));
|
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()
|
// [1] Config data may containt a standard Minecraft string readable with dataTypes.readNextString()
|
||||||
// We're ignoring this packet in MCC
|
// We're ignoring this packet in MCC
|
||||||
|
|
||||||
if (Settings.DebugMessages)
|
if (Settings.Config.Logging.DebugMessages)
|
||||||
{
|
{
|
||||||
string configName = dataTypes.ReadNextString(packetData);
|
string configName = dataTypes.ReadNextString(packetData);
|
||||||
ConsoleIO.WriteLineFormatted(Translations.Get("forge.fml2.config", configName));
|
ConsoleIO.WriteLineFormatted(Translations.Get("forge.fml2.config", configName));
|
||||||
|
|
@ -398,7 +398,7 @@ namespace MinecraftClient.Protocol.Handlers
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
if (Settings.DebugMessages)
|
if (Settings.Config.Logging.DebugMessages)
|
||||||
ConsoleIO.WriteLineFormatted(Translations.Get("forge.fml2.unknown", packetID));
|
ConsoleIO.WriteLineFormatted(Translations.Get("forge.fml2.unknown", packetID));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -413,7 +413,7 @@ namespace MinecraftClient.Protocol.Handlers
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (Settings.DebugMessages)
|
else if (Settings.Config.Logging.DebugMessages)
|
||||||
{
|
{
|
||||||
ConsoleIO.WriteLineFormatted(Translations.Get("forge.fml2.unknown_channel", fmlChannel));
|
ConsoleIO.WriteLineFormatted(Translations.Get("forge.fml2.unknown_channel", fmlChannel));
|
||||||
}
|
}
|
||||||
|
|
@ -505,7 +505,7 @@ namespace MinecraftClient.Protocol.Handlers
|
||||||
if (forgeInfo.Mods.Any())
|
if (forgeInfo.Mods.Any())
|
||||||
{
|
{
|
||||||
ConsoleIO.WriteLineFormatted(Translations.Get("forge.with_mod", forgeInfo.Mods.Count));
|
ConsoleIO.WriteLineFormatted(Translations.Get("forge.with_mod", forgeInfo.Mods.Count));
|
||||||
if (Settings.DebugMessages)
|
if (Settings.Config.Logging.DebugMessages)
|
||||||
{
|
{
|
||||||
Translations.WriteLineFormatted("forge.mod_list");
|
Translations.WriteLineFormatted("forge.mod_list");
|
||||||
foreach (ForgeInfo.ForgeMod mod in forgeInfo.Mods)
|
foreach (ForgeInfo.ForgeMod mod in forgeInfo.Mods)
|
||||||
|
|
|
||||||
|
|
@ -5,13 +5,13 @@ using System.Net.Http;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using MinecraftClient.Protocol.Message;
|
using MinecraftClient.Protocol.Message;
|
||||||
|
using static MinecraftClient.Settings;
|
||||||
|
|
||||||
namespace MinecraftClient.Protocol
|
namespace MinecraftClient.Protocol
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// This class parses JSON chat data from MC 1.6+ and returns the appropriate string to be printed.
|
/// This class parses JSON chat data from MC 1.6+ and returns the appropriate string to be printed.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
||||||
static class ChatParser
|
static class ChatParser
|
||||||
{
|
{
|
||||||
public enum MessageType
|
public enum MessageType
|
||||||
|
|
@ -47,7 +47,7 @@ namespace MinecraftClient.Protocol
|
||||||
/// <returns>Returns the translated text</returns>
|
/// <returns>Returns the translated text</returns>
|
||||||
public static string ParseSignedChat(ChatMessage message, List<string>? links = null)
|
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 content = message.isJson ? ParseText(chatContent, links) : chatContent;
|
||||||
string sender = message.displayName!;
|
string sender = message.displayName!;
|
||||||
|
|
||||||
|
|
@ -107,27 +107,27 @@ namespace MinecraftClient.Protocol
|
||||||
string color = string.Empty;
|
string color = string.Empty;
|
||||||
if (message.isSystemChat)
|
if (message.isSystemChat)
|
||||||
{
|
{
|
||||||
if (Settings.MarkSystemMessage)
|
if (Config.Signature.MarkSystemMessage)
|
||||||
color = "§z §r "; // Custom color code §z : Background Gray
|
color = "§z §r "; // Custom color code §z : Background Gray
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if ((bool)message.isSignatureLegal!)
|
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
|
color = "§x §r "; // Custom color code §x : Background Yellow
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (Settings.MarkLegallySignedMsg)
|
if (Config.Signature.MarkLegallySignedMsg)
|
||||||
color = "§y §r "; // Custom color code §y : Background Green
|
color = "§y §r "; // Custom color code §y : Background Green
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (Settings.MarkIllegallySignedMsg)
|
if (Config.Signature.MarkIllegallySignedMsg)
|
||||||
color = "§w §r "; // Custom color code §w : Background Red
|
color = "§w §r "; // Custom color code §w : Background Red
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -203,12 +203,12 @@ namespace MinecraftClient.Protocol
|
||||||
if (!Directory.Exists("lang"))
|
if (!Directory.Exists("lang"))
|
||||||
Directory.CreateDirectory("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?
|
//File not found? Try downloading language file from Mojang's servers?
|
||||||
if (!File.Exists(Language_File))
|
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();
|
HttpClient httpClient = new();
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
|
@ -217,11 +217,11 @@ namespace MinecraftClient.Protocol
|
||||||
string assets_index = fetch_index.Result;
|
string assets_index = fetch_index.Result;
|
||||||
fetch_index.Dispose();
|
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);
|
tmp = tmp[1].Split(new string[] { "hash\": \"" }, StringSplitOptions.None);
|
||||||
string hash = tmp[1].Split('"')[0]; //Translations file identifier on Mojang's servers
|
string hash = tmp[1].Split('"')[0]; //Translations file identifier on Mojang's servers
|
||||||
string translation_file_location = Settings.TranslationsFile_Website_Download + '/' + hash[..2] + '/' + hash;
|
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));
|
ConsoleIO.WriteLineFormatted(Translations.Get("chat.request", translation_file_location));
|
||||||
|
|
||||||
Task<string> fetch_file = httpClient.GetStringAsync(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");
|
Translations.WriteLineFormatted("chat.loaded");
|
||||||
}
|
}
|
||||||
else //No external dictionnary found.
|
else //No external dictionnary found.
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,8 @@ using System.Globalization;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
|
using static MinecraftClient.Settings;
|
||||||
|
using static MinecraftClient.Settings.MainConfigHealper.MainConfig.GeneralConfig;
|
||||||
|
|
||||||
namespace MinecraftClient.Protocol
|
namespace MinecraftClient.Protocol
|
||||||
{
|
{
|
||||||
|
|
@ -204,7 +206,7 @@ namespace MinecraftClient.Protocol
|
||||||
|
|
||||||
var response = request.Post("application/x-www-form-urlencoded", postData);
|
var response = request.Post("application/x-www-form-urlencoded", postData);
|
||||||
|
|
||||||
if (Settings.DebugMessages)
|
if (Settings.Config.Logging.DebugMessages)
|
||||||
{
|
{
|
||||||
ConsoleIO.WriteLine(response.ToString());
|
ConsoleIO.WriteLine(response.ToString());
|
||||||
}
|
}
|
||||||
|
|
@ -271,7 +273,7 @@ namespace MinecraftClient.Protocol
|
||||||
request.Headers.Add("x-xbl-contract-version", "0");
|
request.Headers.Add("x-xbl-contract-version", "0");
|
||||||
|
|
||||||
var accessToken = loginResponse.AccessToken;
|
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
|
// 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
|
// "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\""
|
+ "\"TokenType\": \"JWT\""
|
||||||
+ "}";
|
+ "}";
|
||||||
var response = request.Post("application/json", payload);
|
var response = request.Post("application/json", payload);
|
||||||
if (Settings.DebugMessages)
|
if (Settings.Config.Logging.DebugMessages)
|
||||||
{
|
{
|
||||||
ConsoleIO.WriteLine(response.ToString());
|
ConsoleIO.WriteLine(response.ToString());
|
||||||
}
|
}
|
||||||
|
|
@ -338,7 +340,7 @@ namespace MinecraftClient.Protocol
|
||||||
+ "\"TokenType\": \"JWT\""
|
+ "\"TokenType\": \"JWT\""
|
||||||
+ "}";
|
+ "}";
|
||||||
var response = request.Post("application/json", payload);
|
var response = request.Post("application/json", payload);
|
||||||
if (Settings.DebugMessages)
|
if (Settings.Config.Logging.DebugMessages)
|
||||||
{
|
{
|
||||||
ConsoleIO.WriteLine(response.ToString());
|
ConsoleIO.WriteLine(response.ToString());
|
||||||
}
|
}
|
||||||
|
|
@ -418,7 +420,7 @@ namespace MinecraftClient.Protocol
|
||||||
string payload = "{\"identityToken\": \"XBL3.0 x=" + userHash + ";" + xstsToken + "\"}";
|
string payload = "{\"identityToken\": \"XBL3.0 x=" + userHash + ";" + xstsToken + "\"}";
|
||||||
var response = request.Post("application/json", payload);
|
var response = request.Post("application/json", payload);
|
||||||
|
|
||||||
if (Settings.DebugMessages)
|
if (Settings.Config.Logging.DebugMessages)
|
||||||
{
|
{
|
||||||
ConsoleIO.WriteLine(response.ToString());
|
ConsoleIO.WriteLine(response.ToString());
|
||||||
}
|
}
|
||||||
|
|
@ -440,7 +442,7 @@ namespace MinecraftClient.Protocol
|
||||||
request.Headers.Add("Authorization", string.Format("Bearer {0}", accessToken));
|
request.Headers.Add("Authorization", string.Format("Bearer {0}", accessToken));
|
||||||
var response = request.Get();
|
var response = request.Get();
|
||||||
|
|
||||||
if (Settings.DebugMessages)
|
if (Settings.Config.Logging.DebugMessages)
|
||||||
{
|
{
|
||||||
ConsoleIO.WriteLine(response.ToString());
|
ConsoleIO.WriteLine(response.ToString());
|
||||||
}
|
}
|
||||||
|
|
@ -456,7 +458,7 @@ namespace MinecraftClient.Protocol
|
||||||
request.Headers.Add("Authorization", string.Format("Bearer {0}", accessToken));
|
request.Headers.Add("Authorization", string.Format("Bearer {0}", accessToken));
|
||||||
var response = request.Get();
|
var response = request.Get();
|
||||||
|
|
||||||
if (Settings.DebugMessages)
|
if (Settings.Config.Logging.DebugMessages)
|
||||||
{
|
{
|
||||||
ConsoleIO.WriteLine(response.ToString());
|
ConsoleIO.WriteLine(response.ToString());
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,7 @@ namespace MinecraftClient.Protocol.Keys
|
||||||
|
|
||||||
response = request.Post("application/json", "");
|
response = request.Post("application/json", "");
|
||||||
|
|
||||||
if (Settings.DebugMessages)
|
if (Settings.Config.Logging.DebugMessages)
|
||||||
{
|
{
|
||||||
ConsoleIO.WriteLine(response.Body.ToString());
|
ConsoleIO.WriteLine(response.Body.ToString());
|
||||||
}
|
}
|
||||||
|
|
@ -47,7 +47,7 @@ namespace MinecraftClient.Protocol.Keys
|
||||||
{
|
{
|
||||||
int code = (response == null) ? 0 : response.StatusCode;
|
int code = (response == null) ? 0 : response.StatusCode;
|
||||||
ConsoleIO.WriteLineFormatted("§cFetch profile key failed: HttpCode = " + code + ", Error = " + e.Message);
|
ConsoleIO.WriteLineFormatted("§cFetch profile key failed: HttpCode = " + code + ", Error = " + e.Message);
|
||||||
if (Settings.DebugMessages)
|
if (Settings.Config.Logging.DebugMessages)
|
||||||
{
|
{
|
||||||
ConsoleIO.WriteLineFormatted("§c" + e.StackTrace);
|
ConsoleIO.WriteLineFormatted("§c" + e.StackTrace);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,8 @@ using System.IO;
|
||||||
using System.Runtime.Serialization.Formatters.Binary;
|
using System.Runtime.Serialization.Formatters.Binary;
|
||||||
using System.Timers;
|
using System.Timers;
|
||||||
using MinecraftClient.Protocol.Session;
|
using MinecraftClient.Protocol.Session;
|
||||||
|
using static MinecraftClient.Settings;
|
||||||
|
using static MinecraftClient.Settings.MainConfigHealper.MainConfig.AdvancedConfig;
|
||||||
|
|
||||||
namespace MinecraftClient.Protocol.Keys
|
namespace MinecraftClient.Protocol.Keys
|
||||||
{
|
{
|
||||||
|
|
@ -46,11 +48,11 @@ namespace MinecraftClient.Protocol.Keys
|
||||||
keys.Add(login, playerKeyPair);
|
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));
|
pendingadds.Add(new KeyValuePair<string, PlayerKeyPair>(login, playerKeyPair));
|
||||||
}
|
}
|
||||||
else if (Settings.ProfileKeyCaching == CacheType.Disk)
|
else if (Config.Main.Advanced.ProfileKeyCache == CacheType.disk)
|
||||||
{
|
{
|
||||||
SaveToDisk();
|
SaveToDisk();
|
||||||
}
|
}
|
||||||
|
|
@ -114,7 +116,7 @@ namespace MinecraftClient.Protocol.Keys
|
||||||
//User-editable keys cache file in text format
|
//User-editable keys cache file in text format
|
||||||
if (File.Exists(KeysCacheFilePlaintext))
|
if (File.Exists(KeysCacheFilePlaintext))
|
||||||
{
|
{
|
||||||
if (Settings.DebugMessages)
|
if (Settings.Config.Logging.DebugMessages)
|
||||||
ConsoleIO.WriteLineFormatted(Translations.Get("cache.loading_keys", KeysCacheFilePlaintext));
|
ConsoleIO.WriteLineFormatted(Translations.Get("cache.loading_keys", KeysCacheFilePlaintext));
|
||||||
|
|
||||||
try
|
try
|
||||||
|
|
@ -133,27 +135,27 @@ namespace MinecraftClient.Protocol.Keys
|
||||||
{
|
{
|
||||||
PlayerKeyPair playerKeyPair = PlayerKeyPair.FromString(value);
|
PlayerKeyPair playerKeyPair = PlayerKeyPair.FromString(value);
|
||||||
keys[login] = playerKeyPair;
|
keys[login] = playerKeyPair;
|
||||||
if (Settings.DebugMessages)
|
if (Settings.Config.Logging.DebugMessages)
|
||||||
ConsoleIO.WriteLineFormatted(Translations.Get("cache.loaded_keys", playerKeyPair.ExpiresAt.ToString()));
|
ConsoleIO.WriteLineFormatted(Translations.Get("cache.loaded_keys", playerKeyPair.ExpiresAt.ToString()));
|
||||||
}
|
}
|
||||||
catch (InvalidDataException e)
|
catch (InvalidDataException e)
|
||||||
{
|
{
|
||||||
if (Settings.DebugMessages)
|
if (Settings.Config.Logging.DebugMessages)
|
||||||
ConsoleIO.WriteLineFormatted(Translations.Get("cache.ignore_string_keys", value, e.Message));
|
ConsoleIO.WriteLineFormatted(Translations.Get("cache.ignore_string_keys", value, e.Message));
|
||||||
}
|
}
|
||||||
catch (FormatException e)
|
catch (FormatException e)
|
||||||
{
|
{
|
||||||
if (Settings.DebugMessages)
|
if (Settings.Config.Logging.DebugMessages)
|
||||||
ConsoleIO.WriteLineFormatted(Translations.Get("cache.ignore_string_keys", value, e.Message));
|
ConsoleIO.WriteLineFormatted(Translations.Get("cache.ignore_string_keys", value, e.Message));
|
||||||
}
|
}
|
||||||
catch (ArgumentNullException e)
|
catch (ArgumentNullException e)
|
||||||
{
|
{
|
||||||
if (Settings.DebugMessages)
|
if (Settings.Config.Logging.DebugMessages)
|
||||||
ConsoleIO.WriteLineFormatted(Translations.Get("cache.ignore_string_keys", value, e.Message));
|
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));
|
ConsoleIO.WriteLineFormatted(Translations.Get("cache.ignore_line_keys", line));
|
||||||
}
|
}
|
||||||
|
|
@ -174,7 +176,7 @@ namespace MinecraftClient.Protocol.Keys
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private static void SaveToDisk()
|
private static void SaveToDisk()
|
||||||
{
|
{
|
||||||
if (Settings.DebugMessages)
|
if (Config.Logging.DebugMessages)
|
||||||
Translations.WriteLineFormatted("cache.saving_keys");
|
Translations.WriteLineFormatted("cache.saving_keys");
|
||||||
|
|
||||||
List<string> KeysCacheLines = new()
|
List<string> KeysCacheLines = new()
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,8 @@ using MinecraftClient.Protocol.Handlers;
|
||||||
using MinecraftClient.Protocol.Handlers.Forge;
|
using MinecraftClient.Protocol.Handlers.Forge;
|
||||||
using MinecraftClient.Protocol.Session;
|
using MinecraftClient.Protocol.Session;
|
||||||
using MinecraftClient.Proxy;
|
using MinecraftClient.Proxy;
|
||||||
|
using static MinecraftClient.Settings;
|
||||||
|
using static MinecraftClient.Settings.MainConfigHealper.MainConfig.GeneralConfig;
|
||||||
|
|
||||||
namespace MinecraftClient.Protocol
|
namespace MinecraftClient.Protocol
|
||||||
{
|
{
|
||||||
|
|
@ -64,7 +66,7 @@ namespace MinecraftClient.Protocol
|
||||||
{
|
{
|
||||||
ConsoleIO.WriteLineFormatted(Translations.Get("mcc.not_found", domainVal, e.GetType().FullName, e.Message));
|
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;
|
domain = domainVal;
|
||||||
|
|
@ -99,7 +101,7 @@ namespace MinecraftClient.Protocol
|
||||||
{
|
{
|
||||||
ConsoleIO.WriteLineFormatted(String.Format("§8{0}: {1}", e.GetType().FullName, e.Message));
|
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)
|
if (protocolversion != 0 && protocolversion != protocolversionTmp)
|
||||||
Translations.WriteLineFormatted("error.version_different");
|
Translations.WriteLineFormatted("error.version_different");
|
||||||
|
|
@ -420,16 +422,16 @@ namespace MinecraftClient.Protocol
|
||||||
/// <param name="pass">Password</param>
|
/// <param name="pass">Password</param>
|
||||||
/// <param name="session">In case of successful login, will contain session information for multiplayer</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>
|
/// <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);
|
return MicrosoftMCCLogin(user, pass, out session);
|
||||||
else
|
else
|
||||||
return MicrosoftBrowserLogin(out session, user);
|
return MicrosoftBrowserLogin(out session, user);
|
||||||
}
|
}
|
||||||
else if (type == AccountType.Mojang)
|
else if (type == LoginType.mojang)
|
||||||
{
|
{
|
||||||
return MojangLogin(user, pass, out session);
|
return MojangLogin(user, pass, out session);
|
||||||
}
|
}
|
||||||
|
|
@ -494,7 +496,7 @@ namespace MinecraftClient.Protocol
|
||||||
}
|
}
|
||||||
catch (System.Security.Authentication.AuthenticationException e)
|
catch (System.Security.Authentication.AuthenticationException e)
|
||||||
{
|
{
|
||||||
if (Settings.DebugMessages)
|
if (Settings.Config.Logging.DebugMessages)
|
||||||
{
|
{
|
||||||
ConsoleIO.WriteLineFormatted("§8" + e.ToString());
|
ConsoleIO.WriteLineFormatted("§8" + e.ToString());
|
||||||
}
|
}
|
||||||
|
|
@ -502,7 +504,7 @@ namespace MinecraftClient.Protocol
|
||||||
}
|
}
|
||||||
catch (System.IO.IOException e)
|
catch (System.IO.IOException e)
|
||||||
{
|
{
|
||||||
if (Settings.DebugMessages)
|
if (Settings.Config.Logging.DebugMessages)
|
||||||
{
|
{
|
||||||
ConsoleIO.WriteLineFormatted("§8" + e.ToString());
|
ConsoleIO.WriteLineFormatted("§8" + e.ToString());
|
||||||
}
|
}
|
||||||
|
|
@ -514,7 +516,7 @@ namespace MinecraftClient.Protocol
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
if (Settings.DebugMessages)
|
if (Settings.Config.Logging.DebugMessages)
|
||||||
{
|
{
|
||||||
ConsoleIO.WriteLineFormatted("§8" + e.ToString());
|
ConsoleIO.WriteLineFormatted("§8" + e.ToString());
|
||||||
}
|
}
|
||||||
|
|
@ -543,7 +545,7 @@ namespace MinecraftClient.Protocol
|
||||||
{
|
{
|
||||||
session = new SessionToken() { ClientID = Guid.NewGuid().ToString().Replace("-", "") };
|
session = new SessionToken() { ClientID = Guid.NewGuid().ToString().Replace("-", "") };
|
||||||
ConsoleIO.WriteLineFormatted("§cMicrosoft authenticate failed: " + e.Message);
|
ConsoleIO.WriteLineFormatted("§cMicrosoft authenticate failed: " + e.Message);
|
||||||
if (Settings.DebugMessages)
|
if (Settings.Config.Logging.DebugMessages)
|
||||||
{
|
{
|
||||||
ConsoleIO.WriteLineFormatted("§c" + e.StackTrace);
|
ConsoleIO.WriteLineFormatted("§c" + e.StackTrace);
|
||||||
}
|
}
|
||||||
|
|
@ -601,7 +603,7 @@ namespace MinecraftClient.Protocol
|
||||||
session.PlayerID = profile.UUID;
|
session.PlayerID = profile.UUID;
|
||||||
session.ID = accessToken;
|
session.ID = accessToken;
|
||||||
session.RefreshToken = msaResponse.RefreshToken;
|
session.RefreshToken = msaResponse.RefreshToken;
|
||||||
Settings.Login = msaResponse.Email;
|
Config.Main.General.Account.Login = msaResponse.Email;
|
||||||
return LoginResult.Success;
|
return LoginResult.Success;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
@ -612,7 +614,7 @@ namespace MinecraftClient.Protocol
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
ConsoleIO.WriteLineFormatted("§cMicrosoft authenticate failed: " + e.Message);
|
ConsoleIO.WriteLineFormatted("§cMicrosoft authenticate failed: " + e.Message);
|
||||||
if (Settings.DebugMessages)
|
if (Settings.Config.Logging.DebugMessages)
|
||||||
{
|
{
|
||||||
ConsoleIO.WriteLineFormatted("§c" + e.StackTrace);
|
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 expTimestamp = long.Parse(json.Properties["exp"].StringValue, NumberStyles.Any, CultureInfo.CurrentCulture);
|
||||||
var now = DateTime.Now;
|
var now = DateTime.Now;
|
||||||
var tokenExp = UnixTimeStampToDateTime(expTimestamp);
|
var tokenExp = UnixTimeStampToDateTime(expTimestamp);
|
||||||
if (Settings.DebugMessages)
|
if (Settings.Config.Logging.DebugMessages)
|
||||||
{
|
{
|
||||||
ConsoleIO.WriteLine("Access token expiration time is " + tokenExp.ToString());
|
ConsoleIO.WriteLine("Access token expiration time is " + tokenExp.ToString());
|
||||||
}
|
}
|
||||||
|
|
@ -772,7 +774,7 @@ namespace MinecraftClient.Protocol
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
ConsoleIO.WriteLineFormatted("§8" + e.GetType().ToString() + ": " + e.Message);
|
ConsoleIO.WriteLineFormatted("§8" + e.GetType().ToString() + ": " + e.Message);
|
||||||
if (Settings.DebugMessages)
|
if (Settings.Config.Logging.DebugMessages)
|
||||||
{
|
{
|
||||||
ConsoleIO.WriteLineFormatted("§8" + e.StackTrace);
|
ConsoleIO.WriteLineFormatted("§8" + e.StackTrace);
|
||||||
}
|
}
|
||||||
|
|
@ -815,7 +817,7 @@ namespace MinecraftClient.Protocol
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
ConsoleIO.WriteLineFormatted("§8" + e.GetType().ToString() + ": " + e.Message);
|
ConsoleIO.WriteLineFormatted("§8" + e.GetType().ToString() + ": " + e.Message);
|
||||||
if (Settings.DebugMessages)
|
if (Settings.Config.Logging.DebugMessages)
|
||||||
{
|
{
|
||||||
ConsoleIO.WriteLineFormatted("§8" + e.StackTrace);
|
ConsoleIO.WriteLineFormatted("§8" + e.StackTrace);
|
||||||
}
|
}
|
||||||
|
|
@ -890,14 +892,14 @@ namespace MinecraftClient.Protocol
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (Settings.DebugMessages)
|
if (Settings.Config.Logging.DebugMessages)
|
||||||
ConsoleIO.WriteLineFormatted(Translations.Get("debug.request", host));
|
ConsoleIO.WriteLineFormatted(Translations.Get("debug.request", host));
|
||||||
|
|
||||||
TcpClient client = ProxyHandler.NewTcpClient(host, 443, true);
|
TcpClient client = ProxyHandler.NewTcpClient(host, 443, true);
|
||||||
SslStream stream = new(client.GetStream());
|
SslStream stream = new(client.GetStream());
|
||||||
stream.AuthenticateAsClient(host, null, SslProtocols.Tls12, true); // Enable TLS 1.2. Hotfix for #1780
|
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)
|
foreach (string line in headers)
|
||||||
ConsoleIO.WriteLineFormatted("§8> " + line);
|
ConsoleIO.WriteLineFormatted("§8> " + line);
|
||||||
|
|
||||||
|
|
@ -905,7 +907,7 @@ namespace MinecraftClient.Protocol
|
||||||
System.IO.StreamReader sr = new(stream);
|
System.IO.StreamReader sr = new(stream);
|
||||||
string raw_result = sr.ReadToEnd();
|
string raw_result = sr.ReadToEnd();
|
||||||
|
|
||||||
if (Settings.DebugMessages)
|
if (Settings.Config.Logging.DebugMessages)
|
||||||
{
|
{
|
||||||
ConsoleIO.WriteLine("");
|
ConsoleIO.WriteLine("");
|
||||||
foreach (string line in raw_result.Split('\n'))
|
foreach (string line in raw_result.Split('\n'))
|
||||||
|
|
@ -915,7 +917,7 @@ namespace MinecraftClient.Protocol
|
||||||
if (raw_result.StartsWith("HTTP/1.1"))
|
if (raw_result.StartsWith("HTTP/1.1"))
|
||||||
{
|
{
|
||||||
postResult = raw_result[(raw_result.IndexOf("\r\n\r\n") + 4)..];
|
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
|
else statusCode = 520; //Web server is returning an unknown error
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -109,7 +109,7 @@ namespace MinecraftClient.Protocol
|
||||||
requestMessage.Add(body);
|
requestMessage.Add(body);
|
||||||
}
|
}
|
||||||
else requestMessage.Add(""); // <CR><LF>
|
else requestMessage.Add(""); // <CR><LF>
|
||||||
if (Settings.DebugMessages)
|
if (Settings.Config.Logging.DebugMessages)
|
||||||
{
|
{
|
||||||
foreach (string l in requestMessage)
|
foreach (string l in requestMessage)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -398,7 +398,7 @@ namespace MinecraftClient.Protocol
|
||||||
|
|
||||||
private static void WriteDebugLog(string t)
|
private static void WriteDebugLog(string t)
|
||||||
{
|
{
|
||||||
if (Settings.DebugMessages && logOutput)
|
if (Settings.Config.Logging.DebugMessages && logOutput)
|
||||||
WriteLog(t);
|
WriteLog(t);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
@ -4,6 +4,8 @@ using System.IO;
|
||||||
using System.Runtime.Serialization;
|
using System.Runtime.Serialization;
|
||||||
using System.Runtime.Serialization.Formatters.Binary;
|
using System.Runtime.Serialization.Formatters.Binary;
|
||||||
using System.Timers;
|
using System.Timers;
|
||||||
|
using static MinecraftClient.Settings;
|
||||||
|
using static MinecraftClient.Settings.MainConfigHealper.MainConfig.AdvancedConfig;
|
||||||
|
|
||||||
namespace MinecraftClient.Protocol.Session
|
namespace MinecraftClient.Protocol.Session
|
||||||
{
|
{
|
||||||
|
|
@ -54,11 +56,11 @@ namespace MinecraftClient.Protocol.Session
|
||||||
sessions.Add(login, 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));
|
pendingadds.Add(new KeyValuePair<string, SessionToken>(login, session));
|
||||||
}
|
}
|
||||||
else if (Settings.SessionCaching == CacheType.Disk)
|
else if (Config.Main.Advanced.SessionCache == CacheType.disk)
|
||||||
{
|
{
|
||||||
SaveToDisk();
|
SaveToDisk();
|
||||||
}
|
}
|
||||||
|
|
@ -122,7 +124,7 @@ namespace MinecraftClient.Protocol.Session
|
||||||
//Grab sessions in the Minecraft directory
|
//Grab sessions in the Minecraft directory
|
||||||
if (File.Exists(SessionCacheFileMinecraft))
|
if (File.Exists(SessionCacheFileMinecraft))
|
||||||
{
|
{
|
||||||
if (Settings.DebugMessages)
|
if (Config.Logging.DebugMessages)
|
||||||
ConsoleIO.WriteLineFormatted(Translations.Get("cache.loading", Path.GetFileName(SessionCacheFileMinecraft)));
|
ConsoleIO.WriteLineFormatted(Translations.Get("cache.loading", Path.GetFileName(SessionCacheFileMinecraft)));
|
||||||
Json.JSONData mcSession = new(Json.JSONData.DataType.String);
|
Json.JSONData mcSession = new(Json.JSONData.DataType.String);
|
||||||
try
|
try
|
||||||
|
|
@ -155,7 +157,7 @@ namespace MinecraftClient.Protocol.Session
|
||||||
sessionItem["uuid"].StringValue.Replace("-", ""),
|
sessionItem["uuid"].StringValue.Replace("-", ""),
|
||||||
clientID
|
clientID
|
||||||
));
|
));
|
||||||
if (Settings.DebugMessages)
|
if (Config.Logging.DebugMessages)
|
||||||
ConsoleIO.WriteLineFormatted(Translations.Get("cache.loaded", login, session.ID));
|
ConsoleIO.WriteLineFormatted(Translations.Get("cache.loaded", login, session.ID));
|
||||||
sessions[login] = session;
|
sessions[login] = session;
|
||||||
}
|
}
|
||||||
|
|
@ -169,7 +171,7 @@ namespace MinecraftClient.Protocol.Session
|
||||||
//Serialized session cache file in binary format
|
//Serialized session cache file in binary format
|
||||||
if (File.Exists(SessionCacheFileSerialized))
|
if (File.Exists(SessionCacheFileSerialized))
|
||||||
{
|
{
|
||||||
if (Settings.DebugMessages)
|
if (Config.Logging.DebugMessages)
|
||||||
ConsoleIO.WriteLineFormatted(Translations.Get("cache.converting", SessionCacheFileSerialized));
|
ConsoleIO.WriteLineFormatted(Translations.Get("cache.converting", SessionCacheFileSerialized));
|
||||||
|
|
||||||
try
|
try
|
||||||
|
|
@ -181,7 +183,7 @@ namespace MinecraftClient.Protocol.Session
|
||||||
#pragma warning restore SYSLIB0011 // BinaryFormatter.Deserialize() is obsolete
|
#pragma warning restore SYSLIB0011 // BinaryFormatter.Deserialize() is obsolete
|
||||||
foreach (KeyValuePair<string, SessionToken> item in sessionsTemp)
|
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));
|
ConsoleIO.WriteLineFormatted(Translations.Get("cache.loaded", item.Key, item.Value.ID));
|
||||||
sessions[item.Key] = item.Value;
|
sessions[item.Key] = item.Value;
|
||||||
}
|
}
|
||||||
|
|
@ -199,7 +201,7 @@ namespace MinecraftClient.Protocol.Session
|
||||||
//User-editable session cache file in text format
|
//User-editable session cache file in text format
|
||||||
if (File.Exists(SessionCacheFilePlaintext))
|
if (File.Exists(SessionCacheFilePlaintext))
|
||||||
{
|
{
|
||||||
if (Settings.DebugMessages)
|
if (Config.Logging.DebugMessages)
|
||||||
ConsoleIO.WriteLineFormatted(Translations.Get("cache.loading_session", SessionCacheFilePlaintext));
|
ConsoleIO.WriteLineFormatted(Translations.Get("cache.loading_session", SessionCacheFilePlaintext));
|
||||||
|
|
||||||
try
|
try
|
||||||
|
|
@ -215,17 +217,17 @@ namespace MinecraftClient.Protocol.Session
|
||||||
{
|
{
|
||||||
string login = Settings.ToLowerIfNeed(keyValue[0]);
|
string login = Settings.ToLowerIfNeed(keyValue[0]);
|
||||||
SessionToken session = SessionToken.FromString(keyValue[1]);
|
SessionToken session = SessionToken.FromString(keyValue[1]);
|
||||||
if (Settings.DebugMessages)
|
if (Config.Logging.DebugMessages)
|
||||||
ConsoleIO.WriteLineFormatted(Translations.Get("cache.loaded", login, session.ID));
|
ConsoleIO.WriteLineFormatted(Translations.Get("cache.loaded", login, session.ID));
|
||||||
sessions[login] = session;
|
sessions[login] = session;
|
||||||
}
|
}
|
||||||
catch (InvalidDataException e)
|
catch (InvalidDataException e)
|
||||||
{
|
{
|
||||||
if (Settings.DebugMessages)
|
if (Config.Logging.DebugMessages)
|
||||||
ConsoleIO.WriteLineFormatted(Translations.Get("cache.ignore_string", keyValue[1], e.Message));
|
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));
|
ConsoleIO.WriteLineFormatted(Translations.Get("cache.ignore_line", line));
|
||||||
}
|
}
|
||||||
|
|
@ -246,7 +248,7 @@ namespace MinecraftClient.Protocol.Session
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private static void SaveToDisk()
|
private static void SaveToDisk()
|
||||||
{
|
{
|
||||||
if (Settings.DebugMessages)
|
if (Config.Logging.DebugMessages)
|
||||||
Translations.WriteLineFormatted("cache.saving");
|
Translations.WriteLineFormatted("cache.saving");
|
||||||
|
|
||||||
List<string> sessionCacheLines = new()
|
List<string> sessionCacheLines = new()
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
using System.Net.Sockets;
|
using System;
|
||||||
|
using System.Net.Sockets;
|
||||||
using Starksoft.Aspen.Proxy;
|
using Starksoft.Aspen.Proxy;
|
||||||
|
using Tomlet.Attributes;
|
||||||
|
|
||||||
namespace MinecraftClient.Proxy
|
namespace MinecraftClient.Proxy
|
||||||
{
|
{
|
||||||
|
|
@ -11,7 +13,45 @@ namespace MinecraftClient.Proxy
|
||||||
|
|
||||||
public static class ProxyHandler
|
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 readonly ProxyClientFactory factory = new();
|
||||||
private static IProxyClient? proxy;
|
private static IProxyClient? proxy;
|
||||||
|
|
@ -28,27 +68,26 @@ namespace MinecraftClient.Proxy
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (login ? Settings.ProxyEnabledLogin : Settings.ProxyEnabledIngame)
|
if (login ? Config.Enabled_Login : Config.Enabled_Ingame)
|
||||||
{
|
{
|
||||||
ProxyType innerProxytype = ProxyType.Http;
|
ProxyType innerProxytype = ProxyType.Http;
|
||||||
|
|
||||||
switch (Settings.proxyType)
|
switch (Config.Proxy_Type)
|
||||||
{
|
{
|
||||||
case Type.HTTP: innerProxytype = ProxyType.Http; break;
|
case Configs.ProxyType.HTTP: innerProxytype = ProxyType.Http; break;
|
||||||
case Type.SOCKS4: innerProxytype = ProxyType.Socks4; break;
|
case Configs.ProxyType.SOCKS4: innerProxytype = ProxyType.Socks4; break;
|
||||||
case Type.SOCKS4a: innerProxytype = ProxyType.Socks4a; break;
|
case Configs.ProxyType.SOCKS4a: innerProxytype = ProxyType.Socks4a; break;
|
||||||
case Type.SOCKS5: innerProxytype = ProxyType.Socks5; break;
|
case Configs.ProxyType.SOCKS5: innerProxytype = ProxyType.Socks5; break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Settings.ProxyUsername != "" && Settings.ProxyPassword != "")
|
if (Config.Username != "" && Config.Password != "")
|
||||||
{
|
proxy = factory.CreateProxyClient(innerProxytype, Config.Server.Host, Config.Server.Port, Config.Username, Config.Password);
|
||||||
proxy = factory.CreateProxyClient(innerProxytype, Settings.ProxyHost, Settings.ProxyPort, Settings.ProxyUsername, Settings.ProxyPassword);
|
else
|
||||||
}
|
proxy = factory.CreateProxyClient(innerProxytype, Config.Server.Host, Config.Server.Port);
|
||||||
else proxy = factory.CreateProxyClient(innerProxytype, Settings.ProxyHost, Settings.ProxyPort);
|
|
||||||
|
|
||||||
if (!proxy_ok)
|
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;
|
proxy_ok = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,8 @@
|
||||||
[mcc]
|
[mcc]
|
||||||
# Messages from MCC itself
|
# Messages from MCC itself
|
||||||
|
mcc.help_us_translate=Help us translate MCC: https://mccteam.github.io/guide/translation.html
|
||||||
|
mcc.run_with_default_settings=\nMCC is running with default settings.
|
||||||
|
mcc.settings_generated=§cSettings file MinecraftClient.ini has been generated.
|
||||||
mcc.login=Login :
|
mcc.login=Login :
|
||||||
mcc.login_basic_io=Please type the username or email of your choice.
|
mcc.login_basic_io=Please type the username or email of your choice.
|
||||||
mcc.password=Password :
|
mcc.password=Password :
|
||||||
|
|
@ -67,7 +70,7 @@ error.forgeforce=Cannot force Forge support for this Minecraft version!
|
||||||
error.login=Login failed :
|
error.login=Login failed :
|
||||||
error.login.migrated=Account migrated, use e-mail as username.
|
error.login.migrated=Account migrated, use e-mail as username.
|
||||||
error.login.server=Login servers are unavailable. Please try again later.
|
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.response=Invalid server response.
|
||||||
error.login.premium=User not premium.
|
error.login.premium=User not premium.
|
||||||
error.login.network=Network error.
|
error.login.network=Network error.
|
||||||
|
|
@ -643,3 +646,215 @@ bot.scriptScheduler.task=triggeronfirstlogin: {0}\n triggeronlogin: {1}\n trigge
|
||||||
# TestBot
|
# TestBot
|
||||||
bot.testBot.told=Bot: {0} told me : {1}
|
bot.testBot.told=Bot: {0} told me : {1}
|
||||||
bot.testBot.said=Bot: {0} said : {1}
|
bot.testBot.said=Bot: {0} said : {1}
|
||||||
|
|
||||||
|
|
||||||
|
[config]
|
||||||
|
|
||||||
|
config.load=Settings have been loaded from {0}
|
||||||
|
config.load.fail=§cFailed to load settings:§r
|
||||||
|
config.saving=§aThe current setting is saved as {0}
|
||||||
|
|
||||||
|
# Head
|
||||||
|
config.Head=Startup Config File\n\n# New to Minecraft Console Client? See README and sample configuration files here:\n# https://github.com/MCCTeam/Minecraft-Console-Client/tree/master/MinecraftClient/config\n\n# Want to upgrade to a newer version? See https://github.com/MCCTeam/Minecraft-Console-Client/#download
|
||||||
|
|
||||||
|
# Main.General
|
||||||
|
config.Main.General.account=Login=Email or Name. Use "-" as password for offline mode. Leave blank to prompt user on startup.
|
||||||
|
config.Main.General.login=Server address and port. Host can be filled in with domain name or IP.
|
||||||
|
config.Main.General.server_info=Account type: mojang OR microsoft. Also affects interactive login in console.
|
||||||
|
config.Main.General.method=Microsoft Account sign-in method: mcc OR browser.
|
||||||
|
|
||||||
|
# Main.Advanced
|
||||||
|
config.Main.Advanced=Make sure you understand what each setting does before changing anything!
|
||||||
|
config.Main.Advanced.language=Fill in with in-game locale code, https://minecraft.fandom.com/wiki/Language
|
||||||
|
config.Main.Advanced.console_title=
|
||||||
|
config.Main.Advanced.internal_cmd_char=Use 'none', 'slash' or 'backslash'
|
||||||
|
config.Main.Advanced.message_cooldown=Minimum delay in seconds between messages to avoid being kicked for spam.
|
||||||
|
config.Main.Advanced.bot_owners=Name list or myfile.txt, one name per line. /!\ Server admins can impersonate owners!
|
||||||
|
config.Main.Advanced.mc_version=Use 'auto' or '1.X.X' values. Allows to skip server info retrieval.
|
||||||
|
config.Main.Advanced.mc_forge=Use 'auto', 'no' or 'force'. Force-enabling only works for MC 1.13+.
|
||||||
|
config.Main.Advanced.brand_info=Use 'mcc', 'vanilla', or 'none'. This is how MCC identifies itself to the server.
|
||||||
|
config.Main.Advanced.chatbot_log_file=Leave empty for no logfile
|
||||||
|
config.Main.Advanced.private_msgs_cmd_name=Used by RemoteControl bot
|
||||||
|
config.Main.Advanced.show_system_messages=System messages for server ops
|
||||||
|
config.Main.Advanced.show_xpbar_messages=Messages displayed above xp bar, set this to false in case of xp bar spam
|
||||||
|
config.Main.Advanced.show_chat_links=Decode links embedded in chat messages and show them in console
|
||||||
|
config.Main.Advanced.show_inventory_layout=Show inventory layout as ASCII art in inventory command
|
||||||
|
config.Main.Advanced.terrain_and_movements=Uses more ram, cpu, bandwidth but allows you to move around
|
||||||
|
config.Main.Advanced.inventory_handling=Toggle inventory handling (beta)
|
||||||
|
config.Main.Advanced.entity_handling=Toggle entity handling (beta)
|
||||||
|
config.Main.Advanced.session_cache=How to retain session tokens. Use 'none', 'memory' or 'disk'
|
||||||
|
config.Main.Advanced.profilekey_cache=How to retain profile key. Use 'none', 'memory' or 'disk'
|
||||||
|
config.Main.Advanced.resolve_srv_records=Use 'no', 'fast' (5s timeout), or 'yes'. Required for joining some servers.
|
||||||
|
config.Main.Advanced.account_list=See README > 'Servers and Accounts file' for more info about this
|
||||||
|
config.Main.Advanced.server_list=See README > 'Servers and Accounts file' for more info about this
|
||||||
|
config.Main.Advanced.player_head_icon=Only works on Windows XP-8 or Windows 10 with old console
|
||||||
|
config.Main.Advanced.exit_on_failure=Disable pauses on error, for using MCC in non-interactive scripts
|
||||||
|
config.Main.Advanced.script_cache=Cache compiled scripts for faster load on low-end devices
|
||||||
|
config.Main.Advanced.timestamps=Prepend timestamps to chat messages
|
||||||
|
config.Main.Advanced.auto_respawn=Toggle auto respawn if client player was dead (make sure your spawn point is safe)
|
||||||
|
config.Main.Advanced.minecraft_realms=Enable support for joining Minecraft Realms worlds
|
||||||
|
config.Main.Advanced.move_head_while_walking=Enable head movement while walking to avoid anti-cheat triggers
|
||||||
|
config.Main.Advanced.timeout=Set a custom timeout in seconds (Default: 30). Use only if you know what you're doing.
|
||||||
|
config.Main.Advanced.enable_emoji=If turned off, the emoji will be replaced with a simpler character (for /chunk status)
|
||||||
|
config.Main.Advanced.movement_speed=A movement speed higher than 2 may be considered cheating.
|
||||||
|
config.Main.Advanced.language.invaild=The language code is invalid.
|
||||||
|
|
||||||
|
# Signature
|
||||||
|
config.Signature=Chat settings (affects minecraft 1.19+)
|
||||||
|
config.Signature.LoginWithSecureProfile=Microsoft accounts only. If disabled, will not be able to sign chat and join servers configured with "enforce-secure-profile=true"
|
||||||
|
config.Signature.SignChat=Whether to sign the chat send from MCC
|
||||||
|
config.Signature.SignMessageInCommand=Whether to sign the messages contained in the commands sent by MCC. For example, the message in "/msg" and "/me"
|
||||||
|
config.Signature.MarkLegallySignedMsg=Use green color block to mark chat with legitimate signatures
|
||||||
|
config.Signature.MarkModifiedMsg=Use yellow color block to mark chat that have been modified by the server.
|
||||||
|
config.Signature.MarkIllegallySignedMsg=Use red color block to mark chat without legitimate signature
|
||||||
|
config.Signature.MarkSystemMessage=Use gray color block to mark system message (always without signature)
|
||||||
|
config.Signature.ShowModifiedChat=Set to true to display messages modified by the server, false to display the original signed messages
|
||||||
|
config.Signature.ShowIllegalSignedChat=Whether to display chat and messages in commands without legal signatures
|
||||||
|
|
||||||
|
# Logging
|
||||||
|
config.Logging=Only affect the messages on console.
|
||||||
|
config.Logging.DebugMessages=Please enable this before submitting bug reports. Thanks!
|
||||||
|
config.Logging.ChatMessages=Show server chat messages
|
||||||
|
config.Logging.InfoMessages=Informative messages (i.e Most of the message from MCC)
|
||||||
|
config.Logging.WarningMessages=Show warning messages
|
||||||
|
config.Logging.ErrorMessages=Show error messages
|
||||||
|
config.Logging.ChatFilter=Regex for filtering chat message
|
||||||
|
config.Logging.DebugFilter=Regex for filtering debug message
|
||||||
|
config.Logging.FilterMode=blacklist OR whitelist. Blacklist hide message match regex. Whitelist show message match regex
|
||||||
|
config.Logging.LogToFile=Write log messages to file
|
||||||
|
config.Logging.LogFile=Log file name
|
||||||
|
config.Logging.PrependTimestamp=Prepend timestamp to messages in log file
|
||||||
|
config.Logging.SaveColorCodes=Keep color codes in the saved text (§b)
|
||||||
|
|
||||||
|
# AppVars
|
||||||
|
config.AppVars.Variables=can be used in some other fields as %yourvar%\n# %username% and %serverip% are reserved variables.
|
||||||
|
|
||||||
|
# Proxy
|
||||||
|
config.Proxy=Connect to a server via a proxy instead of connecting directly\n# If Mojang session services are blocked on your network, set enabled=login to login using proxy but connect directly to the server\n# If connecting to port 25565 (Minecraft) is blocked on your network, set enabled=true to login & connect using the proxy\n# /!\ Make sure your server rules allow Proxies or VPNs before setting enabled=true, or you may face consequences!
|
||||||
|
config.Proxy.Enabled_Login=Whether to connect to the login server through a proxy.
|
||||||
|
config.Proxy.Enabled_Ingame=Whether to connect to the game server through a proxy.
|
||||||
|
config.Proxy.Server=Proxy server must allow HTTPS for login, and non-443 ports for playing
|
||||||
|
config.Proxy.Proxy_Type=Supported types: HTTP, SOCKS4, SOCKS4a, SOCKS5
|
||||||
|
config.Proxy.Username=Only required for password-protected proxies
|
||||||
|
config.Proxy.Password=Only required for password-protected proxies
|
||||||
|
|
||||||
|
# ChatFormat
|
||||||
|
config.ChatFormat=MCC does it best to detect chat messages, but some server have unusual chat formats\n# When this happens, you'll need to configure chat format below, see README > 'Detecting chat messages'\n# Do not forget to uncomment (remove '#') these settings if modifying them
|
||||||
|
config.ChatFormat.Builtins=MCC support for common message formats. Set "false" to avoid conflicts with custom formats.
|
||||||
|
|
||||||
|
# MCSettings
|
||||||
|
config.MCSettings=Settings below are sent to the server and only affect server-side things like your skin
|
||||||
|
config.MCSettings.Enabled=If disabled, settings below are not sent to the server
|
||||||
|
config.MCSettings.Locale=Use any language implemented in Minecraft
|
||||||
|
config.MCSettings.RenderDistance=Value range: [0 - 255]
|
||||||
|
config.MCSettings.Difficulty=MC 1.7- difficulty. peaceful, easy, normal, difficult
|
||||||
|
config.MCSettings.ChatMode=Use 'enabled', 'commands', or 'disabled'. Allows to mute yourself...
|
||||||
|
config.MCSettings.ChatColors=Allows disabling chat colors server-side
|
||||||
|
config.MCSettings.MainHand=MC 1.9+ main hand. left or right
|
||||||
|
|
||||||
|
# ChatBot
|
||||||
|
config.ChatBot================================ #\n# Minecraft Console Client Bots #\n# =============================== #
|
||||||
|
|
||||||
|
# ChatBot.Alerts
|
||||||
|
config.ChatBot.Alerts=Get alerted when specified words are detected in chat\n# Useful for moderating your server or detecting when someone is talking to you
|
||||||
|
config.ChatBot.Alerts.Beep_Enabled=Play a beep sound when a word is detected in addition to highlighting.
|
||||||
|
config.ChatBot.Alerts.Trigger_By_Words=Triggers an alert after receiving a specified keyword.
|
||||||
|
config.ChatBot.Alerts.Trigger_By_Rain=Trigger alerts when it rains and when it stops.
|
||||||
|
config.ChatBot.Alerts.Trigger_By_Thunderstorm=Triggers alerts at the beginning and end of thunderstorms.
|
||||||
|
config.ChatBot.Alerts.Matches_File=List of words/strings to alert you on, e.g. "Yourname"
|
||||||
|
config.ChatBot.Alerts.Excludes_File=List of words/strings to NOT alert you on, e.g. "<Yourname>"
|
||||||
|
config.ChatBot.Alerts.Log_To_File=Log alerts info a file.
|
||||||
|
config.ChatBot.Alerts.Log_File=The name of a file where alers logs will be written.
|
||||||
|
|
||||||
|
# ChatBot.AntiAFK
|
||||||
|
config.ChatBot.AntiAfk=Send a command on a regular or random basis or make the bot walk around randomly to avoid automatic AFK disconnection\n# /!\ Make sure your server rules do not forbid anti-AFK mechanisms!\n# /!\ Make sure you keep the bot in an enclosure to prevent it wandering off if you're using terrain handling! (Recommended size 5x5x5)
|
||||||
|
config.ChatBot.AntiAfk.Delay=10 = 1s (Can also be a random number between 2 numbers, example: 50-600) (Default: 600)
|
||||||
|
config.ChatBot.AntiAfk.Command=Command to send to the server
|
||||||
|
config.ChatBot.AntiAfk.Use_Terrain_Handling=Use terrain handling to enable the bot to move around
|
||||||
|
config.ChatBot.AntiAfk.Walk_Range=The range the bot can move around randomly (Note: the bigger the range, the slower the bot will be)
|
||||||
|
config.ChatBot.AntiAfk.Walk_Retries=How many timec can the bot fail trying to move before using the command method
|
||||||
|
|
||||||
|
# ChatBot.AutoAttack
|
||||||
|
config.ChatBot.AutoAttack=Automatically attack hostile mobs around you\n# You need to enable Entity Handling to use this bot\n# /!\ Make sure server rules allow your planned use of AutoAttack\n# /!\ SERVER PLUGINS may consider AutoAttack to be a CHEAT MOD and TAKE ACTION AGAINST YOUR ACCOUNT so DOUBLE CHECK WITH SERVER RULES!
|
||||||
|
config.ChatBot.AutoAttack.Mode=single or multi. single target one mob per attack. multi target all mobs in range per attack
|
||||||
|
config.ChatBot.AutoAttack.Priority=health or distance. Only needed when using single mode
|
||||||
|
config.ChatBot.AutoAttack.Cooldown_Time=How long to wait between each attack. Use auto to let MCC calculate it
|
||||||
|
config.ChatBot.AutoAttack.Interaction=Possible values: Interact, Attack (default), InteractAt (Interact and Attack)
|
||||||
|
config.ChatBot.AutoAttack.Attack_Hostile=Allow attacking hostile mobs
|
||||||
|
config.ChatBot.AutoAttack.Attack_Passive=Allow attacking passive mobs
|
||||||
|
config.ChatBot.AutoAttack.List_Mode=Wether to treat the entities list as a whitelist or as a blacklist
|
||||||
|
config.ChatBot.AutoAttack.Entites_List=All entity types can be found here: https://bit.ly/3Rg68lp
|
||||||
|
|
||||||
|
# ChatBot.AutoCraft
|
||||||
|
config.ChatBot.AutoCraft=Automatically craft items in your inventory\n# See README > 'Using the AutoCraft bot' for how to use\n# You need to enable Inventory Handling to use this bot\n# You should also enable Terrain and Movements if you need to use a crafting table
|
||||||
|
|
||||||
|
# ChatBot.AutoDrop
|
||||||
|
config.ChatBot.AutoDrop=Automatically drop items in inventory\n# You need to enable Inventory Handling to use this bot\n# See this file for an up-to-date list of item types you can use with this bot:\n# https://github.com/MCCTeam/Minecraft-Console-Client/blob/master/MinecraftClient/Inventory/ItemType.cs
|
||||||
|
config.ChatBot.AutoDrop.Mode=include, exclude or everything. Include: drop item IN the list. Exclude: drop item NOT IN the list
|
||||||
|
config.ChatBot.AutoDrop.Items=separate each item name with a comma ',': "ItemOne", "ItemTwo"
|
||||||
|
|
||||||
|
# ChatBot.AutoEat
|
||||||
|
config.ChatBot.AutoEat=Automatically eat food when your Hunger value is low\n# You need to enable Inventory Handling to use this bot
|
||||||
|
|
||||||
|
# ChatBot.AutoFishing
|
||||||
|
config.ChatBot.AutoFishing=Automatically catch fish using a fishing rod\n# Guide: https://mccteam.github.io/guide/chat-bots.html#auto-fishing\n# /!\ Make sure server rules allow automated farming before using this bot
|
||||||
|
config.ChatBot.AutoFishing.Antidespawn=Keep it as false if you have not changed it before.
|
||||||
|
config.ChatBot.AutoFishing.Mainhand=Use the main hand or the off hand to hold the rod.
|
||||||
|
config.ChatBot.AutoFishing.Auto_Start=Whether to start fishing automatically after entering a world.
|
||||||
|
config.ChatBot.AutoFishing.Cast_Delay=How soon to re-cast after successful fishing.
|
||||||
|
config.ChatBot.AutoFishing.Fishing_Delay=How long after entering the game to start fishing (seconds).
|
||||||
|
config.ChatBot.AutoFishing.Fishing_Timeout=Fishing timeout (seconds). Timeout will trigger a re-cast.
|
||||||
|
config.ChatBot.AutoFishing.Durability_Limit=Will not use rods with less durability than this (full durability is 64). Set to zero to disable this feature.
|
||||||
|
config.ChatBot.AutoFishing.Auto_Rod_Switch=Switch to a new rod from inventory after the current rod is unavailable.
|
||||||
|
config.ChatBot.AutoFishing.Stationary_Threshold=Hooks moving in the X and Z axes below this threshold will be considered stationary.
|
||||||
|
config.ChatBot.AutoFishing.Hook_Threshold=A stationary hook moving on the Y-axis above this threshold will be considered to have caught a fish.
|
||||||
|
config.ChatBot.AutoFishing.Log_Fish_Bobber=For debugging purposes, you can use this log to adjust the two thresholds mentioned above.
|
||||||
|
config.ChatBot.AutoFishing.Movements=Some plugins do not allow the player to fish in one place. This allows the player to change position/angle after each fish caught. Usage can be found in the Guide.
|
||||||
|
|
||||||
|
|
||||||
|
# ChatBot.AutoRelog
|
||||||
|
config.ChatBot.AutoRelog=Automatically relog when disconnected by server, for example because the server is restating\n# Put keywords/strings such as "Server is restarting" in kick messages file to relog when the message is seen\n# /!\ Use ignorekickmessage=true at own risk! Server staff might not appreciate if you auto-relog on manual kicks
|
||||||
|
config.ChatBot.AutoRelog.Delay=use 10 for 10 seconds, 10-60 for a random delay between 10 and 60 seconds
|
||||||
|
config.ChatBot.AutoRelog.Retries=retries when failing to relog to the server. use -1 for unlimited retries
|
||||||
|
config.ChatBot.AutoRelog.Ignore_Kick_Message=when set to true, autorelog will reconnect regardless of kick messages
|
||||||
|
config.ChatBot.AutoRelog.Kick_Messages_File=file with list of matches in kick messages that will trigger autorelog
|
||||||
|
|
||||||
|
# ChatBot.AutoRespond
|
||||||
|
config.ChatBot.AutoRespond=Run commands or send messages automatically when a specified pattern is detected in chat\n# /!\ Server admins can spoof chat messages (/nick, /tellraw) so keep this in mind when implementing AutoRespond rules\n# /!\ This bot may get spammy depending on your rules, although the global messagecooldown setting can help you avoiding accidental spam
|
||||||
|
config.ChatBot.AutoRespond.Match_Colors=Do not remove colors from text (Note: Your matches will have to include color codes (ones using the § character) in order to work)
|
||||||
|
|
||||||
|
# ChatBot.ChatLog
|
||||||
|
config.ChatBot.ChatLog=Logs chat messages in a file on disk.
|
||||||
|
|
||||||
|
# ChatBot.FollowPlayer
|
||||||
|
config.ChatBot.FollowPlayer=Enabled you to make the bot follow you\n# NOTE: This is an experimental feature, the bot can be slow at times, you need to walk with a normal speed and to sometimes stop for it to be able to keep up with you\n# It's similar to making animals follow you when you're holding food in your hand.\n# This is due to a slow pathfinding algorithm, we're working on getting a better one\n# You can tweak the update limit and find what works best for you. (NOTE: Do not but a very low one, because you might achieve the opposite,\n# this might clog the thread for terain handling) and thus slow the bot even more.\n# /!\ Make sure server rules allow an option like this in the rules of the server before using this bot
|
||||||
|
config.ChatBot.FollowPlayer.Update_Limit=The rate at which the bot does calculations (10 = 1s) (Default: 5) (You can tweak this if you feel the bot is too slow)
|
||||||
|
config.ChatBot.FollowPlayer.Stop_At_Distance=Do not follow the player if he is in the range of 3 blocks (prevents the bot from pushing a player in an infinite loop)
|
||||||
|
|
||||||
|
# ChatBot.HangmanGame
|
||||||
|
config.ChatBot.HangmanGame=A small game to demonstrate chat interactions. Players can guess mystery words one letter at a time.\n# You need to have ChatFormat working correctly and add yourself in botowners to start the game with /tell <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's received or updated from/by the server
|
||||||
|
config.ChatBot.Map.Delete_All_On_Unload=Delete all rendered maps on unload/reload (Does not delete the images if you exit the client)
|
||||||
|
config.ChatBot.Map.Notify_On_First_Update=Get a notification when you have gotten a map from the server for the first time
|
||||||
|
|
||||||
|
# ChatBot.PlayerListLogger
|
||||||
|
config.ChatBot.PlayerListLogger=Log the list of players periodically into a textual file
|
||||||
|
config.ChatBot.PlayerListLogger.Delay=10 = 1s
|
||||||
|
|
||||||
|
# ChatBot.RemoteControl
|
||||||
|
config.ChatBot.RemoteControl=Send MCC console commands to your bot through server PMs (/tell)\n# You need to have ChatFormat working correctly and add yourself in botowners to use the bot\n# /!\ Server admins can spoof PMs (/tellraw, /nick) so enable RemoteControl only if you trust server admins
|
||||||
|
|
||||||
|
# ChatBot.ReplayCapture
|
||||||
|
config.ChatBot.ReplayCapture=Enable recording of the game (/replay start) and replay it later using the Replay Mod (https://www.replaymod.com/)\n# Please note that due to technical limitations, the client player (you) will not be shown in the replay file\n# /!\ You SHOULD use /replay stop or exit the program gracefully with /quit OR THE REPLAY FILE MAY GET CORRUPT!
|
||||||
|
config.ChatBot.ReplayCapture.Backup_Interval=How long should replay file be auto-saved, in seconds. Use -1 to disable
|
||||||
|
|
||||||
|
# ChatBot.ScriptScheduler
|
||||||
|
config.ChatBot.ScriptScheduler=Schedule commands and scripts to launch on various events such as server join, date/time or time interval\n# See README > 'Using the Script Scheduler' for more info
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,8 @@
|
||||||
[mcc]
|
[mcc]
|
||||||
# Messages from MCC itself
|
# Messages from MCC itself
|
||||||
|
mcc.help_us_translate=帮助我们翻译MCC:https://mccteam.github.io/guide/translation.html
|
||||||
|
mcc.run_with_default_settings=\nMCC正在使用默认配置运行。
|
||||||
|
mcc.settings_generated=§c配置文件 MinecraftClient.ini 已经生成。
|
||||||
mcc.login=登录:
|
mcc.login=登录:
|
||||||
mcc.login_basic_io=请输入用户名或邮箱。
|
mcc.login_basic_io=请输入用户名或邮箱。
|
||||||
mcc.password=密码:
|
mcc.password=密码:
|
||||||
|
|
@ -30,7 +33,7 @@ mcc.single_cmd=§7已发送命令§8 {0}
|
||||||
mcc.joined=已成功加入服务器。\n输入 '{0}quit' 离开服务器。
|
mcc.joined=已成功加入服务器。\n输入 '{0}quit' 离开服务器。
|
||||||
mcc.reconnect=等待5秒 (剩余{0}次尝试)...
|
mcc.reconnect=等待5秒 (剩余{0}次尝试)...
|
||||||
mcc.disconnect.lost=失去连接。
|
mcc.disconnect.lost=失去连接。
|
||||||
mcc.disconnect.server=从服务器断开:
|
mcc.disconnect.server=从服务器断开连接:
|
||||||
mcc.disconnect.login=连接失败:
|
mcc.disconnect.login=连接失败:
|
||||||
mcc.link=链接:{0}
|
mcc.link=链接:{0}
|
||||||
mcc.player_dead_respawn=你死了!1秒后自动重生。
|
mcc.player_dead_respawn=你死了!1秒后自动重生。
|
||||||
|
|
@ -65,7 +68,7 @@ error.forgeforce=无法为此Minecraft版本强制启动Forge支持!
|
||||||
error.login=登录失败:
|
error.login=登录失败:
|
||||||
error.login.migrated=帐户已迁移,使用电子邮件作为用户名。
|
error.login.migrated=帐户已迁移,使用电子邮件作为用户名。
|
||||||
error.login.server=登录服务器不可用。请稍后再试。
|
error.login.server=登录服务器不可用。请稍后再试。
|
||||||
error.login.blocked=密码错误、IP被禁用或登录次数过多。
|
error.login.blocked=用户名/密码错误、IP被禁用或登录次数过多。
|
||||||
error.login.response=服务器响应无效。
|
error.login.response=服务器响应无效。
|
||||||
error.login.premium=不是Premium用户。
|
error.login.premium=不是Premium用户。
|
||||||
error.login.network=网络错误。
|
error.login.network=网络错误。
|
||||||
|
|
@ -528,3 +531,18 @@ bot.scriptScheduler.task=triggeronfirstlogin: {0}\n triggeronlogin: {1}\n trigge
|
||||||
# TestBot
|
# TestBot
|
||||||
bot.testBot.told=Bot:{0}对我说:{1}
|
bot.testBot.told=Bot:{0}对我说:{1}
|
||||||
bot.testBot.said=Bot:{0}说:{1}
|
bot.testBot.said=Bot:{0}说:{1}
|
||||||
|
|
||||||
|
[config]
|
||||||
|
|
||||||
|
config.load=已从 {0} 加载设置。
|
||||||
|
config.load.fail=§c加载设置时出错:§r
|
||||||
|
config.saving=§a当前设置已保存至 {0}
|
||||||
|
|
||||||
|
# Head
|
||||||
|
config.Head=启动配置文件\n\n# 对 MCC(Minecraft 命令行客户端)不熟悉?请看 README 和示例配置文件:\n# https://github.com/MCCTeam/Minecraft-Console-Client/tree/master/MinecraftClient/config\n\n# 想升级到较新的版本吗?请访问 https://github.com/MCCTeam/Minecraft-Console-Client/#download
|
||||||
|
|
||||||
|
# Main.General
|
||||||
|
config.Main.General.account=Login请填写邮箱或玩家名称。若要以离线模式登录请使用"-"作为密码。若留空则使用交互式登录。
|
||||||
|
config.Main.General.login=游戏服务器的地址和端口,可填入域名或IP地址。(可删除端口字段,会解析SRV记录)
|
||||||
|
config.Main.General.server_info=帐户类型:mojang 或是 microsoft。此项设置也会影响交互式登录。
|
||||||
|
config.Main.General.method=微软账户的登录方式:mcc 或是 browser(手动在网页上登录)。
|
||||||
|
|
@ -5,6 +5,7 @@ using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using DynamicRun.Builder;
|
using DynamicRun.Builder;
|
||||||
|
using static MinecraftClient.Settings;
|
||||||
|
|
||||||
namespace MinecraftClient
|
namespace MinecraftClient
|
||||||
{
|
{
|
||||||
|
|
@ -43,7 +44,7 @@ namespace MinecraftClient
|
||||||
lock (CompileCache)
|
lock (CompileCache)
|
||||||
{
|
{
|
||||||
///Process and compile script only if not already compiled
|
///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
|
//Process different sections of the script file
|
||||||
bool scriptMain = true;
|
bool scriptMain = true;
|
||||||
|
|
@ -111,10 +112,10 @@ namespace MinecraftClient
|
||||||
|
|
||||||
//Retrieve compiled assembly
|
//Retrieve compiled assembly
|
||||||
assembly = result.Assembly;
|
assembly = result.Assembly;
|
||||||
if (Settings.CacheScripts)
|
if (Config.Main.Advanced.CacheScript)
|
||||||
CompileCache[scriptHash] = assembly!;
|
CompileCache[scriptHash] = assembly!;
|
||||||
}
|
}
|
||||||
else if (Settings.CacheScripts)
|
else if (Config.Main.Advanced.CacheScript)
|
||||||
assembly = CompileCache[scriptHash];
|
assembly = CompileCache[scriptHash];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -293,7 +294,7 @@ namespace MinecraftClient
|
||||||
if (localVars != null && localVars.ContainsKey(varName))
|
if (localVars != null && localVars.ContainsKey(varName))
|
||||||
return localVars[varName];
|
return localVars[varName];
|
||||||
else
|
else
|
||||||
return Settings.GetVar(varName);
|
return Settings.Config.AppVar.GetVar(varName);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
@ -305,7 +306,7 @@ namespace MinecraftClient
|
||||||
{
|
{
|
||||||
if (localVars != null && localVars.ContainsKey(varName))
|
if (localVars != null && localVars.ContainsKey(varName))
|
||||||
localVars.Remove(varName);
|
localVars.Remove(varName);
|
||||||
return Settings.SetVar(varName, varValue);
|
return Settings.Config.AppVar.SetVar(varName, varValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
@ -347,7 +348,7 @@ namespace MinecraftClient
|
||||||
/// <returns>True if the account was found and loaded</returns>
|
/// <returns>True if the account was found and loaded</returns>
|
||||||
public bool SetAccount(string accountAlias, bool andReconnect = false)
|
public bool SetAccount(string accountAlias, bool andReconnect = false)
|
||||||
{
|
{
|
||||||
bool result = Settings.SetAccount(accountAlias);
|
bool result = Settings.Config.Main.Advanced.SetAccount(accountAlias);
|
||||||
if (result && andReconnect)
|
if (result && andReconnect)
|
||||||
ReconnectToTheServer();
|
ReconnectToTheServer();
|
||||||
return result;
|
return result;
|
||||||
|
|
@ -360,7 +361,7 @@ namespace MinecraftClient
|
||||||
/// <returns>True if the server IP was valid and loaded, false otherwise</returns>
|
/// <returns>True if the server IP was valid and loaded, false otherwise</returns>
|
||||||
public bool SetServer(string server, bool andReconnect = false)
|
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)
|
if (result && andReconnect)
|
||||||
ReconnectToTheServer();
|
ReconnectToTheServer();
|
||||||
return result;
|
return result;
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ using System.Text;
|
||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
using MinecraftClient.Inventory;
|
using MinecraftClient.Inventory;
|
||||||
using MinecraftClient.Mapping;
|
using MinecraftClient.Mapping;
|
||||||
|
using static MinecraftClient.Settings;
|
||||||
|
|
||||||
namespace MinecraftClient
|
namespace MinecraftClient
|
||||||
{
|
{
|
||||||
|
|
@ -521,9 +522,9 @@ namespace MinecraftClient
|
||||||
text = GetVerbatim(text);
|
text = GetVerbatim(text);
|
||||||
|
|
||||||
//User-defined regex for private chat messages
|
//User-defined regex for private chat messages
|
||||||
if (Settings.ChatFormat_Private != null)
|
if (Config.ChatFormat.Private != null)
|
||||||
{
|
{
|
||||||
Match regexMatch = Settings.ChatFormat_Private.Match(text);
|
Match regexMatch = new Regex(Config.ChatFormat.Private).Match(text);
|
||||||
if (regexMatch.Success && regexMatch.Groups.Count >= 3)
|
if (regexMatch.Success && regexMatch.Groups.Count >= 3)
|
||||||
{
|
{
|
||||||
sender = regexMatch.Groups[1].Value;
|
sender = regexMatch.Groups[1].Value;
|
||||||
|
|
@ -533,7 +534,7 @@ namespace MinecraftClient
|
||||||
}
|
}
|
||||||
|
|
||||||
//Built-in detection routine for private messages
|
//Built-in detection routine for private messages
|
||||||
if (Settings.ChatFormat_Builtins)
|
if (Config.ChatFormat.Builtins)
|
||||||
{
|
{
|
||||||
string[] tmp = text.Split(' ');
|
string[] tmp = text.Split(' ');
|
||||||
try
|
try
|
||||||
|
|
@ -632,9 +633,9 @@ namespace MinecraftClient
|
||||||
text = GetVerbatim(text);
|
text = GetVerbatim(text);
|
||||||
|
|
||||||
//User-defined regex for public chat messages
|
//User-defined regex for public chat messages
|
||||||
if (Settings.ChatFormat_Public != null)
|
if (Config.ChatFormat.Public != null)
|
||||||
{
|
{
|
||||||
Match regexMatch = Settings.ChatFormat_Public.Match(text);
|
Match regexMatch = new Regex(Config.ChatFormat.Public).Match(text);
|
||||||
if (regexMatch.Success && regexMatch.Groups.Count >= 3)
|
if (regexMatch.Success && regexMatch.Groups.Count >= 3)
|
||||||
{
|
{
|
||||||
sender = regexMatch.Groups[1].Value;
|
sender = regexMatch.Groups[1].Value;
|
||||||
|
|
@ -644,7 +645,7 @@ namespace MinecraftClient
|
||||||
}
|
}
|
||||||
|
|
||||||
//Built-in detection routine for public messages
|
//Built-in detection routine for public messages
|
||||||
if (Settings.ChatFormat_Builtins)
|
if (Config.ChatFormat.Builtins)
|
||||||
{
|
{
|
||||||
string[] tmp = text.Split(' ');
|
string[] tmp = text.Split(' ');
|
||||||
|
|
||||||
|
|
@ -735,9 +736,9 @@ namespace MinecraftClient
|
||||||
text = GetVerbatim(text);
|
text = GetVerbatim(text);
|
||||||
|
|
||||||
//User-defined regex for teleport requests
|
//User-defined regex for teleport requests
|
||||||
if (Settings.ChatFormat_TeleportRequest != null)
|
if (Config.ChatFormat.TeleportRequest != null)
|
||||||
{
|
{
|
||||||
Match regexMatch = Settings.ChatFormat_TeleportRequest.Match(text);
|
Match regexMatch = new Regex(Config.ChatFormat.TeleportRequest).Match(text);
|
||||||
if (regexMatch.Success && regexMatch.Groups.Count >= 2)
|
if (regexMatch.Success && regexMatch.Groups.Count >= 2)
|
||||||
{
|
{
|
||||||
sender = regexMatch.Groups[1].Value;
|
sender = regexMatch.Groups[1].Value;
|
||||||
|
|
@ -746,7 +747,7 @@ namespace MinecraftClient
|
||||||
}
|
}
|
||||||
|
|
||||||
//Built-in detection routine for teleport requests
|
//Built-in detection routine for teleport requests
|
||||||
if (Settings.ChatFormat_Builtins)
|
if (Config.ChatFormat.Builtins)
|
||||||
{
|
{
|
||||||
string[] tmp = text.Split(' ');
|
string[] tmp = text.Split(' ');
|
||||||
|
|
||||||
|
|
@ -786,7 +787,26 @@ namespace MinecraftClient
|
||||||
ConsoleIO.WriteLogLine(String.Format("[{0}] {1}", GetType().Name, text));
|
ConsoleIO.WriteLogLine(String.Format("[{0}] {1}", GetType().Name, text));
|
||||||
else
|
else
|
||||||
Handler.Log.Info(String.Format("[{0}] {1}", GetType().Name, text));
|
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))
|
if (!String.IsNullOrEmpty(logfile))
|
||||||
{
|
{
|
||||||
|
|
@ -808,7 +828,7 @@ namespace MinecraftClient
|
||||||
/// <param name="text">Debug log text to write</param>
|
/// <param name="text">Debug log text to write</param>
|
||||||
protected void LogDebugToConsole(object text)
|
protected void LogDebugToConsole(object text)
|
||||||
{
|
{
|
||||||
if (Settings.DebugMessages)
|
if (Settings.Config.Logging.DebugMessages)
|
||||||
LogToConsole(text);
|
LogToConsole(text);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -840,7 +860,7 @@ namespace MinecraftClient
|
||||||
/// <param name="delaySeconds">Optional delay, in seconds, before restarting</param>
|
/// <param name="delaySeconds">Optional delay, in seconds, before restarting</param>
|
||||||
protected void ReconnectToTheServer(int ExtraAttempts = 3, int delaySeconds = 0)
|
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));
|
ConsoleIO.WriteLogLine(Translations.Get("chatbot.reconnect", GetType().Name));
|
||||||
McClient.ReconnectionAttemptsLeft = ExtraAttempts;
|
McClient.ReconnectionAttemptsLeft = ExtraAttempts;
|
||||||
Program.Restart(delaySeconds);
|
Program.Restart(delaySeconds);
|
||||||
|
|
@ -873,7 +893,7 @@ namespace MinecraftClient
|
||||||
/// <param name="message">Message</param>
|
/// <param name="message">Message</param>
|
||||||
protected void SendPrivateMessage(string player, string message)
|
protected void SendPrivateMessage(string player, string message)
|
||||||
{
|
{
|
||||||
SendText(String.Format("/{0} {1} {2}", Settings.PrivateMsgsCmdName, player, message));
|
SendText(String.Format("/{0} {1} {2}", Config.Main.Advanced.PrivateMsgsCmdName, player, message));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
|
|
@ -1,5 +1,6 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
|
@ -15,7 +16,7 @@ namespace MinecraftClient
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
public static class Translations
|
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 translationFilePath = "lang" + Path.DirectorySeparatorChar + "mcc";
|
||||||
private static readonly string defaultTranslation = "en.ini";
|
private static readonly string defaultTranslation = "en.ini";
|
||||||
private static readonly Regex translationKeyRegex = new(@"\(\[(.*?)\]\)", RegexOptions.Compiled); // Extract string inside ([ ])
|
private static readonly Regex translationKeyRegex = new(@"\(\[(.*?)\]\)", RegexOptions.Compiled); // Extract string inside ([ ])
|
||||||
|
|
@ -52,6 +53,21 @@ namespace MinecraftClient
|
||||||
return msgName;
|
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>
|
/// <summary>
|
||||||
/// Replace the translation key inside a sentence to translated text. Wrap the key in ([translation.key])
|
/// Replace the translation key inside a sentence to translated text. Wrap the key in ([translation.key])
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
@ -75,32 +91,495 @@ namespace MinecraftClient
|
||||||
return Get(m.Groups[1].Value);
|
return Get(m.Groups[1].Value);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
public static Tuple<string, string[]> GetTranslationPriority()
|
||||||
/// Initialize translations depending on system language.
|
|
||||||
/// English is the default for all unknown system languages.
|
|
||||||
/// </summary>
|
|
||||||
static Translations()
|
|
||||||
{
|
{
|
||||||
translations = new Dictionary<string, string>();
|
string gameLanguage = "en_gb";
|
||||||
LoadDefaultTranslationsFile();
|
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>
|
/// <summary>
|
||||||
/// Load default translation file (English)
|
/// Load translation files
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <remarks>
|
public static void LoadTranslationFile(string[] languageList)
|
||||||
/// 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)
|
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* External translation files
|
* External translation files
|
||||||
|
|
@ -108,44 +587,39 @@ namespace MinecraftClient
|
||||||
* Lang/abc.ini, e.g. Lang/eng.ini which is the default language file
|
* Lang/abc.ini, e.g. Lang/eng.ini which is the default language file
|
||||||
* Useful for adding new translations of fixing typos without recompiling
|
* 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 baseDir = AppDomain.CurrentDomain.BaseDirectory;
|
||||||
string langDir = baseDir + ((baseDir.EndsWith(Path.DirectorySeparatorChar) ? String.Empty : Path.DirectorySeparatorChar) +
|
string langDir = baseDir + ((baseDir.EndsWith(Path.DirectorySeparatorChar) ? String.Empty : Path.DirectorySeparatorChar) +
|
||||||
translationFilePath + Path.DirectorySeparatorChar);
|
translationFilePath + Path.DirectorySeparatorChar);
|
||||||
string langFileSystemLanguage = langDir + systemLanguage + ".ini";
|
|
||||||
string langFileConfigLanguage = langDir + language + ".ini";
|
|
||||||
|
|
||||||
if (File.Exists(langFileConfigLanguage))
|
foreach (string lang in languageList)
|
||||||
{// Language set in ini config
|
|
||||||
ParseTranslationContent(File.ReadAllLines(langFileConfigLanguage));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
if (Settings.DebugMessages)
|
bool fileLoaded = false;
|
||||||
ConsoleIO.WriteLogLine("[Translations] No translation file found for " + language + ". (Looked '" + langFileConfigLanguage + "'");
|
string langFileName = string.Format("{0}{1}.ini", langDir, lang);
|
||||||
}
|
|
||||||
|
|
||||||
if (File.Exists(langFileSystemLanguage))
|
if (File.Exists(langFileName)) // Language set in ini config
|
||||||
{// Fallback to system language
|
{
|
||||||
ParseTranslationContent(File.ReadAllLines(langFileSystemLanguage));
|
fileLoaded = true;
|
||||||
return;
|
Dictionary<string, string> trans = ParseTranslationContent(File.ReadAllLines(langFileName));
|
||||||
}
|
foreach ((string key, string value) in trans)
|
||||||
else
|
if (!string.IsNullOrWhiteSpace(value) && !translations.ContainsKey(key))
|
||||||
{
|
translations.Add(key, value);
|
||||||
if (Settings.DebugMessages)
|
}
|
||||||
ConsoleIO.WriteLogLine("[Translations] No translation file found for system language (" + systemLanguage + "). (Looked '" + langFileSystemLanguage + "'");
|
|
||||||
|
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,8 +627,9 @@ namespace MinecraftClient
|
||||||
/// Parse the given array to translation map
|
/// Parse the given array to translation map
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="content">Content of the translation file (in ini format)</param>
|
/// <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)
|
foreach (string lineRaw in content)
|
||||||
{
|
{
|
||||||
string line = lineRaw.Trim();
|
string line = lineRaw.Trim();
|
||||||
|
|
@ -172,6 +647,7 @@ namespace MinecraftClient
|
||||||
translations[translationName] = translationValue;
|
translations[translationName] = translationValue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return translations;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
@ -185,7 +661,7 @@ namespace MinecraftClient
|
||||||
{
|
{
|
||||||
Directory.CreateDirectory(translationFilePath);
|
Directory.CreateDirectory(translationFilePath);
|
||||||
}
|
}
|
||||||
File.WriteAllText(defaultPath, DefaultConfigResource.TranslationEnglish, Encoding.UTF8);
|
File.WriteAllText(defaultPath, DefaultConfigResource.Translation_en, Encoding.UTF8);
|
||||||
}
|
}
|
||||||
|
|
||||||
#region Console writing method wrapper
|
#region Console writing method wrapper
|
||||||
|
|
|
||||||
|
|
@ -67,6 +67,16 @@ namespace MinecraftClient.WinAPI
|
||||||
imageStream.Dispose();
|
imageStream.Dispose();
|
||||||
httpWebRequest.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
|
catch (HttpRequestException) //Skin not found? Reset to default icon
|
||||||
{
|
{
|
||||||
RevertToMCCIcon();
|
RevertToMCCIcon();
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
|
using System.Threading;
|
||||||
|
|
||||||
namespace MinecraftClient.WinAPI
|
namespace MinecraftClient.WinAPI
|
||||||
{
|
{
|
||||||
|
|
@ -79,9 +80,10 @@ namespace MinecraftClient.WinAPI
|
||||||
}
|
}
|
||||||
|
|
||||||
[DllImport("Kernel32")]
|
[DllImport("Kernel32")]
|
||||||
private static extern bool SetConsoleCtrlHandler(ConsoleCtrlHandler handler, bool add);
|
private static extern bool SetConsoleCtrlHandler(EventHandler handler, bool add);
|
||||||
private delegate bool ConsoleCtrlHandler(CtrlType sig);
|
|
||||||
private static readonly ConsoleCtrlHandler? _handler;
|
private delegate bool EventHandler(CtrlType sig);
|
||||||
|
static EventHandler? _handler;
|
||||||
|
|
||||||
enum CtrlType
|
enum CtrlType
|
||||||
{
|
{
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue