Give access to AutoRespond matches inside scripts

Available as %match_u%, %match_1% and so on
See #770 for initial suggestion
See #772 for in-progress implementation
This commit is contained in:
ORelio 2020-03-27 21:14:05 +01:00
parent e4e1f0b9fa
commit 00112e4c6a
25 changed files with 129 additions and 69 deletions

View file

@ -25,10 +25,11 @@ namespace MinecraftClient
/// <param name="tickHandler">Tick handler for waiting after some API calls</param> /// <param name="tickHandler">Tick handler for waiting after some API calls</param>
/// <param name="lines">Lines of the script file to run</param> /// <param name="lines">Lines of the script file to run</param>
/// <param name="args">Arguments to pass to the script</param> /// <param name="args">Arguments to pass to the script</param>
/// <param name="localVars">Local variables passed along with the script</param>
/// <param name="run">Set to false to compile and cache the script without launching it</param> /// <param name="run">Set to false to compile and cache the script without launching it</param>
/// <exception cref="CSharpException">Thrown if an error occured</exception> /// <exception cref="CSharpException">Thrown if an error occured</exception>
/// <returns>Result of the execution, returned by the script</returns> /// <returns>Result of the execution, returned by the script</returns>
public static object Run(ChatBot apiHandler, ManualResetEvent tickHandler, string[] lines, string[] args, bool run = true) public static object Run(ChatBot apiHandler, ManualResetEvent tickHandler, string[] lines, string[] args, Dictionary<string, object> localVars, bool run = true)
{ {
//Script compatibility check for handling future versions differently //Script compatibility check for handling future versions differently
if (lines.Length < 1 || lines[0] != "//MCCScript 1.0") if (lines.Length < 1 || lines[0] != "//MCCScript 1.0")
@ -132,7 +133,7 @@ namespace MinecraftClient
.GetType() .GetType()
.GetMethod("__run") .GetMethod("__run")
.Invoke(compiledScript, .Invoke(compiledScript,
new object[] { new CSharpAPI(apiHandler, tickHandler), args }); new object[] { new CSharpAPI(apiHandler, tickHandler, localVars), args });
} }
catch (Exception e) { throw new CSharpException(CSErrorType.RuntimeError, e); } catch (Exception e) { throw new CSharpException(CSErrorType.RuntimeError, e); }
} }
@ -192,15 +193,22 @@ namespace MinecraftClient
/// </summary> /// </summary>
private ManualResetEvent tickHandler; private ManualResetEvent tickHandler;
/// <summary>
/// Holds local variables passed along with the script
/// </summary>
private Dictionary<string, object> localVars;
/// <summary> /// <summary>
/// Create a new C# API Wrapper /// Create a new C# API Wrapper
/// </summary> /// </summary>
/// <param name="apiHandler">ChatBot API Handler</param> /// <param name="apiHandler">ChatBot API Handler</param>
/// <param name="tickHandler">ChatBot tick handler</param> /// <param name="tickHandler">ChatBot tick handler</param>
public CSharpAPI(ChatBot apiHandler, ManualResetEvent tickHandler) /// <param name="localVars">Local variables passed along with the script</param>
public CSharpAPI(ChatBot apiHandler, ManualResetEvent tickHandler, Dictionary<string , object> localVars)
{ {
SetMaster(apiHandler); SetMaster(apiHandler);
this.tickHandler = tickHandler; this.tickHandler = tickHandler;
this.localVars = localVars;
} }
/* == Wrappers for ChatBot API with public visibility and call limit to one per tick for safety == */ /* == Wrappers for ChatBot API with public visibility and call limit to one per tick for safety == */
@ -231,10 +239,13 @@ namespace MinecraftClient
/// Perform an internal MCC command (not a server command, use SendText() instead for that!) /// Perform an internal MCC command (not a server command, use SendText() instead for that!)
/// </summary> /// </summary>
/// <param name="command">The command to process</param> /// <param name="command">The command to process</param>
/// <param name="localVars">Local variables passed along with the script</param>
/// <returns>TRUE if the command was indeed an internal MCC command</returns> /// <returns>TRUE if the command was indeed an internal MCC command</returns>
new public bool PerformInternalCommand(string command) new public bool PerformInternalCommand(string command, Dictionary<string, object> localVars = null)
{ {
bool result = base.PerformInternalCommand(command); if (localVars == null)
localVars = this.localVars;
bool result = base.PerformInternalCommand(command, localVars);
tickHandler.WaitOne(); tickHandler.WaitOne();
return result; return result;
} }
@ -302,6 +313,8 @@ namespace MinecraftClient
/// <returns>Value of the variable or null if no variable</returns> /// <returns>Value of the variable or null if no variable</returns>
public object GetVar(string varName) public object GetVar(string varName)
{ {
if (localVars != null && localVars.ContainsKey(varName))
return localVars[varName];
return Settings.GetVar(varName); return Settings.GetVar(varName);
} }
@ -312,6 +325,8 @@ namespace MinecraftClient
/// <param name="varValue">Value of the variable</param> /// <param name="varValue">Value of the variable</param>
public bool SetVar(string varName, object varValue) public bool SetVar(string varName, object varValue)
{ {
if (localVars != null && localVars.ContainsKey(varName))
localVars.Remove(varName);
return Settings.SetVar(varName, varValue); return Settings.SetVar(varName, varValue);
} }
@ -385,7 +400,7 @@ namespace MinecraftClient
ChatBots.Script.LookForScript(ref script); ChatBots.Script.LookForScript(ref script);
try { lines = File.ReadAllLines(script); } try { lines = File.ReadAllLines(script); }
catch (Exception e) { throw new CSharpException(CSErrorType.FileReadError, e); } catch (Exception e) { throw new CSharpException(CSErrorType.FileReadError, e); }
return CSharpRunner.Run(this, tickHandler, lines, args); return CSharpRunner.Run(this, tickHandler, lines, args, localVars);
} }
} }
} }

View file

@ -138,17 +138,36 @@ namespace MinecraftClient
/// <param name="data">The payload for the message</param> /// <param name="data">The payload for the message</param>
public virtual void OnPluginMessage(string channel, byte[] data) { } public virtual void OnPluginMessage(string channel, byte[] data) { }
/// <summary>
/// Called when properties for the Player entity are received from the server
/// </summary>
/// <param name="prop">Dictionary of player properties</param>
public virtual void OnPlayerProperty(Dictionary<string, Double> prop) { } public virtual void OnPlayerProperty(Dictionary<string, Double> prop) { }
/// <summary>
/// Called when server TPS are recalculated by MCC based on world time updates
/// </summary>
/// <param name="tps">New estimated server TPS (between 0 and 20)</param>
public virtual void OnServerTpsUpdate(Double tps) { } public virtual void OnServerTpsUpdate(Double tps) { }
/// <summary>
/// Called when an entity moved nearby
/// </summary>
/// <param name="entity">Entity with updated location</param>
public virtual void OnEntityMove(Mapping.Entity entity) { } public virtual void OnEntityMove(Mapping.Entity entity) { }
/// <summary>
/// Called when an entity spawned nearby
/// </summary>
/// <param name="entity">New Entity</param>
public virtual void OnEntitySpawn(Mapping.Entity entity) { } public virtual void OnEntitySpawn(Mapping.Entity entity) { }
/// <summary>
/// Called when an entity despawns/dies nearby
/// </summary>
/// <param name="entity">Entity wich has just disappeared</param>
public virtual void OnEntityDespawn(Mapping.Entity entity) { } public virtual void OnEntityDespawn(Mapping.Entity entity) { }
/* =================================================================== */ /* =================================================================== */
/* ToolBox - Methods below might be useful while creating your bot. */ /* ToolBox - Methods below might be useful while creating your bot. */
/* You should not need to interact with other classes of the program. */ /* You should not need to interact with other classes of the program. */
@ -183,11 +202,12 @@ namespace MinecraftClient
/// Perform an internal MCC command (not a server command, use SendText() instead for that!) /// Perform an internal MCC command (not a server command, use SendText() instead for that!)
/// </summary> /// </summary>
/// <param name="command">The command to process</param> /// <param name="command">The command to process</param>
/// <param name="localVars">Local variables passed along with the command</param>
/// <returns>TRUE if the command was indeed an internal MCC command</returns> /// <returns>TRUE if the command was indeed an internal MCC command</returns>
protected bool PerformInternalCommand(string command) protected bool PerformInternalCommand(string command, Dictionary<string, object> localVars = null)
{ {
string temp = ""; string temp = "";
return Handler.PerformInternalCommand(command, ref temp); return Handler.PerformInternalCommand(command, ref temp, localVars);
} }
/// <summary> /// <summary>
@ -195,10 +215,11 @@ namespace MinecraftClient
/// </summary> /// </summary>
/// <param name="command">The command to process</param> /// <param name="command">The command to process</param>
/// <param name="response_msg">May contain a confirmation or error message after processing the command, or "" otherwise.</param> /// <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> /// <returns>TRUE if the command was indeed an internal MCC command</returns>
protected bool PerformInternalCommand(string command, ref string response_msg) protected bool PerformInternalCommand(string command, ref string response_msg, Dictionary<string, object> localVars = null)
{ {
return Handler.PerformInternalCommand(command, ref response_msg); return Handler.PerformInternalCommand(command, ref response_msg, localVars);
} }
/// <summary> /// <summary>
@ -586,9 +607,10 @@ namespace MinecraftClient
/// </summary> /// </summary>
/// <param name="filename">File name</param> /// <param name="filename">File name</param>
/// <param name="playername">Player name to send error messages, if applicable</param> /// <param name="playername">Player name to send error messages, if applicable</param>
protected void RunScript(string filename, string playername = "") /// <param name="localVars">Local variables for use in the Script</param>
protected void RunScript(string filename, string playername = null, Dictionary<string, object> localVars = null)
{ {
Handler.BotLoad(new ChatBots.Script(filename, playername)); Handler.BotLoad(new ChatBots.Script(filename, playername, localVars));
} }
/// <summary> /// <summary>
@ -808,15 +830,23 @@ namespace MinecraftClient
return Handler.InteractEntity(EntityID, type); return Handler.InteractEntity(EntityID, type);
} }
/// <summary>
/// Use item currently in the player's hand (active inventory bar slot)
/// </summary>
/// <returns></returns>
protected bool UseItemOnHand() protected bool UseItemOnHand()
{ {
return Handler.UseItemOnHand(); return Handler.UseItemOnHand();
} }
/// <summary>
/// Get a copy of the player's inventory
/// </summary>
/// <returns>Player inventory</returns>
protected Container GetPlayerInventory() protected Container GetPlayerInventory()
{ {
Container container = Handler.GetPlayerInventory(); Container container = Handler.GetPlayerInventory();
return new Container(container.ID,container.Type,container.Title,container.Items); return new Container(container.ID, container.Type, container.Title, container.Items);
} }
} }
} }

View file

@ -76,8 +76,9 @@ namespace MinecraftClient.ChatBots
/// <param name="username">Player who have sent the message</param> /// <param name="username">Player who have sent the message</param>
/// <param name="message">Message to match against the regex or match string</param> /// <param name="message">Message to match against the regex or match string</param>
/// <param name="msgType">Type of the message public/private message, or other message</param> /// <param name="msgType">Type of the message public/private message, or other message</param>
/// <param name="localVars">Dictionary to populate with match variables in case of Regex match</param>
/// <returns>Internal command to run as a response to this user, or null if no match has been detected</returns> /// <returns>Internal command to run as a response to this user, or null if no match has been detected</returns>
public string Match(string username, string message, MessageType msgType) public string Match(string username, string message, MessageType msgType, Dictionary<string, object> localVars)
{ {
string toSend = null; string toSend = null;
@ -99,9 +100,14 @@ namespace MinecraftClient.ChatBots
if (regex.IsMatch(message)) if (regex.IsMatch(message))
{ {
Match regexMatch = regex.Match(message); Match regexMatch = regex.Match(message);
localVars["match_0"] = regexMatch.Groups[0].Value;
for (int i = regexMatch.Groups.Count - 1; i >= 1; i--) for (int i = regexMatch.Groups.Count - 1; i >= 1; i--)
{
toSend = toSend.Replace("$" + i, regexMatch.Groups[i].Value); toSend = toSend.Replace("$" + i, regexMatch.Groups[i].Value);
localVars["match_" + i] = regexMatch.Groups[i].Value;
}
toSend = toSend.Replace("$u", username); toSend = toSend.Replace("$u", username);
localVars["match_u"] = username;
return toSend; return toSend;
} }
} }
@ -109,6 +115,8 @@ namespace MinecraftClient.ChatBots
{ {
if (message.ToLower().Contains(match.ToLower())) if (message.ToLower().Contains(match.ToLower()))
{ {
localVars["match_0"] = message;
localVars["match_u"] = username;
return toSend.Replace("$u", username); return toSend.Replace("$u", username);
} }
} }
@ -225,12 +233,13 @@ namespace MinecraftClient.ChatBots
{ {
foreach (RespondRule rule in respondRules) foreach (RespondRule rule in respondRules)
{ {
string toPerform = rule.Match(sender, message, msgType); Dictionary<string, object> localVars = new Dictionary<string, object>();
string toPerform = rule.Match(sender, message, msgType, localVars);
if (!String.IsNullOrEmpty(toPerform)) if (!String.IsNullOrEmpty(toPerform))
{ {
string response = null; string response = null;
LogToConsole(toPerform); LogToConsole(toPerform);
PerformInternalCommand(toPerform, ref response); PerformInternalCommand(toPerform, ref response, localVars);
if (!String.IsNullOrEmpty(response)) if (!String.IsNullOrEmpty(response))
LogToConsole(response); LogToConsole(response);
} }

View file

@ -25,17 +25,18 @@ namespace MinecraftClient.ChatBots
private bool csharp; private bool csharp;
private Thread thread; private Thread thread;
private ManualResetEvent tpause; private ManualResetEvent tpause;
private Dictionary<string, object> localVars;
public Script(string filename) public Script(string filename)
{ {
ParseArguments(filename); ParseArguments(filename);
} }
public Script(string filename, string ownername) public Script(string filename, string ownername, Dictionary<string, object> localVars)
: this(filename) : this(filename)
{ {
if (ownername != "") this.owner = ownername;
owner = ownername; this.localVars = localVars;
} }
private void ParseArguments(string argstr) private void ParseArguments(string argstr)
@ -135,14 +136,14 @@ namespace MinecraftClient.ChatBots
csharp = file.EndsWith(".cs"); csharp = file.EndsWith(".cs");
thread = null; thread = null;
if (owner != null) if (!String.IsNullOrEmpty(owner))
SendPrivateMessage(owner, "Script '" + file + "' loaded."); SendPrivateMessage(owner, "Script '" + file + "' loaded.");
} }
else else
{ {
LogToConsole("File not found: '" + System.IO.Path.GetFullPath(file) + "'"); LogToConsole("File not found: '" + System.IO.Path.GetFullPath(file) + "'");
if (owner != null) if (!String.IsNullOrEmpty(owner))
SendPrivateMessage(owner, "File not found: '" + file + "'"); SendPrivateMessage(owner, "File not found: '" + file + "'");
UnloadBot(); //No need to keep the bot active UnloadBot(); //No need to keep the bot active
@ -161,7 +162,7 @@ namespace MinecraftClient.ChatBots
{ {
try try
{ {
CSharpRunner.Run(this, tpause, lines, args); CSharpRunner.Run(this, tpause, lines, args, localVars);
} }
catch (CSharpException e) catch (CSharpException e)
{ {
@ -198,7 +199,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); instruction_line = Settings.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())
{ {

View file

@ -11,40 +11,35 @@ namespace MinecraftClient
/// If inheriting from the 'Command' class and placed in the 'Commands' namespace, the command will be /// If inheriting from the 'Command' class and placed in the 'Commands' namespace, the command will be
/// automatically loaded and available in main chat prompt, scripts, remote control and command help. /// automatically loaded and available in main chat prompt, scripts, remote control and command help.
/// </summary> /// </summary>
public abstract class Command public abstract class Command
{ {
/// <summary> /// <summary>
/// The command name /// The command name
/// </summary> /// </summary>
public abstract string CMDName { get; } public abstract string CMDName { get; }
/// <summary> /// <summary>
/// Usage message, eg: 'name [args]: do something' /// Usage message, eg: 'name [args]: do something'
/// </summary> /// </summary>
public abstract string CMDDesc { get; } public abstract string CMDDesc { get; }
/// <summary> /// <summary>
/// Perform the command /// Perform the command
/// </summary> /// </summary>
/// <param name="command">The full command, eg: 'mycommand arg1 arg2'</param> /// <param name="command">The full command, eg: 'mycommand arg1 arg2'</param>
/// <param name="localVars">Local variables passed along with the command (may be null)</param>
/// <returns>A confirmation/error message, or "" if no message</returns> /// <returns>A confirmation/error message, or "" if no message</returns>
public abstract string Run(McTcpClient handler, string command, Dictionary<string, object> localVars);
public abstract string Run(McTcpClient handler, string command);
/// <summary> /// <summary>
/// Return a list of aliases for this command. /// Return a list of aliases for this command.
/// Override this method if you wish to put aliases to the command /// Override this method if you wish to put aliases to the command
/// </summary> /// </summary>
public virtual IEnumerable<string> getCMDAliases() { return new string[0]; } public virtual IEnumerable<string> getCMDAliases() { return new string[0]; }
/// <summary> /// <summary>
/// Check if at least one argument has been passed to the command /// Check if at least one argument has been passed to the command
/// </summary> /// </summary>
public static bool hasArg(string command) public static bool hasArg(string command)
{ {
int first_space = command.IndexOf(' '); int first_space = command.IndexOf(' ');
@ -55,7 +50,6 @@ namespace MinecraftClient
/// Extract the argument string from the command /// Extract the argument string from the command
/// </summary> /// </summary>
/// <returns>Argument or "" if no argument</returns> /// <returns>Argument or "" if no argument</returns>
public static string getArg(string command) public static string getArg(string command)
{ {
if (hasArg(command)) if (hasArg(command))
@ -69,7 +63,6 @@ namespace MinecraftClient
/// Extract the arguments as a string array from the command /// Extract the arguments as a string array from the command
/// </summary> /// </summary>
/// <returns>Argument array or empty array if no arguments</returns> /// <returns>Argument array or empty array if no arguments</returns>
public static string[] getArgs(string command) public static string[] getArgs(string command)
{ {
string[] args = getArg(command).Split(' '); string[] args = getArg(command).Split(' ');

View file

@ -10,7 +10,7 @@ namespace MinecraftClient.Commands
public override string CMDName { get { return "changeslot"; } } public override string CMDName { get { return "changeslot"; } }
public override string CMDDesc { get { return "changeslot <1-9>: Change hotbar"; } } public override string CMDDesc { get { return "changeslot <1-9>: Change hotbar"; } }
public override string Run(McTcpClient handler, string command) public override string Run(McTcpClient handler, string command, Dictionary<string, object> localVars)
{ {
if (!handler.GetInventoryEnabled()) return "Please enable InventoryHandling in the config file first."; if (!handler.GetInventoryEnabled()) return "Please enable InventoryHandling in the config file first.";
if (hasArg(command)) if (hasArg(command))

View file

@ -10,7 +10,7 @@ namespace MinecraftClient.Commands
public override string CMDName { get { return "connect"; } } public override string CMDName { get { return "connect"; } }
public override string CMDDesc { get { return "connect <server> [account]: connect to the specified server."; } } public override string CMDDesc { get { return "connect <server> [account]: connect to the specified server."; } }
public override string Run(McTcpClient handler, string command) public override string Run(McTcpClient handler, string command, Dictionary<string, object> localVars)
{ {
if (hasArg(command)) if (hasArg(command))
{ {

View file

@ -10,7 +10,7 @@ namespace MinecraftClient.Commands
public override string CMDName { get { return "debug"; } } public override string CMDName { get { return "debug"; } }
public override string CMDDesc { get { return "debug [on|off]: toggle debug messages."; } } public override string CMDDesc { get { return "debug [on|off]: toggle debug messages."; } }
public override string Run(McTcpClient handler, string command) public override string Run(McTcpClient handler, string command, Dictionary<string, object> localVars)
{ {
if (hasArg(command)) if (hasArg(command))
{ {

View file

@ -10,7 +10,7 @@ namespace MinecraftClient.Commands
public override string CMDName { get { return "exit"; } } public override string CMDName { get { return "exit"; } }
public override string CMDDesc { get { return "exit: disconnect from the server."; } } public override string CMDDesc { get { return "exit: disconnect from the server."; } }
public override string Run(McTcpClient handler, string command) public override string Run(McTcpClient handler, string command, Dictionary<string, object> localVars)
{ {
Program.Exit(); Program.Exit();
return ""; return "";

View file

@ -11,7 +11,7 @@ namespace MinecraftClient.Commands
public override string CMDName { get { return "getinventory"; } } public override string CMDName { get { return "getinventory"; } }
public override string CMDDesc { get { return "getinventory: Show your inventory."; } } public override string CMDDesc { get { return "getinventory: Show your inventory."; } }
public override string Run(McTcpClient handler, string command) public override string Run(McTcpClient handler, string command, Dictionary<string, object> localVars)
{ {
Dictionary<int,Item> items = handler.GetPlayerInventory().Items; Dictionary<int,Item> items = handler.GetPlayerInventory().Items;
foreach(KeyValuePair<int,Item> a in items) foreach(KeyValuePair<int,Item> a in items)

View file

@ -10,7 +10,7 @@ namespace MinecraftClient.Commands
public override string CMDName { get { return "list"; } } public override string CMDName { get { return "list"; } }
public override string CMDDesc { get { return "list: get the player list."; } } public override string CMDDesc { get { return "list: get the player list."; } }
public override string Run(McTcpClient handler, string command) public override string Run(McTcpClient handler, string command, Dictionary<string, object> localVars)
{ {
return "PlayerList: " + String.Join(", ", handler.GetOnlinePlayers()); return "PlayerList: " + String.Join(", ", handler.GetOnlinePlayers());
} }

View file

@ -10,7 +10,7 @@ namespace MinecraftClient.Commands
public override string CMDName { get { return "log"; } } public override string CMDName { get { return "log"; } }
public override string CMDDesc { get { return "log <text>: log some text to the console."; } } public override string CMDDesc { get { return "log <text>: log some text to the console."; } }
public override string Run(McTcpClient handler, string command) public override string Run(McTcpClient handler, string command, Dictionary<string, object> localVars)
{ {
if (hasArg(command)) if (hasArg(command))
{ {

View file

@ -11,7 +11,7 @@ namespace MinecraftClient.Commands
public override string CMDName { get { return "look"; } } public override string CMDName { get { return "look"; } }
public override string CMDDesc { get { return "look <x y z|yaw pitch|up|down|east|west|north|south>: look at direction or coordinates."; } } public override string CMDDesc { get { return "look <x y z|yaw pitch|up|down|east|west|north|south>: look at direction or coordinates."; } }
public override string Run(McTcpClient handler, string command) public override string Run(McTcpClient handler, string command, Dictionary<string, object> localVars)
{ {
if (handler.GetTerrainEnabled()) if (handler.GetTerrainEnabled())
{ {

View file

@ -11,7 +11,7 @@ namespace MinecraftClient.Commands
public override string CMDName { get { return "move"; } } public override string CMDName { get { return "move"; } }
public override string CMDDesc { get { return "move <on|off|get|up|down|east|west|north|south|x y z>: walk or start walking."; } } public override string CMDDesc { get { return "move <on|off|get|up|down|east|west|north|south|x y z>: walk or start walking."; } }
public override string Run(McTcpClient handler, string command) public override string Run(McTcpClient handler, string command, Dictionary<string, object> localVars)
{ {
string[] args = getArgs(command); string[] args = getArgs(command);
string argStr = getArg(command).Trim().ToLower(); string argStr = getArg(command).Trim().ToLower();

View file

@ -10,7 +10,7 @@ namespace MinecraftClient.Commands
public override string CMDName { get { return "reco"; } } public override string CMDName { get { return "reco"; } }
public override string CMDDesc { get { return "reco [account]: restart and reconnect to the server."; } } public override string CMDDesc { get { return "reco [account]: restart and reconnect to the server."; } }
public override string Run(McTcpClient handler, string command) public override string Run(McTcpClient handler, string command, Dictionary<string, object> localVars)
{ {
string[] args = getArgs(command); string[] args = getArgs(command);
if (args.Length > 0) if (args.Length > 0)

View file

@ -10,7 +10,7 @@ namespace MinecraftClient.Commands
public override string CMDName { get { return "respawn"; } } public override string CMDName { get { return "respawn"; } }
public override string CMDDesc { get { return "respawn: Use this to respawn if you are dead."; } } public override string CMDDesc { get { return "respawn: Use this to respawn if you are dead."; } }
public override string Run(McTcpClient handler, string command) public override string Run(McTcpClient handler, string command, Dictionary<string, object> localVars)
{ {
handler.SendRespawnPacket(); handler.SendRespawnPacket();
return "You have respawned."; return "You have respawned.";

View file

@ -10,11 +10,11 @@ namespace MinecraftClient.Commands
public override string CMDName { get { return "script"; } } public override string CMDName { get { return "script"; } }
public override string CMDDesc { get { return "script <scriptname>: run a script file."; } } public override string CMDDesc { get { return "script <scriptname>: run a script file."; } }
public override string Run(McTcpClient handler, string command) public override string Run(McTcpClient handler, string command, Dictionary<string, object> localVars)
{ {
if (hasArg(command)) if (hasArg(command))
{ {
handler.BotLoad(new ChatBots.Script(getArg(command))); handler.BotLoad(new ChatBots.Script(getArg(command), null, localVars));
return ""; return "";
} }
else return CMDDesc; else return CMDDesc;

View file

@ -10,7 +10,7 @@ namespace MinecraftClient.Commands
public override string CMDName { get { return "send"; } } public override string CMDName { get { return "send"; } }
public override string CMDDesc { get { return "send <text>: send a chat message or command."; } } public override string CMDDesc { get { return "send <text>: send a chat message or command."; } }
public override string Run(McTcpClient handler, string command) public override string Run(McTcpClient handler, string command, Dictionary<string, object> localVars)
{ {
if (hasArg(command)) if (hasArg(command))
{ {

View file

@ -10,7 +10,7 @@ namespace MinecraftClient.Commands
public override string CMDName { get { return "set"; } } public override string CMDName { get { return "set"; } }
public override string CMDDesc { get { return "set varname=value: set a custom %variable%."; } } public override string CMDDesc { get { return "set varname=value: set a custom %variable%."; } }
public override string Run(McTcpClient handler, string command) public override string Run(McTcpClient handler, string command, Dictionary<string, object> localVars)
{ {
if (hasArg(command)) if (hasArg(command))
{ {

View file

@ -10,7 +10,7 @@ namespace MinecraftClient.Commands
public override string CMDName { get { return "useitem"; } } public override string CMDName { get { return "useitem"; } }
public override string CMDDesc { get { return "useitem: Use (left click) an item on the hand"; } } public override string CMDDesc { get { return "useitem: Use (left click) an item on the hand"; } }
public override string Run(McTcpClient handler, string command) public override string Run(McTcpClient handler, string command, Dictionary<string, object> localVars)
{ {
handler.UseItemOnHand(); handler.UseItemOnHand();
return "Use an item"; return "Use an item";

View file

@ -313,8 +313,9 @@ namespace MinecraftClient
/// </summary> /// </summary>
/// <param name="command">The command</param> /// <param name="command">The command</param>
/// <param name="response_msg">May contain a confirmation or error message after processing the command, or "" otherwise.</param> /// <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> /// <returns>TRUE if the command was indeed an internal MCC command</returns>
public bool PerformInternalCommand(string command, ref string response_msg) public bool PerformInternalCommand(string command, ref string response_msg, Dictionary<string, object> localVars = null)
{ {
/* Load commands from the 'Commands' namespace */ /* Load commands from the 'Commands' namespace */
@ -363,7 +364,7 @@ namespace MinecraftClient
} }
else if (cmds.ContainsKey(command_name)) else if (cmds.ContainsKey(command_name))
{ {
response_msg = cmds[command_name].Run(this, command); response_msg = cmds[command_name].Run(this, command, localVars);
} }
else else
{ {

View file

@ -388,15 +388,15 @@ namespace MinecraftClient
if (command.StartsWith("reco")) if (command.StartsWith("reco"))
{ {
message = new Commands.Reco().Run(null, Settings.ExpandVars(command)); message = new Commands.Reco().Run(null, Settings.ExpandVars(command), null);
} }
else if (command.StartsWith("connect")) else if (command.StartsWith("connect"))
{ {
message = new Commands.Connect().Run(null, Settings.ExpandVars(command)); message = new Commands.Connect().Run(null, Settings.ExpandVars(command), null);
} }
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)); message = new Commands.Exit().Run(null, Settings.ExpandVars(command), null);
} }
else if (command.StartsWith("help")) else if (command.StartsWith("help"))
{ {

View file

@ -792,11 +792,12 @@ namespace MinecraftClient
} }
/// <summary> /// <summary>
/// Replace %variables% with their value /// Replace %variables% with their value from global AppVars
/// </summary> /// </summary>
/// <param name="str">String to parse</param> /// <param name="str">String to parse</param>
/// <param name="localContext">Optional local variables overriding global variables</param>
/// <returns>Modifier string</returns> /// <returns>Modifier string</returns>
public static string ExpandVars(string str) public static string ExpandVars(string str, Dictionary<string, object> localVars = null)
{ {
StringBuilder result = new StringBuilder(); StringBuilder result = new StringBuilder();
for (int i = 0; i < str.Length; i++) for (int i = 0; i < str.Length; i++)
@ -808,7 +809,7 @@ namespace MinecraftClient
for (int j = i + 1; j < str.Length; j++) for (int j = i + 1; j < str.Length; j++)
{ {
if (!char.IsLetterOrDigit(str[j])) if (!char.IsLetterOrDigit(str[j]) && str[j] != '_')
{ {
if (str[j] == '%') if (str[j] == '%')
varname_ok = var_name.Length > 0; varname_ok = var_name.Length > 0;
@ -829,7 +830,11 @@ namespace MinecraftClient
case "serverip": result.Append(ServerIP); break; case "serverip": result.Append(ServerIP); break;
case "serverport": result.Append(ServerPort); break; case "serverport": result.Append(ServerPort); break;
default: default:
if (AppVars.ContainsKey(varname_lower)) if (localVars != null && localVars.ContainsKey(varname_lower))
{
result.Append(localVars[varname_lower].ToString());
}
else if (AppVars.ContainsKey(varname_lower))
{ {
result.Append(AppVars[varname_lower].ToString()); result.Append(AppVars[varname_lower].ToString());
} }

View file

@ -1,4 +1,4 @@
Minecraft Client v1.13.0 for Minecraft 1.4.6 to 1.13.2 - By ORelio & Contributors Minecraft Console Client User Manual
====== ======
**Thanks for dowloading Minecraft Console Client!** **Thanks for dowloading Minecraft Console Client!**
@ -17,7 +17,7 @@ On Mac or Linux you need to install the Mono Runtime:
- On Linux: sudo apt-get install mono-runtime libmono-reflection-cil - On Linux: sudo apt-get install mono-runtime libmono-reflection-cil
Then, open a terminal in this folder and run "mono MinecraftClient.exe". Then, open a terminal in this folder and run "mono MinecraftClient.exe".
If you cannot authenticate on Mono, you'll need to run "mozroots --import --ask-remove" once. If you cannot authenticate on Mono, you'll need to run "mozroots --import --ask-remove" once.
If Mono crashes, retry with mono-complete instead of mono-runtime. Mono v4.0 to 4.2 is recommended. If Mono crashes, retry with mono-complete instead of mono-runtime. Use at least Mono v4.0.
Using Configuration files & Enabling bots Using Configuration files & Enabling bots
------ ------
@ -235,7 +235,6 @@ Using the Auto Attack
The AutoAttack bot allows you to automatically attack mobs around you (precisely within radius of 4 block). The AutoAttack bot allows you to automatically attack mobs around you (precisely within radius of 4 block).
To use this bot, you will need to enable **Entity Handling** in the config file first. To use this bot, you will need to enable **Entity Handling** in the config file first.
**You have been reminded that we will not take any responsible if you got banned by your server while using this bot.**
Using the Auto Fishing Using the Auto Fishing
------ ------
@ -249,19 +248,21 @@ Steps for using this bot:
1. Hold a fishing rod and aim towards the sea before login with MCC 1. Hold a fishing rod and aim towards the sea before login with MCC
2. Make sure AutoFish is enabled in config file 2. Make sure AutoFish is enabled in config file
3. Login with MCC 3. Login with MCC
4. Do /useitem and you should see "threw a fishing rod" 4. Do `/useitem` and you should see "threw a fishing rod"
5. To stop fishing, do /useitem again 5. To stop fishing, do `/useitem` again
Disclaimer Disclaimer
------ ------
Even if everything should work, I am not responsible of any damage this app could cause to your computer or your server. Even if everything should work, We are not responsible for any damage this app could cause to your computer or your server.
This app does not steal your password. If you don't trust it, don't use it or check & compile from the source code. This app does not steal your password. If you don't trust it, don't use it or check & compile from the source code.
Also, remember that when you connect to a server with this program, you will appear where you left the last time. Also, remember that when you connect to a server with this program, you will appear where you left the last time.
This means that you can die if you log in in an unsafe place on a survival server! This means that **you can die if you log in in an unsafe place on a survival server!**
Use the script scheduler bot to send a teleport command after logging in. Use the script scheduler bot to send a teleport command after logging in.
You have been reminded that **you may get banned** by your server for using this program. Use accordinly with server rules.
License License
------ ------
@ -294,8 +295,8 @@ would not have been possible without the help of talented contributors:
**Code contributions:** **Code contributions:**
Allyoutoo, Aragas, Bancey, bearbear12345, corbanmailloux, dbear20, dogwatch, initsuj, Allyoutoo, Aragas, Bancey, bearbear12345, corbanmailloux, dbear20, dogwatch, initsuj,
JamieSinn, justcool393, lokulin, maxpowa, medxo, Pokechu22, repository, TheMeq, TheSnoozer, JamieSinn, justcool393, lokulin, maxpowa, medxo, milutinke, Pokechu22, ReinforceZwei,
vkorn, v1RuX, ZizzyDizzyMC, milutinke repository, TheMeq, TheSnoozer, vkorn, v1RuX, yunusemregul, ZizzyDizzyMC
**Libraries:** **Libraries:**
@ -324,5 +325,5 @@ Like Minecraft Console Client? You can buy me a coffee here:
Code contributions, bug reports and any kind of comments are also highly appreciated :) Code contributions, bug reports and any kind of comments are also highly appreciated :)
+-----------------------------------+ +-----------------------------------+
| © 2012-2019 ORelio & Contributors | | © 2012-2020 ORelio & Contributors |
+-----------------------------------+ +-----------------------------------+

View file

@ -10,6 +10,11 @@
# Regex matches are also supported eg $1, $2, $3.. in actions # Regex matches are also supported eg $1, $2, $3.. in actions
# Matches can optionally be restricted to bot owners only # Matches can optionally be restricted to bot owners only
# When running a script from an AutoRespond match,
# additional %variables% are available from within your script:
# %match_u% will hold username of the player triggering the match
# %match_1%, %match_2%, %match_3%.. will hold regex matches
# Simple example: Respond to a message containing a keyword # Simple example: Respond to a message containing a keyword
[Match] [Match]