Skip to content
Closed

Indev #105

Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
112 commits
Select commit Hold shift + click to select a range
734d267
Merge pull request #70 from ORelio/master
ORelio Mar 11, 2015
e3c38ed
Update version info for 1.8.2 release
ORelio Mar 11, 2015
858ad12
Fix concurrency crashes for player list
ORelio Mar 19, 2015
c30d302
Use BouncyCastle for handling AES on Mono Framework
ORelio Mar 19, 2015
aaced85
Catch exceptions for bots for onTextReceived
ORelio Mar 23, 2015
82c95be
Fix console background color
ORelio Mar 25, 2015
7757d5a
Upgrade login/session timeout to 30 seconds
ORelio Mar 25, 2015
05a141c
Improve offline interactions
ORelio Mar 25, 2015
2c31efd
Add server IP in default window title
ORelio Mar 28, 2015
ea17ec8
Better exception catching
ORelio Apr 6, 2015
2cf46c0
Fix crash when resizing terminal
ORelio Apr 11, 2015
791ecba
Add timeout for server ping
ORelio Apr 14, 2015
6261e7a
More startup error handling
ORelio Apr 20, 2015
7deec58
Add Build Configuration
ORelio Apr 20, 2015
8b26189
Remove Build Configuration
ORelio Apr 20, 2015
57c66c8
Merge error handlers
ORelio Apr 22, 2015
72498a6
Fix ping failure causing double failure handling
ORelio Apr 22, 2015
3376247
Fix concurrency in ConsoleIO
ORelio May 10, 2015
33b8458
Indentation change for Fix concurrency[..]
ORelio May 10, 2015
834e446
Add 1.8.4 in supported version list
ORelio May 13, 2015
93d58a8
Ignore invalid UUIDs for tab-list
ORelio May 17, 2015
dd5e2f8
Rewrite translation rule processing
ORelio May 17, 2015
5b662e2
Fix HeroChat public messages treated as private
ORelio May 18, 2015
43fa3fb
Auto Respond Bot
bancey May 19, 2015
fa626d4
Merge pull request #75 from Bancey/Indev
ORelio May 19, 2015
f7c7298
Add delay between sends of long messages
ORelio May 26, 2015
b07091e
Merge branch 'Indev' of https://github.com/ORelio/Minecraft-Console-C…
ORelio May 26, 2015
53156bd
Normalize AutoRespond bot
ORelio May 26, 2015
80b468b
Add Mention to Mozroots in Readme file
ORelio Jun 1, 2015
840ac01
Fix crash on empty player list updates
ORelio Jun 3, 2015
0029561
AutoRespond improvements
ORelio Jun 11, 2015
365af03
Remove invalid disconnect packet
ORelio Jun 14, 2015
c957ed0
Remove invalid disconnect packet (2)
ORelio Jun 16, 2015
a7f0897
Add 1.8.5 - 1.8.7 as supported versions
ORelio Jun 19, 2015
67affc6
Fix 1.7+ server list ping by properly parsing Json
ORelio Jun 19, 2015
3224c59
Remove padding mechanism
ORelio Jun 19, 2015
3ce9118
Add support for C# scripts in scripting bot
ORelio Jun 20, 2015
a6b3bf0
AutoRespond tests and fixes
ORelio Jun 21, 2015
e29b4ee
Add support for C# script extensions
ORelio Jun 21, 2015
f076e1f
Add argument passing for C# scripts
ORelio Jun 25, 2015
f5a6709
Add comments for server IP parsing
ORelio Jul 5, 2015
a6a9814
MC 1.7: Skip potential extra data in tab-list items
ORelio Jul 7, 2015
546119a
Fix ] password typing on QWERTY keyboards
ORelio Jul 17, 2015
1e801ad
Fix tab autocompletion when no result is found
ORelio Jul 21, 2015
c88d150
Fix Offline BungeeCord 1.5.2 requiring encryption
ORelio Jul 23, 2015
80b4422
Further autocompletion fixes
ORelio Jul 23, 2015
729960d
Add 1.8.8 as supported version
ORelio Jul 30, 2015
3a76024
Move 1.7 handling into 1.8 handler
ORelio Jul 30, 2015
67f17cb
Remove packet debugging code
ORelio Jul 30, 2015
12b9499
Add joshbean39's chat formats
ORelio Jul 31, 2015
de43224
Add 'other' messages support in AutoRespond
ORelio Aug 2, 2015
295dfe7
Fixed issues with passwords containing unicode special characters.
Pokechu22 Aug 17, 2015
ebc4d9f
Merge pull request #90 from Pokechu22/password-unicode-fix
ORelio Aug 17, 2015
86711ad
Fake resource pack acceptance
ORelio Aug 21, 2015
c1d2cbd
Merge branch 'Indev' of https://github.com/ORelio/Minecraft-Console-C…
ORelio Aug 21, 2015
a0683e1
Add '/' as valid separator for detecting 1.8 proxies
ORelio Aug 21, 2015
344749e
Add 'accepted' response pour resource packs
ORelio Aug 21, 2015
9fefcb4
Send MC|Brand information upon joining the game
Pokechu22 Aug 22, 2015
ca02c7f
Merge pull request #92 from Pokechu22/send-brand-info
ORelio Aug 23, 2015
3e2622f
Various C# Script improvements
ORelio Aug 23, 2015
88c9605
Added a new PM regex
invalid-email-address Sep 3, 2015
450cb4c
Revert "Added a new PM regex"
invalid-email-address Sep 3, 2015
35365a4
Revert "Revert "Added a new PM regex""
invalid-email-address Sep 3, 2015
6ed17f5
Removal of .suo
ZizzyDizzyMC Sep 4, 2015
60c95a6
Added /.vs/ to git ignore.
ZizzyDizzyMC Sep 3, 2015
cdec34d
I messed up and put the herochat *back* into a faulty position.
ZizzyDizzyMC Sep 4, 2015
b233b60
Default acceptance of Hero-Chat public messages changed.
ZizzyDizzyMC Sep 4, 2015
1abb46b
Added / Cleaned Enable features of Chat Messages
ZizzyDizzyMC Sep 4, 2015
93aae2d
Commented Auto-Generated MinecraftClient.ini
ZizzyDizzyMC Sep 4, 2015
d9a916b
Merge pull request #93 from ZizzyDizzyMC/Indev
ORelio Sep 4, 2015
385a1f9
Added another setting.
ZizzyDizzyMC Sep 4, 2015
1223c91
Added setting to make sending brand info optional.
ZizzyDizzyMC Sep 4, 2015
fe68e88
Merge pull request #94 from ZizzyDizzyMC/Indev
ORelio Sep 4, 2015
8560753
Extend BrandInfo setting
ORelio Sep 29, 2015
8bd130e
Add setting for hiding system/xpbar messages
ORelio Sep 29, 2015
b25a665
Delay BrandInfo sending
ORelio Sep 30, 2015
4df5cb7
Fix copy and past mistake with XPBar setting
ORelio Sep 30, 2015
8f6b59e
Add help section for AutoRelog
ORelio Oct 11, 2015
b3c9a20
Fix AutoRespond not handling "other" message type
ORelio Oct 12, 2015
0b870e2
Proxy Setting addition.
ZizzyDizzyMC Oct 16, 2015
a65e632
Fixed some things about pull request 99.
ZizzyDizzyMC Oct 16, 2015
a5bf62b
Merge pull request #99 from ZizzyDizzyMC/Indev
ORelio Oct 18, 2015
e8a8ca4
Catch exception while moving cursor in ConsoleIO
ORelio Oct 20, 2015
29975da
Merge onlyforlogin and enabled in proxy settings
ORelio Oct 22, 2015
5038c3d
Add regex settings for parsing chat messages
ORelio Oct 22, 2015
f67a3e3
Attempted to add basic forge support. This does not work, but it's a…
Pokechu22 Oct 22, 2015
7cc87d8
Detect and store the list of forge mods.
Pokechu22 Oct 23, 2015
b154639
Handle forge handshake up to mod list sending.
Pokechu22 Oct 24, 2015
c1c1c10
Relocate forge handshake code into the main packet handler.
Pokechu22 Oct 24, 2015
ad38154
Full forge (1.8) connection support!
Pokechu22 Oct 24, 2015
7c8e856
Fix connection to forge 1.7.10 servers.
Pokechu22 Oct 25, 2015
77277bc
Add SendPluginChannelPacket to the IMinecraftCom interface.
Pokechu22 Oct 25, 2015
b746b56
Only add `\0FML\0` to the IP if forgeinfo is not null (+ whitespace f…
Pokechu22 Oct 25, 2015
fb87de1
Fix compatability with Feed The Beast servers
Pokechu22 Oct 25, 2015
3a19de8
Finish forge hand shaking before enabling the chat prompt.
Pokechu22 Oct 25, 2015
29a9fe8
Merge pull request #100 from Pokechu22/forge-support
ORelio Oct 25, 2015
e536456
Catch IndexOutOfRangeException for IsChatMessage
ORelio Oct 26, 2015
6dd003d
Disable Forge when no mods are installed
ORelio Oct 29, 2015
5654871
First attempt at Realms list retrieval
ORelio Nov 27, 2015
72bd485
Add basic location handling
ORelio Nov 27, 2015
2e4544f
Fix location sendback (Item pickup!)
ORelio Nov 29, 2015
cb00c28
Add world handling (and fall to ground)
ORelio Nov 30, 2015
5d8d42e
Terrain: Fix coordinate parsing (negative coords)
ORelio Dec 7, 2015
49702e3
Add block material database
ORelio Dec 9, 2015
00131de
Fix CanHarmPlayers in Material.cs
ORelio Dec 10, 2015
b0c8f82
Add simple movements with /move command
ORelio Dec 12, 2015
902b046
Fix pathfinding to coordinates
ORelio Dec 13, 2015
7127736
Add timeout when calculating unreachable path
ORelio Dec 17, 2015
d36647a
Add GetWorld() API method for ChatBots
ORelio Jan 16, 2016
6793977
Chat formats : Catch Argument out of range
ORelio Jan 26, 2016
14b8895
Add regex access for C# scripts
ORelio Jan 26, 2016
ba41268
Add setting for setting private msg command
ORelio Jan 26, 2016
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@
/MinecraftClientGUI.v11.suo
/MinecraftClientGUI.suo
/MinecraftClient.userprefs
/.vs/
374 changes: 374 additions & 0 deletions MinecraftClient/CSharpRunner.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,374 @@
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.Text.RegularExpressions;",
"using System.Linq;",
"using System.Text;",
"using System.IO;",
"using System.Threading;",
"using MinecraftClient;",
"using MinecraftClient.Mapping;",
"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>
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);
}
}
}
Loading