Fix standard lib pathes
This commit is contained in:
parent
baa26769b7
commit
b75f383df1
3 changed files with 159 additions and 8 deletions
|
@ -14,15 +14,15 @@ namespace GamecraftScripting.Commands
|
||||||
{
|
{
|
||||||
class DebugCommandEngine : ICustomCommandEngine
|
class DebugCommandEngine : ICustomCommandEngine
|
||||||
{
|
{
|
||||||
public string Description { get; } = "";
|
public string Description { get; } = "Display Python debug info";
|
||||||
|
|
||||||
public string Name { get; } = "";
|
public string Name { get; } = "PythonInfo";
|
||||||
|
|
||||||
public IEntitiesDB entitiesDB { set; private get; }
|
public IEntitiesDB entitiesDB { set; private get; }
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
CommandRegistrationHelper.Unregister("IronPythonInfo");
|
CommandRegistrationHelper.Unregister("PythonInfo");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Ready()
|
public void Ready()
|
||||||
|
@ -32,7 +32,7 @@ namespace GamecraftScripting.Commands
|
||||||
|
|
||||||
private void ironPythonInfo()
|
private void ironPythonInfo()
|
||||||
{
|
{
|
||||||
Logging.CommandLog(typeof(PythonOptions).Assembly.GetName().ToString());
|
Logging.CommandLog($"Assembly {typeof(PythonOptions).Assembly.GetName().ToString()}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,14 +5,18 @@ using System.Numerics;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using System.Security.Policy;
|
||||||
|
|
||||||
using GamecraftModdingAPI.Commands;
|
using GamecraftModdingAPI.Commands;
|
||||||
using GamecraftModdingAPI.Utility;
|
using GamecraftModdingAPI.Utility;
|
||||||
using Svelto.ECS;
|
using Svelto.ECS;
|
||||||
|
using RobocraftX.Common;
|
||||||
|
|
||||||
using IronPython.Hosting;
|
using IronPython.Hosting;
|
||||||
using Microsoft.Scripting.Hosting;
|
using Microsoft.Scripting.Hosting;
|
||||||
|
|
||||||
|
using GamecraftScripting.Environment;
|
||||||
|
|
||||||
namespace GamecraftScripting.Commands
|
namespace GamecraftScripting.Commands
|
||||||
{
|
{
|
||||||
class PythonRunnerCommandEngine : ICustomCommandEngine
|
class PythonRunnerCommandEngine : ICustomCommandEngine
|
||||||
|
@ -23,25 +27,85 @@ namespace GamecraftScripting.Commands
|
||||||
|
|
||||||
public IEntitiesDB entitiesDB { set; private get; }
|
public IEntitiesDB entitiesDB { set; private get; }
|
||||||
|
|
||||||
private ScriptEngine pythonEngine;
|
private ScriptEngine pyEngine;
|
||||||
|
|
||||||
private ScriptScope gameScope;
|
private ScriptScope gameScope;
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
CommandRegistrationHelper.Unregister("RunPythonScript");
|
CommandRegistrationHelper.Unregister("RunPythonScript");
|
||||||
|
CommandRegistrationHelper.Unregister("RunPython");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Ready()
|
public void Ready()
|
||||||
{
|
{
|
||||||
CommandRegistrationHelper.Register<string>("RunPythonScript", RunPythonScript, "Run a python script stored on your computer");
|
CommandRegistrationHelper.Register<string>("RunPythonScript", RunPythonScript, "Run a python script stored on your computer");
|
||||||
this.pythonEngine = Python.CreateEngine();
|
CommandRegistrationHelper.Register<string>("RunPython", RunPythonString, "Run a python argument");
|
||||||
this.gameScope = pythonEngine.CreateScope();
|
// 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)
|
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()
|
public PythonRunnerCommandEngine()
|
||||||
|
|
87
GamecraftScripting/Environment/LogStream.cs
Normal file
87
GamecraftScripting/Environment/LogStream.cs
Normal file
|
@ -0,0 +1,87 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
using GamecraftModdingAPI.Utility;
|
||||||
|
|
||||||
|
namespace GamecraftScripting.Environment
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Writeable Stream for Python's print function
|
||||||
|
/// </summary>
|
||||||
|
class PythonLogStream : Stream
|
||||||
|
{
|
||||||
|
public Encoding Encoding { get; set; } = Encoding.Default;
|
||||||
|
|
||||||
|
public override bool CanRead => false;
|
||||||
|
|
||||||
|
public override bool CanSeek => false;
|
||||||
|
|
||||||
|
public override bool CanWrite => true;
|
||||||
|
|
||||||
|
public override long Length => _length;
|
||||||
|
|
||||||
|
private long _length = 0L;
|
||||||
|
|
||||||
|
private StringBuilder strBuffer = new StringBuilder();
|
||||||
|
|
||||||
|
public override long Position { get => _length-1; set => throw new NotImplementedException(); }
|
||||||
|
|
||||||
|
public override void Flush()
|
||||||
|
{
|
||||||
|
if (strBuffer.Length > 0)
|
||||||
|
{
|
||||||
|
Logging.CommandLog(strBuffer.ToString().Trim());
|
||||||
|
strBuffer.Clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override int Read(byte[] buffer, int offset, int count)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override long Seek(long offset, SeekOrigin origin)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void SetLength(long value)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Write(byte[] buffer, int offset, int count)
|
||||||
|
{
|
||||||
|
byte[] realBuffer = new byte[count + offset];
|
||||||
|
for (int i = 0; i < realBuffer.Length-offset; i++)
|
||||||
|
{
|
||||||
|
realBuffer[i + offset] = buffer[i];
|
||||||
|
}
|
||||||
|
string toWrite = this.Encoding.GetString(realBuffer);
|
||||||
|
for (int i = 0; i < toWrite.Length; i++)
|
||||||
|
{
|
||||||
|
WriteChar(toWrite[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void WriteChar(char c)
|
||||||
|
{
|
||||||
|
if (c == '\n')
|
||||||
|
{
|
||||||
|
Flush();
|
||||||
|
}
|
||||||
|
else if (c == '\r')
|
||||||
|
{
|
||||||
|
// Microsoft motto: Why use 1 when 2 will clearly be more bloated!
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
strBuffer.Append(c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Add table
Reference in a new issue