/// <summary> /// Adds another LoaderInfo to the current result set. /// </summary> /// <param name="info">Additional LoaderInfo</param> public void AddRange(LoaderInfo info) { Campaigns.AddRange(info.Campaigns); Errors.AddRange(info.Errors); Levels.AddRange(info.Levels); Players.AddRange(info.Players); }
/// <summary> /// Searches in the given Assembly for the requested Player Type within a closed AppDomain. /// </summary> /// <param name="extensionPaths">List of pathes to search for Extensions</param> /// <param name="file">Filedump of the Assembly</param> /// <param name="typeName">Name of the Type</param> /// <returns>PlayerInfo of the fitting Player or null in case of no result</returns> public static PlayerInfo SecureFindPlayer(string[] extensionPaths, byte[] file, string typeName) { LoaderInfo info = SecureAnalyseExtension(extensionPaths, file, false, true); foreach (var player in info.Players) { if (player.Type.TypeName.Equals(typeName)) { return(player); } } return(null); }
/// <summary> /// Searches in the given Assembly for the requested Level Type within a closed AppDomain. /// </summary> /// <param name="extensionPaths">List of pathes to search for Extensions</param> /// <param name="file">Filedump of the Assembly</param> /// <param name="typeName">Name of the Type</param> /// <returns>LevelInfo of the fitting Level or null in case of no result</returns> public static LevelInfo SecureFindLevel(string[] extensionPaths, byte[] file, string typeName) { LoaderInfo info = SecureAnalyseExtension(extensionPaths, file, true, false); foreach (var level in info.Levels) { if (level.Type.TypeName.Equals(typeName)) { return(level); } } return(null); }
/// <summary> /// Scans the given Assembly for additional Level-, Campaign- and Player-Elements within a closed AppDomain. /// </summary> /// <param name="extensionPaths">List of pathes to search for Extensions</param> /// <param name="file">Filedump</param> /// <param name="level">Search for Levels and Campagins</param> /// <param name="player">Search for Players</param> /// <returns>Collection of found Elements and occured Errors</returns> public static LoaderInfo SecureAnalyseExtension(string[] extensionPaths, byte[] file, bool level, bool player) { AppDomainSetup setup = new AppDomainSetup(); setup.ApplicationBase = AppDomain.CurrentDomain.SetupInformation.ApplicationBase; Evidence evidence = new Evidence(); AppDomain appDomain = AppDomain.CreateDomain("AntMe! Analyzer", evidence, setup); Type hostType = typeof(ExtensionLoaderHost); ExtensionLoaderHost host = appDomain.CreateInstanceAndUnwrap(hostType.Assembly.FullName, hostType.FullName) as ExtensionLoaderHost; LoaderInfo info = host.AnalyseExtension(extensionPaths, file, level, level, player); foreach (var item in info.Players) { item.Source = PlayerSource.Imported; } AppDomain.Unload(appDomain); return(info); }
/// <summary> /// Scans the given Assembly for potential stuff like Campaigns, Levels and Players. /// </summary> /// <param name="assembly">Assembly to search in</param> /// <param name="campaign">Scan for new Campaigns</param> /// <param name="level">Scan for new Levels</param> /// <param name="player">Scan for new Players</param> /// <returns>Scan Results</returns> internal static LoaderInfo AnalyseAssembly(Assembly assembly, bool level, bool campaign, bool player) { LoaderInfo loaderInfo = new LoaderInfo(); bool isStatic = false; foreach (var type in assembly.GetTypes()) { // Static-Flag abfragen // TODO: Abhängigkeiten in andere Assemblies müssen hier auch aufgegriffen werden var members = type.GetMembers(BindingFlags.Static); isStatic |= members.Length > 0; if (type.IsClass && type.IsPublic && !type.IsAbstract) { // Found Level if (level && type.IsSubclassOf(typeof(Level))) { try { LevelInfo levelInfo = AnalyseLevelType(type); loaderInfo.Levels.Add(levelInfo); } catch (Exception ex) { loaderInfo.Errors.Add(ex); } } // Found Campaign if (campaign && type.IsSubclassOf(typeof(Campaign))) { try { CampaignInfo campaignInfo = AnalyseCampaignType(type); loaderInfo.Campaigns.Add(campaignInfo); } catch (Exception ex) { loaderInfo.Errors.Add(ex); } } // Found Player (Ignorieren, falls Faction-Liste null) if (player && type.GetCustomAttributes(typeof(FactoryAttribute), true).Length > 0) { try { PlayerInfo playerInfo = AnalysePlayerType(type); loaderInfo.Players.Add(playerInfo); } catch (Exception ex) { loaderInfo.Errors.Add(ex); } } // Found Extender if (type.GetInterface("IExtender") != null) { Type[] interfaces = type.GetInterfaces(); } } } // Static Flag nachtragen foreach (var item in loaderInfo.Players) { item.IsStatic = isStatic; } return(loaderInfo); }
/// <summary> /// Tries to Loads all available Extensions within the valid extension pathes. /// /// The method searchs for Extensions in the following pathes: /// - Application Path (e.g. "C:\Program Files\AntMe!\") /// - Extension Folder of the Application Path (e.g. "C:\Program Files\AntMe!\Extensions") /// - App Data Folder ("C:\Users\[username]\AppData\Local\AntMe\Extensions") /// /// The method loads the following fragments: /// - Factions (always) /// - GameItems (always) /// - Extenders (always) /// - Campaigns (only full) /// - Players (only full) /// - Levels (only full) /// </summary> /// <param name="extensionPaths">List of pathes to search for Extensions</param> /// <param name="token">Optional Reference to a Progress Token</param> /// <param name="full">Switch between basic Extension Loader or full Content Load.</param> public static void LoadExtensions(string[] extensionPaths, ProgressToken token, bool full) { if (extensionsLoaded) { return; } List <string> files = new List <string>(); List <Exception> errors = new List <Exception>(); List <Assembly> assemblies = new List <Assembly>(); foreach (var path in extensionPaths) { // Check if Path exists if (!Directory.Exists(path)) { continue; } // Enumerate all dll-Files files.AddRange(Directory.EnumerateFiles(path, "*.dll")); } // Calculation of total Tasks (based on the number of files) int currentTask = 0; if (token != null) { token.TotalTasks = (full ? files.Count * 2 : files.Count) + 1; token.CurrentTask = currentTask; } // Try to load all files from list foreach (var file in files) { try { // Try to load and add to list assemblies.Add(Assembly.LoadFile(file)); } catch (Exception ex) { // Add Loading Error to List if (token != null && token.Errors != null) { token.Errors.Add(ex); } errors.Add(ex); } // Cancel if (token != null && token.Cancel) { return; } } // Recalculation of total Tasks (based on the number of loaded assemblies) currentTask = 1; if (token != null) { token.TotalTasks = (full ? assemblies.Count * 2 : assemblies.Count) + 1; token.CurrentTask = currentTask; } // Cancel if (token != null && token.Cancel) { return; } // Pass 1 Load Extension Packs List <IExtensionPack> extensionPacks = new List <IExtensionPack>(); KeyValueStore settings = new KeyValueStore(); foreach (var assembly in assemblies) { foreach (var type in assembly.GetExportedTypes()) { if (type.IsClass && !type.IsAbstract && typeof(IExtensionPack).IsAssignableFrom(type)) { IExtensionPack extensionPack = null; try { // Instanz erzeugen & Laden extensionPack = Activator.CreateInstance(type) as IExtensionPack; extensionPack.Load(DefaultTypeMapper, settings); extensionPacks.Add(extensionPack); } catch (Exception ex) { // Error dokumentieren if (token != null && token.Errors != null) { token.Errors.Add(ex); } errors.Add(ex); // Remove all Type Mapper elements if (extensionPack != null) { DefaultTypeMapper.RemoveExtensionPack(extensionPack); } } } if (token != null) { token.CurrentTask = currentTask; if (token.Cancel) { return; } } } currentTask++; } extensionPackCache = extensionPacks; extensionSettings = settings; // Fill Caches if (full) { List <CampaignInfo> campaigns = new List <CampaignInfo>(); List <LevelInfo> levels = new List <LevelInfo>(); List <PlayerInfo> players = new List <PlayerInfo>(); // Pass 2 (Levels & Players) [campaigns, levels, players] foreach (var assembly in assemblies) { LoaderInfo loader = AnalyseAssembly(assembly, true, true, true); // Types mit File Dump if (loader.Campaigns.Count > 0 || loader.Levels.Count > 0 || loader.Players.Count > 0) { // File dump Stream stream = assembly.GetFiles()[0]; byte[] file = new byte[stream.Length]; stream.Read(file, 0, file.Length); // Campaigns laden foreach (var campaign in loader.Campaigns) { foreach (var level in campaign.Levels) { level.Type.AssemblyFile = file; } campaigns.Add(campaign); } // Levels laden foreach (var level in loader.Levels) { level.Type.AssemblyFile = file; levels.Add(level); } // Player laden foreach (var player in loader.Players) { player.Type.AssemblyFile = file; player.Source = PlayerSource.Native; players.Add(player); } } currentTask++; errors.AddRange(loader.Errors); if (token != null) { token.Errors.AddRange(loader.Errors); token.CurrentTask = currentTask; if (token.Cancel) { return; } } } campaignCache = campaigns; levelCache = levels; playerCache = players; } extensionsLoaded = true; if (errors.Count > 0) { throw new AggregateException("Extension Loader had some Exceptions", errors); } }