mirror of
https://github.com/MCCTeam/Minecraft-Console-Client
synced 2025-10-14 21:22:49 +00:00
Implement command completion suggestions.
This commit is contained in:
parent
5d2589b10f
commit
84cf749344
115 changed files with 4684 additions and 2695 deletions
|
|
@ -2,22 +2,23 @@ using System;
|
|||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net.Sockets;
|
||||
using System.Security.Cryptography.Pkcs;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using Brigadier.NET;
|
||||
using Brigadier.NET.Exceptions;
|
||||
using MinecraftClient.ChatBots;
|
||||
using MinecraftClient.Commands;
|
||||
using MinecraftClient.CommandHandler;
|
||||
using MinecraftClient.CommandHandler.Patch;
|
||||
using MinecraftClient.Inventory;
|
||||
using MinecraftClient.Logger;
|
||||
using MinecraftClient.Mapping;
|
||||
using MinecraftClient.Protocol;
|
||||
using MinecraftClient.Protocol.Handlers.Forge;
|
||||
using MinecraftClient.Protocol.Keys;
|
||||
using MinecraftClient.Protocol.Message;
|
||||
using MinecraftClient.Protocol.ProfileKey;
|
||||
using MinecraftClient.Protocol.Session;
|
||||
using MinecraftClient.Proxy;
|
||||
using MinecraftClient.Scripting;
|
||||
using static MinecraftClient.Settings;
|
||||
|
||||
namespace MinecraftClient
|
||||
|
|
@ -29,10 +30,7 @@ namespace MinecraftClient
|
|||
{
|
||||
public static int ReconnectionAttemptsLeft = 0;
|
||||
|
||||
public static readonly CommandSource cmd_source = new();
|
||||
public static readonly CommandDispatcher<CommandSource> dispatcher = new();
|
||||
//private static readonly List<string> cmd_names = new();
|
||||
//private static readonly Dictionary<string, Command> cmds = new();
|
||||
public static CommandDispatcher<CmdResult> dispatcher = new();
|
||||
private readonly Dictionary<Guid, PlayerInfo> onlinePlayers = new();
|
||||
|
||||
private static bool commandsLoaded = false;
|
||||
|
|
@ -152,6 +150,8 @@ namespace MinecraftClient
|
|||
/// <param name="forgeInfo">ForgeInfo item stating that Forge is enabled</param>
|
||||
public McClient(SessionToken session, PlayerKeyPair? playerKeyPair, string server_ip, ushort port, int protocolversion, ForgeInfo? forgeInfo)
|
||||
{
|
||||
dispatcher = new();
|
||||
CmdResult.client = this;
|
||||
terrainAndMovementsEnabled = Config.Main.Advanced.TerrainAndMovements;
|
||||
inventoryHandlingEnabled = Config.Main.Advanced.InventoryHandling;
|
||||
entityHandlingEnabled = Config.Main.Advanced.EntityHandling;
|
||||
|
|
@ -206,7 +206,7 @@ namespace MinecraftClient
|
|||
cmdprompt = new CancellationTokenSource();
|
||||
ConsoleInteractive.ConsoleReader.BeginReadThread(cmdprompt);
|
||||
ConsoleInteractive.ConsoleReader.MessageReceived += ConsoleReaderOnMessageReceived;
|
||||
ConsoleInteractive.ConsoleReader.OnKeyInput += ConsoleIO.AutocompleteHandler;
|
||||
ConsoleInteractive.ConsoleReader.OnInputChange += ConsoleIO.AutocompleteHandler;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -230,7 +230,7 @@ namespace MinecraftClient
|
|||
|
||||
return;
|
||||
|
||||
Retry:
|
||||
Retry:
|
||||
if (timeoutdetector != null)
|
||||
{
|
||||
timeoutdetector.Item2.Cancel();
|
||||
|
|
@ -247,7 +247,7 @@ namespace MinecraftClient
|
|||
{
|
||||
ConsoleInteractive.ConsoleReader.StopReadThread();
|
||||
ConsoleInteractive.ConsoleReader.MessageReceived -= ConsoleReaderOnMessageReceived;
|
||||
ConsoleInteractive.ConsoleReader.OnKeyInput -= ConsoleIO.AutocompleteHandler;
|
||||
ConsoleInteractive.ConsoleReader.OnInputChange -= ConsoleIO.AutocompleteHandler;
|
||||
Program.HandleFailure();
|
||||
}
|
||||
|
||||
|
|
@ -456,6 +456,8 @@ namespace MinecraftClient
|
|||
/// </summary>
|
||||
public void OnConnectionLost(ChatBot.DisconnectReason reason, string message)
|
||||
{
|
||||
ConsoleIO.CancelAutocomplete();
|
||||
|
||||
handler.Dispose();
|
||||
|
||||
world.Clear();
|
||||
|
|
@ -514,7 +516,7 @@ namespace MinecraftClient
|
|||
{
|
||||
ConsoleInteractive.ConsoleReader.StopReadThread();
|
||||
ConsoleInteractive.ConsoleReader.MessageReceived -= ConsoleReaderOnMessageReceived;
|
||||
ConsoleInteractive.ConsoleReader.OnKeyInput -= ConsoleIO.AutocompleteHandler;
|
||||
ConsoleInteractive.ConsoleReader.OnInputChange -= ConsoleIO.AutocompleteHandler;
|
||||
Program.HandleFailure();
|
||||
}
|
||||
}
|
||||
|
|
@ -553,7 +555,9 @@ namespace MinecraftClient
|
|||
switch (command[0].ToLower())
|
||||
{
|
||||
case "autocomplete":
|
||||
if (command.Length > 1) { ConsoleIO.WriteLine((char)0x00 + "autocomplete" + (char)0x00 + handler.AutoComplete(command[1])); }
|
||||
int id = handler.AutoComplete(command[1]);
|
||||
while (!ConsoleIO.AutoCompleteDone) { Thread.Sleep(100); }
|
||||
if (command.Length > 1) { ConsoleIO.WriteLine((char)0x00 + "autocomplete" + (char)0x00 + ConsoleIO.AutoCompleteResult); }
|
||||
else ConsoleIO.WriteLine((char)0x00 + "autocomplete" + (char)0x00);
|
||||
break;
|
||||
}
|
||||
|
|
@ -561,70 +565,44 @@ namespace MinecraftClient
|
|||
else
|
||||
{
|
||||
text = text.Trim();
|
||||
if (text.Length > 0)
|
||||
|
||||
if (text.Length > 1
|
||||
&& Config.Main.Advanced.InternalCmdChar == MainConfigHealper.MainConfig.AdvancedConfig.InternalCmdCharType.none
|
||||
&& text[0] == '/')
|
||||
{
|
||||
if (Config.Main.Advanced.InternalCmdChar.ToChar() == ' ' || text[0] == Config.Main.Advanced.InternalCmdChar.ToChar())
|
||||
SendText(text);
|
||||
}
|
||||
else if (text.Length > 2
|
||||
&& Config.Main.Advanced.InternalCmdChar != MainConfigHealper.MainConfig.AdvancedConfig.InternalCmdCharType.none
|
||||
&& text[0] == Config.Main.Advanced.InternalCmdChar.ToChar()
|
||||
&& text[1] == '/')
|
||||
{
|
||||
SendText(text[1..]);
|
||||
}
|
||||
else if (text.Length > 0)
|
||||
{
|
||||
if (Config.Main.Advanced.InternalCmdChar == MainConfigHealper.MainConfig.AdvancedConfig.InternalCmdCharType.none
|
||||
|| text[0] == Config.Main.Advanced.InternalCmdChar.ToChar())
|
||||
{
|
||||
string? response_msg = "";
|
||||
CmdResult result = new();
|
||||
string command = Config.Main.Advanced.InternalCmdChar.ToChar() == ' ' ? text : text[1..];
|
||||
if (!PerformInternalCommand(Config.AppVar.ExpandVars(command), ref response_msg, Settings.Config.AppVar.GetVariables()) && Config.Main.Advanced.InternalCmdChar.ToChar() == '/')
|
||||
if (!PerformInternalCommand(Config.AppVar.ExpandVars(command), ref result, Settings.Config.AppVar.GetVariables()) && Config.Main.Advanced.InternalCmdChar.ToChar() == '/')
|
||||
{
|
||||
SendText(text);
|
||||
}
|
||||
else if (!String.IsNullOrEmpty(response_msg))
|
||||
else if (result.status != CmdResult.Status.NotRun && (result.status != CmdResult.Status.Done || !string.IsNullOrWhiteSpace(result.result)))
|
||||
{
|
||||
Log.Info(response_msg);
|
||||
Log.Info(result);
|
||||
}
|
||||
}
|
||||
else SendText(text);
|
||||
else
|
||||
{
|
||||
SendText(text);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Register a custom console command
|
||||
/// </summary>
|
||||
/// <param name="cmdName">Name of the command</param>
|
||||
/// <param name="cmdDesc">Description/usage of the command</param>
|
||||
/// <param name="callback">Method for handling the command</param>
|
||||
/// <returns>True if successfully registered</returns>
|
||||
public bool RegisterCommand(string cmdName, string cmdDesc, string cmdUsage, ChatBot.CommandRunner callback)
|
||||
{
|
||||
// if (cmds.ContainsKey(cmdName.ToLower()))
|
||||
// {
|
||||
// return false;
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// Command cmd = new ChatBot.ChatBotCommand(cmdName, cmdDesc, cmdUsage, callback);
|
||||
// cmds.Add(cmdName.ToLower(), cmd);
|
||||
// cmd_names.Add(cmdName.ToLower());
|
||||
// return true;
|
||||
// }
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Unregister a console command
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// There is no check for the command is registered by above method or is embedded command.
|
||||
/// Which mean this can unload any command
|
||||
/// </remarks>
|
||||
/// <param name="cmdName">The name of command to be unregistered</param>
|
||||
/// <returns></returns>
|
||||
public bool UnregisterCommand(string cmdName)
|
||||
{
|
||||
// if (cmds.ContainsKey(cmdName.ToLower()))
|
||||
// {
|
||||
// cmds.Remove(cmdName.ToLower());
|
||||
// cmd_names.Remove(cmdName.ToLower());
|
||||
// return true;
|
||||
// }
|
||||
// else return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Perform an internal MCC command (not a server command, use SendText() instead for that!)
|
||||
/// </summary>
|
||||
|
|
@ -632,82 +610,55 @@ namespace MinecraftClient
|
|||
/// <param name="response_msg">May contain a confirmation or error message after processing the command, or "" otherwise.</param>
|
||||
/// <param name="localVars">Local variables passed along with the command</param>
|
||||
/// <returns>TRUE if the command was indeed an internal MCC command</returns>
|
||||
public bool PerformInternalCommand(string command, ref string? response_msg, Dictionary<string, object>? localVars = null)
|
||||
public bool PerformInternalCommand(string command, ref CmdResult result, Dictionary<string, object>? localVars = null)
|
||||
{
|
||||
/* Process the provided command */
|
||||
ParseResults<CommandSource> parse;
|
||||
ParseResults<CmdResult> parse;
|
||||
try
|
||||
{
|
||||
parse = dispatcher.Parse(command, cmd_source);
|
||||
parse = dispatcher.Parse(command, result);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.Error(e.GetFullMessage());
|
||||
return true;
|
||||
Log.Debug("Parse fail: " + e.GetFullMessage());
|
||||
return false;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
int res = dispatcher.Execute(parse);
|
||||
Log.Info("res = " + res);
|
||||
dispatcher.Execute(parse);
|
||||
|
||||
foreach (ChatBot bot in bots.ToArray())
|
||||
{
|
||||
try
|
||||
{
|
||||
bot.OnInternalCommand(command, string.Join(" ", Command.GetArgs(command)), result);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
if (e is not ThreadAbortException)
|
||||
{
|
||||
Log.Warn(string.Format(Translations.icmd_error, bot.ToString() ?? string.Empty, e.ToString()));
|
||||
}
|
||||
else throw; //ThreadAbortException should not be caught
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
catch (CommandSyntaxException e)
|
||||
{
|
||||
Log.Warn(e.GetFullMessage());
|
||||
return true;
|
||||
if (parse.Context.Nodes.Count == 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
Log.Info("§e" + e.Message ?? e.StackTrace ?? "Incorrect argument.");
|
||||
Log.Info(dispatcher.GetAllUsageString(parse.Context.Nodes[0].Node.Name, false));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.Error(e.GetFullMessage());
|
||||
return true;
|
||||
}
|
||||
|
||||
//string command_name = command.Split(' ')[0].ToLower();
|
||||
//if (command_name == "help")
|
||||
//{
|
||||
// if (Command.HasArg(command))
|
||||
// {
|
||||
// string help_cmdname = Command.GetArgs(command)[0].ToLower();
|
||||
// if (help_cmdname == "help")
|
||||
// {
|
||||
// response_msg = Translations.icmd_help;
|
||||
// }
|
||||
// else if (cmds.ContainsKey(help_cmdname))
|
||||
// {
|
||||
// response_msg = cmds[help_cmdname].GetCmdDescTranslated();
|
||||
// }
|
||||
// else response_msg = string.Format(Translations.icmd_unknown, command_name);
|
||||
// }
|
||||
// else response_msg = string.Format(Translations.icmd_list, String.Join(", ", cmd_names.ToArray()), Config.Main.Advanced.InternalCmdChar.ToChar());
|
||||
//}
|
||||
//else if (cmds.ContainsKey(command_name))
|
||||
//{
|
||||
// response_msg = cmds[command_name].Run(this, command, localVars);
|
||||
|
||||
// foreach (ChatBot bot in bots.ToArray())
|
||||
// {
|
||||
// try
|
||||
// {
|
||||
// bot.OnInternalCommand(command_name, string.Join(" ", Command.GetArgs(command)), response_msg);
|
||||
// }
|
||||
// catch (Exception e)
|
||||
// {
|
||||
// if (e is not ThreadAbortException)
|
||||
// {
|
||||
// Log.Warn(string.Format(Translations.icmd_error, bot.ToString() ?? string.Empty, e.ToString()));
|
||||
// }
|
||||
// else throw; //ThreadAbortException should not be caught
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
//else
|
||||
//{
|
||||
// response_msg = string.Format(Translations.icmd_unknown, command_name);
|
||||
// return false;
|
||||
//}
|
||||
|
||||
//return true;
|
||||
}
|
||||
|
||||
public void LoadCommands()
|
||||
|
|
@ -725,10 +676,6 @@ namespace MinecraftClient
|
|||
{
|
||||
Command cmd = (Command)Activator.CreateInstance(type)!;
|
||||
cmd.RegisterCommand(this, dispatcher);
|
||||
// cmds[Settings.ToLowerIfNeed(cmd.CmdName)] = cmd;
|
||||
// cmd_names.Add(Settings.ToLowerIfNeed(cmd.CmdName));
|
||||
// foreach (string alias in cmd.GetCMDAliases())
|
||||
// cmds[Settings.ToLowerIfNeed(alias)] = cmd;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
|
|
@ -863,7 +810,7 @@ namespace MinecraftClient
|
|||
b.SetHandler(this);
|
||||
bots.Add(b);
|
||||
if (init)
|
||||
DispatchBotEvent(bot => bot.Initialize(), new ChatBot[] { b });
|
||||
DispatchBotEvent(bot => bot.Initialize(dispatcher), new ChatBot[] { b });
|
||||
if (handler != null)
|
||||
DispatchBotEvent(bot => bot.AfterGameJoined(), new ChatBot[] { b });
|
||||
}
|
||||
|
|
@ -879,8 +826,9 @@ namespace MinecraftClient
|
|||
return;
|
||||
}
|
||||
|
||||
b.OnUnload();
|
||||
bots.RemoveAll(item => object.ReferenceEquals(item, b));
|
||||
b.OnUnload(dispatcher);
|
||||
|
||||
bots.RemoveAll(item => ReferenceEquals(item, b));
|
||||
|
||||
// ToList is needed to avoid an InvalidOperationException from modfiying the list while it's being iterated upon.
|
||||
var botRegistrations = registeredBotPluginChannels.Where(entry => entry.Value.Contains(b)).ToList();
|
||||
|
|
@ -2449,6 +2397,8 @@ namespace MinecraftClient
|
|||
ClearInventories();
|
||||
|
||||
DispatchBotEvent(bot => bot.AfterGameJoined());
|
||||
|
||||
ConsoleIO.InitAutocomplete();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -3471,6 +3421,16 @@ namespace MinecraftClient
|
|||
DispatchBotEvent(bot => bot.OnBlockChange(location, block));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called when "AutoComplete" completes.
|
||||
/// </summary>
|
||||
/// <param name="transactionId">The number of this result.</param>
|
||||
/// <param name="result">All commands.</param>
|
||||
public void OnAutoCompleteDone(int transactionId, string[] result)
|
||||
{
|
||||
ConsoleIO.OnAutoCompleteDone(transactionId, result);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Send a click container button packet to the server.
|
||||
/// Used for Enchanting table, Lectern, stone cutter and loom
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue