Beispiel #1
0
        public void Run(ModData modData, string[] args)
        {
            // HACK: The engine code assumes that Game.modData is set.
            Game.ModData = modData;

            Console.WriteLine("This is an automatically generated listing 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 or 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 expose a collection of properties and commands that query information or 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();
            Console.WriteLine("For a basic guide about map scripts see the [`Map Scripting` wiki page](https://github.com/OpenRA/OpenRA/wiki/Map-scripting).");
            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))
                {
                    var 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>");
            }
        }
        void IUtilityCommand.Run(Utility utility, string[] args)
        {
            // HACK: The engine code assumes that Game.modData is set.
            Game.ModData = utility.ModData;

            Console.WriteLine("local interpreter = {");
            Console.WriteLine("  name = \"OpenRA\",");
            Console.WriteLine("  description = \"OpenRA map scripting Lua API\",");
            Console.WriteLine("  api = {\"baselib\", \"openra\"},");
            Console.WriteLine("  hasdebugger = false,");
            Console.WriteLine("  skipcompile = true,");
            Console.WriteLine("}");
            Console.WriteLine();

            Console.WriteLine("-- This is an automatically generated Lua API definition generated for {0} of OpenRA.", Game.ModData.Manifest.Metadata.Version);
            Console.WriteLine("-- https://github.com/OpenRA/OpenRA/wiki/Utility was used with the --zbstudio-lua-api parameter.");
            Console.WriteLine("-- See https://github.com/OpenRA/OpenRA/wiki/Lua-API for human readable documentation.");
            Console.WriteLine();
            Console.WriteLine("local api = {");

            var tables = Game.ModData.ObjectCreator.GetTypesImplementing <ScriptGlobal>().OrderBy(t => t.Name);

            foreach (var t in tables)
            {
                var name = t.GetCustomAttributes <ScriptGlobalAttribute>(true).First().Name;
                Console.WriteLine("  " + name + " = {");
                Console.WriteLine("    type = \"class\",");
                Console.WriteLine("    childs = {");

                var members = ScriptMemberWrapper.WrappableMembers(t);
                foreach (var member in members.OrderBy(m => m.Name))
                {
                    Console.WriteLine("      " + member.Name + " = {");
                    var methodInfo = member as MethodInfo;
                    if (methodInfo != null)
                    {
                        Console.WriteLine("        type = \"function\",");
                    }

                    var propertyInfo = member as PropertyInfo;
                    if (propertyInfo != null)
                    {
                        Console.WriteLine("        type = \"value\",");
                    }

                    if (member.HasAttribute <DescAttribute>())
                    {
                        var desc = member.GetCustomAttributes <DescAttribute>(true).First().Lines.JoinWith("\n");
                        Console.WriteLine("        description = [[{0}]],", desc);
                    }

                    if (methodInfo != null)
                    {
                        var parameters = methodInfo.GetParameters().Select(pi => pi.LuaDocString());
                        Console.WriteLine("        args = \"({0})\",", parameters.JoinWith(", "));

                        var returnType = methodInfo.ReturnType.LuaDocString();
                        Console.WriteLine("        returns = \"({0})\",", returnType);
                    }

                    Console.WriteLine("      },");
                }

                Console.WriteLine("    }");
                Console.WriteLine("  },");
            }

            var actorProperties = Game.ModData.ObjectCreator.GetTypesImplementing <ScriptActorProperties>().SelectMany(cg =>
            {
                return(ScriptMemberWrapper.WrappableMembers(cg));
            });

            var scriptProperties = Game.ModData.ObjectCreator.GetTypesImplementing <ScriptPlayerProperties>().SelectMany(cg =>
            {
                return(ScriptMemberWrapper.WrappableMembers(cg));
            });

            var properties = actorProperties.Concat(scriptProperties);

            foreach (var property in properties.OrderBy(m => m.Name))
            {
                Console.WriteLine("  " + property.Name + " = {");

                var methodInfo = property as MethodInfo;
                if (methodInfo != null)
                {
                    Console.WriteLine("    type = \"function\",");
                }

                var propertyInfo = property as PropertyInfo;
                if (propertyInfo != null)
                {
                    Console.WriteLine("    type = \"value\",");
                }

                if (property.HasAttribute <DescAttribute>())
                {
                    var desc = property.GetCustomAttributes <DescAttribute>(true).First().Lines.JoinWith("\n");
                    Console.WriteLine("    description = [[{0}]],", desc);
                }

                if (methodInfo != null)
                {
                    var parameters = methodInfo.GetParameters().Select(pi => pi.LuaDocString());
                    Console.WriteLine("    args = \"({0})\",", parameters.JoinWith(", "));

                    var returnType = methodInfo.ReturnType.LuaDocString();
                    Console.WriteLine("    returns = \"({0})\",", returnType);
                }

                Console.WriteLine("  },");
            }

            Console.WriteLine("}");
            Console.WriteLine();
            Console.WriteLine("return {");
            Console.WriteLine("  name = \"OpenRA\",");
            Console.WriteLine("  description = \"Adds API description for auto-complete and tooltip support for OpenRA.\",");
            Console.WriteLine("  author = \"Matthias Mailänder\",");
            Console.WriteLine($"  version = \"{Game.ModData.Manifest.Metadata.Version.Split('-').LastOrDefault()}\",");
            Console.WriteLine();
            Console.WriteLine("  onRegister = function(self)");
            Console.WriteLine("    ide:AddAPI(\"lua\", \"openra\", api)");
            Console.WriteLine("    ide:AddInterpreter(\"openra\", interpreter)");
            Console.WriteLine("  end,");
            Console.WriteLine();
            Console.WriteLine("  onUnRegister = function(self)");
            Console.WriteLine("    ide:RemoveAPI(\"lua\", \"openra\")");
            Console.WriteLine("    ide:RemoveInterpreter(\"openra\")");
            Console.WriteLine("  end,");
            Console.WriteLine("}");
        }
        void IUtilityCommand.Run(Utility utility, string[] args)
        {
            // HACK: The engine code assumes that Game.modData is set.
            Game.ModData = utility.ModData;

            var version = utility.ModData.Manifest.Metadata.Version;

            if (args.Length > 1)
            {
                version = args[1];
            }

            Console.WriteLine("This is an automatically generated listing of the Lua map scripting API for version {0} of OpenRA.", version);
            Console.WriteLine();
            Console.WriteLine("OpenRA allows custom maps and missions to be scripted using Lua 5.1.");
            Console.WriteLine("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:");
            Console.WriteLine();
            Console.WriteLine("* Global tables provide functions for interacting with the global world state, or performing general helper tasks.");
            Console.WriteLine("They exist in the global namespace, and can be called directly using ```<table name>.<function name>```.");
            Console.WriteLine("* Individual actors expose a collection of properties and commands that query information or modify their state.");
            Console.WriteLine("  * 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.");
            Console.WriteLine("* Individual players expose a collection of properties and commands that query information or modify their state.");
            Console.WriteLine("The properties and commands available on each actor depends on the traits that the actor specifies in its rule definitions.");
            Console.WriteLine();
            Console.WriteLine("For a basic guide about map scripts see the [`Map Scripting` wiki page](https://github.com/OpenRA/OpenRA/wiki/Map-scripting).");
            Console.WriteLine();

            var tables = utility.ModData.ObjectCreator.GetTypesImplementing <ScriptGlobal>()
                         .OrderBy(t => t.Name);

            Console.WriteLine("## Global Tables");

            foreach (var t in tables)
            {
                var name    = t.GetCustomAttributes <ScriptGlobalAttribute>(true).First().Name;
                var members = ScriptMemberWrapper.WrappableMembers(t);

                Console.WriteLine();
                Console.WriteLine("### " + name);
                Console.WriteLine();
                Console.WriteLine("| Function | Description |");
                Console.WriteLine("|---------:|-------------|");
                foreach (var m in members.OrderBy(m => m.Name))
                {
                    var desc = m.HasAttribute <DescAttribute>() ? m.GetCustomAttributes <DescAttribute>(true).First().Lines.JoinWith("<br />") : "";
                    Console.WriteLine($"| **{m.LuaDocString()}** | {desc} |");
                }
            }

            Console.WriteLine();

            Console.WriteLine("## Actor Properties / Commands");

            var actorCategories = utility.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 => (category, mi, required)));
            }).GroupBy(g => g.Item1).OrderBy(g => g.Key);

            foreach (var kv in actorCategories)
            {
                Console.WriteLine();
                Console.WriteLine("### " + kv.Key);
                Console.WriteLine();
                Console.WriteLine("| Function | Description |");
                Console.WriteLine("|---------:|-------------|");

                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.Write($"| **{mi.LuaDocString()}**");

                    if (isActivity)
                    {
                        Console.Write("<br />*Queued Activity*");
                    }

                    Console.Write(" | ");

                    if (hasDesc)
                    {
                        Console.Write(mi.GetCustomAttributes <DescAttribute>(false).First().Lines.JoinWith("<br />"));
                    }

                    if (hasDesc && hasRequires)
                    {
                        Console.Write("<br />");
                    }

                    if (hasRequires)
                    {
                        Console.Write($"**Requires {(required.Length == 1 ? "Trait" : "Traits")}:** {required.JoinWith(", ")}");
                    }

                    Console.WriteLine(" |");
                }
            }

            Console.WriteLine();

            Console.WriteLine("## Player Properties / Commands");

            var playerCategories = utility.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 => (category, mi, required)));
            }).GroupBy(g => g.Item1).OrderBy(g => g.Key);

            foreach (var kv in playerCategories)
            {
                Console.WriteLine();
                Console.WriteLine("### " + kv.Key);
                Console.WriteLine();
                Console.WriteLine("| Function | Description |");
                Console.WriteLine("|---------:|-------------|");

                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.Write($"| **{mi.LuaDocString()}**");

                    if (isActivity)
                    {
                        Console.Write("<br />*Queued Activity*");
                    }

                    Console.Write(" | ");

                    if (hasDesc)
                    {
                        Console.Write(mi.GetCustomAttributes <DescAttribute>(false).First().Lines.JoinWith("<br />"));
                    }

                    if (hasDesc && hasRequires)
                    {
                        Console.Write("<br />");
                    }

                    if (hasRequires)
                    {
                        Console.Write($"**Requires {(required.Length == 1 ? "Trait" : "Traits")}:** {required.JoinWith(", ")}");
                    }

                    Console.WriteLine(" |");
                }

                Console.WriteLine();
            }
        }