Update Lua bindings to use array arguments.

This commit is contained in:
Paul Chote
2014-10-04 11:14:14 +13:00
parent 471dc409b7
commit 85b26d1ff8
7 changed files with 70 additions and 164 deletions

View File

@@ -164,14 +164,5 @@ namespace OpenRA.Scripting
throw new InvalidOperationException("Cannot convert type '{0}' to Lua. Class must implement IScriptBindable.".F(obj.GetType()));
}
public static LuaTable ToLuaTable(this IEnumerable collection, ScriptContext context)
{
var i = 1;
var table = context.CreateTable();
foreach (var x in collection)
table.Add(i++, x.ToLuaValue(context));
return table;
}
}
}

View File

@@ -29,35 +29,37 @@ namespace OpenRA.Mods.RA.Scripting
}
[Desc("Returns a table of all actors within the requested region, filtered using the specified function.")]
public LuaTable ActorsInCircle(WPos location, WRange radius, LuaFunction filter = null)
public Actor[] ActorsInCircle(WPos location, WRange radius, LuaFunction filter = null)
{
var actors = context.World.FindActorsInCircle(location, radius)
.Select(a => a.ToLuaValue(context));
var actors = context.World.FindActorsInCircle(location, radius);
if (filter != null)
{
actors = actors.Where(a =>
{
using (var f = filter.Call(a))
using (var f = filter.Call(a.ToLuaValue(context)))
return f.First().ToBoolean();
});
}
return actors.ToLuaTable(context);
return actors.ToArray();
}
[Desc("Returns a table of all actors within the requested rectangle, filtered using the specified function.")]
public LuaTable ActorsInBox(WPos topLeft, WPos bottomRight, LuaFunction filter = null)
public Actor[] ActorsInBox(WPos topLeft, WPos bottomRight, LuaFunction filter = null)
{
var actors = context.World.ActorMap.ActorsInBox(topLeft, bottomRight)
.Select(a => a.ToLuaValue(context));
var actors = context.World.ActorMap.ActorsInBox(topLeft, bottomRight);
if (filter != null)
{
actors = actors.Where(a =>
{
using (var f = filter.Call(a))
using (var f = filter.Call(a.ToLuaValue(context)))
return f.First().ToBoolean();
});
}
return actors.ToLuaTable(context);
return actors.ToArray();
}
[Desc("Returns the location of the top-left corner of the map.")]
@@ -91,13 +93,7 @@ namespace OpenRA.Mods.RA.Scripting
public string Difficulty { get { return context.World.LobbyInfo.GlobalSettings.Difficulty; } }
[Desc("Returns a table of all the actors that were specified in the map file.")]
public LuaTable NamedActors
{
get
{
return sma.Actors.Values.ToLuaTable(context);
}
}
public Actor[] NamedActors { get { return sma.Actors.Values.ToArray(); } }
[Desc("Returns the actor that was specified with a given name in " +
"the map file (or nil, if the actor is dead or not found).")]

View File

@@ -25,17 +25,14 @@ namespace OpenRA.Scripting
}
[Desc("Returns a table of players filtered by the specified function.")]
public LuaTable GetPlayers(LuaFunction filter)
public Player[] GetPlayers(LuaFunction filter)
{
var players = context.World.Players
.Select(p => p.ToLuaValue(context))
.Where(a =>
return context.World.Players
.Where(p =>
{
using (var f = filter.Call(a))
using (var f = filter.Call(p.ToLuaValue(context)))
return f.First().ToBoolean();
});
return players.ToLuaTable(context);
}).ToArray();
}
}
}

View File

@@ -72,51 +72,36 @@ namespace OpenRA.Mods.RA.Scripting
"while the last one will be their destination. If actionFunc is given, " +
"it will be executed once a unit has reached its destination. actionFunc " +
"will be called as actionFunc(Actor actor)")]
public LuaTable Reinforce(Player owner, LuaTable actorTypes, LuaTable entryPath, int interval = 25, LuaFunction actionFunc = null)
public Actor[] Reinforce(Player owner, string[] actorTypes, CPos[] entryPath, int interval = 25, LuaFunction actionFunc = null)
{
var actors = new List<Actor>();
for (var i = 1; i <= actorTypes.Count; i++)
for (var i = 0; i < actorTypes.Length; i++)
{
string actorType;
if (!(actorTypes[i].TryGetClrValue<String>(out actorType)))
throw new LuaException("Invalid data in actorTypes array");
CPos entry, next = new CPos();
if (!(entryPath[1].TryGetClrValue<CPos>(out entry)
&& (entryPath.Count < 2 || entryPath[2].TryGetClrValue<CPos>(out next))))
throw new LuaException("Invalid data in entryPath array");
var actor = CreateActor(owner, actorType, false, entry, entryPath.Count > 1 ? next : (CPos?)null);
var af = actionFunc != null ? actionFunc.CopyReference() as LuaFunction : null;
var actor = CreateActor(owner, actorTypes[i], false, entryPath[0], entryPath.Length > 1 ? entryPath[1] : (CPos?)null);
actors.Add(actor);
var ep = entryPath.CopyReference() as LuaTable;
var af = actionFunc != null ? actionFunc.CopyReference() as LuaFunction : null;
var actionDelay = (i - 1) * interval;
var actionDelay = i * interval;
Action actorAction = () =>
{
context.World.Add(actor);
for (var j = 2; j <= ep.Count; j++)
{
CPos wpt;
if (!(ep[j].TryGetClrValue<CPos>(out wpt)))
throw new LuaException("Invalid data in entryPath array");
Move(actor, wpt);
}
ep.Dispose();
for (var j = 1; j < entryPath.Length; j++)
Move(actor, entryPath[j]);
if (af != null)
{
actor.QueueActivity(new CallFunc(() =>
{
af.Call(actor.ToLuaValue(context));
af.Dispose();
}));
}
};
context.World.AddFrameEndTask(w => w.Add(new DelayedAction(actionDelay, actorAction)));
}
return actors.Select(a => a.ToLuaValue(context)).ToLuaTable(context);
return actors.ToArray();
}
[Desc("Send reinforcements in a transport. A transport can be a ground unit (APC etc.), ships and aircraft. " +
@@ -127,48 +112,32 @@ namespace OpenRA.Mods.RA.Scripting
"been supplied. Afterwards, the transport will follow the exitPath and leave the map, " +
"unless a custom exitFunc has been supplied. actionFunc will be called as " +
"actionFunc(Actor transport, Actor[] cargo). exitFunc will be called as exitFunc(Actor transport).")]
public LuaTable ReinforceWithTransport(Player owner, string actorType, LuaTable cargoTypes, LuaTable entryPath, LuaTable exitPath = null,
public LuaTable ReinforceWithTransport(Player owner, string actorType, string[] cargoTypes, CPos[] entryPath, CPos[] exitPath = null,
LuaFunction actionFunc = null, LuaFunction exitFunc = null)
{
CPos entry, next = new CPos();
if (!(entryPath[1].TryGetClrValue<CPos>(out entry)
&& (entryPath.Count < 2 || entryPath[2].TryGetClrValue<CPos>(out next))))
throw new LuaException("Invalid data in entryPath array");
var transport = CreateActor(owner, actorType, true, entry, entryPath.Count > 1 ? next : (CPos?)null);
var transport = CreateActor(owner, actorType, true, entryPath[0], entryPath.Length > 1 ? entryPath[1] : (CPos?)null);
var cargo = transport.TraitOrDefault<Cargo>();
var passengers = context.CreateTable();
var passengers = new List<Actor>();
if (cargo != null && cargoTypes != null)
{
for (var i = 1; i <= cargoTypes.Count; i++)
foreach (var cargoType in cargoTypes)
{
string cargoType;
if (!(cargoTypes [i].TryGetClrValue<String>(out cargoType)))
throw new LuaException("Invalid data in cargoTypes array");
var passenger = CreateActor(owner, cargoType, false);
passengers.Add(passengers.Count + 1, passenger.ToLuaValue(context));
passengers.Add(passenger);
cargo.Load(transport, passenger);
}
}
for (var i = 2; i <= entryPath.Count; i++)
{
CPos wpt;
if (!(entryPath[i].TryGetClrValue<CPos>(out wpt)))
throw new LuaException("Invalid data in entryPath array");
Move(transport, wpt);
}
for (var i = 1; i < entryPath.Length; i++)
Move(transport, entryPath[i]);
if (actionFunc != null)
{
var af = actionFunc.CopyReference() as LuaFunction;
transport.QueueActivity(new CallFunc(() =>
{
af.Call(transport.ToLuaValue(context), passengers);
af.Call(transport.ToLuaValue(context), passengers.ToArray().ToLuaValue(context));
af.Dispose();
}));
}
@@ -181,11 +150,13 @@ namespace OpenRA.Mods.RA.Scripting
transport.QueueActivity(new HeliLand(true));
transport.QueueActivity(new Wait(15));
}
if (cargo != null)
{
transport.QueueActivity(new UnloadCargo(transport, true));
transport.QueueActivity(new WaitFor(() => cargo.IsEmpty(transport)));
}
transport.QueueActivity(new Wait(heli != null ? 50 : 25));
}
@@ -200,20 +171,15 @@ namespace OpenRA.Mods.RA.Scripting
}
else if (exitPath != null)
{
for (var i = 1; i <= exitPath.Count; i++)
{
CPos wpt;
if (!(exitPath[i].TryGetClrValue<CPos>(out wpt)))
throw new LuaException("Invalid data in exitPath array.");
foreach (var wpt in exitPath)
Move(transport, wpt);
}
transport.QueueActivity(new RemoveSelf());
}
var ret = context.CreateTable();
ret.Add(1, transport.ToLuaValue(context));
ret.Add(2, passengers);
ret.Add(2, passengers.ToArray().ToLuaValue(context));
return ret;
}
}

View File

@@ -75,18 +75,9 @@ namespace OpenRA.Mods.RA.Scripting
[Desc("Call a function when all of the actors in a group are killed. The callback " +
"function will be called as func().")]
public void OnAllKilled(LuaTable actors, LuaFunction func)
public void OnAllKilled(Actor[] actors, LuaFunction func)
{
var group = new List<Actor>();
foreach (var kv in actors)
{
Actor actor;
if (!kv.Value.TryGetClrValue<Actor>(out actor))
throw new LuaException("OnAllKilled requires a table of int,Actor pairs. Recieved {0},{1}".F(kv.Key.GetType().Name, kv.Value.GetType().Name));
group.Add(actor);
}
var group = actors.ToList();
var copy = (LuaFunction)func.CopyReference();
Action<Actor> OnMemberKilled = m =>
{
@@ -104,18 +95,8 @@ namespace OpenRA.Mods.RA.Scripting
[Desc("Call a function when one of the actors in a group is killed. The callback " +
"function will be called as func(Actor killed).")]
public void OnAnyKilled(LuaTable actors, LuaFunction func)
public void OnAnyKilled(Actor[] actors, LuaFunction func)
{
var group = new List<Actor>();
foreach (var kv in actors)
{
Actor actor;
if (!kv.Value.TryGetClrValue<Actor>(out actor))
throw new LuaException("OnAnyKilled requires a table of int,Actor pairs. Recieved {0},{1}".F(kv.Key.GetType().Name, kv.Value.GetType().Name));
group.Add(actor);
}
var called = false;
var copy = (LuaFunction)func.CopyReference();
Action<Actor> OnMemberKilled = m =>
@@ -130,7 +111,7 @@ namespace OpenRA.Mods.RA.Scripting
called = true;
};
foreach (var a in group)
foreach (var a in actors)
GetScriptTriggers(a).OnKilledInternal += OnMemberKilled;
}
@@ -197,25 +178,10 @@ namespace OpenRA.Mods.RA.Scripting
GetScriptTriggers(a).RegisterCallback(Trigger.OnCapture, func, context);
}
static CPos[] MakeCellFootprint(LuaTable table)
{
var cells = new List<CPos>();
foreach (var kv in table)
{
CPos cell;
if (!kv.Value.TryGetClrValue<CPos>(out cell))
throw new LuaException("Cell footprints must be specified as a table of int,Cell pairs. Recieved {0},{1}".F(kv.Key.GetType().Name, kv.Value.GetType().Name));
cells.Add(cell);
}
return cells.ToArray();
}
[Desc("Call a function when a ground-based actor enters this cell footprint." +
"Returns the trigger id for later removal using RemoveFootprintTrigger(int id)." +
"The callback function will be called as func(Actor a, int id).")]
public int OnEnteredFootprint(LuaTable cells, LuaFunction func)
public int OnEnteredFootprint(CPos[] cells, LuaFunction func)
{
var triggerId = 0;
var onEntry = (LuaFunction)func.CopyReference();
@@ -226,7 +192,7 @@ namespace OpenRA.Mods.RA.Scripting
onEntry.Call(luaActor, id).Dispose();
};
triggerId = context.World.ActorMap.AddCellTrigger(MakeCellFootprint(cells), invokeEntry, null);
triggerId = context.World.ActorMap.AddCellTrigger(cells, invokeEntry, null);
return triggerId;
}
@@ -234,7 +200,7 @@ namespace OpenRA.Mods.RA.Scripting
[Desc("Call a function when a ground-based actor leaves this cell footprint." +
"Returns the trigger id for later removal using RemoveFootprintTrigger(int id)." +
"The callback function will be called as func(Actor a, int id).")]
public int OnExitedFootprint(LuaTable cells, LuaFunction func)
public int OnExitedFootprint(CPos[] cells, LuaFunction func)
{
var triggerId = 0;
var onExit = (LuaFunction)func.CopyReference();
@@ -245,7 +211,7 @@ namespace OpenRA.Mods.RA.Scripting
onExit.Call(luaActor, id).Dispose();
};
triggerId = context.World.ActorMap.AddCellTrigger(MakeCellFootprint(cells), null, invokeExit);
triggerId = context.World.ActorMap.AddCellTrigger(cells, null, invokeExit);
return triggerId;
}

View File

@@ -19,19 +19,19 @@ namespace OpenRA.Mods.RA.Scripting
{
public UtilsGlobal(ScriptContext context) : base(context) { }
[Desc("Calls a function on every value in table.")]
public void Do(LuaTable table, LuaFunction func)
[Desc("Calls a function on every element in a collection.")]
public void Do(LuaValue[] collection, LuaFunction func)
{
foreach (var kv in table)
func.Call(kv.Value).Dispose();
foreach (var c in collection)
func.Call(c).Dispose();
}
[Desc("Returns true if func returns true for any value in table.")]
public bool Any(LuaTable table, LuaFunction func)
[Desc("Returns true if func returns true for any element in a collection.")]
public bool Any(LuaValue[] collection, LuaFunction func)
{
foreach (var kv in table)
foreach (var c in collection)
{
using (var ret = func.Call(kv.Value))
using (var ret = func.Call(c))
{
var result = ret.FirstOrDefault();
if (result != null && result.ToBoolean())
@@ -42,12 +42,12 @@ namespace OpenRA.Mods.RA.Scripting
return false;
}
[Desc("Returns true if func returns true for all values in table.")]
public bool All(LuaTable table, LuaFunction func)
[Desc("Returns true if func returns true for all elements in a collection.")]
public bool All(LuaValue[] collection, LuaFunction func)
{
foreach (var kv in table)
foreach (var c in collection)
{
using (var ret = func.Call(kv.Value))
using (var ret = func.Call(c))
{
var result = ret.FirstOrDefault();
if (result == null || !result.ToBoolean())
@@ -58,7 +58,7 @@ namespace OpenRA.Mods.RA.Scripting
return true;
}
[Desc("Skips over the first numElements members of the array and returns the rest.")]
[Desc("Skips over the first numElements members of a table and return the rest.")]
public LuaTable Skip(LuaTable table, int numElements)
{
var t = context.CreateTable();
@@ -69,26 +69,16 @@ namespace OpenRA.Mods.RA.Scripting
return t;
}
[Desc("Returns a random value from table.")]
public LuaValue Random(LuaTable table)
[Desc("Returns a random value from a collection.")]
public LuaValue Random(LuaValue[] collection)
{
return table.Values.Random<LuaValue>(context.World.SharedRandom);
return collection.Random(context.World.SharedRandom);
}
[Desc("Expands the given footprint one step along the coordinate axes, and (if requested) diagonals.")]
public LuaTable ExpandFootprint(LuaTable cells, bool allowDiagonal)
public CPos[] ExpandFootprint(CPos[] footprint, bool allowDiagonal)
{
var footprint = cells.Values.Select(c =>
{
CPos cell;
if (!c.TryGetClrValue<CPos>(out cell))
throw new LuaException("ExpandFootprint only accepts a table of CPos");
return cell;
});
var expanded = Traits.Util.ExpandFootprint(footprint, allowDiagonal);
return expanded.ToLuaTable(context);
return Traits.Util.ExpandFootprint(footprint, allowDiagonal).ToArray();
}
[Desc("Returns a random integer x in the range low &lt;= x &lt; high.")]

View File

@@ -26,11 +26,11 @@ namespace OpenRA.Mods.RA.Scripting
public string Name { get { return player.PlayerName; } }
[Desc("Returns an array of actors representing all ground attack units of this player.")]
public LuaTable GetGroundAttackers()
public Actor[] GetGroundAttackers()
{
return player.World.ActorsWithTrait<AttackBase>().Select(a => a.Actor)
.Where(a => a.Owner == player && !a.IsDead() && a.IsInWorld && a.HasTrait<Mobile>())
.Select(a => a.ToLuaValue(context)).ToLuaTable(context);
.ToArray();
}
}
}