diff --git a/OpenRA.Editor/Form1.cs b/OpenRA.Editor/Form1.cs index e165fbaeed..f465ba493c 100644 --- a/OpenRA.Editor/Form1.cs +++ b/OpenRA.Editor/Form1.cs @@ -33,7 +33,7 @@ namespace OpenRA.Editor Text = "OpenRA Editor (mod:{0})".F(currentMod); var manifest = new Manifest(new[] { currentMod }); - Game.LoadModAssemblies(manifest); + Game.modData = new ModData( manifest ); FileSystem.UnmountAll(); foreach (var folder in manifest.Folders) FileSystem.Mount(folder); @@ -63,7 +63,7 @@ namespace OpenRA.Editor loadedMapName = mapname; var manifest = new Manifest(new[] { currentMod }); - Game.LoadModAssemblies(manifest); + Game.modData = new ModData( manifest ); FileSystem.UnmountAll(); foreach (var folder in manifest.Folders) FileSystem.Mount(folder); @@ -92,7 +92,7 @@ namespace OpenRA.Editor loadedMapName = null; var manifest = new Manifest(new[] { currentMod }); - Game.LoadModAssemblies(manifest); + Game.modData = new ModData( manifest ); FileSystem.UnmountAll(); foreach (var folder in manifest.Folders) FileSystem.Mount(folder); diff --git a/OpenRA.Game/Game.cs b/OpenRA.Game/Game.cs index b588805d7b..f01efbd4b0 100644 --- a/OpenRA.Game/Game.cs +++ b/OpenRA.Game/Game.cs @@ -35,6 +35,7 @@ namespace OpenRA { public static readonly int CellSize = 24; + public static ModData modData; public static World world; public static Viewport viewport; public static UserSettings Settings; @@ -49,53 +50,18 @@ namespace OpenRA public static Session LobbyInfo = new Session(); static bool packageChangePending; static bool mapChangePending; - static Pair[] ModAssemblies; - static void LoadModPackages() + static void LoadModPackages( Manifest manifest ) { FileSystem.UnmountAll(); Timer.Time("reset: {0}"); - foreach (var dir in Manifest.Folders) FileSystem.Mount(dir); - foreach (var pkg in Manifest.Packages) FileSystem.Mount(pkg); + foreach (var dir in manifest.Folders) FileSystem.Mount(dir); + foreach (var pkg in manifest.Packages) FileSystem.Mount(pkg); Timer.Time("mount temporary packages: {0}"); } - public static void LoadModAssemblies(Manifest m) - { - // All the core namespaces - var asms = typeof(Game).Assembly.GetNamespaces() - .Select(c => Pair.New(typeof(Game).Assembly, c)) - .ToList(); - - // Namespaces from each mod assembly - foreach (var a in m.Assemblies) - { - var asm = Assembly.LoadFile(Path.GetFullPath(a)); - asms.AddRange(asm.GetNamespaces().Select(ns => Pair.New(asm, ns))); - } - - ModAssemblies = asms.ToArray(); - } - - public static Action MissingTypeAction = - s => { throw new InvalidOperationException("Cannot locate type: {0}".F(s)); }; - - public static T CreateObject(string classname) - { - foreach (var mod in ModAssemblies) - { - var fullTypeName = mod.Second + "." + classname; - var obj = mod.First.CreateInstance(fullTypeName); - if (obj != null) - return (T)obj; - } - - MissingTypeAction(classname); - return default(T); - } - public static Dictionary AvailableMaps; // TODO: Do this nicer @@ -111,23 +77,22 @@ namespace OpenRA static void ChangeMods() { Timer.Time("----ChangeMods"); - Manifest = new Manifest(LobbyInfo.GlobalSettings.Mods); + var manifest = new Manifest(LobbyInfo.GlobalSettings.Mods); Timer.Time("manifest: {0}"); - LoadModAssemblies(Manifest); + modData = new ModData( manifest ); SheetBuilder.Initialize(); - LoadModPackages(); + LoadModPackages( manifest ); Timer.Time("load assemblies, packages: {0}"); - ChromeProvider.Initialize(Manifest.Chrome); + ChromeProvider.Initialize(manifest.Chrome); packageChangePending = false; } - public static Manifest Manifest; - static void LoadMap(string mapName) { Timer.Time("----LoadMap"); SheetBuilder.Initialize(); - Manifest = new Manifest(LobbyInfo.GlobalSettings.Mods); + var manifest = new Manifest(LobbyInfo.GlobalSettings.Mods); + modData = new ModData( manifest ); Timer.Time("manifest: {0}"); if (!Game.AvailableMaps.ContainsKey(mapName)) @@ -139,14 +104,14 @@ namespace OpenRA world = null; // trying to access the old world will NRE, rather than silently doing it wrong. Timer.Time("viewport: {0}"); - Rules.LoadRules(Manifest,map); + Rules.LoadRules(manifest,map); Timer.Time( "load rules: {0}" ); SpriteSheetBuilder.Initialize( Rules.TileSets[map.Tileset] ); - SequenceProvider.Initialize(Manifest.Sequences); + SequenceProvider.Initialize(manifest.Sequences); Timer.Time("SeqProv: {0}"); - world = new World(Manifest, map); + world = new World(manifest, map); Timer.Time("world: {0}"); Timer.Time("----end LoadMap"); @@ -355,8 +320,8 @@ namespace OpenRA LobbyInfo = session; - if (!world.GameHasStarted) - world.SharedRandom = new OpenRA.Thirdparty.Random(LobbyInfo.GlobalSettings.RandomSeed); + if( !world.GameHasStarted ) + world.SharedRandom = new OpenRA.Thirdparty.Random( LobbyInfo.GlobalSettings.RandomSeed ); if (orderManager.Connection.ConnectionState == ConnectionState.Connected) world.SetLocalPlayer(orderManager.Connection.LocalClientId); @@ -495,10 +460,11 @@ namespace OpenRA Log.AddChannel("sync", "syncreport.log"); LobbyInfo.GlobalSettings.Mods = Settings.InitialMods; - Manifest = new Manifest(LobbyInfo.GlobalSettings.Mods); + var manifest = new Manifest(LobbyInfo.GlobalSettings.Mods); + modData = new ModData( manifest ); // Load the default mod to access required files - LoadModPackages(); + LoadModPackages( manifest ); Renderer.SheetSize = Settings.SheetSize; @@ -521,7 +487,7 @@ namespace OpenRA else JoinLocal(); - StartGame(Manifest.ShellmapUid); + StartGame(manifest.ShellmapUid); ResetTimer(); @@ -549,7 +515,7 @@ namespace OpenRA public static void Disconnect() { orderManager.Dispose(); - var shellmap = Manifest.ShellmapUid; + var shellmap = modData.Manifest.ShellmapUid; LobbyInfo = new Session(); LobbyInfo.GlobalSettings.Mods = Settings.InitialMods; JoinLocal(); @@ -580,14 +546,19 @@ namespace OpenRA public static void InitializeEngineWithMods(string[] mods) { AppDomain.CurrentDomain.AssemblyResolve += FileSystem.ResolveAssembly; - Manifest = new Manifest(mods); - LoadModAssemblies(Manifest); + var manifest = new Manifest(mods); + modData = new ModData( manifest ); FileSystem.UnmountAll(); - foreach (var folder in Manifest.Folders) FileSystem.Mount(folder); - foreach (var pkg in Manifest.Packages) FileSystem.Mount(pkg); + foreach (var folder in manifest.Folders) FileSystem.Mount(folder); + foreach (var pkg in manifest.Packages) FileSystem.Mount(pkg); - Rules.LoadRules(Manifest, new Map()); + Rules.LoadRules(manifest, new Map()); + } + + public static T CreateObject( string name ) + { + return modData.ObjectCreator.CreateObject( name ); } } } diff --git a/OpenRA.Game/ModData.cs b/OpenRA.Game/ModData.cs new file mode 100755 index 0000000000..91e621163f --- /dev/null +++ b/OpenRA.Game/ModData.cs @@ -0,0 +1,20 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using OpenRA.FileFormats; + +namespace OpenRA +{ + public class ModData + { + public readonly Manifest Manifest; + public readonly ObjectCreator ObjectCreator; + + public ModData( Manifest manifest ) + { + Manifest = manifest; + ObjectCreator = new ObjectCreator( manifest ); + } + } +} diff --git a/OpenRA.Game/ObjectCreator.cs b/OpenRA.Game/ObjectCreator.cs new file mode 100755 index 0000000000..2d5aab0a83 --- /dev/null +++ b/OpenRA.Game/ObjectCreator.cs @@ -0,0 +1,50 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using OpenRA.FileFormats; +using System.Reflection; +using System.IO; + +namespace OpenRA +{ + public class ObjectCreator + { + Pair[] ModAssemblies; + + public ObjectCreator( Manifest manifest ) + { + // All the core namespaces + var asms = typeof(Game).Assembly.GetNamespaces() + .Select(c => Pair.New(typeof(Game).Assembly, c)) + .ToList(); + + // Namespaces from each mod assembly + foreach (var a in manifest.Assemblies) + { + var asm = Assembly.LoadFile(Path.GetFullPath(a)); + asms.AddRange(asm.GetNamespaces().Select(ns => Pair.New(asm, ns))); + } + + ModAssemblies = asms.ToArray(); + } + + public static Action MissingTypeAction = + s => { throw new InvalidOperationException("Cannot locate type: {0}".F(s)); }; + + public T CreateObject(string classname) + { + foreach (var mod in ModAssemblies) + { + var fullTypeName = mod.Second + "." + classname; + var obj = mod.First.CreateInstance(fullTypeName); + if (obj != null) + return (T)obj; + } + + MissingTypeAction(classname); + return default(T); + } + + } +} diff --git a/OpenRA.Game/OpenRA.Game.csproj b/OpenRA.Game/OpenRA.Game.csproj index 6e0c2b5b9c..42d76f2455 100755 --- a/OpenRA.Game/OpenRA.Game.csproj +++ b/OpenRA.Game/OpenRA.Game.csproj @@ -1,4 +1,4 @@ - + Debug @@ -232,7 +232,9 @@ + + diff --git a/OpenRA.Game/Widgets/Widget.cs b/OpenRA.Game/Widgets/Widget.cs index 907dfec966..df42cca714 100644 --- a/OpenRA.Game/Widgets/Widget.cs +++ b/OpenRA.Game/Widgets/Widget.cs @@ -54,7 +54,7 @@ namespace OpenRA.Widgets if (rootWidget == null) { rootWidget = new ContainerWidget(); - foreach( var file in Game.Manifest.ChromeLayout.Select( a => MiniYaml.FromFile( a ) ) ) + foreach( var file in Game.modData.Manifest.ChromeLayout.Select( a => MiniYaml.FromFile( a ) ) ) foreach( var w in file ) rootWidget.AddChild( WidgetLoader.LoadWidget( w ) ); diff --git a/RALint/RALint.cs b/RALint/RALint.cs index 4ec929db57..eb2a9bac64 100644 --- a/RALint/RALint.cs +++ b/RALint/RALint.cs @@ -36,7 +36,7 @@ namespace RALint try { // bind some nonfatal error handling into FieldLoader, so we don't just *explode*. - Game.MissingTypeAction = s => EmitError("Missing Type: {0}".F(s)); + ObjectCreator.MissingTypeAction = s => EmitError("Missing Type: {0}".F(s)); FieldLoader.UnknownFieldAction = (s, f) => EmitError("FieldLoader: Missing field `{0}` on `{1}`".F(s, f.Name)); Game.InitializeEngineWithMods(args);