Throw early when Lua function parameters are null.

This commit is contained in:
Matthias Mailänder
2023-05-19 16:21:25 +02:00
committed by Gustas
parent 52a916012f
commit 8433bc0948
2 changed files with 110 additions and 35 deletions

View File

@@ -50,7 +50,7 @@ namespace OpenRA.Scripting
try try
{ {
if (!IsMethod) if (!IsMethod)
throw new LuaException("Trying to invoke a ScriptMemberWrapper that isn't a method!"); throw new LuaException($"Trying to invoke a {nameof(ScriptMemberWrapper)} that isn't a method!");
var mi = (MethodInfo)Member; var mi = (MethodInfo)Member;
var pi = mi.GetParameters(); var pi = mi.GetParameters();

View File

@@ -23,11 +23,11 @@ namespace OpenRA.Mods.Common.Scripting
public TriggerGlobal(ScriptContext context) public TriggerGlobal(ScriptContext context)
: base(context) { } : base(context) { }
public static ScriptTriggers GetScriptTriggers(Actor a) public static ScriptTriggers GetScriptTriggers(Actor actor)
{ {
var events = a.TraitOrDefault<ScriptTriggers>(); var events = actor.TraitOrDefault<ScriptTriggers>();
if (events == null) if (events == null)
throw new LuaException($"Actor '{a.Info.Name}' requires the ScriptTriggers trait before attaching a trigger"); throw new LuaException($"Actor '{actor.Info.Name}' requires the ScriptTriggers trait before attaching a trigger");
return events; return events;
} }
@@ -54,43 +54,61 @@ namespace OpenRA.Mods.Common.Scripting
[Desc("Call a function for each passenger when it enters a transport. " + [Desc("Call a function for each passenger when it enters a transport. " +
"The callback function will be called as func(Actor transport, Actor passenger).")] "The callback function will be called as func(Actor transport, Actor passenger).")]
public void OnPassengerEntered(Actor a, LuaFunction func) public void OnPassengerEntered(Actor actor, LuaFunction func)
{ {
GetScriptTriggers(a).RegisterCallback(Trigger.OnPassengerEntered, func, Context); if (actor == null)
throw new NullReferenceException(nameof(actor));
GetScriptTriggers(actor).RegisterCallback(Trigger.OnPassengerEntered, func, Context);
} }
[Desc("Call a function for each passenger when it exits a transport. " + [Desc("Call a function for each passenger when it exits a transport. " +
"The callback function will be called as func(Actor transport, Actor passenger).")] "The callback function will be called as func(Actor transport, Actor passenger).")]
public void OnPassengerExited(Actor a, LuaFunction func) public void OnPassengerExited(Actor actor, LuaFunction func)
{ {
GetScriptTriggers(a).RegisterCallback(Trigger.OnPassengerExited, func, Context); if (actor == null)
throw new NullReferenceException(nameof(actor));
GetScriptTriggers(actor).RegisterCallback(Trigger.OnPassengerExited, func, Context);
} }
[Desc("Call a function each tick that the actor is idle. " + [Desc("Call a function each tick that the actor is idle. " +
"The callback function will be called as func(Actor self).")] "The callback function will be called as func(Actor self).")]
public void OnIdle(Actor a, LuaFunction func) public void OnIdle(Actor actor, LuaFunction func)
{ {
GetScriptTriggers(a).RegisterCallback(Trigger.OnIdle, func, Context); if (actor == null)
throw new NullReferenceException(nameof(actor));
GetScriptTriggers(actor).RegisterCallback(Trigger.OnIdle, func, Context);
} }
[Desc("Call a function when the actor is damaged. The callback " + [Desc("Call a function when the actor is damaged. The callback " +
"function will be called as func(Actor self, Actor attacker, int damage).")] "function will be called as func(Actor self, Actor attacker, int damage).")]
public void OnDamaged(Actor a, LuaFunction func) public void OnDamaged(Actor actor, LuaFunction func)
{ {
GetScriptTriggers(a).RegisterCallback(Trigger.OnDamaged, func, Context); if (actor == null)
throw new NullReferenceException(nameof(actor));
GetScriptTriggers(actor).RegisterCallback(Trigger.OnDamaged, func, Context);
} }
[Desc("Call a function when the actor is killed. The callback " + [Desc("Call a function when the actor is killed. The callback " +
"function will be called as func(Actor self, Actor killer).")] "function will be called as func(Actor self, Actor killer).")]
public void OnKilled(Actor a, LuaFunction func) public void OnKilled(Actor actor, LuaFunction func)
{ {
GetScriptTriggers(a).RegisterCallback(Trigger.OnKilled, func, Context); if (actor == null)
throw new NullReferenceException(nameof(actor));
GetScriptTriggers(actor).RegisterCallback(Trigger.OnKilled, func, Context);
} }
[Desc("Call a function when all of the actors in a group are killed. The callback " + [Desc("Call a function when all of the actors in a group are killed. The callback " +
"function will be called as func().")] "function will be called as func().")]
public void OnAllKilled(Actor[] actors, LuaFunction func) public void OnAllKilled(Actor[] actors, LuaFunction func)
{ {
if (actors == null)
throw new NullReferenceException(nameof(actors));
var group = actors.ToList(); var group = actors.ToList();
var f = (LuaFunction)func.CopyReference(); var f = (LuaFunction)func.CopyReference();
void OnMemberKilled(Actor m) void OnMemberKilled(Actor m)
@@ -137,15 +155,21 @@ namespace OpenRA.Mods.Common.Scripting
} }
} }
if (actors == null)
throw new NullReferenceException(nameof(actors));
foreach (var a in actors) foreach (var a in actors)
GetScriptTriggers(a).OnKilledInternal += OnMemberKilled; GetScriptTriggers(a).OnKilledInternal += OnMemberKilled;
} }
[Desc("Call a function when this actor produces another actor. " + [Desc("Call a function when this actor produces another actor. " +
"The callback function will be called as func(Actor producer, Actor produced).")] "The callback function will be called as func(Actor producer, Actor produced).")]
public void OnProduction(Actor a, LuaFunction func) public void OnProduction(Actor actors, LuaFunction func)
{ {
GetScriptTriggers(a).RegisterCallback(Trigger.OnProduction, func, Context); if (actors == null)
throw new NullReferenceException(nameof(actors));
GetScriptTriggers(actors).RegisterCallback(Trigger.OnProduction, func, Context);
} }
[Desc("Call a function when any actor produces another actor. The callback " + [Desc("Call a function when any actor produces another actor. The callback " +
@@ -159,6 +183,9 @@ namespace OpenRA.Mods.Common.Scripting
"The callback function will be called as func(Player player).")] "The callback function will be called as func(Player player).")]
public void OnPlayerWon(Player player, LuaFunction func) public void OnPlayerWon(Player player, LuaFunction func)
{ {
if (player == null)
throw new NullReferenceException(nameof(player));
GetScriptTriggers(player.PlayerActor).RegisterCallback(Trigger.OnPlayerWon, func, Context); GetScriptTriggers(player.PlayerActor).RegisterCallback(Trigger.OnPlayerWon, func, Context);
} }
@@ -166,6 +193,9 @@ namespace OpenRA.Mods.Common.Scripting
"The callback function will be called as func(Player player).")] "The callback function will be called as func(Player player).")]
public void OnPlayerLost(Player player, LuaFunction func) public void OnPlayerLost(Player player, LuaFunction func)
{ {
if (player == null)
throw new NullReferenceException(nameof(player));
GetScriptTriggers(player.PlayerActor).RegisterCallback(Trigger.OnPlayerLost, func, Context); GetScriptTriggers(player.PlayerActor).RegisterCallback(Trigger.OnPlayerLost, func, Context);
} }
@@ -173,6 +203,9 @@ namespace OpenRA.Mods.Common.Scripting
"The callback function will be called as func(Player player, int objectiveID).")] "The callback function will be called as func(Player player, int objectiveID).")]
public void OnObjectiveAdded(Player player, LuaFunction func) public void OnObjectiveAdded(Player player, LuaFunction func)
{ {
if (player == null)
throw new NullReferenceException(nameof(player));
GetScriptTriggers(player.PlayerActor).RegisterCallback(Trigger.OnObjectiveAdded, func, Context); GetScriptTriggers(player.PlayerActor).RegisterCallback(Trigger.OnObjectiveAdded, func, Context);
} }
@@ -180,6 +213,9 @@ namespace OpenRA.Mods.Common.Scripting
"The callback function will be called as func(Player player, int objectiveID).")] "The callback function will be called as func(Player player, int objectiveID).")]
public void OnObjectiveCompleted(Player player, LuaFunction func) public void OnObjectiveCompleted(Player player, LuaFunction func)
{ {
if (player == null)
throw new NullReferenceException(nameof(player));
GetScriptTriggers(player.PlayerActor).RegisterCallback(Trigger.OnObjectiveCompleted, func, Context); GetScriptTriggers(player.PlayerActor).RegisterCallback(Trigger.OnObjectiveCompleted, func, Context);
} }
@@ -187,27 +223,39 @@ namespace OpenRA.Mods.Common.Scripting
"The callback function will be called as func(Player player, int objectiveID).")] "The callback function will be called as func(Player player, int objectiveID).")]
public void OnObjectiveFailed(Player player, LuaFunction func) public void OnObjectiveFailed(Player player, LuaFunction func)
{ {
if (player == null)
throw new NullReferenceException(nameof(player));
GetScriptTriggers(player.PlayerActor).RegisterCallback(Trigger.OnObjectiveFailed, func, Context); GetScriptTriggers(player.PlayerActor).RegisterCallback(Trigger.OnObjectiveFailed, func, Context);
} }
[Desc("Call a function when this actor is added to the world. " + [Desc("Call a function when this actor is added to the world. " +
"The callback function will be called as func(Actor self).")] "The callback function will be called as func(Actor self).")]
public void OnAddedToWorld(Actor a, LuaFunction func) public void OnAddedToWorld(Actor actor, LuaFunction func)
{ {
GetScriptTriggers(a).RegisterCallback(Trigger.OnAddedToWorld, func, Context); if (actor == null)
throw new NullReferenceException(nameof(actor));
GetScriptTriggers(actor).RegisterCallback(Trigger.OnAddedToWorld, func, Context);
} }
[Desc("Call a function when this actor is removed from the world. " + [Desc("Call a function when this actor is removed from the world. " +
"The callback function will be called as func(Actor self).")] "The callback function will be called as func(Actor self).")]
public void OnRemovedFromWorld(Actor a, LuaFunction func) public void OnRemovedFromWorld(Actor actor, LuaFunction func)
{ {
GetScriptTriggers(a).RegisterCallback(Trigger.OnRemovedFromWorld, func, Context); if (actor == null)
throw new NullReferenceException(nameof(actor));
GetScriptTriggers(actor).RegisterCallback(Trigger.OnRemovedFromWorld, func, Context);
} }
[Desc("Call a function when all of the actors in a group have been removed from the world. " + [Desc("Call a function when all of the actors in a group have been removed from the world. " +
"The callback function will be called as func().")] "The callback function will be called as func().")]
public void OnAllRemovedFromWorld(Actor[] actors, LuaFunction func) public void OnAllRemovedFromWorld(Actor[] actors, LuaFunction func)
{ {
if (actors == null)
throw new NullReferenceException(nameof(actors));
var group = actors.ToList(); var group = actors.ToList();
var f = (LuaFunction)func.CopyReference(); var f = (LuaFunction)func.CopyReference();
@@ -256,14 +304,17 @@ namespace OpenRA.Mods.Common.Scripting
[Desc("Call a function when this actor is captured. The callback function " + [Desc("Call a function when this actor is captured. The callback function " +
"will be called as func(Actor self, Actor captor, Player oldOwner, Player newOwner).")] "will be called as func(Actor self, Actor captor, Player oldOwner, Player newOwner).")]
public void OnCapture(Actor a, LuaFunction func) public void OnCapture(Actor actors, LuaFunction func)
{ {
GetScriptTriggers(a).RegisterCallback(Trigger.OnCapture, func, Context); if (actors == null)
throw new NullReferenceException(nameof(actors));
GetScriptTriggers(actors).RegisterCallback(Trigger.OnCapture, func, Context);
} }
[Desc("Call a function when this actor is killed or captured. " + [Desc("Call a function when this actor is killed or captured. " +
"The callback function will be called as func().")] "The callback function will be called as func().")]
public void OnKilledOrCaptured(Actor a, LuaFunction func) public void OnKilledOrCaptured(Actor actor, LuaFunction func)
{ {
var called = false; var called = false;
@@ -286,14 +337,20 @@ namespace OpenRA.Mods.Common.Scripting
} }
} }
GetScriptTriggers(a).OnCapturedInternal += OnKilledOrCaptured; if (actor == null)
GetScriptTriggers(a).OnKilledInternal += OnKilledOrCaptured; throw new NullReferenceException(nameof(actor));
GetScriptTriggers(actor).OnCapturedInternal += OnKilledOrCaptured;
GetScriptTriggers(actor).OnKilledInternal += OnKilledOrCaptured;
} }
[Desc("Call a function when all of the actors in a group have been killed or captured. " + [Desc("Call a function when all of the actors in a group have been killed or captured. " +
"The callback function will be called as func().")] "The callback function will be called as func().")]
public void OnAllKilledOrCaptured(Actor[] actors, LuaFunction func) public void OnAllKilledOrCaptured(Actor[] actors, LuaFunction func)
{ {
if (actors == null)
throw new NullReferenceException(nameof(actors));
var group = actors.ToList(); var group = actors.ToList();
var f = (LuaFunction)func.CopyReference(); var f = (LuaFunction)func.CopyReference();
@@ -443,17 +500,23 @@ namespace OpenRA.Mods.Common.Scripting
[Desc("Call a function when this actor is infiltrated. The callback function " + [Desc("Call a function when this actor is infiltrated. The callback function " +
"will be called as func(Actor self, Actor infiltrator).")] "will be called as func(Actor self, Actor infiltrator).")]
public void OnInfiltrated(Actor a, LuaFunction func) public void OnInfiltrated(Actor actor, LuaFunction func)
{ {
GetScriptTriggers(a).RegisterCallback(Trigger.OnInfiltrated, func, Context); if (actor == null)
throw new NullReferenceException(nameof(actor));
GetScriptTriggers(actor).RegisterCallback(Trigger.OnInfiltrated, func, Context);
} }
[Desc("Call a function when this actor is discovered by an enemy or a player with a Neutral stance. " + [Desc("Call a function when this actor is discovered by an enemy or a player with a Neutral stance. " +
"The callback function will be called as func(Actor discovered, Player discoverer). " + "The callback function will be called as func(Actor discovered, Player discoverer). " +
"The player actor needs the 'EnemyWatcher' trait. The actors to discover need the 'AnnounceOnSeen' trait.")] "The player actor needs the 'EnemyWatcher' trait. The actors to discover need the 'AnnounceOnSeen' trait.")]
public void OnDiscovered(Actor a, LuaFunction func) public void OnDiscovered(Actor actor, LuaFunction func)
{ {
GetScriptTriggers(a).RegisterCallback(Trigger.OnDiscovered, func, Context); if (actor == null)
throw new NullReferenceException(nameof(actor));
GetScriptTriggers(actor).RegisterCallback(Trigger.OnDiscovered, func, Context);
} }
[Desc("Call a function when this player is discovered by an enemy or neutral player. " + [Desc("Call a function when this player is discovered by an enemy or neutral player. " +
@@ -461,14 +524,20 @@ namespace OpenRA.Mods.Common.Scripting
"The player actor needs the 'EnemyWatcher' trait. The actors to discover need the 'AnnounceOnSeen' trait.")] "The player actor needs the 'EnemyWatcher' trait. The actors to discover need the 'AnnounceOnSeen' trait.")]
public void OnPlayerDiscovered(Player discovered, LuaFunction func) public void OnPlayerDiscovered(Player discovered, LuaFunction func)
{ {
if (discovered == null)
throw new NullReferenceException(nameof(discovered));
GetScriptTriggers(discovered.PlayerActor).RegisterCallback(Trigger.OnPlayerDiscovered, func, Context); GetScriptTriggers(discovered.PlayerActor).RegisterCallback(Trigger.OnPlayerDiscovered, func, Context);
} }
[Desc("Call a function when this actor is sold. The callback function " + [Desc("Call a function when this actor is sold. The callback function " +
"will be called as func(Actor self).")] "will be called as func(Actor self).")]
public void OnSold(Actor a, LuaFunction func) public void OnSold(Actor actor, LuaFunction func)
{ {
GetScriptTriggers(a).RegisterCallback(Trigger.OnSold, func, Context); if (actor == null)
throw new NullReferenceException(nameof(actor));
GetScriptTriggers(actor).RegisterCallback(Trigger.OnSold, func, Context);
} }
[Desc("Call a function when the game timer expires. The callback function will be called as func().")] [Desc("Call a function when the game timer expires. The callback function will be called as func().")]
@@ -480,19 +549,25 @@ namespace OpenRA.Mods.Common.Scripting
[Desc("Removes all triggers from this actor. " + [Desc("Removes all triggers from this actor. " +
"Note that the removal will only take effect at the end of a tick, " + "Note that the removal will only take effect at the end of a tick, " +
"so you must not add new triggers at the same time that you are calling this function.")] "so you must not add new triggers at the same time that you are calling this function.")]
public void ClearAll(Actor a) public void ClearAll(Actor actor)
{ {
GetScriptTriggers(a).ClearAll(); if (actor == null)
throw new NullReferenceException(nameof(actor));
GetScriptTriggers(actor).ClearAll();
} }
[Desc("Removes the specified trigger from this actor. " + [Desc("Removes the specified trigger from this actor. " +
"Note that the removal will only take effect at the end of a tick, " + "Note that the removal will only take effect at the end of a tick, " +
"so you must not add new triggers at the same time that you are calling this function.")] "so you must not add new triggers at the same time that you are calling this function.")]
public void Clear(Actor a, string triggerName) public void Clear(Actor actor, string triggerName)
{ {
var trigger = (Trigger)Enum.Parse(typeof(Trigger), triggerName); var trigger = (Trigger)Enum.Parse(typeof(Trigger), triggerName);
GetScriptTriggers(a).Clear(trigger); if (actor == null)
throw new NullReferenceException(nameof(actor));
GetScriptTriggers(actor).Clear(trigger);
} }
} }
} }