示例#1
0
        /// <summary>
        /// Initializes a new instance of the <see cref="GgpkArchive"/> class.
        /// </summary>
        /// <param name="fileName">The ggpk archive file.</param>
        /// <exception cref="GgpkException">Error while reading the archive.</exception>
        internal GgpkArchive(string fileName)
        {
            IEnumerable <GgpkRecord> records    = GgpkRecords.From(fileName);
            GgpkMainRecord           mainRecord = records.OfType <GgpkMainRecord>().FirstOrDefault();

            this.RawRecords = records;
            this.root       = new GgpkDirectory();
            this.FileName   = fileName;

            if (mainRecord is null)
            {
                throw new GgpkException($"Error while analyzing the ggpk archive file: no record of type GGPK found");
            }

            // Convert references in main record (ulong) to type GgpkDirectoryRecordEntry required by BuildDirectoryTree-method
            IEnumerable <GgpkDirectoryRecordEntry> createdEntries = mainRecord.RecordOffsets.Select((offset) => new GgpkDirectoryRecordEntry()
            {
                Offset    = offset,
                TimeStamp = 0
            }).ToList();

            // Create record dictionary (which is /much/ faster than querying the IEnumerable with Linq)
            Dictionary <ulong, GgpkRecord> recordDictionary = new Dictionary <ulong, GgpkRecord>();

            foreach (GgpkRecord record in records)
            {
                recordDictionary.Add(record.Offset, record);
            }

            this.BuildDirectoryTree(null, createdEntries, recordDictionary);
        }
示例#2
0
        /// <summary>
        /// Builds the directory and file tree.
        /// </summary>
        /// <param name="currentDirectory">The current directory.</param>
        /// <param name="currentDirectoryContent">The desired content of the current directory.</param>
        /// <param name="records">All <see cref="GgpkRecord">records</see> from the ggpk archive used to find the references.</param>
        private void BuildDirectoryTree(
            GgpkDirectory currentDirectory,
            IEnumerable <GgpkDirectoryRecordEntry> currentDirectoryContent,
            IDictionary <ulong, GgpkRecord> records)
        {
            foreach (GgpkDirectoryRecordEntry recordEntry in currentDirectoryContent)
            {
                GgpkRecord referencedRecord = records[recordEntry.Offset];

                if (referencedRecord is null)
                {
                    throw new GgpkException($"Error while analyzing the ggpk archive file: no element found at offset {recordEntry.Offset}");
                }

                switch (referencedRecord)
                {
                case GgpkDirectoryRecord directoryRecord:

                    GgpkDirectory directory = new GgpkDirectory()
                    {
                        Name            = directoryRecord.DirectoryName,
                        TimeStamp       = recordEntry.TimeStamp,
                        Hash            = directoryRecord.Hash,
                        Parent          = currentDirectory,
                        ArchiveFileName = this.FileName
                    };

                    if (currentDirectory != null)
                    {
                        currentDirectory.Add(directory);
                    }
                    else
                    {
                        this.root = directory;
                    }

                    this.BuildDirectoryTree(directory, directoryRecord.Entries, records);

                    break;

                case GgpkFileRecord fileRecord:

                    GgpkFile file = new GgpkFile()
                    {
                        Name            = fileRecord.FileName,
                        TimeStamp       = recordEntry.TimeStamp,
                        Hash            = fileRecord.Hash,
                        Offset          = fileRecord.FileOffset,
                        Length          = fileRecord.FileLength,
                        Parent          = currentDirectory,
                        ArchiveFileName = this.FileName
                    };

                    currentDirectory.Add(file);

                    break;

                case GgpkFreeRecord freeRecord:
                    break;

                default:
                    throw new GgpkException($"Error while analyzing the ggpk archive file: no element of type directory or file found at offset {recordEntry.Offset}");
                }
            }
        }
示例#3
0
 /// <summary>
 /// Adds a directory to the list of directories.
 /// </summary>
 /// <param name="directory">The directory to add.</param>
 public void Add(GgpkDirectory directory)
 {
     this.directories.Add(directory);
 }