/// <summary> /// Checks for specified reference and updates issues list /// </summary> /// <param name="topic"></param> /// <param name="cell"></param> /// <param name="issues"></param> private void _CheckReferenceValue(DB.Topic topic, DB.Cell cell, Collection <DatabaseFixer.Corruption> issues) { if (cell.optionalRef != null && issues != null) { string topicId = cell.optionalRef; DB.Topic referencedTopic = DB.TopicPerTopicId[topicId]; if (referencedTopic == DB.Topic.None) { // Report unknown topic DatabaseFixer.Corruption newCorruption = new DatabaseFixer.Corruption { corruptedCell = cell, corruptedValue = topicId, culture = DB.Culture.Global, entryId = cell.entryIndex, kind = DatabaseFixer.CorruptionKind. UnknownReferencedTopic, referencedTopic = DB.Topic.None, topic = topic }; issues.Add(newCorruption); } else { // Getting referenced topic TduFile[] databaseItems = _LoadedData[referencedTopic]; DB dbTopic = databaseItems[0] as DB; if (dbTopic == null) { throw new Exception("Unable to get database information for topic: " + referencedTopic); } // Get referenced value List <DB.Entry> referencedEntries = DatabaseHelper.SelectAllCellsFromTopicWherePrimaryKey(dbTopic, cell.value); if (referencedEntries.Count == 0) { // Report missing reference DatabaseFixer.Corruption newCorruption = new DatabaseFixer.Corruption { corruptedCell = cell, corruptedValue = cell.value, culture = DB.Culture.Global, entryId = cell.entryIndex, kind = DatabaseFixer.CorruptionKind.MissingReference, referencedTopic = dbTopic.CurrentTopic, topic = topic }; issues.Add(newCorruption); } } } }
/// <summary> /// Checks specified topic in loaded data then returns eventual issues /// </summary> /// <param name="topic"></param> /// <returns></returns> private IEnumerable <DatabaseFixer.Corruption> _CheckTopic(DB.Topic topic) { Collection <DatabaseFixer.Corruption> returnedIssues = new Collection <DatabaseFixer.Corruption>(); if (topic != DB.Topic.None) { // Getting data and resource DB dbTopic = _LoadedData[topic][0] as DB; DBResource dbResource = _LoadedData[topic][1] as DBResource; if (dbTopic == null || dbResource == null) { throw new Exception("Invalid topic can't be loaded: " + topic); } // Values foreach (DB.Entry anotherEntry in dbTopic.Entries) { // Structure checks _CheckStructure(dbTopic, anotherEntry, returnedIssues); foreach (DB.Cell anotherCell in anotherEntry.cells) { // According to data type... switch (anotherCell.valueType) { case DB.ValueType.PrimaryKey: // Check disabled break; case DB.ValueType.Reference: _CheckReferenceValue(topic, anotherCell, returnedIssues); break; case DB.ValueType.ReferenceL: _CheckResourceValue(topic, anotherCell, null, returnedIssues); break; case DB.ValueType.ValueInResourceH: _CheckResourceValue(topic, anotherCell, dbResource, returnedIssues); break; case DB.ValueType.ValueInResource: _CheckResourceValue(topic, anotherCell, dbResource, returnedIssues); break; case DB.ValueType.BitField: // Check disabled break; default: break; } } } } return(returnedIssues); }
/// <summary> /// Retrieves the db file topic by watching given comment entry /// </summary> /// <param name="entry">Comment entry to analyze</param> /// <returns>Current topic for this DB dile, Topic.None if not found</returns> private static DB.Topic _SearchForCurrentTopic(Entry entry) { DB.Topic resultTopic = DB.Topic.None; if (entry.isComment && entry.value != null) { resultTopic = DB._GetTopicByName(entry.value); } return(resultTopic); }
/// <summary> /// Loads a particular topic and its resource to fix it. To fix an already loaded database, just set Data property and do not use this method. /// </summary> /// <param name="dbTopic"></param> /// <param name="dbResource"></param> public static void LoadTopic(DB dbTopic, DBResource dbResource) { if (dbTopic != null && dbResource != null) { // Data init if needed if (_Data == null) { _Data = new Dictionary <DB.Topic, TduFile[]>(); } DB.Topic currentTopic = dbTopic.CurrentTopic; _Data.Remove(currentTopic); _Data.Add(currentTopic, new TduFile[] { dbTopic, dbResource }); } }
/// <summary> /// Prépare le chargement d'une catégorie depuis la base de données courante /// </summary> /// <param name="category">Type de données recherché</param> /// <param name="culture">Code pays</param> private void _LoadFromCurrentDatabase(DB.Topic category, DB.Culture culture) { // Localisation du fichier BNK string bnkPath = Program.ApplicationSettings.TduMainFolder + LibraryConstants.FOLDER_DB + DB.GetBNKFileName(culture); BNK bnk = TduFile.GetFile(bnkPath) as BNK; if (bnk != null && bnk.Exists) { string fileName = DB.GetFileName(culture, category); string filePath = bnk.GetPackedFilesPaths(fileName)[0]; // EVO_91: using edit support from ModdingLibrary EditHelper.Task currentTask = EditHelper.Instance.AddTask(bnk, filePath, true); _EditedFile = currentTask.extractedFile; } }
/// <summary> /// Loads the whole specified topic for edit mode and returns corresponding TduFiles and EditTasks /// </summary> /// <param name="topic"></param> /// <param name="culture"></param> /// <param name="bnkFile"></param> /// <param name="rBnkFile"></param> /// <param name="returnedTasks"></param> /// <returns></returns> public static TduFile[] LoadTopicForEdit(DB.Topic topic, DB.Culture culture, BNK bnkFile, BNK rBnkFile, out EditHelper.Task[] returnedTasks) { TduFile[] returnedFiles = new TduFile[2]; returnedTasks = new EditHelper.Task[2]; if (bnkFile != null && bnkFile.Exists) { // Getting files string dbFilePath = bnkFile.GetPackedFilesPaths(DB.GetFileName(DB.Culture.Global, topic))[0]; returnedTasks[0] = EditHelper.Instance.AddTask(bnkFile, dbFilePath, true); if (culture != DB.Culture.Global && rBnkFile != null && rBnkFile.Exists) { string dbrFilePath = rBnkFile.GetPackedFilesPaths(DB.GetFileName(culture, topic))[0]; returnedTasks[1] = EditHelper.Instance.AddTask(rBnkFile, dbrFilePath, true); } // Loading these files DB main = TduFile.GetFile(returnedTasks[0].extractedFile) as DB; if (main == null || !main.Exists) { throw new Exception(topic + " main database loading failure."); } returnedFiles[0] = main; // Resource (optional) if (returnedTasks[1].isValid) { DBResource resource = TduFile.GetFile(returnedTasks[1].extractedFile) as DBResource; if (resource == null || !resource.Exists) { throw new Exception(string.Concat(topic, "-", culture, " resource database loading failure.")); } returnedFiles[1] = resource; } } return(returnedFiles); }
/// <summary> /// Initialise les infos avec le contenu du fichier (redéfinition) /// </summary> protected override void _ReadData() { using (TextReader reader = new StreamReader(new FileStream(_FileName, FileMode.Open, FileAccess.Read))) { // Clearing all data _Entries.Clear(); entriesById.Clear(); // Browsing all lines string contents = reader.ReadToEnd(); string[] endOfEntrySeparator = new string[] { "\r\n" }; int entryCount = 0; foreach (string currentLine in contents.Split(endOfEntrySeparator, StringSplitOptions.RemoveEmptyEntries)) { Entry entry = _GenerateEntryFromLine(currentLine); if (entry.isValid) { // Searching topic in first comment entry if (_CurrentTopic == DB.Topic.None && entry.isComment) { _CurrentTopic = _SearchForCurrentTopic(entry); } entry.index = ++entryCount; _Entries.Add(entry); // Accelerator update if (entry.id != null && !entriesById.ContainsKey(entry.id)) { entriesById.Add(entry.id, entry); } } } } // EVO_65: Properties Property.ComputeValueDelegate encryptedDelegate = (() => "No"); Property.ComputeValueDelegate entryCountDelegate = (() => _Entries.Count.ToString()); Properties.Add(new Property("Encrypted ?", "DB Resources", encryptedDelegate)); Properties.Add(new Property("Entry count", "DB Resources", entryCountDelegate)); }
/// <summary> /// Checks cell value for specified resource and updates issues list /// </summary> /// <param name="topic"></param> /// <param name="cell"></param> /// <param name="dbResource"></param> /// <param name="issues"></param> /// <returns></returns> private void _CheckResourceValue(DB.Topic topic, DB.Cell cell, DBResource dbResource, Collection <DatabaseFixer.Corruption> issues) { if (dbResource == null) { // Resource from another topic if (cell.optionalRef != null) { DB.Topic referencedTopic = DB.TopicPerTopicId[cell.optionalRef]; // Is topic to be loaded ? TduFile[] databaseItems = _LoadedData[referencedTopic]; dbResource = databaseItems[1] as DBResource; if (dbResource == null) { throw new Exception("Unable to get database resource information for referenced topic: " + referencedTopic); } } } if (dbResource == null) { throw new Exception("Unable to get database resource information for topic: " + topic); } if (!dbResource.GetEntryFromId(cell.value).isValid) { // Report missing resource DatabaseFixer.Corruption newCorruption = new DatabaseFixer.Corruption { corruptedCell = cell, corruptedValue = cell.value, culture = dbResource.CurrentCulture, entryId = cell.entryIndex, kind = DatabaseFixer.CorruptionKind.MissingResource, referencedTopic = dbResource.CurrentTopic, topic = topic }; issues.Add(newCorruption); } }
/// <summary> /// Loads the whole specified topic in current database for read-only mode /// </summary> /// <param name="topic"></param> /// <param name="culture"></param> /// <returns>Array of database loaded TduFile. Index 0 is the main (encrypted) file, index 1 is the resource one</returns> public static TduFile[] LoadTopicForReadOnly(DB.Topic topic, DB.Culture culture) { TduFile[] returnedFiles = new TduFile[2]; // Loading BNKs string databaseFolder = LibraryConstants.GetSpecialFolder(LibraryConstants.TduSpecialFolder.Database); string mainBnkFile = string.Concat(databaseFolder, DB.GetBNKFileName(DB.Culture.Global)); string resourceBnkFile = string.Concat(databaseFolder, DB.GetBNKFileName(culture)); BNK mainBnk = TduFile.GetFile(mainBnkFile) as BNK; BNK resourceBnk = TduFile.GetFile(resourceBnkFile) as BNK; // Getting read-only files if (mainBnk != null && resourceBnk != null) { string dbPackedFileName = DB.GetFileName(DB.Culture.Global, topic); string fileName = EditHelper.Instance.PrepareFile(mainBnk, mainBnk.GetPackedFilesPaths(dbPackedFileName)[0]); string dbrPackedFileName = DB.GetFileName(culture, topic); string resourceFileName = EditHelper.Instance.PrepareFile(resourceBnk, resourceBnk.GetPackedFilesPaths(dbrPackedFileName)[0]); // Loading these files DB main = TduFile.GetFile(fileName) as DB; DBResource resource = TduFile.GetFile(resourceFileName) as DBResource; if (main == null || !main.Exists) { throw new Exception(topic + " main database failure."); } if (resource == null || !resource.Exists) { throw new Exception(string.Concat(topic, "-", culture, " resource database failure.")); } // Filling array returnedFiles[0] = main; returnedFiles[1] = resource; } return(returnedFiles); }
private void refreshButton_Click(object sender, EventArgs e) { // Contrôle de la saisie ... if (openRadioButton.Checked && inputFilePath.Text.Equals("")) { return; } // Pending changes ? if (_ManagePendingChanges()) { // Récupération des infos try { string dbFileName; EditHelper.Task currentTask = EditHelper.Instance.GetTask(_EditedFile); Cursor = Cursors.WaitCursor; // Task update if (currentTask.isValid) { EditHelper.Instance.RemoveTask(currentTask); _EditedFile = null; } // Selon le type if (openRadioButton.Checked) { // Par nom de fichier dbFileName = inputFilePath.Text; } else { // Par catégorie string category = catComboBox.SelectedItem.ToString(); DB.Topic topic = (DB.Topic)Enum.Parse(typeof(DB.Topic), category); _LoadFromCurrentDatabase(topic, Program.ApplicationSettings.GetCurrentCulture()); dbFileName = _EditedFile; } _LeDB = TduFile.GetFile(dbFileName) as DBResource; if (_LeDB != null) { // Mise à jour des entrées _UpdateEntryList(false); } // Réinitialisation des champs d'édition lineLabel.Text = _LABEL_ENTRY_NUMBER; idTextBox.Text = valueTextBox.Text = ""; // Mise à jour statut toolStripStatusLabel.Text = ""; Cursor = Cursors.Default; } catch (Exception ex) { // EVO_91: Manage EditHelper's error codes switch (ex.Message) { case EditHelper.ERROR_CODE_TASK_EXISTS: ex = new Exception(_ERROR_EDITED_TWICE, ex); break; case EditHelper.ERROR_CODE_EXTRACT_FAILED: case EditHelper.ERROR_CODE_INVALID_PACKED_FILE: case EditHelper.ERROR_CODE_TEMP_FOLDER: ex = new Exception(_ERROR_EDITING, ex); break; } MessageBoxes.ShowError(this, ex); } } }
/// <summary> /// Main constructor /// </summary> /// <param name="identifier"></param> /// <param name="topic"></param> public ResourceIdentifier(string identifier, DB.Topic topic) { _Id = identifier.Clone() as string; _EnclosingTopic = topic; }
/// <summary> /// What the instruction should do /// </summary> protected override void _Process() { // Checking parameters string fileName = _GetParameter(PatchInstructionParameter.ParameterName.resourceFileName); string values = _GetParameter(PatchInstructionParameter.ParameterName.resourceValues); // Modifying corresponding topic DB.Topic currentTopic = (DB.Topic)Enum.Parse(typeof(DB.Topic), fileName); EditHelper.Task dbTask = new EditHelper.Task(); string bnkFilePath = ""; try { string dbFileName = null; // 1. Creating edit task try { bnkFilePath = string.Concat(LibraryConstants.GetSpecialFolder(LibraryConstants.TduSpecialFolder.Database), DB.GetBNKFileName(DB.Culture.Global)); BNK databaseBNK = TduFile.GetFile(bnkFilePath) as BNK; if (databaseBNK != null) { dbFileName = DB.GetFileName(DB.Culture.Global, currentTopic); dbTask = EditHelper.Instance.AddTask(databaseBNK, databaseBNK.GetPackedFilesPaths(dbFileName)[0], true); } } catch (Exception ex) { throw new Exception("Unable to create edit task on BNK file: " + bnkFilePath, ex); } // 2. Getting TduFile DB db; try { db = TduFile.GetFile(dbTask.extractedFile) as DB; if (db == null || !db.Exists) { throw new Exception("Extracted db file not found!"); } } catch (Exception ex) { throw new Exception("Unable to gain access to DB contents: " + dbFileName, ex); } // 3. Setting values in DB file // One identifier (primary key: REF) or 2 identifiers (2 first columns) List <Couple <string> > couples = Tools.ParseCouples(values); string[] idArray = new string[couples.Count]; int counter = 0; // Parsing couples foreach (Couple <string> couple in couples) { string id = couple.FirstValue; string value = couple.SecondValue; // Does id exist ? if (db.EntriesByPrimaryKey.ContainsKey(id)) { // Already exists > modify it DatabaseHelper.UpdateAllCellsFromTopicWherePrimaryKey(db, id, value); Log.Info("Entry updating completed: " + id + " - " + value); } else { // Does not exist > create it DatabaseHelper.InsertAllCellsIntoTopic(db, value); Log.Info("Entry adding completed: " + value); } idArray[counter++] = id; } // 4. Saving try { db.Save(); EditHelper.Instance.ApplyChanges(dbTask); } catch (Exception ex) { throw new Exception("Unable to save BNK file: " + bnkFilePath, ex); } } finally { // Cleaning up EditHelper.Instance.RemoveTask(dbTask); } }
/// <summary> /// What the instruction should do /// </summary> protected override void _Process() { // Checking parameters string fileName = _GetParameter(PatchInstructionParameter.ParameterName.resourceFileName); string id = _GetParameter(PatchInstructionParameter.ParameterName.databaseId); // Modifying corresponding topic DB.Topic currentTopic = (DB.Topic)Enum.Parse(typeof(DB.Topic), fileName); EditHelper.Task dbTask = new EditHelper.Task(); string bnkFilePath = ""; try { string dbFileName = null; // 1. Creating edit task try { bnkFilePath = string.Concat(LibraryConstants.GetSpecialFolder(LibraryConstants.TduSpecialFolder.Database), DB.GetBNKFileName(DB.Culture.Global)); BNK databaseBNK = TduFile.GetFile(bnkFilePath) as BNK; if (databaseBNK != null) { dbFileName = DB.GetFileName(DB.Culture.Global, currentTopic); dbTask = EditHelper.Instance.AddTask(databaseBNK, databaseBNK.GetPackedFilesPaths(dbFileName)[0], true); } } catch (Exception ex) { throw new Exception("Unable to create edit task on BNK file: " + bnkFilePath, ex); } // 2. Getting TduFile DB db; try { db = TduFile.GetFile(dbTask.extractedFile) as DB; if (db == null || !db.Exists) { throw new Exception("Extracted db file not found!"); } } catch (Exception ex) { throw new Exception("Unable to gain access to DB contents: " + dbFileName, ex); } // 3. Removing values in DB file DatabaseHelper.DeleteFromTopicWhereIdentifier(db, id); // 4. Saving try { db.Save(); EditHelper.Instance.ApplyChanges(dbTask); } catch (Exception ex) { throw new Exception("Unable to save BNK file: " + bnkFilePath, ex); } } finally { // Cleaning up EditHelper.Instance.RemoveTask(dbTask); } }
/// <summary> /// What the instruction should do /// </summary> protected override void _Process() { // Checking parameters string fileName = _GetParameter(PatchInstructionParameter.ParameterName.resourceFileName); string values = _GetParameter(PatchInstructionParameter.ParameterName.resourceValues); // For each language file DB.Topic currentTopic = (DB.Topic)Enum.Parse(typeof(DB.Topic), fileName); for (int i = 0; i < 8; i++) { DB.Culture currentCulture = (DB.Culture)Enum.Parse(typeof(DB.Culture), i.ToString()); EditHelper.Task resourceTask = new EditHelper.Task(); string bnkFilePath = ""; string resourceFileName = null; // 1. Creating edit task try { bnkFilePath = string.Concat(LibraryConstants.GetSpecialFolder(LibraryConstants.TduSpecialFolder.Database), DB.GetBNKFileName(currentCulture)); BNK databaseBNK = TduFile.GetFile(bnkFilePath) as BNK; if (databaseBNK != null) { resourceFileName = DB.GetFileName(currentCulture, currentTopic); resourceTask = EditHelper.Instance.AddTask(databaseBNK, databaseBNK.GetPackedFilesPaths(resourceFileName)[0], true); } } catch (Exception ex) { throw new Exception("Unable to create edit task on BNK file: " + bnkFilePath, ex); } // 2. Getting TduFile DBResource resource; try { resource = TduFile.GetFile(resourceTask.extractedFile) as DBResource; if (resource == null || !resource.Exists) { throw new Exception("Extracted resource db file not found!"); } } catch (Exception ex) { throw new Exception("Unable to gain access to DB contents: " + resourceFileName, ex); } // 3. Setting values in DB file List <Couple <string> > couples = Tools.ParseCouples(values); // Parsing couples foreach (Couple <string> couple in couples) { string id = couple.FirstValue; string value = couple.SecondValue; // Does id exist ? DBResource.Entry currentEntry = resource.GetEntryFromId(id); if (currentEntry.isValid) { // Already exists > modify it currentEntry.value = value; resource.UpdateEntry(currentEntry); Log.Info("Entry succesfully updated : " + id + " - " + value); } else { // Does not exist > create it currentEntry.isValid = true; currentEntry.id = new ResourceIdentifier(id, currentTopic); currentEntry.value = value; currentEntry.index = resource.EntryList.Count + 1; resource.InsertEntry(currentEntry); Log.Info("Entry succesfully added : " + id + " - " + value); } } // 4. Saving try { resource.Save(); EditHelper.Instance.ApplyChanges(resourceTask); } catch (Exception ex) { throw new Exception("Unable to save BNK file: " + bnkFilePath, ex); } // 5. Cleaning up EditHelper.Instance.RemoveTask(resourceTask); } }