Add a new native-lua implementation.
This commit is contained in:
@@ -17,10 +17,14 @@ using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using Eluant;
|
||||
using Eluant.ObjectBinding;
|
||||
using OpenRA.FileFormats;
|
||||
using OpenRA.FileSystem;
|
||||
using OpenRA.GameRules;
|
||||
using OpenRA.Graphics;
|
||||
using OpenRA.Primitives;
|
||||
using OpenRA.Scripting;
|
||||
using OpenRA.Traits;
|
||||
|
||||
namespace OpenRA.Utility
|
||||
@@ -340,6 +344,157 @@ namespace OpenRA.Utility
|
||||
Console.Write(doc.ToString());
|
||||
}
|
||||
|
||||
static string[] RequiredTraitNames(Type t)
|
||||
{
|
||||
// Returns the inner types of all the Requires<T> interfaces on this type
|
||||
var outer = t.GetInterfaces()
|
||||
.Where(i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(Requires<>));
|
||||
|
||||
// Get the inner types
|
||||
var inner = outer.SelectMany(i => i.GetGenericArguments()).ToArray();
|
||||
|
||||
// Remove the namespace and the trailing "Info"
|
||||
return inner.Select(i => i.Name.Split(new [] { '.' }, StringSplitOptions.RemoveEmptyEntries).LastOrDefault())
|
||||
.Select(s => s.EndsWith("Info") ? s.Remove(s.Length - 4, 4) : s)
|
||||
.ToArray();
|
||||
}
|
||||
|
||||
[Desc("MOD", "Generate Lua API documentation in MarkDown format.")]
|
||||
public static void ExtractLuaDocs(string[] args)
|
||||
{
|
||||
Game.modData = new ModData(args[1]);
|
||||
Rules.LoadRules(Game.modData.Manifest, new Map());
|
||||
|
||||
Console.WriteLine("This is an automatically generated lising of the new Lua map scripting API, generated for {0} of OpenRA.", Game.modData.Manifest.Mod.Version);
|
||||
Console.WriteLine();
|
||||
Console.WriteLine("OpenRA allows custom maps and missions to be scripted using Lua 5.1.\n" +
|
||||
"These scripts run in a sandbox that prevents access to unsafe functions (e.g. OS or file access), " +
|
||||
"and limits the memory and CPU usage of the scripts.");
|
||||
Console.WriteLine();
|
||||
Console.WriteLine("You can access this interface by adding the [LuaScript](Traits#luascript) trait to the world actor in your map rules (note, you must replace the spaces in the snippet below with a single tab for each level of indentation):");
|
||||
Console.WriteLine("```\nRules:\n\tWorld:\n\t\tLuaScript:\n\t\t\tScripts: myscript.lua\n```");
|
||||
Console.WriteLine();
|
||||
Console.WriteLine("Map scripts can interact with the game engine in three ways:\n" +
|
||||
"* Global tables provide functions for interacting with the global world state, or performing general helper tasks.\n" +
|
||||
"They exist in the global namespace, and can be called directly using ```<table name>.<function name>```.\n" +
|
||||
"* Individual actors expose a collection of properties and commands that query information of modify their state.\n" +
|
||||
" * Some commands, marked as <em>queued activity</em>, are asynchronous. Activities are queued on the actor, and will run in " +
|
||||
"sequence until the queue is empty or the Stop command is called. Actors that are not performing an activity are Idle " +
|
||||
"(actor.IsIdle will return true). The properties and commands available on each actor depends on the traits that the actor " +
|
||||
"specifies in its rule definitions.\n" +
|
||||
"* Individual players explose a collection of properties and commands that query information of modify their state.\n" +
|
||||
"The properties and commands available on each actor depends on the traits that the actor specifies in its rule definitions.\n");
|
||||
Console.WriteLine();
|
||||
|
||||
var tables = Game.modData.ObjectCreator.GetTypesImplementing<ScriptGlobal>()
|
||||
.OrderBy(t => t.Name);
|
||||
|
||||
Console.WriteLine("<h3>Global Tables</h3>");
|
||||
|
||||
foreach (var t in tables)
|
||||
{
|
||||
var name = t.GetCustomAttributes<ScriptGlobalAttribute>(true).First().Name;
|
||||
var members = ScriptMemberWrapper.WrappableMembers(t);
|
||||
|
||||
Console.WriteLine("<table align=\"center\" width=\"1024\"><tr><th colspan=\"2\" width=\"1024\">{0}</th></tr>", name);
|
||||
foreach (var m in members.OrderBy(m => m.Name))
|
||||
{
|
||||
string desc = m.HasAttribute<DescAttribute>() ? m.GetCustomAttributes<DescAttribute>(true).First().Lines.JoinWith("\n") : "";
|
||||
Console.WriteLine("<tr><td align=\"right\" width=\"50%\"><strong>{0}</strong></td><td>{1}</td></tr>".F(m.LuaDocString(), desc));
|
||||
}
|
||||
Console.WriteLine("</table>");
|
||||
}
|
||||
|
||||
Console.WriteLine("<h3>Actor Properties / Commands</h3>");
|
||||
|
||||
var actorCategories = Game.modData.ObjectCreator.GetTypesImplementing<ScriptActorProperties>().SelectMany(cg =>
|
||||
{
|
||||
var catAttr = cg.GetCustomAttributes<ScriptPropertyGroupAttribute>(false).FirstOrDefault();
|
||||
var category = catAttr != null ? catAttr.Category : "Unsorted";
|
||||
|
||||
var required = RequiredTraitNames(cg);
|
||||
return ScriptMemberWrapper.WrappableMembers(cg).Select(mi => Tuple.Create(category, mi, required));
|
||||
}).GroupBy(g => g.Item1).OrderBy(g => g.Key);
|
||||
|
||||
foreach (var kv in actorCategories)
|
||||
{
|
||||
Console.WriteLine("<table align=\"center\" width=\"1024\"><tr><th colspan=\"2\" width=\"1024\">{0}</th></tr>", kv.Key);
|
||||
|
||||
foreach (var property in kv.OrderBy(p => p.Item2.Name))
|
||||
{
|
||||
var mi = property.Item2;
|
||||
var required = property.Item3;
|
||||
var hasDesc = mi.HasAttribute<DescAttribute>();
|
||||
var hasRequires = required.Any();
|
||||
var isActivity = mi.HasAttribute<ScriptActorPropertyActivityAttribute>();
|
||||
|
||||
Console.WriteLine("<tr><td width=\"50%\" align=\"right\"><strong>{0}</strong>", mi.LuaDocString());
|
||||
|
||||
if (isActivity)
|
||||
Console.WriteLine("<br /><em>Queued Activity</em>");
|
||||
|
||||
Console.WriteLine("</td><td>");
|
||||
|
||||
if (hasDesc)
|
||||
Console.WriteLine(mi.GetCustomAttributes<DescAttribute>(false).First().Lines.JoinWith("\n"));
|
||||
|
||||
if (hasDesc && hasRequires)
|
||||
Console.WriteLine("<br />");
|
||||
|
||||
if (hasRequires)
|
||||
Console.WriteLine("<b>Requires {1}:</b> {0}".F(required.JoinWith(", "), required.Length == 1 ? "Trait" : "Traits"));
|
||||
|
||||
Console.WriteLine("</td></tr>");
|
||||
}
|
||||
Console.WriteLine("</table>");
|
||||
}
|
||||
|
||||
Console.WriteLine("<h3>Player Properties / Commands</h3>");
|
||||
|
||||
var playerCategories = Game.modData.ObjectCreator.GetTypesImplementing<ScriptPlayerProperties>().SelectMany(cg =>
|
||||
{
|
||||
var catAttr = cg.GetCustomAttributes<ScriptPropertyGroupAttribute>(false).FirstOrDefault();
|
||||
var category = catAttr != null ? catAttr.Category : "Unsorted";
|
||||
|
||||
var required = RequiredTraitNames(cg);
|
||||
return ScriptMemberWrapper.WrappableMembers(cg).Select(mi => Tuple.Create(category, mi, required));
|
||||
}).GroupBy(g => g.Item1).OrderBy(g => g.Key);
|
||||
|
||||
foreach (var kv in playerCategories)
|
||||
{
|
||||
Console.WriteLine("<table align=\"center\" width=\"1024\"><tr><th colspan=\"2\" width=\"1024\">{0}</th></tr>", kv.Key);
|
||||
|
||||
foreach (var property in kv.OrderBy(p => p.Item2.Name))
|
||||
{
|
||||
var mi = property.Item2;
|
||||
var required = property.Item3;
|
||||
var hasDesc = mi.HasAttribute<DescAttribute>();
|
||||
var hasRequires = required.Any();
|
||||
var isActivity = mi.HasAttribute<ScriptActorPropertyActivityAttribute>();
|
||||
|
||||
Console.WriteLine("<tr><td width=\"50%\" align=\"right\"><strong>{0}</strong>", mi.LuaDocString());
|
||||
|
||||
if (isActivity)
|
||||
Console.WriteLine("<br /><em>Queued Activity</em>");
|
||||
|
||||
Console.WriteLine("</td><td>");
|
||||
|
||||
if (hasDesc)
|
||||
Console.WriteLine(mi.GetCustomAttributes<DescAttribute>(false).First().Lines.JoinWith("\n"));
|
||||
|
||||
if (hasDesc && hasRequires)
|
||||
Console.WriteLine("<br />");
|
||||
|
||||
if (hasRequires)
|
||||
Console.WriteLine("<b>Requires {1}:</b> {0}".F(required.JoinWith(", "), required.Length == 1 ? "Trait" : "Traits"));
|
||||
|
||||
Console.WriteLine("</td></tr>");
|
||||
}
|
||||
|
||||
Console.WriteLine("</table>");
|
||||
}
|
||||
}
|
||||
|
||||
[Desc("MAPFILE", "Generate hash of specified oramap file.")]
|
||||
public static void GetMapHash(string[] args)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user