private void CompileAndCreateInstance(string program, string storage) { if (MySession.Static.EnableIngameScripts == false) { return; } m_wasTerminated = false; Assembly temp = null; MyGuiScreenEditor.CompileProgram(program, m_compilerErrors, ref temp); if (temp != null) { try { m_assembly = IlInjector.InjectCodeToAssembly("IngameScript_safe", temp, typeof(IlInjector).GetMethod("CountInstructions", BindingFlags.Public | BindingFlags.Static), typeof(IlInjector).GetMethod("CountMethodCalls", BindingFlags.Public | BindingFlags.Static)); var type = m_assembly.GetType("Program"); if (type != null) { IlInjector.RestartCountingInstructions(MAX_NUM_EXECUTED_INSTRUCTIONS); IlInjector.RestartCountingMethods(MAX_NUM_METHOD_CALLS); try { m_instance = Activator.CreateInstance(type) as IMyGridProgram; if (m_instance != null) { m_previousRunTimestamp = 0; m_instance.Storage = storage; m_instance.Me = this; m_instance.Echo = EchoTextToDetailInfo; } } catch (TargetInvocationException ex) { if (ex.InnerException != null) { string response = MyTexts.GetString(MySpaceTexts.ProgrammableBlock_Exception_ExceptionCaught) + ex.InnerException.Message; if (DetailedInfo.ToString() != response) { SyncObject.SendProgramResponseMessage(response); WriteProgramResponse(response); } } } } } catch (Exception ex) { string response = MyTexts.GetString(MySpaceTexts.ProgrammableBlock_Exception_ExceptionCaught) + ex.Message; if (DetailedInfo.ToString() != response) { SyncObject.SendProgramResponseMessage(response); WriteProgramResponse(response); } } } }
private void CompileAndCreateInstance(string program, string storage) { if (MySession.Static.EnableIngameScripts == false) { return; } m_wasTerminated = false; m_mainMethod = null; Assembly temp = null; MyGuiScreenEditor.CompileProgram(program, m_compilerErrors, ref temp); if (temp != null) { try { m_assembly = IlInjector.InjectCodeToAssembly("IngameScript_safe", temp, typeof(IlInjector).GetMethod("CountInstructions", BindingFlags.Public | BindingFlags.Static)); var type = m_assembly.GetType("Program"); if (type != null) { IlInjector.RestartCountingInstructions(MAX_NUM_EXECUTED_INSTRUCTIONS); try { m_instance = Activator.CreateInstance(type); m_programGridGroup = type.GetField("GridTerminalSystem", BindingFlags.NonPublic | BindingFlags.GetField | BindingFlags.Instance); m_storageField = type.GetField("Storage", BindingFlags.NonPublic | BindingFlags.GetField | BindingFlags.Instance); m_meField = type.GetField("Me", BindingFlags.NonPublic | BindingFlags.GetField | BindingFlags.Instance); m_echoField = type.GetField("Echo", BindingFlags.NonPublic | BindingFlags.GetField | BindingFlags.Instance); m_elapsedTimeField = type.GetField("ElapsedTime", BindingFlags.NonPublic | BindingFlags.GetField | BindingFlags.Instance); if (m_programGridGroup != null) { // First try to get the main method with a string argument. If this fails, try to get one without. m_mainMethod = type.GetMethod("Main", BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance, null, new[] { typeof(string) }, null); m_mainMethodSupportsArgument = m_mainMethod != null; if (m_mainMethod == null) { m_mainMethod = type.GetMethod("Main", BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance); } } if (m_storageField != null) { m_storageField.SetValue(m_instance, storage); } if (m_meField != null) { m_meField.SetValue(m_instance, this); } if (m_echoField != null) { m_echoField.SetValue(m_instance, new Action <string>(EchoTextToDetailInfo)); } } catch (TargetInvocationException ex) { if (ex.InnerException != null) { string response = MyTexts.GetString(MySpaceTexts.ProgrammableBlock_Exception_ExceptionCaught) + ex.InnerException.Message; if (DetailedInfo.ToString() != response) { SyncObject.SendProgramResponseMessage(response); WriteProgramResponse(response); } } } } } catch (Exception ex) { string response = MyTexts.GetString(MySpaceTexts.ProgrammableBlock_Exception_ExceptionCaught) + ex.Message; if (DetailedInfo.ToString() != response) { SyncObject.SendProgramResponseMessage(response); WriteProgramResponse(response); } } } }
public string ExecuteCode(string argument) { if (m_isRunning) { return(MyTexts.GetString(MySpaceTexts.ProgrammableBlock_Exception_AllreadyRunning)); } if (m_wasTerminated == true) { return(DetailedInfo.ToString()); } DetailedInfo.Clear(); m_echoOutput.Clear(); if (m_assembly == null) { return(MyTexts.GetString(MySpaceTexts.ProgrammableBlock_Exception_NoAssembly)); } if (m_mainMethod == null) { return(MyTexts.GetString(MySpaceTexts.ProgrammableBlock_Exception_NoMain)); } if (this.m_elapsedTimeField != null) { if (m_previousRunTimestamp == 0) { m_previousRunTimestamp = Stopwatch.GetTimestamp(); m_elapsedTimeField.SetValue(m_instance, TimeSpan.Zero); } else { var currentTimestamp = Stopwatch.GetTimestamp(); var elapsedTime = (currentTimestamp - m_previousRunTimestamp) * Sync.RelativeSimulationRatio; m_elapsedTimeField.SetValue(m_instance, TimeSpan.FromSeconds(elapsedTime * STOPWATCH_FREQUENCY)); m_previousRunTimestamp = currentTimestamp; } } if (m_programGridGroup != null) { var gridGroup = MyCubeGridGroups.Static.Logical.GetGroup(CubeGrid); var terminalSystem = gridGroup.GroupData.TerminalSystem; terminalSystem.UpdateGridBlocksOwnership(this.OwnerId); m_programGridGroup.SetValue(m_instance, terminalSystem); } m_isRunning = true; string retVal = ""; IlInjector.RestartCountingInstructions(MAX_NUM_EXECUTED_INSTRUCTIONS); try { if (m_mainMethodSupportsArgument) { // Don't know if it's really necessary to predefine this argument array, I suspect not // due to the cleverness of the compiler, but I do it this way just in case. // Obviously if programmable block execution becomes asynchronous at some point this // must be reworked. m_argumentArray[0] = argument ?? string.Empty; m_mainMethod.Invoke(m_instance, m_argumentArray); } else { m_mainMethod.Invoke(m_instance, null); } if (m_echoOutput.Length > 0) { retVal = m_echoOutput.ToString(); } } catch (TargetInvocationException ex) { // Since we just had an exception I'm not fussed about using old // fashioned string concatenation here. We'll still want the echo // output, since its primary purpose is debugging. if (m_echoOutput.Length > 0) { retVal = m_echoOutput.ToString(); } OnProgramTermination(); if (ex.InnerException is ScriptOutOfRangeException) { retVal += MyTexts.GetString(MySpaceTexts.ProgrammableBlock_Exception_TooComplex); } else if (ex.InnerException != null) { retVal += MyTexts.GetString(MySpaceTexts.ProgrammableBlock_Exception_ExceptionCaught) + ex.InnerException.Message; } } m_isRunning = false; return(retVal); }
public string ExecuteCode(string argument) { if (m_isRunning) { return(MyTexts.GetString(MySpaceTexts.ProgrammableBlock_Exception_AllreadyRunning)); } if (m_wasTerminated == true) { return(DetailedInfo.ToString()); } DetailedInfo.Clear(); m_echoOutput.Clear(); if (m_assembly == null) { return(MyTexts.GetString(MySpaceTexts.ProgrammableBlock_Exception_NoAssembly)); } if (!m_instance.HasMainMethod) { return(MyTexts.GetString(MySpaceTexts.ProgrammableBlock_Exception_NoMain)); } if (m_previousRunTimestamp == 0) { m_previousRunTimestamp = Stopwatch.GetTimestamp(); m_instance.ElapsedTime = TimeSpan.Zero; } else { var currentTimestamp = Stopwatch.GetTimestamp(); var elapsedTime = (currentTimestamp - m_previousRunTimestamp) * Sync.RelativeSimulationRatio; m_instance.ElapsedTime = TimeSpan.FromSeconds(elapsedTime * STOPWATCH_FREQUENCY); m_previousRunTimestamp = currentTimestamp; } var gridGroup = MyCubeGridGroups.Static.Logical.GetGroup(CubeGrid); var terminalSystem = gridGroup.GroupData.TerminalSystem; terminalSystem.UpdateGridBlocksOwnership(this.OwnerId); m_instance.GridTerminalSystem = terminalSystem; m_isRunning = true; string retVal = ""; IlInjector.RestartCountingInstructions(MAX_NUM_EXECUTED_INSTRUCTIONS); try { m_instance.Main(argument); if (m_echoOutput.Length > 0) { retVal = m_echoOutput.ToString(); } } catch (Exception ex) { // Since we just had an exception I'm not fussed about using old // fashioned string concatenation here. We'll still want the echo // output, since its primary purpose is debugging. if (m_echoOutput.Length > 0) { retVal = m_echoOutput.ToString(); } OnProgramTermination(); if (ex is ScriptOutOfRangeException) { retVal += MyTexts.GetString(MySpaceTexts.ProgrammableBlock_Exception_TooComplex); } else { retVal += MyTexts.GetString(MySpaceTexts.ProgrammableBlock_Exception_ExceptionCaught) + ex.Message; } } m_isRunning = false; return(retVal); }