|
|
@@ -5,14 +5,18 @@ using System.Numerics; |
|
|
|
using System.Linq; |
|
|
|
using System.Text; |
|
|
|
using System.Threading.Tasks; |
|
|
|
using System.Security.Policy; |
|
|
|
|
|
|
|
using GamecraftModdingAPI.Commands; |
|
|
|
using GamecraftModdingAPI.Utility; |
|
|
|
using Svelto.ECS; |
|
|
|
using RobocraftX.Common; |
|
|
|
|
|
|
|
using IronPython.Hosting; |
|
|
|
using Microsoft.Scripting.Hosting; |
|
|
|
|
|
|
|
using GamecraftScripting.Environment; |
|
|
|
|
|
|
|
namespace GamecraftScripting.Commands |
|
|
|
{ |
|
|
|
class PythonRunnerCommandEngine : ICustomCommandEngine |
|
|
@@ -23,25 +27,85 @@ namespace GamecraftScripting.Commands |
|
|
|
|
|
|
|
public IEntitiesDB entitiesDB { set; private get; } |
|
|
|
|
|
|
|
private ScriptEngine pythonEngine; |
|
|
|
private ScriptEngine pyEngine; |
|
|
|
|
|
|
|
private ScriptScope gameScope; |
|
|
|
|
|
|
|
public void Dispose() |
|
|
|
{ |
|
|
|
CommandRegistrationHelper.Unregister("RunPythonScript"); |
|
|
|
CommandRegistrationHelper.Unregister("RunPython"); |
|
|
|
} |
|
|
|
|
|
|
|
public void Ready() |
|
|
|
{ |
|
|
|
CommandRegistrationHelper.Register<string>("RunPythonScript", RunPythonScript, "Run a python script stored on your computer"); |
|
|
|
this.pythonEngine = Python.CreateEngine(); |
|
|
|
this.gameScope = pythonEngine.CreateScope(); |
|
|
|
CommandRegistrationHelper.Register<string>("RunPython", RunPythonString, "Run a python argument"); |
|
|
|
// create insecure Python namespace |
|
|
|
CreateFreeInstance(); |
|
|
|
// make "import GamecraftModdingAPI" work without the clr boilerplate |
|
|
|
pyEngine.Execute("import clr\nclr.AddReference(\"GamecraftModdingAPI\")", gameScope); |
|
|
|
ICollection<string> searchPaths = pyEngine.GetSearchPaths(); |
|
|
|
searchPaths.Add(@".\Lib\"); |
|
|
|
searchPaths.Add(@".\Gamecraft_Data\Managed\Lib\"); |
|
|
|
pyEngine.SetSearchPaths(searchPaths); |
|
|
|
Logging.MetaLog(string.Join(", ", pyEngine.GetSearchPaths().ToArray())); |
|
|
|
} |
|
|
|
|
|
|
|
private void RunPythonScript(string scriptPath) |
|
|
|
{ |
|
|
|
pythonEngine.ExecuteFile(scriptPath, gameScope); |
|
|
|
string script = File.ReadAllText(scriptPath); |
|
|
|
ExecuteScript(script); |
|
|
|
} |
|
|
|
|
|
|
|
private void RunPythonString(string expression) |
|
|
|
{ |
|
|
|
ExecuteScript(expression); |
|
|
|
} |
|
|
|
|
|
|
|
private void ExecuteScript(string script, bool logError=true) |
|
|
|
{ |
|
|
|
ScriptSource src = pyEngine.CreateScriptSourceFromString(script); |
|
|
|
try |
|
|
|
{ |
|
|
|
src.Execute(gameScope); |
|
|
|
} |
|
|
|
catch (Exception e) |
|
|
|
{ |
|
|
|
if (logError) |
|
|
|
{ |
|
|
|
Logging.CommandLogError($"Python error: {e.Message}"); |
|
|
|
} |
|
|
|
else |
|
|
|
{ |
|
|
|
throw e; |
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/// <summary> |
|
|
|
/// [Experimental] Create a Python instance without access to any(?) assemblies |
|
|
|
/// </summary> |
|
|
|
private void CreateSandboxedInstance() |
|
|
|
{ |
|
|
|
Evidence evidence = new Evidence(); // an uninformative class name to limit accessible Assemblies |
|
|
|
AppDomain domain = AppDomain.CreateDomain(GameMode.SaveGameDetails.Name, evidence); |
|
|
|
this.pyEngine = Python.CreateEngine(domain); |
|
|
|
PythonLogStream pyLog = new PythonLogStream(); |
|
|
|
pyEngine.Runtime.IO.SetOutput(pyLog, pyLog.Encoding); |
|
|
|
this.gameScope = pyEngine.CreateScope(); |
|
|
|
} |
|
|
|
|
|
|
|
/// <summary> |
|
|
|
/// Create an unsecured Python instance |
|
|
|
/// </summary> |
|
|
|
private void CreateFreeInstance() |
|
|
|
{ |
|
|
|
this.pyEngine = Python.CreateEngine(); |
|
|
|
PythonLogStream pyLog = new PythonLogStream(); |
|
|
|
pyEngine.Runtime.IO.SetOutput(pyLog, pyLog.Encoding); |
|
|
|
this.gameScope = pyEngine.CreateScope(); |
|
|
|
} |
|
|
|
|
|
|
|
public PythonRunnerCommandEngine() |
|
|
|