diff --git a/OpenRA.FileFormats/Mod.cs b/OpenRA.FileFormats/Mod.cs new file mode 100644 index 0000000000..a73ae3fd0c --- /dev/null +++ b/OpenRA.FileFormats/Mod.cs @@ -0,0 +1,40 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.IO; + +namespace OpenRA.FileFormats +{ + public class Mod + { + public string Title; + public string Description; + public string Version; + public string Author; + public string[] RequiresMods; + public bool Standalone = false; + + public static readonly Dictionary AllMods = ValidateMods(Directory.GetDirectories("mods").Select(x => x.Substring(5)).ToArray()); + + public static Dictionary ValidateMods(string[] mods) + { + var ret = new Dictionary(); + foreach (var m in mods) + { + if (!File.Exists("mods" + Path.DirectorySeparatorChar + m + Path.DirectorySeparatorChar + "mod.yaml")) + continue; + + var yaml = new MiniYaml(null, MiniYaml.FromFile("mods" + Path.DirectorySeparatorChar + m + Path.DirectorySeparatorChar + "mod.yaml")); + if (!yaml.NodesDict.ContainsKey("Metadata")) + { + System.Console.WriteLine("Invalid mod: " + m); + continue; + } + + ret.Add(m, FieldLoader.Load(yaml.NodesDict["Metadata"])); + } + return ret; + } + } +} diff --git a/OpenRA.FileFormats/OpenRA.FileFormats.csproj b/OpenRA.FileFormats/OpenRA.FileFormats.csproj index 51d81a7bff..e0abdd058f 100644 --- a/OpenRA.FileFormats/OpenRA.FileFormats.csproj +++ b/OpenRA.FileFormats/OpenRA.FileFormats.csproj @@ -3,7 +3,7 @@ Debug AnyCPU - 9.0.21022 + 9.0.30729 2.0 {BDAEAB25-991E-46A7-AF1E-4F0E03358DAA} Library @@ -64,6 +64,7 @@ + diff --git a/OpenRA.Game/Game.cs b/OpenRA.Game/Game.cs index a282b3f7af..54eb9e5cb4 100644 --- a/OpenRA.Game/Game.cs +++ b/OpenRA.Game/Game.cs @@ -239,11 +239,11 @@ namespace OpenRA Renderer = new Renderer(); Console.WriteLine("Available mods:"); - foreach(var mod in ModData.AllMods) + foreach(var mod in Mod.AllMods) Console.WriteLine("\t{0}: {1} ({2})", mod.Key, mod.Value.Title, mod.Value.Version); // Discard any invalid mods - var mods = Settings.Game.Mods.Where( m => ModData.AllMods.ContainsKey( m ) ).ToArray(); + var mods = Settings.Game.Mods.Where( m => Mod.AllMods.ContainsKey( m ) ).ToArray(); Console.WriteLine("Loading mods: {0}",string.Join(",",mods)); modData = new ModData( mods ); diff --git a/OpenRA.Game/ModData.cs b/OpenRA.Game/ModData.cs index 99f52392fc..277fbf5833 100755 --- a/OpenRA.Game/ModData.cs +++ b/OpenRA.Game/ModData.cs @@ -19,38 +19,6 @@ namespace OpenRA { public class ModData { - public static readonly Dictionary AllMods = ValidateMods(Directory.GetDirectories("mods").Select(x => x.Substring(5)).ToArray()); - - public static Dictionary ValidateMods(string[] mods) - { - var ret = new Dictionary(); - foreach (var m in mods) - { - if (!File.Exists("mods" + Path.DirectorySeparatorChar + m + Path.DirectorySeparatorChar + "mod.yaml")) - continue; - - var yaml = new MiniYaml( null, MiniYaml.FromFile("mods" + Path.DirectorySeparatorChar + m + Path.DirectorySeparatorChar + "mod.yaml")); - if (!yaml.NodesDict.ContainsKey("Metadata")) - { - System.Console.WriteLine("Invalid mod: "+m); - continue; - } - - ret.Add(m,FieldLoader.Load(yaml.NodesDict["Metadata"])); - } - return ret; - } - - public class Mod - { - public string Title; - public string Description; - public string Version; - public string Author; - public string[] RequiresMods; - public bool Standalone = false; - } - public readonly Manifest Manifest; public readonly ObjectCreator ObjectCreator; public readonly SheetBuilder SheetBuilder; diff --git a/OpenRA.Game/Widgets/Delegates/ServerBrowserDelegate.cs b/OpenRA.Game/Widgets/Delegates/ServerBrowserDelegate.cs index bdc46cb971..1c213ce789 100644 --- a/OpenRA.Game/Widgets/Delegates/ServerBrowserDelegate.cs +++ b/OpenRA.Game/Widgets/Delegates/ServerBrowserDelegate.cs @@ -124,7 +124,7 @@ namespace OpenRA.Widgets.Delegates string GenerateModsLabel() { return string.Join("\n", currentServer.Mods.Select(m => - ModData.AllMods.ContainsKey(m) ? string.Format("{0} ({1})", ModData.AllMods[m].Title, ModData.AllMods[m].Version) + Mod.AllMods.ContainsKey(m) ? string.Format("{0} ({1})", Mod.AllMods[m].Title, Mod.AllMods[m].Version) : string.Format("Unknown Mod: {0}",m)).ToArray()); } diff --git a/OpenRA.Utility/OpenRA.Utility.csproj b/OpenRA.Utility/OpenRA.Utility.csproj new file mode 100644 index 0000000000..0ecd8aedc8 --- /dev/null +++ b/OpenRA.Utility/OpenRA.Utility.csproj @@ -0,0 +1,65 @@ + + + + Debug + AnyCPU + 9.0.30729 + 2.0 + {F33337BE-CB69-4B24-850F-07D23E408DDF} + Exe + Properties + OpenRA.Utility + OpenRA.Utility + v3.5 + 512 + + + true + full + false + ..\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + + 3.5 + + + 3.5 + + + 3.5 + + + + + + + + + + + {BDAEAB25-991E-46A7-AF1E-4F0E03358DAA} + OpenRA.FileFormats + + + + + \ No newline at end of file diff --git a/OpenRA.Utility/Program.cs b/OpenRA.Utility/Program.cs new file mode 100644 index 0000000000..b7de82e9af --- /dev/null +++ b/OpenRA.Utility/Program.cs @@ -0,0 +1,27 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using OpenRA.FileFormats; + +namespace OpenRA.Utility +{ + class Program + { + static void Main(string[] args) + { + for (int i = 0; i < args.Length; i++) + { + switch (args[i]) + { + case "--list-mods": + foreach (var m in Mod.AllMods.Select( x => x.Key )) + Console.WriteLine(m); + break; + default: + break; + } + } + } + } +} diff --git a/OpenRA.Utility/Properties/AssemblyInfo.cs b/OpenRA.Utility/Properties/AssemblyInfo.cs new file mode 100644 index 0000000000..38c3031c4d --- /dev/null +++ b/OpenRA.Utility/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("OpenRA.Utility")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("OpenRA")] +[assembly: AssemblyCopyright("Copyright © 2010 OpenRA Development Team")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("64363ecc-4102-4a38-a108-427de0af5dcb")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/OpenRA.sln b/OpenRA.sln index f25a2195f4..3d1a695d05 100644 --- a/OpenRA.sln +++ b/OpenRA.sln @@ -27,6 +27,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RALint", "RALint\RALint.csp EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FileExtractor", "FileExtractor\FileExtractor.csproj", "{210645C7-E99E-46B6-863E-E211AE6C7D70}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OpenRA.Utility", "OpenRA.Utility\OpenRA.Utility.csproj", "{F33337BE-CB69-4B24-850F-07D23E408DDF}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -114,6 +116,14 @@ Global {210645C7-E99E-46B6-863E-E211AE6C7D70}.Release|Any CPU.Build.0 = Release|Any CPU {210645C7-E99E-46B6-863E-E211AE6C7D70}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU {210645C7-E99E-46B6-863E-E211AE6C7D70}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {F33337BE-CB69-4B24-850F-07D23E408DDF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F33337BE-CB69-4B24-850F-07D23E408DDF}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F33337BE-CB69-4B24-850F-07D23E408DDF}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {F33337BE-CB69-4B24-850F-07D23E408DDF}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {F33337BE-CB69-4B24-850F-07D23E408DDF}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F33337BE-CB69-4B24-850F-07D23E408DDF}.Release|Any CPU.Build.0 = Release|Any CPU + {F33337BE-CB69-4B24-850F-07D23E408DDF}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {F33337BE-CB69-4B24-850F-07D23E408DDF}.Release|Mixed Platforms.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/doc/launcher.txt b/doc/launcher.txt new file mode 100644 index 0000000000..71bcb999f2 --- /dev/null +++ b/doc/launcher.txt @@ -0,0 +1,60 @@ +Crossplatform "Launcher" ideas: + +provides facility for commands like "--install-ra-packages", etc instead of having to reinvent the wheel on each platform. + Command ideas: + --list-mods: Simple list of available mods + - This is already done on game init, just needs pulling somewhere generic + --mod-info : Metadata on specific mod + --list-mod-heirarchy: Like above, but shows mod heirarchy + Is this needed? With a combination of listing and mod info, you can easily build the tree yourself. But if every platform has to do this, we may as well share the code. *shrug* its not a big deal at this stage. + --install-ra-music : Extracts scores.mix and copies it to the ra/packages dir + --install-cnc-music : Copies scores.mix from cnc disk to cnc/packages dir + --download-(ra|cnc)-packages: downloads ds and extracts packages from web + --install-(ra|cnc)-packages : copies required files from ra/cnc cd + +Implementation: + Either separate exe or in the OpenRA.Game executable as a cli interface for modifying + the game install. + Platform specific guis that call the appropriate commands, and launch the game itself. + + Separate Exe: <-- lets go with this for the first version. It can link against Fileformats to get + the mix extraction and mod list stuff. + Pros: + Small + Doesn't clutter main executable with functionality not used elsewhere. + Cons: + + OpenRA.Game executable: + Pros: + + Cons: + +Platform specific gui scope: + -- Allow setting basic settings before launch? (toggle fullscreen is frequently asked for) + This would be a nice feature given setting them in game requires a restart. + Lets limit this to graphical settings. I'd rather not reinvent the wheel for things that + don't need it. + -- Give an overview of installed mods. + -- Install new mods from site/downloaded archive. + -- Install new maps for a mod. + -- Update core game and mods + -- Launch game with a selection of mods. + -- Also allow the user to set custom commandline args + Via GUI selection? Via a textfield below the mods checkbox + That would be unfriendly to a lot of users or is this for "power user" options? + Power users. It can be hidden behind a toggle/pref if necessary. + +Gameplan: + -- Start by building the cli interface, and hook up the existing postinstall scripts to use them + -- Code for listing mods exists, move this into fileformats (for --list-mods) + -- Code for extracting files from mixes exists in fileformats (for --install-ra-music). + -- Copying files: filesystem permissions? Do we require root? How do we handle this? + We do on Windows and Linux at least. Unless we do per user. + -- Is installing files to the support dir acceptable? + For mods, perhaps. For core game: no. + -- Gui launchers can run the cli app with appropriate permissions. cli can be dumb. + -- Require code to download files from intarwebs, and report progress to stdout. + This is about the only non-trivial code that we need to write. Its still relatively trivial. + -- Platform-specific maintainers work on their own launcher later + -- ???? +