diff --git a/OpenRA.Game/Scripting/ScriptContext.cs b/OpenRA.Game/Scripting/ScriptContext.cs index b1109229e6..456ea60923 100644 --- a/OpenRA.Game/Scripting/ScriptContext.cs +++ b/OpenRA.Game/Scripting/ScriptContext.cs @@ -173,12 +173,12 @@ namespace OpenRA.Scripting } } - bool error; + public bool FatalErrorOccurred { get; private set; } public void FatalError(string message) { Console.WriteLine("Fatal Lua Error: {0}", message); Game.AddChatLine(Color.White, "Fatal Lua Error", message); - error = true; + FatalErrorOccurred = true; } public void RegisterMapActor(string name, Actor a) @@ -195,7 +195,7 @@ namespace OpenRA.Scripting public void WorldLoaded() { - if (error) + if (FatalErrorOccurred) return; using (var worldLoaded = (LuaFunction)runtime.Globals["WorldLoaded"]) @@ -204,7 +204,7 @@ namespace OpenRA.Scripting public void Tick(Actor self) { - if (error || disposed) + if (FatalErrorOccurred || disposed) return; using (new PerfSample("tick_lua")) @@ -215,6 +215,7 @@ namespace OpenRA.Scripting { if (disposed) return; + disposed = true; if (runtime != null) runtime.Dispose(); diff --git a/OpenRA.Mods.RA/Scripting/Global/TriggerGlobal.cs b/OpenRA.Mods.RA/Scripting/Global/TriggerGlobal.cs index d67f17035e..08a2b5be90 100644 --- a/OpenRA.Mods.RA/Scripting/Global/TriggerGlobal.cs +++ b/OpenRA.Mods.RA/Scripting/Global/TriggerGlobal.cs @@ -43,7 +43,7 @@ namespace OpenRA.Mods.RA.Scripting using (f) f.Call(); } - catch (LuaException e) + catch (Exception e) { context.FatalError(e.Message); } @@ -81,11 +81,18 @@ namespace OpenRA.Mods.RA.Scripting var copy = (LuaFunction)func.CopyReference(); Action OnMemberKilled = m => { - group.Remove(m); - if (!group.Any()) + try { - copy.Call(); - copy.Dispose(); + group.Remove(m); + if (!group.Any()) + { + copy.Call(); + copy.Dispose(); + } + } + catch (Exception e) + { + context.FatalError(e.Message); } }; @@ -101,14 +108,21 @@ namespace OpenRA.Mods.RA.Scripting var copy = (LuaFunction)func.CopyReference(); Action OnMemberKilled = m => { - if (called) - return; + try + { + if (called) + return; - using (var killed = m.ToLuaValue(context)) - copy.Call(killed).Dispose(); + using (var killed = m.ToLuaValue(context)) + copy.Call(killed).Dispose(); - copy.Dispose(); - called = true; + copy.Dispose(); + called = true; + } + catch (Exception e) + { + context.FatalError(e.Message); + } }; foreach (var a in actors) @@ -180,11 +194,18 @@ namespace OpenRA.Mods.RA.Scripting var copy = (LuaFunction)func.CopyReference(); Action OnMemberRemoved = m => { - group.Remove(m); - if (!group.Any()) + try { - copy.Call().Dispose(); - copy.Dispose(); + group.Remove(m); + if (!group.Any()) + { + copy.Call().Dispose(); + copy.Dispose(); + } + } + catch (Exception e) + { + context.FatalError(e.Message); } }; @@ -208,9 +229,16 @@ namespace OpenRA.Mods.RA.Scripting var onEntry = (LuaFunction)func.CopyReference(); Action invokeEntry = a => { - using (var luaActor = a.ToLuaValue(context)) - using (var id = triggerId.ToLuaValue(context)) - onEntry.Call(luaActor, id).Dispose(); + try + { + using (var luaActor = a.ToLuaValue(context)) + using (var id = triggerId.ToLuaValue(context)) + onEntry.Call(luaActor, id).Dispose(); + } + catch (Exception e) + { + context.FatalError(e.Message); + } }; triggerId = context.World.ActorMap.AddCellTrigger(cells, invokeEntry, null); @@ -227,9 +255,16 @@ namespace OpenRA.Mods.RA.Scripting var onExit = (LuaFunction)func.CopyReference(); Action invokeExit = a => { - using (var luaActor = a.ToLuaValue(context)) - using (var id = triggerId.ToLuaValue(context)) - onExit.Call(luaActor, id).Dispose(); + try + { + using (var luaActor = a.ToLuaValue(context)) + using (var id = triggerId.ToLuaValue(context)) + onExit.Call(luaActor, id).Dispose(); + } + catch (Exception e) + { + context.FatalError(e.Message); + } }; triggerId = context.World.ActorMap.AddCellTrigger(cells, null, invokeExit); diff --git a/OpenRA.Mods.RA/Scripting/ScriptTriggers.cs b/OpenRA.Mods.RA/Scripting/ScriptTriggers.cs index b7d226c742..aeee22ce1b 100644 --- a/OpenRA.Mods.RA/Scripting/ScriptTriggers.cs +++ b/OpenRA.Mods.RA/Scripting/ScriptTriggers.cs @@ -45,25 +45,55 @@ namespace OpenRA.Mods.RA.Scripting public void TickIdle(Actor self) { foreach (var f in Triggers[Trigger.OnIdle]) - using (var a = self.ToLuaValue(f.Second)) - f.First.Call(a).Dispose(); + { + try + { + using (var a = self.ToLuaValue(f.Second)) + f.First.Call(a).Dispose(); + } + catch (Exception ex) + { + f.Second.FatalError(ex.Message); + return; + } + } } public void Damaged(Actor self, AttackInfo e) { foreach (var f in Triggers[Trigger.OnDamaged]) - using (var a = self.ToLuaValue(f.Second)) - using (var b = e.Attacker.ToLuaValue(f.Second)) - f.First.Call(a, b).Dispose(); + { + try + { + using (var a = self.ToLuaValue(f.Second)) + using (var b = e.Attacker.ToLuaValue(f.Second)) + f.First.Call(a, b).Dispose(); + } + catch (Exception ex) + { + f.Second.FatalError(ex.Message); + return; + } + } } public void Killed(Actor self, AttackInfo e) { // Run Lua callbacks foreach (var f in Triggers[Trigger.OnKilled]) - using (var a = self.ToLuaValue(f.Second)) - using (var b = e.Attacker.ToLuaValue(f.Second)) - f.First.Call(a, b).Dispose(); + { + try + { + using (var a = self.ToLuaValue(f.Second)) + using (var b = e.Attacker.ToLuaValue(f.Second)) + f.First.Call(a, b).Dispose(); + } + catch (Exception ex) + { + f.Second.FatalError(ex.Message); + return; + } + } // Run any internally bound callbacks OnKilledInternal(self); @@ -72,72 +102,162 @@ namespace OpenRA.Mods.RA.Scripting public void UnitProduced(Actor self, Actor other, CPos exit) { foreach (var f in Triggers[Trigger.OnProduction]) - using (var a = self.ToLuaValue(f.Second)) - using (var b = other.ToLuaValue(f.Second)) - f.First.Call(a, b).Dispose(); + { + try + { + using (var a = self.ToLuaValue(f.Second)) + using (var b = other.ToLuaValue(f.Second)) + f.First.Call(a, b).Dispose(); + } + catch (Exception ex) + { + f.Second.FatalError(ex.Message); + return; + } + } } public void OnPlayerWon(Player player) { foreach (var f in Triggers[Trigger.OnPlayerWon]) - using (var a = player.ToLuaValue(f.Second)) - f.First.Call(a).Dispose(); + { + try + { + using (var a = player.ToLuaValue(f.Second)) + f.First.Call(a).Dispose(); + } + catch (Exception ex) + { + f.Second.FatalError(ex.Message); + return; + } + } } public void OnPlayerLost(Player player) { foreach (var f in Triggers[Trigger.OnPlayerLost]) - using (var a = player.ToLuaValue(f.Second)) - f.First.Call(a).Dispose(); + { + try + { + using (var a = player.ToLuaValue(f.Second)) + f.First.Call(a).Dispose(); + } + catch (Exception ex) + { + f.Second.FatalError(ex.Message); + return; + } + } } public void OnObjectiveAdded(Player player, int id) { foreach (var f in Triggers[Trigger.OnObjectiveAdded]) - using (var a = player.ToLuaValue(f.Second)) - using (var b = id.ToLuaValue(f.Second)) - f.First.Call(a, b).Dispose(); + { + try + { + using (var a = player.ToLuaValue(f.Second)) + using (var b = id.ToLuaValue(f.Second)) + f.First.Call(a, b).Dispose(); + } + catch (Exception ex) + { + f.Second.FatalError(ex.Message); + return; + } + } } public void OnObjectiveCompleted(Player player, int id) { foreach (var f in Triggers[Trigger.OnObjectiveCompleted]) - using (var a = player.ToLuaValue(f.Second)) - using (var b = id.ToLuaValue(f.Second)) - f.First.Call(a, b).Dispose(); + { + try + { + using (var a = player.ToLuaValue(f.Second)) + using (var b = id.ToLuaValue(f.Second)) + f.First.Call(a, b).Dispose(); + } + catch (Exception ex) + { + f.Second.FatalError(ex.Message); + return; + } + } } public void OnObjectiveFailed(Player player, int id) { foreach (var f in Triggers[Trigger.OnObjectiveFailed]) - using (var a = player.ToLuaValue(f.Second)) - using (var b = id.ToLuaValue(f.Second)) - f.First.Call(a, b).Dispose(); + { + try + { + using (var a = player.ToLuaValue(f.Second)) + using (var b = id.ToLuaValue(f.Second)) + f.First.Call(a, b).Dispose(); + } + catch (Exception ex) + { + f.Second.FatalError(ex.Message); + return; + } + } } public void OnCapture(Actor self, Actor captor, Player oldOwner, Player newOwner) { foreach (var f in Triggers[Trigger.OnCapture]) - using (var a = self.ToLuaValue(f.Second)) - using (var b = captor.ToLuaValue(f.Second)) - using (var c = oldOwner.ToLuaValue(f.Second)) - using (var d = newOwner.ToLuaValue(f.Second)) - f.First.Call(a, b, c, d).Dispose(); + { + try + { + using (var a = self.ToLuaValue(f.Second)) + using (var b = captor.ToLuaValue(f.Second)) + using (var c = oldOwner.ToLuaValue(f.Second)) + using (var d = newOwner.ToLuaValue(f.Second)) + f.First.Call(a, b, c, d).Dispose(); + } + catch (Exception ex) + { + f.Second.FatalError(ex.Message); + return; + } + } } public void AddedToWorld(Actor self) { foreach (var f in Triggers[Trigger.OnAddedToWorld]) - using (var a = self.ToLuaValue(f.Second)) - f.First.Call(a).Dispose(); + { + try + { + using (var a = self.ToLuaValue(f.Second)) + f.First.Call(a).Dispose(); + } + catch (Exception ex) + { + f.Second.FatalError(ex.Message); + return; + } + } } public void RemovedFromWorld(Actor self) { // Run Lua callbacks foreach (var f in Triggers[Trigger.OnRemovedFromWorld]) - using (var a = self.ToLuaValue(f.Second)) - f.First.Call(a).Dispose(); + { + try + { + using (var a = self.ToLuaValue(f.Second)) + f.First.Call(a).Dispose(); + } + catch (Exception ex) + { + f.Second.FatalError(ex.Message); + return; + } + } // Run any internally bound callbacks OnRemovedInternal(self);