/// <summary> /// /// </summary> /// <param name="xmlRelativePath">Path of the xml file relative to the <see cref="PackageDirectoryAbsolutePath"/></param> /// <returns></returns> /// <exception cref="ArgumentException"/> /// <exception cref="FatalPackagingException"/> /// <exception cref="PackageLoadingException"/> public GamePackRep AddGamePack(string xmlRelativePath) { GamePackRep newPack = LoadPack(xmlRelativePath); if (newPack != null) { if (availablePacks.ContainsKey(newPack.Name)) { throw new ArgumentException("GamePack of the same name was already loaded", nameof(xmlRelativePath)); } //Already validated XDocument document; try { document = LoadGamePackDirXml(GamePackDirFilePath); } catch (XmlSchemaValidationException e) { throw new FatalPackagingException($"Package directory xml document does not conform to GamePack.xsd schema: {e.Message}", e); } XElement root = document.Root; root.Add(new XElement(GamePackDirectoryXml.Inst.GamePack, xmlRelativePath)); WriteGamePackDir(document, GamePackDirFilePath); AddToAvailable(newPack, xmlRelativePath); } return(newPack); }
/// <summary> /// <para>Unloads the <see cref="ActivePackage"/> if there is any and then loads /// the package represented by <paramref name="package"/></para> /// /// <para>Optionally can signal loading progress if provided with <paramref name="loadingProgress"/></para> /// </summary> /// <param name="package">Representation of the package to be loaded</param> /// <param name="loadingProgress">Optional watcher of the loading progress</param> /// <returns>A task that represents the asynchronous loading of the package</returns> /// <exception cref="PackageLoadingException">Thrown when the loading of the new package failed</exception> public async Task <GamePack> LoadPackage(GamePackRep package, IProgressEventWatcher loadingProgress = null) { const double clearPartSize = 10; const double loadPartSize = 90; if (loadingProgress == null) { loadingProgress = new ProgressWatcher(); } loadingProgress.SendTextUpdate("Clearing previous games"); if (ActivePackage != null) { UnloadActivePack(); } loadingProgress.SendUpdate(clearPartSize, "Cleared previous games"); resourceCache.AddResourceDir(Path.Combine(App.Files.DynamicDirPath, package.XmlDirectoryPath), 1); loadingProgress.SendTextUpdate("Loading new package"); ActivePackage = await package.LoadPack(schemas, new ProgressWatcher(loadingProgress, loadPartSize)); loadingProgress.SendFinished(); return(ActivePackage); }
/// <summary> /// /// </summary> /// <param name="gamePack"></param> public void RemoveGamePack(GamePackRep gamePack) { if (!availablePacks.ContainsValue(gamePack)) { throw new ArgumentException("GamePack was not registered as available"); } string dirEntry = dirEntries[gamePack]; //Already validated XDocument document = null; try { document = LoadGamePackDirXml(GamePackDirFilePath); } catch (XmlSchemaValidationException e) { throw new FatalPackagingException($"Package directory xml document does not conform to GamePack.xsd schema: {e.Message}", e); } catch (IOException e) { throw new FatalPackagingException($"Could not open the package directory xml file, {e.Message}", e); } XElement packDirElement = (from element in document.Root.Elements() where element.Value == dirEntry select element).FirstOrDefault(); if (packDirElement == null) { throw new FatalPackagingException($"Did not find entry for the gamePack at {dirEntry} in gamePack directory xml file"); } packDirElement.Remove(); try { WriteGamePackDir(document, GamePackDirFilePath); } catch (XmlSchemaValidationException e) { throw new FatalPackagingException($"Package directory xml document did not conform to GamePack.xsd schema after adding new entry: {e.Message}", e); } catch (IOException e) { throw new FatalPackagingException($"Could not write to the package directory xml file, {e.Message}", e); } //Only after the change to xml file went through, remove from runtime RemoveFromAvailable(gamePack); }
GamePackRep LoadPack(string pathInDirEntry) { string packXmlPath = Path.Combine(PackageDirectoryPath, FileManager.ReplaceDirectorySeparators(pathInDirEntry)); GamePackRep newPack = null; newPack = new GamePackRep(packXmlPath, this, schemas); return(newPack); }
void AddToAvailable(GamePackRep newPack, string pathInDirEntry) { if (availablePacks.ContainsKey(newPack.Name)) { string message = $"GamePack of the name \"{newPack.Name}\" from \"{newPack.XmlDirectoryPath}\" was already loaded."; Urho.IO.Log.Write(LogLevel.Warning, message); throw new ArgumentException(message, nameof(newPack)); } availablePacks.Add(newPack.Name, newPack); dirEntries.Add(newPack, pathInDirEntry); }
void RemoveFromAvailable(GamePackRep gamePack) { if (!availablePacks.ContainsValue(gamePack)) { string message = $"GamePack {gamePack.Name} at {gamePack.XmlDirectoryPath} was not registered as available"; Urho.IO.Log.Write(LogLevel.Warning, message); throw new ArgumentException(message, nameof(gamePack)); } availablePacks.Remove(gamePack.Name); dirEntries.Remove(gamePack); }
/// <summary> /// Pulls data about the resource packs contained in this directory from XML file /// </summary> /// <returns>Array of package paths that could not be loaded</returns> /// <exception cref="FatalPackagingException">Thrown when package directory loading completely failed, and the game can terminate</exception> public string[] ParseGamePackDir() { IEnumerable <string> packagePaths = null; try { XDocument doc = LoadGamePackDirXml(GamePackDirFilePath); packagePaths = from packagePath in doc.Root.Elements(GamePackDirectoryXml.Inst.GamePack) select packagePath.Value; } catch (IOException e) { //Creation of the FileStream failed, cannot load this directory string message = $"Opening ResourcePack directory file at {GamePackDirFilePath} failed: {e}"; Log.Write(LogLevel.Error, message); if (Debugger.IsAttached) { Debugger.Break(); } throw new FatalPackagingException(message, e); } catch (XmlSchemaValidationException e) { string message = $"ResourcePack directory file at {GamePackDirFilePath} does not conform to the schema: {e.Message}"; //Invalid resource pack description file, dont load this pack directory Log.Write(LogLevel.Error, message); if (Debugger.IsAttached) { Debugger.Break(); } throw new FatalPackagingException(message, e); } catch (XmlException e) { string message = $"ResourcePack directory file at {GamePackDirFilePath} was corrupted : {e.Message}"; Log.Write(LogLevel.Error, message); if (Debugger.IsAttached) { Debugger.Break(); } throw new FatalPackagingException(message, e); } List <string> failedPackagePaths = new List <string>(); //Adds all the discovered packs into the availablePacks list foreach (var packagePath in packagePaths) { try { GamePackRep newPack = LoadPack(packagePath); AddToAvailable(newPack, packagePath); } catch (Exception) { //The package writes the error to the log by itself //Urho.IO.Log.Write(LogLevel.Warning, $"Loading package at {packagePath} failed with: {e}"); failedPackagePaths.Add(packagePath); } } return(failedPackagePaths.ToArray()); }