ConsoleIO: Sync with SharpTools

Had 2 versions of the ConsoleIO class, one here inc MCC (the original),
and another one in SharpTools, more generic, for use in other projects.

Both had diverged, this commit imports changes from the other repository.
This should not have any particular effect on MCC, besides adding more
documentation and settings in the source code of the class.

If any issue arises, as always, please report it :)
This commit is contained in:
ORelio 2018-05-28 22:01:51 +02:00
parent b5c8bf683f
commit ecf0114f62
6 changed files with 139 additions and 51 deletions

View file

@ -41,7 +41,7 @@ namespace MinecraftClient.ChatBots
if (Settings.Alerts_Beep_Enabled)
Console.Beep(); //Text found !
if (ConsoleIO.basicIO) //Using a GUI? Pass text as is.
if (ConsoleIO.BasicIO) //Using a GUI? Pass text as is.
ConsoleIO.WriteLine(text.Replace(alert, "§c" + alert + "§r"));
else //Using Console Prompt : Print text with alert highlighted

View file

@ -10,10 +10,11 @@ namespace MinecraftClient
/// <summary>
/// Allows simultaneous console input and output without breaking user input
/// (Without having this annoying behaviour : User inp[Some Console output]ut)
/// Provide some fancy features such as formatted output, text pasting and tab-completion.
/// By ORelio - (c) 2012-2018 - Available under the CDDL-1.0 license
/// </summary>
public static class ConsoleIO
{
public static bool basicIO = false;
private static IAutoComplete autocomplete_engine;
private static LinkedList<string> autocomplete_words = new LinkedList<string>();
private static LinkedList<string> previous = new LinkedList<string>();
@ -38,6 +39,32 @@ namespace MinecraftClient
}
}
/// <summary>
/// Set an auto-completion engine for TAB autocompletion.
/// </summary>
/// <param name="engine">Engine implementing the IAutoComplete interface</param>
public static void SetAutoCompleteEngine(IAutoComplete engine)
{
autocomplete_engine = engine;
}
/// <summary>
/// Determines whether to use interactive IO or basic IO.
/// Set to true to disable interactive command prompt and use the default Console.Read|Write() methods.
/// Color codes are printed as is when BasicIO is enabled.
/// </summary>
public static bool BasicIO = false;
/// <summary>
/// Determine whether WriteLineFormatted() should prepend lines with timestamps by default.
/// </summary>
public static bool EnableTimestamps = false;
/// <summary>
/// Specify a generic log line prefix for WriteLogLine()
/// </summary>
public static string LogPrefix = "§8[Log] ";
/// <summary>
/// Read a password from the standard input
/// </summary>
@ -88,7 +115,11 @@ namespace MinecraftClient
/// </summary>
public static string ReadLine()
{
if (basicIO) { return Console.ReadLine(); }
if (BasicIO)
{
return Console.ReadLine();
}
ConsoleKeyInfo k = new ConsoleKeyInfo();
lock (io_lock)
@ -199,7 +230,7 @@ namespace MinecraftClient
}
/// <summary>
/// Debug routine
/// Debug routine: print all keys pressed in the console
/// </summary>
public static void DebugReadInput()
{
@ -216,7 +247,7 @@ namespace MinecraftClient
/// </summary>
public static void Write(string text)
{
if (!basicIO)
if (!BasicIO)
{
lock (io_lock)
{
@ -276,29 +307,48 @@ namespace MinecraftClient
}
/// <summary>
/// Write a Minecraft-Formatted string to the standard output, using §c color codes
/// Write a Minecraft-Like formatted string to the standard output, using §c color codes
/// See minecraft.gamepedia.com/Classic_server_protocol#Color_Codes for more info
/// </summary>
/// <param name="str">String to write</param>
/// <param name="acceptnewlines">If false, space are printed instead of newlines</param>
public static void WriteLineFormatted(string str, bool acceptnewlines = true)
/// <param name="displayTimestamps">
/// If false, no timestamp is prepended.
/// If true, "hh-mm-ss" timestamp will be prepended.
/// If unspecified, value is retrieved from EnableTimestamps.
/// </param>
public static void WriteLineFormatted(string str, bool acceptnewlines = true, bool? displayTimestamp = null)
{
if (basicIO) { Console.WriteLine(str); return; }
if (!String.IsNullOrEmpty(str))
{
if (Settings.chatTimeStamps)
if (!acceptnewlines)
{
str = str.Replace('\n', ' ');
}
if (displayTimestamp == null)
{
displayTimestamp = EnableTimestamps;
}
if (displayTimestamp.Value)
{
int hour = DateTime.Now.Hour, minute = DateTime.Now.Minute, second = DateTime.Now.Second;
ConsoleIO.Write(String.Format("{0}:{1}:{2} ", hour.ToString("00"), minute.ToString("00"), second.ToString("00")));
}
if (!acceptnewlines) { str = str.Replace('\n', ' '); }
if (ConsoleIO.basicIO) { ConsoleIO.WriteLine(str); return; }
string[] subs = str.Split(new char[] { '§' });
if (subs[0].Length > 0) { ConsoleIO.Write(subs[0]); }
for (int i = 1; i < subs.Length; i++)
if (BasicIO)
{
if (subs[i].Length > 0)
Console.WriteLine(str);
return;
}
string[] parts = str.Split(new char[] { '§' });
if (parts[0].Length > 0)
{
ConsoleIO.Write(parts[0]);
}
for (int i = 1; i < parts.Length; i++)
{
if (parts[i].Length > 0)
{
switch (subs[i][0])
switch (parts[i][0])
{
case '0': Console.ForegroundColor = ConsoleColor.Gray; break; //Should be Black but Black is non-readable on a black background
case '1': Console.ForegroundColor = ConsoleColor.DarkBlue; break;
@ -319,32 +369,46 @@ namespace MinecraftClient
case 'r': Console.ForegroundColor = ConsoleColor.Gray; break;
}
if (subs[i].Length > 1)
if (parts[i].Length > 1)
{
ConsoleIO.Write(subs[i].Substring(1, subs[i].Length - 1));
ConsoleIO.Write(parts[i].Substring(1, parts[i].Length - 1));
}
}
}
Console.ForegroundColor = ConsoleColor.Gray;
ConsoleIO.Write('\n');
}
ConsoleIO.Write('\n');
}
/// <summary>
/// Write a Minecraft Console Client Log line
/// Write a prefixed log line. Prefix is set in LogPrefix.
/// </summary>
/// <param name="text">Text of the log line</param>
public static void WriteLogLine(string text)
{
WriteLineFormatted("§8[MCC] " + text);
WriteLineFormatted(LogPrefix + text);
}
#region Subfunctions
/// <summary>
/// Clear all text inside the input prompt
/// </summary>
private static void ClearLineAndBuffer()
{
while (buffer2.Length > 0) { GoRight(); }
while (buffer.Length > 0) { RemoveOneChar(); }
while (buffer2.Length > 0)
{
GoRight();
}
while (buffer.Length > 0)
{
RemoveOneChar();
}
}
/// <summary>
/// Remove one character on the left of the cursor in input prompt
/// </summary>
private static void RemoveOneChar()
{
if (buffer.Length > 0)
@ -369,10 +433,17 @@ namespace MinecraftClient
if (buffer2.Length > 0)
{
Console.Write(buffer2 + " \b");
for (int i = 0; i < buffer2.Length; i++) { GoBack(); }
for (int i = 0; i < buffer2.Length; i++)
{
GoBack();
}
}
}
}
/// <summary>
/// Move the cursor one character to the left inside the console, regardless of input prompt state
/// </summary>
private static void GoBack()
{
try
@ -387,6 +458,10 @@ namespace MinecraftClient
}
catch (ArgumentOutOfRangeException) { /* Console was resized!? */ }
}
/// <summary>
/// Move the cursor one character to the left in input prompt, adjusting buffers accordingly
/// </summary>
private static void GoLeft()
{
if (buffer.Length > 0)
@ -396,6 +471,10 @@ namespace MinecraftClient
Console.Write('\b');
}
}
/// <summary>
/// Move the cursor one character to the right in input prompt, adjusting buffers accordingly
/// </summary>
private static void GoRight()
{
if (buffer2.Length > 0)
@ -405,16 +484,30 @@ namespace MinecraftClient
buffer2 = buffer2.Substring(1);
}
}
/// <summary>
/// Insert a new character in the input prompt
/// </summary>
/// <param name="c">New character</param>
private static void AddChar(char c)
{
Console.Write(c);
buffer += c;
Console.Write(buffer2);
for (int i = 0; i < buffer2.Length; i++) { GoBack(); }
for (int i = 0; i < buffer2.Length; i++)
{
GoBack();
}
}
#endregion
#region Clipboard management
/// <summary>
/// Read a string from the Windows clipboard
/// </summary>
/// <returns>String from the Windows clipboard</returns>
private static string ReadClipboard()
{
string clipdata = "";
@ -433,17 +526,7 @@ namespace MinecraftClient
staThread.Join();
return clipdata;
}
#endregion
#region AutoComplete API
/// <summary>
/// Set an auto-completion engine for TAB autocompletion
/// </summary>
/// <param name="engine">Engine implementing the IAutoComplete interface</param>
public static void SetAutoCompleteEngine(IAutoComplete engine)
{
autocomplete_engine = engine;
}
#endregion
}
@ -453,6 +536,11 @@ namespace MinecraftClient
/// </summary>
public interface IAutoComplete
{
/// <summary>
/// Provide a list of auto-complete strings based on the provided input behing the cursor
/// </summary>
/// <param name="BehindCursor">Text behind the cursor, e.g. "my input comm"</param>
/// <returns>List of auto-complete words, e.g. ["command", "comment"]</returns>
IEnumerable<string> AutoComplete(string BehindCursor);
}
}

View file

@ -202,7 +202,7 @@ namespace MinecraftClient
while (client.Client.Connected)
{
text = ConsoleIO.ReadLine();
if (ConsoleIO.basicIO && text.Length > 0 && text[0] == (char)0x00)
if (ConsoleIO.BasicIO && text.Length > 0 && text[0] == (char)0x00)
{
//Process a request from the GUI
string[] command = text.Substring(1).Split((char)0x00);

View file

@ -49,10 +49,11 @@ namespace MinecraftClient
ConsoleIO.DebugReadInput();
}
//Basic Input/Output ?
//Setup ConsoleIO
ConsoleIO.LogPrefix = "§8[MCC] ";
if (args.Length >= 1 && args[args.Length - 1] == "BasicIO")
{
ConsoleIO.basicIO = true;
ConsoleIO.BasicIO = true;
args = args.Where(o => !Object.ReferenceEquals(o, args[args.Length - 1])).ToArray();
}
@ -116,7 +117,7 @@ namespace MinecraftClient
if (Settings.Login == "")
{
Console.Write(ConsoleIO.basicIO ? "Please type the username or email of your choice.\n" : "Login : ");
Console.Write(ConsoleIO.BasicIO ? "Please type the username or email of your choice.\n" : "Login : ");
Settings.Login = Console.ReadLine();
}
if (Settings.Password == "" && (Settings.SessionCaching == CacheType.None || !SessionCache.Contains(Settings.Login.ToLower())))
@ -133,10 +134,10 @@ namespace MinecraftClient
/// </summary>
private static void RequestPassword()
{
Console.Write(ConsoleIO.basicIO ? "Please type the password for " + Settings.Login + ".\n" : "Password : ");
Settings.Password = ConsoleIO.basicIO ? Console.ReadLine() : ConsoleIO.ReadPassword();
Console.Write(ConsoleIO.BasicIO ? "Please type the password for " + Settings.Login + ".\n" : "Password : ");
Settings.Password = ConsoleIO.BasicIO ? Console.ReadLine() : ConsoleIO.ReadPassword();
if (Settings.Password == "") { Settings.Password = "-"; }
if (!ConsoleIO.basicIO)
if (!ConsoleIO.BasicIO)
{
//Hide password length
Console.CursorTop--; Console.Write("Password : <******>");
@ -262,7 +263,6 @@ namespace MinecraftClient
}
else
{
Console.ForegroundColor = ConsoleColor.Gray;
string failureMessage = "Minecraft Login failed : ";
switch (result)
{
@ -366,7 +366,10 @@ namespace MinecraftClient
ConsoleIO.WriteLineFormatted("Or press Enter to exit Minecraft Console Client.");
while (command.Length > 0)
{
if (!ConsoleIO.basicIO) { ConsoleIO.Write('>'); }
if (!ConsoleIO.BasicIO)
{
ConsoleIO.Write('>');
}
command = Console.ReadLine().Trim();
if (command.Length > 0)
{

View file

@ -92,8 +92,7 @@ namespace MinecraftClient.Protocol
//File not found? Try downloading language file from Mojang's servers?
if (!System.IO.File.Exists(Language_File))
{
Console.ForegroundColor = ConsoleColor.DarkGray;
ConsoleIO.WriteLine("Downloading '" + Settings.Language + ".lang' from Mojang servers...");
ConsoleIO.WriteLineFormatted("§8Downloading '" + Settings.Language + ".lang' from Mojang servers...");
try
{
string assets_index = DownloadString(Settings.TranslationsFile_Website_Index);
@ -101,13 +100,12 @@ namespace MinecraftClient.Protocol
tmp = tmp[1].Split(new string[] { "hash\": \"" }, StringSplitOptions.None);
string hash = tmp[1].Split('"')[0]; //Translations file identifier on Mojang's servers
System.IO.File.WriteAllText(Language_File, DownloadString(Settings.TranslationsFile_Website_Download + '/' + hash.Substring(0, 2) + '/' + hash));
ConsoleIO.WriteLine("Done. File saved as '" + Language_File + '\'');
ConsoleIO.WriteLineFormatted("§8Done. File saved as '" + Language_File + '\'');
}
catch
{
ConsoleIO.WriteLine("Failed to download the file.");
ConsoleIO.WriteLineFormatted("§8Failed to download the file.");
}
Console.ForegroundColor = ConsoleColor.Gray;
}
//Download Failed? Defaulting to en_GB.lang if the game is installed

View file

@ -79,7 +79,6 @@ namespace MinecraftClient
public static List<string> Bots_Owners = new List<string>();
public static TimeSpan botMessageDelay = TimeSpan.FromSeconds(2);
public static string Language = "en_GB";
public static bool chatTimeStamps = false;
public static bool interactiveMode = true;
public static char internalCmdChar = '/';
public static bool playerHeadAsIcon = false;
@ -214,7 +213,7 @@ namespace MinecraftClient
case "singlecommand": SingleCommand = argValue; break;
case "language": Language = argValue; break;
case "consoletitle": ConsoleTitle = argValue; break;
case "timestamps": chatTimeStamps = str2bool(argValue); break;
case "timestamps": ConsoleIO.EnableTimestamps = str2bool(argValue); break;
case "exitonfailure": interactiveMode = !str2bool(argValue); break;
case "playerheadicon": playerHeadAsIcon = str2bool(argValue); break;
case "chatbotlogfile": chatbotLogFile = argValue; break;