Fix standard lib pathes

This commit is contained in:
NGnius (Graham) 2019-12-25 16:17:19 -05:00
parent baa26769b7
commit b75f383df1
3 changed files with 159 additions and 8 deletions

View file

@ -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()}");
} }
} }
} }

View file

@ -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()

View 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);
}
}
}
}