mirror of
https://github.com/MCCTeam/Minecraft-Console-Client
synced 2025-10-14 21:22:49 +00:00
Various C# Script improvements
Move handling code in a separate file Add caching ability for low-power devices (rpi..) Use a distinct API with MCC.MethodName() Stop script execution only on specific API calls
This commit is contained in:
parent
ca02c7f2e6
commit
3e2622fbb7
8 changed files with 407 additions and 159 deletions
372
MinecraftClient/CSharpRunner.cs
Normal file
372
MinecraftClient/CSharpRunner.cs
Normal file
|
|
@ -0,0 +1,372 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.IO;
|
||||
using Microsoft.CSharp;
|
||||
using System.CodeDom.Compiler;
|
||||
using System.Reflection;
|
||||
using System.Threading;
|
||||
|
||||
namespace MinecraftClient
|
||||
{
|
||||
/// <summary>
|
||||
/// C# Script runner - Compile on-the-fly and run C# scripts
|
||||
/// </summary>
|
||||
class CSharpRunner
|
||||
{
|
||||
private static readonly Dictionary<ulong, Assembly> CompileCache = new Dictionary<ulong, Assembly>();
|
||||
|
||||
/// <summary>
|
||||
/// Run the specified C# script file
|
||||
/// </summary>
|
||||
/// <param name="apiHandler">ChatBot handler for accessing ChatBot API</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="args">Arguments to pass to the script</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>
|
||||
/// <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)
|
||||
{
|
||||
//Script compatibility check for handling future versions differently
|
||||
if (lines.Length < 1 || lines[0] != "//MCCScript 1.0")
|
||||
throw new CSharpException(CSErrorType.InvalidScript,
|
||||
new InvalidDataException("The provided script does not have a valid MCCScript header"));
|
||||
|
||||
//Script hash for determining if it was previously compiled
|
||||
ulong scriptHash = QuickHash(lines);
|
||||
Assembly assembly = null;
|
||||
|
||||
//No need to compile two scripts at the same time
|
||||
lock (CompileCache)
|
||||
{
|
||||
///Process and compile script only if not already compiled
|
||||
if (!Settings.CacheScripts || !CompileCache.ContainsKey(scriptHash))
|
||||
{
|
||||
//Process different sections of the script file
|
||||
bool scriptMain = true;
|
||||
List<string> script = new List<string>();
|
||||
List<string> extensions = new List<string>();
|
||||
foreach (string line in lines)
|
||||
{
|
||||
if (line.StartsWith("//MCCScript"))
|
||||
{
|
||||
if (line.EndsWith("Extensions"))
|
||||
scriptMain = false;
|
||||
}
|
||||
else if (scriptMain)
|
||||
script.Add(line);
|
||||
else extensions.Add(line);
|
||||
}
|
||||
|
||||
//Add return statement if missing
|
||||
if (script.All(line => !line.StartsWith("return ") && !line.Contains(" return ")))
|
||||
script.Add("return null;");
|
||||
|
||||
//Generate a class from the given script
|
||||
string code = String.Join("\n", new string[]
|
||||
{
|
||||
"using System;",
|
||||
"using System.Collections.Generic;",
|
||||
"using System.Linq;",
|
||||
"using System.Text;",
|
||||
"using System.IO;",
|
||||
"using System.Threading;",
|
||||
"using MinecraftClient;",
|
||||
"namespace ScriptLoader {",
|
||||
"public class Script {",
|
||||
"public CSharpAPI MCC;",
|
||||
"public object __run(CSharpAPI __apiHandler, string[] args) {",
|
||||
"this.MCC = __apiHandler;",
|
||||
String.Join("\n", script),
|
||||
"}",
|
||||
String.Join("\n", extensions),
|
||||
"}}",
|
||||
});
|
||||
|
||||
//Compile the C# class in memory using all the currently loaded assemblies
|
||||
CSharpCodeProvider compiler = new CSharpCodeProvider();
|
||||
CompilerParameters parameters = new CompilerParameters();
|
||||
parameters.ReferencedAssemblies
|
||||
.AddRange(AppDomain.CurrentDomain
|
||||
.GetAssemblies()
|
||||
.Where(a => !a.IsDynamic)
|
||||
.Select(a => a.Location).ToArray());
|
||||
parameters.CompilerOptions = "/t:library";
|
||||
parameters.GenerateInMemory = true;
|
||||
CompilerResults result = compiler.CompileAssemblyFromSource(parameters, code);
|
||||
|
||||
//Process compile warnings and errors
|
||||
if (result.Errors.Count > 0)
|
||||
throw new CSharpException(CSErrorType.LoadError,
|
||||
new InvalidOperationException(result.Errors[0].ErrorText));
|
||||
|
||||
//Retrieve compiled assembly
|
||||
assembly = result.CompiledAssembly;
|
||||
if (Settings.CacheScripts)
|
||||
CompileCache[scriptHash] = result.CompiledAssembly;
|
||||
}
|
||||
else if (Settings.CacheScripts)
|
||||
assembly = CompileCache[scriptHash];
|
||||
}
|
||||
|
||||
//Run the compiled assembly with exception handling
|
||||
if (run)
|
||||
{
|
||||
try
|
||||
{
|
||||
object compiledScript
|
||||
= CompileCache[scriptHash].CreateInstance("ScriptLoader.Script");
|
||||
return
|
||||
compiledScript
|
||||
.GetType()
|
||||
.GetMethod("__run")
|
||||
.Invoke(compiledScript,
|
||||
new object[] { new CSharpAPI(apiHandler, tickHandler), args });
|
||||
}
|
||||
catch (Exception e) { throw new CSharpException(CSErrorType.RuntimeError, e); }
|
||||
}
|
||||
else return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Quickly calculate a hash for the given script
|
||||
/// </summary>
|
||||
/// <param name="lines">script lines</param>
|
||||
/// <returns>Quick hash as unsigned long</returns>
|
||||
private static ulong QuickHash(string[] lines)
|
||||
{
|
||||
ulong hashedValue = 3074457345618258791ul;
|
||||
for (int i = 0; i < lines.Length; i++)
|
||||
{
|
||||
for (int j = 0; j < lines[i].Length; j++)
|
||||
{
|
||||
hashedValue += lines[i][j];
|
||||
hashedValue *= 3074457345618258799ul;
|
||||
}
|
||||
hashedValue += '\n';
|
||||
hashedValue *= 3074457345618258799ul;
|
||||
}
|
||||
return hashedValue;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Describe a C# script error type
|
||||
/// </summary>
|
||||
public enum CSErrorType { FileReadError, InvalidScript, LoadError, RuntimeError };
|
||||
|
||||
/// <summary>
|
||||
/// Describe a C# script error with associated error type
|
||||
/// </summary>
|
||||
public class CSharpException : Exception
|
||||
{
|
||||
private CSErrorType _type;
|
||||
public CSErrorType ExceptionType { get { return _type; } }
|
||||
public override string Message { get { return InnerException.Message; } }
|
||||
public override string ToString() { return InnerException.ToString(); }
|
||||
public CSharpException(CSErrorType type, Exception inner)
|
||||
: base(inner != null ? inner.Message : "", inner)
|
||||
{
|
||||
_type = type;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents the C# API object accessible from C# Scripts
|
||||
/// </summary>
|
||||
public class CSharpAPI : ChatBot
|
||||
{
|
||||
/// <summary>
|
||||
/// Thread blocking utility for stopping execution when making a ChatBot API call
|
||||
/// </summary>
|
||||
private ManualResetEvent tickHandler;
|
||||
|
||||
/// <summary>
|
||||
/// Create a new C# API Wrapper
|
||||
/// </summary>
|
||||
/// <param name="apiHandler">ChatBot API Handler</param>
|
||||
/// <param name="tickHandler">ChatBot tick handler</param>
|
||||
public CSharpAPI(ChatBot apiHandler, ManualResetEvent tickHandler)
|
||||
{
|
||||
SetMaster(apiHandler);
|
||||
this.tickHandler = tickHandler;
|
||||
}
|
||||
|
||||
/* == Wrappers for ChatBot API with public visibility and call limit to one per tick for safety == */
|
||||
|
||||
/// <summary>
|
||||
/// Write some text in the console. Nothing will be sent to the server.
|
||||
/// </summary>
|
||||
/// <param name="text">Log text to write</param>
|
||||
new public void LogToConsole(object text)
|
||||
{
|
||||
base.LogToConsole(text);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Send text to the server. Can be anything such as chat messages or commands
|
||||
/// </summary>
|
||||
/// <param name="text">Text to send to the server</param>
|
||||
/// <returns>True if the text was sent with no error</returns>
|
||||
new public bool SendText(object text)
|
||||
{
|
||||
bool result = base.SendText(text is string ? (string)text : text.ToString());
|
||||
tickHandler.WaitOne();
|
||||
Thread.Sleep(1000);
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Perform an internal MCC command (not a server command, use SendText() instead for that!)
|
||||
/// </summary>
|
||||
/// <param name="command">The command to process</param>
|
||||
/// <returns>TRUE if the command was indeed an internal MCC command</returns>
|
||||
new public bool PerformInternalCommand(string command)
|
||||
{
|
||||
bool result = base.PerformInternalCommand(command);
|
||||
tickHandler.WaitOne();
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Disconnect from the server and restart the program
|
||||
/// It will unload and reload all the bots and then reconnect to the server
|
||||
/// </summary>
|
||||
/// <param name="extraAttempts">If connection fails, the client will make X extra attempts</param>
|
||||
new public void ReconnectToTheServer(int extraAttempts = -999999)
|
||||
{
|
||||
if (extraAttempts == -999999)
|
||||
base.ReconnectToTheServer();
|
||||
else base.ReconnectToTheServer(extraAttempts);
|
||||
tickHandler.WaitOne();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Disconnect from the server and exit the program
|
||||
/// </summary>
|
||||
new public void DisconnectAndExit()
|
||||
{
|
||||
base.DisconnectAndExit();
|
||||
tickHandler.WaitOne();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Load the provided ChatBot object
|
||||
/// </summary>
|
||||
/// <param name="bot">Bot to load</param>
|
||||
new public void LoadBot(ChatBot bot)
|
||||
{
|
||||
base.LoadBot(bot);
|
||||
tickHandler.WaitOne();
|
||||
}
|
||||
|
||||
/* == Additional Methods useful for Script API == */
|
||||
|
||||
/// <summary>
|
||||
/// Get a global variable by name
|
||||
/// </summary>
|
||||
/// <param name="varName">Name of the variable</param>
|
||||
/// <returns>Value of the variable or null if no variable</returns>
|
||||
public object GetVar(string varName)
|
||||
{
|
||||
return Settings.GetVar(varName);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get a global variable by name, as a string
|
||||
/// </summary>
|
||||
/// <param name="varName">Name of the variable</param>
|
||||
/// <returns>Value of the variable as string, or null if no variable</returns>
|
||||
public string GetVarAsString(string varName)
|
||||
{
|
||||
object val = GetVar(varName);
|
||||
if (val != null)
|
||||
return val.ToString();
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get a global variable by name, as an integer
|
||||
/// </summary>
|
||||
/// <param name="varName">Name of the variable</param>
|
||||
/// <returns>Value of the variable as int, or 0 if no variable or not a number</returns>
|
||||
public int GetVarAsInt(string varName)
|
||||
{
|
||||
if (GetVar(varName) is int)
|
||||
return (int)GetVar(varName);
|
||||
int result;
|
||||
if (int.TryParse(GetVarAsString(varName), out result))
|
||||
return result;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get a global variable by name, as a boolean
|
||||
/// </summary>
|
||||
/// <param name="varName">Name of the variable</param>
|
||||
/// <returns>Value of the variable as bool, or false if no variable or not a boolean</returns>
|
||||
public bool GetVarAsBool(string varName)
|
||||
{
|
||||
if (GetVar(varName) is bool)
|
||||
return (bool)GetVar(varName);
|
||||
bool result;
|
||||
if (bool.TryParse(GetVarAsString(varName), out result))
|
||||
return result;
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set a global variable for further use in any other script
|
||||
/// </summary>
|
||||
/// <param name="varName">Name of the variable</param>
|
||||
/// <param name="varValue">Value of the variable</param>
|
||||
public bool SetVar(string varName, object varValue)
|
||||
{
|
||||
return Settings.SetVar(varName, varValue);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Load login/password using an account alias and optionally reconnect to the server
|
||||
/// </summary>
|
||||
/// <param name="accountAlias">Account alias</param>
|
||||
/// <param name="andReconnect">Set to true to reconnecto to the server afterwards</param>
|
||||
/// <returns>True if the account was found and loaded</returns>
|
||||
public bool SetAccount(string accountAlias, bool andReconnect = false)
|
||||
{
|
||||
bool result = Settings.SetAccount(accountAlias);
|
||||
if (result && andReconnect)
|
||||
ReconnectToTheServer();
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Load new server information and optionally reconnect to the server
|
||||
/// </summary>
|
||||
/// <param name="server">"serverip:port" couple or server alias</param>
|
||||
/// <returns>True if the server IP was valid and loaded, false otherwise</returns>
|
||||
public bool SetServer(string server, bool andReconnect = false)
|
||||
{
|
||||
bool result = Settings.SetServerIP(server);
|
||||
if (result && andReconnect)
|
||||
ReconnectToTheServer();
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Synchronously call another script and retrieve the result
|
||||
/// </summary>
|
||||
/// <param name="script">Script to call</param>
|
||||
/// <param name="args">Arguments to pass to the script</param>
|
||||
/// <returns>An object returned by the script, or null</returns>
|
||||
public object CallScript(string script, string[] args)
|
||||
{
|
||||
string[] lines = null;
|
||||
ChatBots.Script.LookForScript(ref script);
|
||||
try { lines = File.ReadAllLines(script); }
|
||||
catch (Exception e) { throw new CSharpException(CSErrorType.FileReadError, e); }
|
||||
return CSharpRunner.Run(this, tickHandler, lines, args);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -85,12 +85,10 @@ namespace MinecraftClient
|
|||
/// <param name="text">Text to send to the server</param>
|
||||
/// <returns>True if the text was sent with no error</returns>
|
||||
|
||||
protected bool SendText(object text)
|
||||
protected bool SendText(string text)
|
||||
{
|
||||
LogToConsole("Sending '" + text + "'");
|
||||
bool result = Handler.SendText(text is string ? (string)text : text.ToString());
|
||||
Thread.Sleep(1000);
|
||||
return result;
|
||||
return Handler.SendText(text);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -348,7 +346,7 @@ namespace MinecraftClient
|
|||
/// </summary>
|
||||
/// <param name="text">Log text to write</param>
|
||||
|
||||
public void LogToConsole(object text)
|
||||
protected void LogToConsole(object text)
|
||||
{
|
||||
ConsoleIO.WriteLogLine(String.Format("[{0}] {1}", this.GetType().Name, text));
|
||||
string logfile = Settings.ExpandVars(Settings.chatbotLogFile);
|
||||
|
|
@ -458,59 +456,5 @@ namespace MinecraftClient
|
|||
return new string[0];
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set a custom %variable% which will be available through expandVars()
|
||||
/// </summary>
|
||||
/// <param name="varName">Name of the variable</param>
|
||||
/// <param name="varData">Value of the variable</param>
|
||||
/// <returns>True if the parameters were valid</returns>
|
||||
|
||||
protected static bool SetVar(string varName, object varData)
|
||||
{
|
||||
return Settings.SetVar(varName, varData.ToString());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get a custom %variable% or null if the variable does not exist
|
||||
/// </summary>
|
||||
/// <param name="varName">Variable name</param>
|
||||
/// <returns>The value or null if the variable does not exists</returns>
|
||||
|
||||
protected static string GetVar(string varName)
|
||||
{
|
||||
return Settings.GetVar(varName);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get a custom %variable% as an Integer or null if the variable does not exist
|
||||
/// </summary>
|
||||
/// <param name="varName">Variable name</param>
|
||||
/// <returns>The value or null if the variable does not exists</returns>
|
||||
|
||||
protected static int GetVarAsInt(string varName)
|
||||
{
|
||||
return Settings.str2int(Settings.GetVar(varName));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Load login/password using an account alias
|
||||
/// </summary>
|
||||
/// <returns>True if the account was found and loaded</returns>
|
||||
|
||||
protected static bool SetAccount(string accountAlias)
|
||||
{
|
||||
return Settings.SetAccount(accountAlias);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Load server information in ServerIP and ServerPort variables from a "serverip:port" couple or server alias
|
||||
/// </summary>
|
||||
/// <returns>True if the server IP was valid and loaded, false otherwise</returns>
|
||||
|
||||
protected static bool SetServerIP(string server)
|
||||
{
|
||||
return Settings.SetServerIP(server);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ using System.Text;
|
|||
using System.Threading;
|
||||
using Microsoft.CSharp;
|
||||
using System.CodeDom.Compiler;
|
||||
using System.Reflection;
|
||||
|
||||
namespace MinecraftClient.ChatBots
|
||||
{
|
||||
|
|
@ -143,8 +144,18 @@ namespace MinecraftClient.ChatBots
|
|||
tpause = new ManualResetEvent(false);
|
||||
thread = new Thread(() =>
|
||||
{
|
||||
if (!RunCSharpScript() && owner != null)
|
||||
SendPrivateMessage(owner, "Script '" + file + "' failed to run.");
|
||||
try
|
||||
{
|
||||
CSharpRunner.Run(this, tpause, lines, args);
|
||||
}
|
||||
catch (CSharpException e)
|
||||
{
|
||||
string errorMessage = "Script '" + file + "' failed to run (" + e.ExceptionType + ").";
|
||||
LogToConsole(errorMessage);
|
||||
if (owner != null)
|
||||
SendPrivateMessage(owner, errorMessage);
|
||||
LogToConsole(e.InnerException);
|
||||
}
|
||||
});
|
||||
thread.Start();
|
||||
}
|
||||
|
|
@ -154,7 +165,7 @@ namespace MinecraftClient.ChatBots
|
|||
{
|
||||
tpause.Set();
|
||||
tpause.Reset();
|
||||
if (thread.Join(100))
|
||||
if (!thread.IsAlive)
|
||||
UnloadBot();
|
||||
}
|
||||
}
|
||||
|
|
@ -205,84 +216,5 @@ namespace MinecraftClient.ChatBots
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
private bool RunCSharpScript()
|
||||
{
|
||||
//Script compatibility check for handling future versions differently
|
||||
if (lines.Length < 1 || lines[0] != "//MCCScript 1.0")
|
||||
{
|
||||
LogToConsole("Script file '" + file + "' does not start with a valid //MCCScript identifier.");
|
||||
return false;
|
||||
}
|
||||
|
||||
//Process different sections of the script file
|
||||
bool scriptMain = true;
|
||||
List<string> script = new List<string>();
|
||||
List<string> extensions = new List<string>();
|
||||
foreach (string line in lines)
|
||||
{
|
||||
if (line.StartsWith("//MCCScript"))
|
||||
{
|
||||
if (line.EndsWith("Extensions"))
|
||||
scriptMain = false;
|
||||
}
|
||||
else if (scriptMain)
|
||||
{
|
||||
script.Add(line);
|
||||
//Add breakpoints for step-by-step execution of the script
|
||||
if (tpause != null && line.Trim().EndsWith(";"))
|
||||
script.Add("tpause.WaitOne();");
|
||||
}
|
||||
else extensions.Add(line);
|
||||
}
|
||||
|
||||
//Generate a ChatBot class, allowing access to the ChatBot API
|
||||
string code = String.Join("\n", new string[]
|
||||
{
|
||||
"using System;",
|
||||
"using System.IO;",
|
||||
"using System.Threading;",
|
||||
"using MinecraftClient;",
|
||||
"namespace ScriptLoader {",
|
||||
"public class Script : ChatBot {",
|
||||
"public void __run(ChatBot master, ManualResetEvent tpause, string[] args) {",
|
||||
"SetMaster(master);",
|
||||
String.Join("\n", script),
|
||||
"}",
|
||||
String.Join("\n", extensions),
|
||||
"}}",
|
||||
});
|
||||
|
||||
//Compile the C# class in memory using all the currently loaded assemblies
|
||||
CSharpCodeProvider compiler = new CSharpCodeProvider();
|
||||
CompilerParameters parameters = new CompilerParameters();
|
||||
parameters.ReferencedAssemblies
|
||||
.AddRange(AppDomain.CurrentDomain
|
||||
.GetAssemblies()
|
||||
.Where(a => !a.IsDynamic)
|
||||
.Select(a => a.Location).ToArray());
|
||||
parameters.CompilerOptions = "/t:library";
|
||||
parameters.GenerateInMemory = true;
|
||||
CompilerResults result
|
||||
= compiler.CompileAssemblyFromSource(parameters, code);
|
||||
|
||||
//Process compile warnings and errors
|
||||
if (result.Errors.Count > 0)
|
||||
{
|
||||
LogToConsole("Error loading '" + file + "':\n" + result.Errors[0].ErrorText);
|
||||
return false;
|
||||
}
|
||||
|
||||
//Run the compiled script with exception handling
|
||||
object compiledScript = result.CompiledAssembly.CreateInstance("ScriptLoader.Script");
|
||||
try { compiledScript.GetType().GetMethod("__run").Invoke(compiledScript, new object[] { this, tpause, args }); }
|
||||
catch (Exception e)
|
||||
{
|
||||
LogToConsole("Runtime error for '" + file + "':\n" + e);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -113,6 +113,7 @@
|
|||
<Compile Include="Crypto\Streams\MonoAesStream.cs" />
|
||||
<Compile Include="Crypto\Streams\RegularAesStream.cs" />
|
||||
<Compile Include="Crypto\CryptoHandler.cs" />
|
||||
<Compile Include="CSharpRunner.cs" />
|
||||
<Compile Include="Protocol\Handlers\Compression\CRC32.cs" />
|
||||
<Compile Include="Protocol\Handlers\Compression\Deflate.cs" />
|
||||
<Compile Include="Protocol\Handlers\Compression\GZipStream.cs" />
|
||||
|
|
|
|||
|
|
@ -45,6 +45,7 @@ namespace MinecraftClient
|
|||
public static char internalCmdChar = '/';
|
||||
public static bool playerHeadAsIcon = false;
|
||||
public static string chatbotLogFile = "";
|
||||
public static bool CacheScripts = true;
|
||||
|
||||
//AntiAFK Settings
|
||||
public static bool AntiAFK_Enabled = false;
|
||||
|
|
@ -94,7 +95,7 @@ namespace MinecraftClient
|
|||
public static string AutoRespond_Matches = "matches.ini";
|
||||
|
||||
//Custom app variables and Minecraft accounts
|
||||
private static readonly Dictionary<string, string> AppVars = new Dictionary<string, string>();
|
||||
private static readonly Dictionary<string, object> AppVars = new Dictionary<string, object>();
|
||||
private static readonly Dictionary<string, KeyValuePair<string, string>> Accounts = new Dictionary<string, KeyValuePair<string, string>>();
|
||||
private static readonly Dictionary<string, KeyValuePair<string, ushort>> Servers = new Dictionary<string, KeyValuePair<string, ushort>>();
|
||||
|
||||
|
|
@ -159,6 +160,7 @@ namespace MinecraftClient
|
|||
case "chatbotlogfile": chatbotLogFile = argValue; break;
|
||||
case "mcversion": ServerVersion = argValue; break;
|
||||
case "splitmessagedelay": splitMessageDelay = TimeSpan.FromSeconds(str2int(argValue)); break;
|
||||
case "scriptcache": CacheScripts = str2bool(argValue); break;
|
||||
|
||||
case "botowners":
|
||||
Bots_Owners.Clear();
|
||||
|
|
@ -366,6 +368,7 @@ namespace MinecraftClient
|
|||
+ "serverlist=servers.txt\r\n"
|
||||
+ "playerheadicon=true\r\n"
|
||||
+ "exitonfailure=false\r\n"
|
||||
+ "scriptcache=true\r\n"
|
||||
+ "timestamps=false\r\n"
|
||||
+ "\r\n"
|
||||
+ "[AppVars]\r\n"
|
||||
|
|
@ -491,7 +494,7 @@ namespace MinecraftClient
|
|||
/// <param name="varData">Value of the variable</param>
|
||||
/// <returns>True if the parameters were valid</returns>
|
||||
|
||||
public static bool SetVar(string varName, string varData)
|
||||
public static bool SetVar(string varName, object varData)
|
||||
{
|
||||
lock (AppVars)
|
||||
{
|
||||
|
|
@ -511,7 +514,7 @@ namespace MinecraftClient
|
|||
/// <param name="varName">Variable name</param>
|
||||
/// <returns>The value or null if the variable does not exists</returns>
|
||||
|
||||
public static string GetVar(string varName)
|
||||
public static object GetVar(string varName)
|
||||
{
|
||||
if (AppVars.ContainsKey(varName))
|
||||
return AppVars[varName];
|
||||
|
|
@ -559,7 +562,7 @@ namespace MinecraftClient
|
|||
default:
|
||||
if (AppVars.ContainsKey(varname_lower))
|
||||
{
|
||||
result.Append(AppVars[varname_lower]);
|
||||
result.Append(AppVars[varname_lower].ToString());
|
||||
}
|
||||
else result.Append("%" + varname + '%');
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -9,8 +9,8 @@ if (args.Length > 0)
|
|||
|
||||
for (int i = 0; i < 5; i++)
|
||||
{
|
||||
int count = GetVarAsInt("test") + 1;
|
||||
SetVar("test", count);
|
||||
int count = MCC.GetVarAsInt("test") + 1;
|
||||
MCC.SetVar("test", count);
|
||||
SendHelloWorld(count, text);
|
||||
SleepBetweenSends();
|
||||
}
|
||||
|
|
@ -21,15 +21,11 @@ for (int i = 0; i < 5; i++)
|
|||
|
||||
void SendHelloWorld(int count, string text)
|
||||
{
|
||||
/* Warning: Do not make more than one server-related call into a method
|
||||
* defined as a script extension eg SendText or switching servers,
|
||||
* as execution flow is not managed in the Extensions section */
|
||||
|
||||
SendText("Hello World no. " + count + ": " + text);
|
||||
MCC.SendText("Hello World no. " + count + ": " + text);
|
||||
}
|
||||
|
||||
void SleepBetweenSends()
|
||||
{
|
||||
LogToConsole("Sleeping for 5 seconds...");
|
||||
MCC.LogToConsole("Sleeping for 5 seconds...");
|
||||
Thread.Sleep(5000);
|
||||
}
|
||||
|
|
@ -3,7 +3,7 @@
|
|||
/* This is a sample script that will load a ChatBot into Minecraft Console Client
|
||||
* Simply execute the script once with /script or the script scheduler to load the bot */
|
||||
|
||||
LoadBot(new ExampleBot());
|
||||
MCC.LoadBot(new ExampleBot());
|
||||
|
||||
//MCCScript Extensions
|
||||
|
||||
|
|
|
|||
|
|
@ -2,13 +2,13 @@
|
|||
|
||||
/* This is a sample script for Minecraft Console Client
|
||||
* The code provided in this file will be compiled at runtime and executed
|
||||
* Allowed instructions: Any C# code AND all methods provided by the bot API */
|
||||
* Allowed instructions: Any C# code AND methods provided by the MCC API */
|
||||
|
||||
for (int i = 0; i < 5; i++)
|
||||
{
|
||||
int count = GetVarAsInt("test") + 1;
|
||||
SetVar("test", count);
|
||||
SendText("Hello World no. " + count);
|
||||
LogToConsole("Sleeping for 5 seconds...");
|
||||
int count = MCC.GetVarAsInt("test") + 1;
|
||||
MCC.SetVar("test", count);
|
||||
MCC.SendText("Hello World no. " + count);
|
||||
MCC.LogToConsole("Sleeping for 5 seconds...");
|
||||
Thread.Sleep(5000);
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue