public async System.Threading.Tasks.Task <DynValue> ExecuteAsync(params object[] args) { if (IsCoroutine) { var co = Coroutine.Coroutine; if (co.State == CoroutineState.Dead || !CheckYieldStatus()) //Doesn't run check yield if coroutine is dead { return(DynValue.Nil); } DynValue ret; if (co.State == CoroutineState.NotStarted) { ret = await co.ResumeAsync(args); } else { ret = await co.ResumeAsync(); } switch (co.State) { case CoroutineState.Suspended: if (ret.IsNotNil()) { try { CurYielder = ret.ToObject <Yielder>(); } catch { //TODO: throw error? } } break; case CoroutineState.Dead: CurYielder = null; if (AutoResetCoroutine) { //Create new coroutine, assign it to our dynvalue Coroutine = ScriptRef.CreateCoroutine(LuaFunc); } break; default: break; } return(ret); } else { //Not coroutine, just call the function var ret = await ScriptRef.CallAsync(LuaFunc, args); return(ret); } }
public virtual void ResetCoroutine() { if (IsCoroutine) { CurYielder = null; //It is expensive to create coroutines, also DynVal.Assign() function is more expensive than just assigning in C# if (CoroutineState != CoroutineState.NotStarted) { Coroutine = ScriptRef.CreateCoroutine(LuaFunc); } } }
/// <summary> /// Clone the other scripthook. Also creates a new coroutine with the same settings as the original /// </summary> /// <param name="other"></param> public ScriptFunction(ScriptFunction other) { this.ScriptRef = other.ScriptRef; LuaFunc = other.LuaFunc; IsCoroutine = other.IsCoroutine; AutoResetCoroutine = other.AutoResetCoroutine; Coroutine = IsCoroutine ? ScriptRef.CreateCoroutine(LuaFunc) : null; if (IsCoroutine) { Coroutine.Coroutine.AutoYieldCounter = other.Coroutine.Coroutine.AutoYieldCounter; } FuncType = other.FuncType; }
/// <summary> /// Executes this function with a callback. The callback will be called when the coroutine dies, or every time if it is a normal function /// </summary> /// <param name="callback"></param> /// <param name="args"></param> /// <returns></returns> public DynValue ExecuteWithCallback(Action callback, params object[] args) { if (IsCoroutine) { if (Coroutine.Coroutine.State == CoroutineState.Dead || !CheckYieldStatus()) //Doesn't run check yield if coroutine is dead { return(null); } DynValue ret = Coroutine.Coroutine.Resume(args); switch (Coroutine.Coroutine.State) { case CoroutineState.Suspended: if (ret.IsNotNil()) { CurYielder = ret.ToObject <Yielder>(); } else { CurYielder = null; } break; case CoroutineState.Dead: CurYielder = null; callback?.Invoke(); if (AutoResetCoroutine) { Coroutine = ScriptRef.CreateCoroutine(LuaFunc); } break; default: break; } return(ret); } else { var ret = ScriptRef.Call(LuaFunc, args); callback?.Invoke(); return(ret); } }
public OptimizedUnityCoroutine(ScriptRunnerBase runner, string functionBody, params string[] parameters) { UnityCoroutineState = $"{ID}_UNITY_COROUTINE_STATE"; this.ScriptRef = runner.Lua; ScriptRef.Globals[UnityCoroutineState] = true; string nxtV = $"{ID}_NextVals"; StringBuilder sb = new StringBuilder(); //1 based lua indices, ugh for (int i = 1; i < parameters.Length + 1; i++) { sb.Append($"{parameters[i - 1]} = {nxtV}[{i}] "); } string NextParamsStr = sb.ToString(); string funcString = $"function({string.Join(",", parameters)}) while (true) do{Environment.NewLine}{functionBody}{Environment.NewLine}{UnityCoroutineState} = false " + $"local {nxtV} = coroutine.yield() " + $"{NextParamsStr} " + $"end end"; LuaFunc = ScriptRef.LoadFunction(funcString); Coroutine = ScriptRef.CreateCoroutine(LuaFunc); }
public void ForceFullReset() { Coroutine = ScriptRef.CreateCoroutine(LuaFunc); started = false; ScriptRef.Globals[$"{ID}_UNITY_COROUTINE_STATE"] = true; }
/// <summary> /// Executes this function whether it is a normal function or a coroutine. Dead coroutines do not run and return DynValue.Nil /// </summary> /// <param name="args"></param> /// <returns></returns> public DynValue Execute(params object[] args) { try { if (IsCoroutine) { var co = Coroutine.Coroutine; if (co.State == CoroutineState.Dead || !CheckYieldStatus()) //Doesn't run check yield if coroutine is dead { return(DynValue.Nil); } DynValue ret = co.Resume(args); //if (co.State == CoroutineState.NotStarted) //{ // ret = co.Resume(args); //} //else //{ // ret = co.Resume(); //} switch (co.State) { case CoroutineState.Suspended: if (ret.IsNotNil()) { try { CurYielder = ret.ToObject <Yielder>(); } catch //Todo: catch specific exception { //Moonsharp does not have a good way of checking the userdata type //The way to check just throws an error anyways, so this is more efficient } } break; case CoroutineState.Dead: CurYielder = null; if (AutoResetCoroutine) { //Create new coroutine, assign it to our dynvalue Coroutine = ScriptRef.CreateCoroutine(LuaFunc); } break; default: break; } return(ret); } else { //Not coroutine, just call the function var ret = ScriptRef.Call(LuaFunc, args); return(ret); } } catch (Exception ex) { if (ex is InterpreterException ex2) { //For unity throw new Exception(ex2.DecoratedMessage, ex); } else { throw ex; } } }