Beispiel #1
0
        /// <summary>
        /// Adds a file from a file path on disk
        /// </summary>
        public LotdFile AddFileOnDisk(string filePath, string rootDir)
        {
            if (File.Exists(filePath))
            {
                string relativePath = GetRelativeFilePathOnDisk(filePath, rootDir);

                LotdFile existingFile = FindFile(relativePath);
                if (existingFile != null)
                {
                    if (!existingFile.IsFileOnDisk)
                    {
                        // Already exists as an archive file or a placeholder
                        // Set the file path (this will favor loading from the file rather than the archive)
                        existingFile.FilePathOnDisk = filePath;
                    }
                    return(existingFile);
                }

                string[] splitted = SplitPath(relativePath);
                if (splitted.Length > 0)
                {
                    LotdDirectory directory = ResolveDirectory(splitted, true, true);
                    if (directory != null)
                    {
                        LotdFile file = new LotdFile();
                        file.Name           = splitted[splitted.Length - 1];
                        file.Directory      = directory;
                        file.FilePathOnDisk = filePath;
                        return(file);
                    }
                }
            }
            return(null);
        }
Beispiel #2
0
        private LotdDirectory ResolveDirectory(string[] path, bool isFilePath, bool create)
        {
            LotdDirectory directory = this;

            int pathCount = path.Length + (isFilePath ? -1 : 0);

            for (int i = 0; i < pathCount; i++)
            {
                if (path[i] == "..")
                {
                    directory = directory.Parent;
                    if (directory == null)
                    {
                        return(null);
                    }
                }
                else
                {
                    LotdDirectory subDir;
                    if (directory.Directories.TryGetValue(path[i], out subDir))
                    {
                        directory = subDir;
                    }
                    else
                    {
                        subDir        = new LotdDirectory();
                        subDir.Name   = path[i];
                        subDir.Parent = directory;
                        directory     = subDir;
                    }
                }
            }

            return(directory);
        }
Beispiel #3
0
        public void CreateDirectory(string path)
        {
            LotdDirectory directory = ResolveDirectory(path, false, true);

            if (directory == null)
            {
                throw new Exception("Invalid path '" + path + "'");
            }
        }
Beispiel #4
0
 public LotdFile FindFile(string path)
 {
     string[] splitted = SplitPath(path);
     if (splitted.Length > 0)
     {
         LotdDirectory directory = ResolveDirectory(splitted, true, false);
         LotdFile      file;
         if (directory != null && directory.Files.TryGetValue(splitted[splitted.Length - 1], out file))
         {
             return(file);
         }
     }
     return(null);
 }
Beispiel #5
0
 public LotdFile AddFile(string path, long offset, long length)
 {
     string[] splitted = SplitPath(path);
     if (splitted.Length > 0)
     {
         LotdDirectory directory = ResolveDirectory(splitted, true, true);
         if (directory != null)
         {
             LotdFile file = new LotdFile();
             file.Name          = splitted[splitted.Length - 1];
             file.Directory     = directory;
             file.ArchiveOffset = offset;
             file.ArchiveLength = length;
             return(file);
         }
     }
     return(null);
 }
Beispiel #6
0
        public void Load()
        {
            if (string.IsNullOrEmpty(InstallDirectory) || !Directory.Exists(InstallDirectory))
            {
                throw new Exception("Couldn't find the install directory for Legacy of the Duelist '" + InstallDirectory + "'");
            }

            string tocPath = Path.Combine(InstallDirectory, TocFileName);
            string datPath = Path.Combine(InstallDirectory, DatFileName);

            if (!File.Exists(tocPath) || !File.Exists(datPath))
            {
                throw new Exception("Failed to find data files");
            }

            if (Reader != null)
            {
                Reader.Close();
                Reader = null;
            }

            Root         = new LotdDirectory();
            Root.Archive = this;
            Root.IsRoot  = true;

            List <string> filePaths = new List <string>();

            try
            {
                long offset = 0;

                string[] lines = File.ReadAllLines(tocPath);
                for (int i = 0; i < lines.Length; i++)
                {
                    string line = lines[i];

                    if (!line.StartsWith("UT"))
                    {
                        int offsetStart = -1;
                        for (int charIndex = 0; charIndex < line.Length; charIndex++)
                        {
                            if (line[charIndex] != ' ')
                            {
                                offsetStart = charIndex;
                                break;
                            }
                        }

                        int offsetEnd    = offsetStart == -1 ? -1 : line.IndexOf(' ', offsetStart);
                        int unknownStart = offsetEnd == -1 ? -1 : offsetEnd + 1;
                        int unknownEnd   = unknownStart == -1 ? -1 : line.IndexOf(' ', unknownStart + 1);

                        bool validLine = unknownEnd >= 0;

                        if (validLine)
                        {
                            string lengthStr         = line.Substring(offsetStart, offsetEnd - offsetStart);
                            string filePathLengthStr = line.Substring(unknownStart, unknownEnd - unknownStart);
                            string filePath          = line.Substring(unknownEnd + 1);

                            long length;
                            int  filePathLength;
                            if (long.TryParse(lengthStr, NumberStyles.HexNumber, null, out length) &&
                                int.TryParse(filePathLengthStr, NumberStyles.HexNumber, null, out filePathLength) &&
                                filePathLength == filePath.Length)
                            {
                                Root.AddFile(filePath, offset, length);

                                offset += length;

                                // Add the offset for the data alignment
                                const int align = 4;
                                if (length % align != 0)
                                {
                                    offset += align - (length % align);
                                }

                                filePaths.Add(filePath);
                            }
                            else
                            {
                                validLine = false;
                            }
                        }

                        if (!validLine)
                        {
                            throw new Exception("Failed to parse line in toc file " + line);
                        }
                    }
                }
            }
            catch (Exception e)
            {
                throw new Exception("Error when reading .toc file: " + e);
            }

            try
            {
                if (WriteAccess)
                {
                    Reader = new BinaryReader(File.Open(datPath, FileMode.Open, FileAccess.ReadWrite));
                }
                else
                {
                    Reader = new BinaryReader(File.OpenRead(datPath));
                }
            }
            catch (Exception e)
            {
                throw new Exception("Error when opening .dat file: " + e);
            }

            // Validate all file paths
            foreach (string filePath in filePaths)
            {
                LotdFile file = Root.FindFile(filePath);
                if (file == null)
                {
                    throw new Exception("Archive loader is broken. File path not found in archive structure: '" + filePath + "'");
                }
            }
        }