/// <summary> /// Converts to the format /// </summary> /// <returns>The task</returns> public override async Task ConvertToAsync() { var attr = GameModeSelection.SelectedValue.GetAttribute <OpenSpaceGameModeInfoAttribute>(); var settings = OpenSpaceSettings.GetDefaultSettings(attr.Game, attr.Platform); await ConvertToAsync <OpenSpaceGFFile>(settings, (filePath, format) => { // Create the GF data var gf = new OpenSpaceGFFile { // Set the .gf format GFPixelFormat = Enum.Parse(typeof(OpenSpaceGFFormat), format).CastTo <OpenSpaceGFFormat>() }; // Read the image using var bmp = new Bitmap(filePath); // IDEA: If bmp is not in supported format, then convert it? // Import from the bitmap gf.ImportFromBitmap(settings, new RawBitmapData(bmp), RCPServices.Data.Archive_GF_GenerateMipmaps); // Return the data return(gf); }, new FileFilterItemCollection(ImageHelpers.GetSupportedBitmapExtensions().Select(x => new FileFilterItem($"*{x}", x.Substring(1).ToUpper()))).ToString(), new FileExtension(".gf"), Enum.GetNames(typeof(OpenSpaceGFFormat))); }
/// <summary> /// Opens the archive explorer /// </summary> /// <returns>The task</returns> public async Task OpenAsync() { var attr = GameMode.GetAttribute <OpenSpaceGameModeInfoAttribute>(); var settings = OpenSpaceSettings.GetDefaultSettings(attr.Game, attr.Platform); // Show the archive explorer await RCPServices.UI.ShowArchiveExplorerAsync(new OpenSpaceCntArchiveExplorerDataManager(settings), ArchiveFiles.Where(x => x.FileExists)); }
/// <summary> /// Imports an exported save slot to the save slot from the specified path /// </summary> /// <param name="inputFilePath">The input file path</param> /// <returns>The task</returns> protected override Task ImportSaveDataAsync(FileSystemPath inputFilePath) { // Deserialize the input data var data = JsonHelpers.DeserializeFromFile <RaymanMPCSaveData>(inputFilePath); // Import the data BinarySerializableHelpers.WriteToFile(data, SaveSlotFilePath, OpenSpaceSettings.GetDefaultSettings(OpenSpaceGame.RaymanM, Platform.PC), RCPServices.App.GetBinarySerializerLogger()); return(Task.CompletedTask); }
/// <summary> /// Converts to the format /// </summary> /// <returns>The task</returns> public override async Task ConvertToAsync() { var settings = OpenSpaceSettings.GetDefaultSettings(OpenSpaceGame.Rayman2, Platform.PC); await ConvertToAsync(settings, (filePath, format) => { // Read the data return(DeserializeJSON <Rayman2PCConfigData>(filePath)); }, new FileFilterItem("*.json", "JSON").ToString(), new FileExtension(".cfg"), null, new Rayman12PCSaveDataEncoder()); }
/// <summary> /// Converts to the format /// </summary> /// <returns>The task</returns> public override async Task ConvertToAsync() { var settings = OpenSpaceSettings.GetDefaultSettings(OpenSpaceGame.Rayman3, GameModeSelection.SelectedValue); await ConvertToAsync(settings, (filePath, format) => { // Read the data return(DeserializeJSON <Rayman3PCSaveData>(filePath)); }, new FileFilterItem("*.json", "JSON").ToString(), new FileExtension(".sav"), null, new Rayman3SaveDataEncoder()); }
/// <summary> /// Converts to the format /// </summary> /// <returns>The task</returns> public override async Task ConvertToAsync() { var attr = GameModeSelection.SelectedValue.GetAttribute <OpenSpaceGameModeInfoAttribute>(); var settings = OpenSpaceSettings.GetDefaultSettings(attr.Game, attr.Platform); await ConvertToAsync(settings, (filePath, format) => { // Read the data return(DeserializeJSON <RaymanMPCSaveData>(filePath)); }, new FileFilterItem("*.json", "JSON").ToString(), new FileExtension(".sav")); }
/// <summary> /// Synchronizes the texture info for the selected game data directory /// </summary> /// <returns>The task</returns> public async Task SyncTextureInfoAsync() { var result = await Services.BrowseUI.BrowseDirectoryAsync(new DirectoryBrowserViewModel() { Title = Resources.Utilities_SyncTextureInfo_SelectDirHeader, DefaultDirectory = GameModeSelection.SelectedValue.GetGame()?.GetInstallDir(false) ?? FileSystemPath.EmptyPath }); if (result.CanceledByUser) { return; } try { IsLoading = true; var syncResult = await Task.Run(() => { // Get the settings var attr = GameModeSelection.SelectedValue.GetAttribute <OpenSpaceGameModeInfoAttribute>(); var gameSettings = OpenSpaceSettings.GetDefaultSettings(attr.Game, attr.Platform); // Get the file extension for the level data files var fileExt = GetLevelFileExtension(gameSettings); // Get the level data files var dataFiles = Directory.GetFiles(result.SelectedDirectory, $"*{fileExt}", SearchOption.AllDirectories).Select(x => new FileSystemPath(x)); // Get the .cnt file names var fileNames = GetCntFileNames(gameSettings); // Get the full paths and only keep the ones which exist var cntFiles = fileNames.Select(x => result.SelectedDirectory + x).Where(x => x.FileExists); // Sync the texture info return(EditTextureInfo(gameSettings, dataFiles, cntFiles)); }); await Services.MessageUI.DisplaySuccessfulActionMessageAsync(String.Format(Resources.Utilities_SyncTextureInfo_Success, syncResult.EditedTextures, syncResult.TotalTextures)); } catch (Exception ex) { ex.HandleError("Syncing texture info"); await Services.MessageUI.DisplayExceptionMessageAsync(ex, Resources.Utilities_SyncTextureInfo_Error); } finally { IsLoading = false; } }
/// <summary> /// Converts from the format /// </summary> /// <returns>The task</returns> public override async Task ConvertFromAsync() { var settings = OpenSpaceSettings.GetDefaultSettings(OpenSpaceGame.Rayman2, Platform.PC); await ConvertFromAsync <Rayman2PCConfigData>(settings, (data, filePath) => { // Save the data SerializeJSON(data, filePath); }, new FileFilterItem("*.cfg", "CFG").ToString(), new[] { ".json" }, Games.Rayman2.GetInstallDir(false), new Rayman12PCSaveDataEncoder()); }
/// <summary> /// Converts from the format /// </summary> /// <returns>The task</returns> public override async Task ConvertFromAsync() { var settings = OpenSpaceSettings.GetDefaultSettings(OpenSpaceGame.Rayman3, GameModeSelection.SelectedValue); await ConvertFromAsync <Rayman3PCSaveData>(settings, (data, filePath) => { // Save the data SerializeJSON(data, filePath); }, new FileFilterItem("*.sav", "SAV").ToString(), new[] { ".json" }, Games.Rayman3.GetInstallDir(false), new Rayman3SaveDataEncoder()); }
/// <summary> /// Converts from the format /// </summary> /// <returns>The task</returns> public override async Task ConvertFromAsync() { var attr = GameModeSelection.SelectedValue.GetAttribute <OpenSpaceGameModeInfoAttribute>(); var settings = OpenSpaceSettings.GetDefaultSettings(attr.Game, attr.Platform); await ConvertFromAsync <OpenSpaceGFFile>(settings, (data, filePath) => { // Get a bitmap from the image data using var bmp = data.GetRawBitmapData().GetBitmap(); // Save the image bmp.Save(filePath, ImageHelpers.GetImageFormat(filePath.FileExtension)); }, new FileFilterItem("*.gf", "GF").ToString(), ImageHelpers.GetSupportedBitmapExtensions(), null); }
/// <summary> /// Converts from the format /// </summary> /// <returns>The task</returns> public override async Task ConvertFromAsync() { var attr = GameModeSelection.SelectedValue.GetAttribute <OpenSpaceGameModeInfoAttribute>(); var settings = OpenSpaceSettings.GetDefaultSettings(attr.Game, attr.Platform); await ConvertFromAsync <RaymanMPCSaveData>(settings, (data, filePath) => { // Save the data SerializeJSON(data, filePath); }, new FileFilterItem("*.sav", "SAV").ToString(), new[] { ".json" }, GameModeSelection.SelectedValue.GetGame()?.GetInstallDir(false)); }
/// <summary> /// Synchronizes the texture info for the selected game data directory /// </summary> /// <returns>The task</returns> public async Task SyncTextureInfoAsync() { try { IsLoading = true; var syncResult = await Task.Run(() => { // Get the game install directory var installDir = Game.GetInstallDir(); // Get the settings var attr = GameMode.GetAttribute <OpenSpaceGameModeInfoAttribute>(); var gameSettings = OpenSpaceSettings.GetDefaultSettings(attr.Game, attr.Platform); // Get the file extension for the level data files var fileExt = GetLevelFileExtension(gameSettings); // Get the level data files var dataFiles = GameDataDirNames.Select(x => Directory.GetFiles(installDir + x, $"*{fileExt}", SearchOption.AllDirectories).Select(y => new FileSystemPath(y))).SelectMany(x => x); // Get the .cnt file names var fileNames = GetCntFileNames(gameSettings); // Get the full paths and only keep the ones which exist var cntFiles = GameDataDirNames.Select(dataDir => fileNames.Select(cnt => installDir + dataDir + cnt).Where(cntPath => cntPath.FileExists)).SelectMany(x => x); // Sync the texture info return(EditTextureInfo(gameSettings, dataFiles, cntFiles)); }); await WPF.Services.MessageUI.DisplaySuccessfulActionMessageAsync(String.Format(Resources.Utilities_SyncTextureInfo_Success, syncResult.EditedTextures, syncResult.TotalTextures)); } catch (Exception ex) { ex.HandleError("Syncing texture info"); await WPF.Services.MessageUI.DisplayExceptionMessageAsync(ex, Resources.Utilities_SyncTextureInfo_Error); } finally { IsLoading = false; } }
/// <summary> /// Imports an exported save slot to the save slot from the specified path /// </summary> /// <param name="inputFilePath">The input file path</param> /// <returns>The task</returns> protected override Task ImportSaveDataAsync(FileSystemPath inputFilePath) { // Deserialize the input data var data = JsonHelpers.DeserializeFromFile <Rayman3PCSaveData>(inputFilePath); // Create streams using var decodedDataStream = new MemoryStream(); using var saveFileStream = File.Create(SaveSlotFilePath); // Import the data BinarySerializableHelpers.WriteToStream(data, decodedDataStream, OpenSpaceSettings.GetDefaultSettings(OpenSpaceGame.Rayman3, Platform.PC), RCPServices.App.GetBinarySerializerLogger()); // Set position to 0 decodedDataStream.Position = 0; // Encode the data to the file new Rayman3SaveDataEncoder().Encode(decodedDataStream, saveFileStream); return(Task.CompletedTask); }
/// <summary> /// Exports the save slot from the specified path /// </summary> /// <param name="outputFilePath">The output file path</param> /// <returns>The task</returns> protected override Task ExportSaveDataAsync(FileSystemPath outputFilePath) { // Create streams using var saveFileStream = File.OpenRead(SaveSlotFilePath); using var decodedDataStream = new MemoryStream(); // Decode the save file new Rayman3SaveDataEncoder().Decode(saveFileStream, decodedDataStream); // Set position to 0 decodedDataStream.Position = 0; // Get the serialized data var data = BinarySerializableHelpers.ReadFromStream <Rayman3PCSaveData>(decodedDataStream, OpenSpaceSettings.GetDefaultSettings(OpenSpaceGame.Rayman3, Platform.PC), RCPServices.App.GetBinarySerializerLogger()); // Export the data JsonHelpers.SerializeToFile(data, outputFilePath); return(Task.CompletedTask); }
/// <summary> /// Exports the save slot from the specified path /// </summary> /// <param name="outputFilePath">The output file path</param> /// <returns>The task</returns> protected override Task ExportSaveDataAsync(FileSystemPath outputFilePath) { // Get the serialized data var data = BinarySerializableHelpers.ReadFromFile <RaymanMPCSaveData>(SaveSlotFilePath, OpenSpaceSettings.GetDefaultSettings(OpenSpaceGame.RaymanM, Platform.PC), RCPServices.App.GetBinarySerializerLogger()); // Export the data JsonHelpers.SerializeToFile(data, outputFilePath); return(Task.CompletedTask); }
/// <summary> /// Get the progression slot view model for the save data from the specified file /// </summary> /// <param name="filePath">The slot file path</param> /// <param name="slotName">The generator for the name of the save slot</param> /// <returns>The progression slot view model</returns> protected ProgressionSlotViewModel GetProgressionSlotViewModel(FileSystemPath filePath, string slotName) { RL.Logger?.LogInformationSource($"Rayman 2 slot {slotName} is being loaded..."); // Make sure the file exists if (!filePath.FileExists) { RL.Logger?.LogInformationSource($"Slot was not loaded due to not being found"); return(null); } // Open the file in a stream using var fileStream = File.Open(filePath, FileMode.Open, FileAccess.Read); // Create a memory stream using var memStream = new MemoryStream(); // Decode the data new Rayman12PCSaveDataEncoder().Decode(fileStream, memStream); // Set the position memStream.Position = 0; // Deserialize and return the data var saveData = BinarySerializableHelpers.ReadFromStream <Rayman2PCSaveData>(memStream, OpenSpaceSettings.GetDefaultSettings(OpenSpaceGame.Rayman2, Platform.PC), RCPServices.App.GetBinarySerializerLogger()); RL.Logger?.LogInformationSource($"Slot has been deserialized"); // Get the bit array var array = saveData.GlobalArrayAsBitFlags(); // Get total amount of Lums and cages var lums = array.Skip(0).Take(800).Select(x => x ? 1 : 0).Sum() + array.Skip(1200).Take(194).Select(x => x ? 1 : 0).Sum() + // Woods of Light array.Skip(1395).Take(5).Select(x => x ? 1 : 0).Sum() + // 1000th Lum (array[1013] ? 1 : 0); var cages = array.Skip(839).Take(80).Select(x => x ? 1 : 0).Sum(); var walkOfLifeTime = saveData.GlobalArray[12] * 10; var walkOfPowerTime = saveData.GlobalArray[11] * 10; // Create the collection with items for cages + lives var progressItems = new List <ProgressionInfoItemViewModel> { new ProgressionInfoItemViewModel(ProgressionIcons.R2_Lum, new LocalizedString(() => $"{lums}/1000")), new ProgressionInfoItemViewModel(ProgressionIcons.R2_Cage, new LocalizedString(() => $"{cages}/80")), }; if (walkOfLifeTime > 120) { progressItems.Add(new ProgressionInfoItemViewModel(ProgressionIcons.R2_Clock, new LocalizedString(() => $"{new TimeSpan(0, 0, 0, 0, walkOfLifeTime):mm\\:ss\\:ff}"), new LocalizedString(() => Resources.R2_BonusLevelName_1))); } if (walkOfPowerTime > 120) { progressItems.Add(new ProgressionInfoItemViewModel(ProgressionIcons.R2_Clock, new LocalizedString(() => $"{new TimeSpan(0, 0, 0, 0, walkOfPowerTime):mm\\:ss\\:ff}"), new LocalizedString(() => Resources.R2_BonusLevelName_2))); } RL.Logger?.LogInformationSource($"General progress info has been set"); // Get the name and percentage var separatorIndex = slotName.LastIndexOf((char)0x20); var name = slotName.Substring(0, separatorIndex); var percentage = slotName.Substring(separatorIndex + 1); RL.Logger?.LogInformationSource($"Slot percentage is {percentage}%"); // Return the data with the collection return(new Rayman2ProgressionSlotViewModel(new LocalizedString(() => $"{name} ({percentage}%)"), progressItems.ToArray(), filePath, this)); }
/// <summary> /// Loads the current save data if available /// </summary> protected override void LoadData() { // Make sure the file exists if (!ConfigFilePath.FileExists) { return; } // Create streams using var saveFileStream = File.OpenRead(ConfigFilePath); using var decodedDataStream = new MemoryStream(); // Decode the save file new Rayman12PCSaveDataEncoder().Decode(saveFileStream, decodedDataStream); // Set position to 0 decodedDataStream.Position = 0; // Get the serialized data var config = BinarySerializableHelpers.ReadFromStream <Rayman2PCConfigData>(decodedDataStream, OpenSpaceSettings.GetDefaultSettings(OpenSpaceGame.Rayman2, Platform.PC), RCPServices.App.GetBinarySerializerLogger()); // Read and set slot data ProgressionSlots.AddRange(config.Slots.Select(x => GetProgressionSlotViewModel(SaveGamePath + $"Slot{x.SlotIndex}" + "General.sav", x.SlotDisplayName))); }
/// <summary> /// Get the progression slot view model for the save data from the specified file /// </summary> /// <param name="filePath">The slot file path</param> /// <returns>The progression slot view model</returns> protected ProgressionSlotViewModel GetProgressionSlotViewModel(FileSystemPath filePath) { RL.Logger?.LogInformationSource($"Rayman 3 slot {filePath.Name} is being loaded..."); // Make sure the file exists if (!filePath.FileExists) { RL.Logger?.LogInformationSource($"Slot was not loaded due to not being found"); return(null); } // Open the file in a stream using var fileStream = File.Open(filePath, FileMode.Open, FileAccess.Read); // Create a memory stream using var memStream = new MemoryStream(); // Decode the data new Rayman3SaveDataEncoder().Decode(fileStream, memStream); // Set the position memStream.Position = 0; // Deserialize the data var saveData = BinarySerializableHelpers.ReadFromStream <Rayman3PCSaveData>(memStream, OpenSpaceSettings.GetDefaultSettings(OpenSpaceGame.Rayman3, Platform.PC), RCPServices.App.GetBinarySerializerLogger()); RL.Logger?.LogInformationSource($"Slot has been deserialized"); var formatInfo = new NumberFormatInfo() { NumberGroupSeparator = " ", NumberDecimalDigits = 0 }; // Create the collection with items for each level + general information var progressItems = new ProgressionInfoItemViewModel[] { new ProgressionInfoItemViewModel(ProgressionIcons.R3_Cage, new LocalizedString(() => $"{saveData.TotalCages}/60")), new ProgressionInfoItemViewModel(ProgressionIcons.R3_Score, new LocalizedString(() => $"{Resources.Progression_R3_TotalHeader}: {saveData.TotalScore.ToString("n", formatInfo)}")), new ProgressionInfoItemViewModel(ProgressionIcons.R3_Score, new LocalizedString(() => $"{Resources.Progression_R3_Level1Header}: {saveData.Levels[0].Score.ToString("n", formatInfo)}")), new ProgressionInfoItemViewModel(ProgressionIcons.R3_Score, new LocalizedString(() => $"{Resources.Progression_R3_Level2Header}: {saveData.Levels[1].Score.ToString("n", formatInfo)}")), new ProgressionInfoItemViewModel(ProgressionIcons.R3_Score, new LocalizedString(() => $"{Resources.Progression_R3_Level3Header}: {saveData.Levels[2].Score.ToString("n", formatInfo)}")), new ProgressionInfoItemViewModel(ProgressionIcons.R3_Score, new LocalizedString(() => $"{Resources.Progression_R3_Level4Header}: {saveData.Levels[3].Score.ToString("n", formatInfo)}")), new ProgressionInfoItemViewModel(ProgressionIcons.R3_Score, new LocalizedString(() => $"{Resources.Progression_R3_Level5Header}: {saveData.Levels[4].Score.ToString("n", formatInfo)}")), new ProgressionInfoItemViewModel(ProgressionIcons.R3_Score, new LocalizedString(() => $"{Resources.Progression_R3_Level6Header}: {saveData.Levels[5].Score.ToString("n", formatInfo)}")), new ProgressionInfoItemViewModel(ProgressionIcons.R3_Score, new LocalizedString(() => $"{Resources.Progression_R3_Level7Header}: {saveData.Levels[6].Score.ToString("n", formatInfo)}")), new ProgressionInfoItemViewModel(ProgressionIcons.R3_Score, new LocalizedString(() => $"{Resources.Progression_R3_Level8Header}: {saveData.Levels[7].Score.ToString("n", formatInfo)}")), new ProgressionInfoItemViewModel(ProgressionIcons.R3_Score, new LocalizedString(() => $"{Resources.Progression_R3_Level9Header}: {saveData.Levels[8].Score.ToString("n", formatInfo)}")) }; RL.Logger?.LogInformationSource($"General progress info has been set"); // Return the data with the collection return(new Rayman3ProgressionSlotViewModel(new LocalizedString(() => $"{filePath.RemoveFileExtension().Name}"), progressItems, filePath, this)); }
/// <summary> /// Get the progression slot view models for the save data from the specified file /// </summary> /// <param name="filePath">The slot file path</param> /// <returns>The progression slot view models</returns> protected IEnumerable <ProgressionSlotViewModel> GetProgressionSlotViewModels(FileSystemPath filePath) { RL.Logger?.LogInformationSource($"Rayman M/Arena save file {filePath.Name} is being loaded..."); // Make sure the file exists if (!filePath.FileExists) { RL.Logger?.LogInformationSource($"Slot was not loaded due to not being found"); yield break; } // Deserialize the save data var saveData = BinarySerializableHelpers.ReadFromFile <RaymanMPCSaveData>(filePath, OpenSpaceSettings.GetDefaultSettings(OpenSpaceGame.RaymanM, Platform.PC), RCPServices.App.GetBinarySerializerLogger()); RL.Logger?.LogInformationSource($"Save file has been deserialized"); // Helper for getting the entry with a specific key int[] GetValues(string key) => saveData.Items.First(x => x.Key == key).Values;