/// <summary> /// Runs the given program. If the program's runtime derives from <see cref="SimpleRuntimeInfo" />, it's metrics will /// be updated. /// </summary> /// <param name="gridProgram">The program to run</param> /// <param name="argument">The argument to pass to the program</param> /// <param name="timeSinceLastRun">The simulated time since the last time the program was run</param> /// <param name="updateType">The source of this simulated run. Defaults to Trigger.</param> public static void Run(IMyGridProgram gridProgram, string argument = "", TimeSpan timeSinceLastRun = default(TimeSpan), UpdateType updateType = UpdateType.Trigger) { if (gridProgram == null) { throw new ArgumentNullException(nameof(gridProgram)); } var runtime = gridProgram.Runtime as SimpleRuntimeInfo; if (runtime != null) { runtime.TimeSinceLastRun = timeSinceLastRun; } var stopwatch = Stopwatch.StartNew(); gridProgram.Main(argument ?? "", updateType); if (runtime != null) { runtime.LastRunTimeMs = stopwatch.Elapsed.TotalMilliseconds; } }
public ScriptTerminationReason ExecuteCode(string argument, out string response) { if (m_isRunning) { response = MyTexts.GetString(MySpaceTexts.ProgrammableBlock_Exception_AllreadyRunning); return(ScriptTerminationReason.AlreadyRunning); } if (m_terminationReason != ScriptTerminationReason.None) { response = DetailedInfo.ToString(); return(m_terminationReason); } DetailedInfo.Clear(); m_echoOutput.Clear(); if (m_assembly == null) { response = MyTexts.GetString(MySpaceTexts.ProgrammableBlock_Exception_NoAssembly); return(ScriptTerminationReason.NoScript); } if (!m_instance.HasMainMethod) { response = MyTexts.GetString(MySpaceTexts.ProgrammableBlock_Exception_NoMain); return(ScriptTerminationReason.NoEntryPoint); } 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; response = ""; try { using (IlInjector.BeginRunBlock(MAX_NUM_EXECUTED_INSTRUCTIONS, MAX_NUM_METHOD_CALLS)) { m_instance.Main(argument); } if (m_echoOutput.Length > 0) { response = 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) { response = m_echoOutput.ToString(); } if (ex is ScriptOutOfRangeException) { if (IlInjector.IsWithinRunBlock()) { // If we're within a nested run, we don't reset the program, we just pass the error response += MyTexts.GetString(MySpaceTexts.ProgrammableBlock_Exception_NestedTooComplex); return(ScriptTerminationReason.InstructionOverflow); } else { response += MyTexts.GetString(MySpaceTexts.ProgrammableBlock_Exception_TooComplex); OnProgramTermination(ScriptTerminationReason.InstructionOverflow); } } else { response += MyTexts.GetString(MySpaceTexts.ProgrammableBlock_Exception_ExceptionCaught) + ex.Message; OnProgramTermination(ScriptTerminationReason.RuntimeException); } } finally { m_isRunning = false; } return(m_terminationReason); }
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); }