Beispiel #1
0
        public CommandList LinkAirModifications(IReadOnlyList <Modification> modifications)
        {
            DefaultCommandList commandList = new DefaultCommandList();

            foreach (var modification in modifications)
            {
                var resolutionTableComponent = modification.GetComponent <LeagueResolutionTableComponent>();
                var resolutionTable          = resolutionTableComponent.Table;
                var contentPath          = Path.Combine(modification.RepositoryPath, "content");
                var contentDirectory     = fileSystemProxy.GetDirectoryInfo(contentPath);
                var contentFiles         = contentDirectory.EnumerateFiles("*", SearchOption.AllDirectories);
                var contentRelativePaths = contentFiles.Select(f => f.FullName.Substring(contentPath.Length + 1));
                var objectsPath          = Path.Combine(modification.RepositoryPath, "objects");

                foreach (var contentRelativePath in contentRelativePaths)
                {
                    LeagueResolutionTableValue resolutionTableValue;
                    if (!resolutionTable.TryGetValue(contentRelativePath, out resolutionTableValue))
                    {
                        logger?.Warn($"Not linking {contentRelativePath}: resolution table lookup failed");
                        continue;
                    }
                    if (resolutionTableValue.Target != LeagueModificationTarget.Client)
                    {
                        logger?.Warn($"Not linking {contentRelativePath}: does not target air client.");
                        continue;
                    }
                    string replacedPath    = resolutionTableValue.ResolvedPath;
                    string replacementPath = Path.Combine(contentPath, contentRelativePath);
                    commandList.Add(commandFactory.CreateFileRedirectionCommand(replacedPath, replacementPath));
                }
            }
            return(commandList);
        }
Beispiel #2
0
        public CommandList LinkGameModifications(IReadOnlyList <Modification> modifications)
        {
            var archiveLoader = new RiotArchiveLoader(leagueConfiguration.RadsPath);
            Dictionary <uint, List <KeyValuePair <RiotArchive, SectorCollection> > > archivePairsById = new Dictionary <uint, List <KeyValuePair <RiotArchive, SectorCollection> > >();

            var riotSolution = riotSolutionLoader.Load(leagueConfiguration.RadsPath, RiotProjectType.GameClient);
            var gameProject  = riotSolution.ProjectsByType[RiotProjectType.GameClient];
            var gameManifest = gameProject.ReleaseManifest;

            foreach (var modification in modifications)
            {
                var resolutionTableComponent = modification.GetComponent <LeagueResolutionTableComponent>();
                var resolutionTable          = resolutionTableComponent.Table;
                var contentPath          = Path.Combine(modification.RepositoryPath, "content");
                var contentDirectory     = fileSystemProxy.GetDirectoryInfo(contentPath);
                var contentFiles         = contentDirectory.EnumerateFiles("*", SearchOption.AllDirectories);
                var contentRelativePaths = contentFiles.Select(f => f.FullName.Substring(contentPath.Length + 1));
                var objectsPath          = Path.Combine(modification.RepositoryPath, "objects");

                foreach (var contentRelativePath in contentRelativePaths)
                {
                    LeagueResolutionTableValue resolutionTableValue;
                    if (!resolutionTable.TryGetValue(contentRelativePath, out resolutionTableValue))
                    {
                        logger?.Warn($"Not linking {contentRelativePath}: resolution table lookup failed");
                        continue;
                    }
                    if (resolutionTableValue.Target != LeagueModificationTarget.Game)
                    {
                        logger?.Warn($"Not linking {contentRelativePath}: does not target game client.");
                        continue;
                    }
                    var manifestEntry = gameManifest.Root.GetRelativeOrNull <ReleaseManifestFileEntry>(resolutionTableValue.ResolvedPath);
                    if (manifestEntry == null)
                    {
                        logger?.Warn($"Not linking {contentRelativePath}: could not find {resolutionTableValue.ResolvedPath} in manifest.");
                        continue;
                    }

                    List <KeyValuePair <RiotArchive, SectorCollection> > archivePairs;
                    if (!archivePairsById.TryGetValue(manifestEntry.ArchiveId, out archivePairs))
                    {
                        archivePairs = new List <KeyValuePair <RiotArchive, SectorCollection> >();
                        IReadOnlyList <RiotArchive> archives;
                        if (!archiveLoader.TryLoadArchives(manifestEntry.ArchiveId, out archives))
                        {
                            logger?.Error($"Not linking {contentRelativePath}: could not load archives for {manifestEntry.ArchiveId}!");
                            continue;
                        }
                        archives.ForEach(archive => {
                            var datLength = new FileInfo(archive.DatFilePath).Length;
                            SectorCollection sectorCollection = new SectorCollection();
                            sectorCollection.AssignSector(new SectorRange(0, datLength), new FileSector(archive.DatFilePath, 0, datLength));
                            archivePairs.Add(archive.PairValue(sectorCollection));
                        });
                        archivePairsById.Add(manifestEntry.ArchiveId, archivePairs);
                    }

                    var rafPath = RAFUtil.FormatPathToRAFPath(resolutionTableValue.ResolvedPath);
                    RAFFileListEntry rafEntry = null;
                    SectorCollection sectors  = null;
                    foreach (var archivePair in archivePairs)
                    {
                        rafEntry = archivePair.Key.GetDirectoryFile().GetFileList().GetFileEntryOrNull(rafPath);
                        if (rafEntry != null)
                        {
                            sectors = archivePair.Value;
                            break;
                        }
                    }
                    if (rafEntry == null)
                    {
                        logger?.Warn($"Not linking {contentRelativePath}: could not find {resolutionTableValue.ResolvedPath} in {manifestEntry.ArchiveId} archives.");
                        continue;
                    }

                    var vfmEndOffset = sectors.EnumerateSectorPairs().Last().Key.endExclusive;

                    sectors.DeleteRange(rafEntry.FileOffset, rafEntry.FileOffset + rafEntry.FileSize);

                    var objectsFilePath   = Path.Combine(objectsPath, contentRelativePath);
                    var objectsFileLength = new FileInfo(objectsFilePath).Length;

                    rafEntry.FileOffset = (uint)vfmEndOffset;
                    rafEntry.FileSize   = (uint)objectsFileLength;

                    sectors.AssignSector(new SectorRange(vfmEndOffset, vfmEndOffset + objectsFileLength), new FileSector(objectsFilePath, 0, objectsFileLength));

                    var originalFileLength = new FileInfo(Path.Combine(contentPath, contentRelativePath)).Length;
                    manifestEntry.CompressedSize   = (uint)objectsFileLength;
                    manifestEntry.DecompressedSize = (uint)originalFileLength;

                    logger?.Warn("Successfully linked " + resolutionTableValue.ResolvedPath + " in archive " + manifestEntry.ArchiveId + ".");
                }
            }

            var commandList            = new DefaultCommandList();
            var versionStringUtilities = new VersionStringUtilities();
            var tempDir = temporaryFileService.AllocateTemporaryDirectory(TimeSpan.FromMinutes(1));

            logger?.Info("Allocated temporary directory " + tempDir);
            foreach (var archivePair in archivePairsById)
            {
                string versionString = versionStringUtilities.GetVersionString(archivePair.Key);

                foreach (var archiveData in archivePair.Value)
                {
                    // Get archive name (e.g. archive_2.raf or archive_12930813.raf)
                    string archiveFileName = archiveData.Key.RAFFilePath.With(x => x.Substring(x.LastIndexOfAny(new[] { '/', '\\' }) + 1));

                    // Serialize the VFM
                    var vfmSerializer = new SectorCollectionSerializer();
                    var vfmFileName   = versionString + "/" + archiveFileName + ".dat.vfm";
                    var vfmPath       = temporaryFileService.AllocateTemporaryFile(tempDir, vfmFileName);
                    using (var vfmFileStream = File.Open(vfmPath, FileMode.Create, FileAccess.Write, FileShare.None))
                        using (var writer = new BinaryWriter(vfmFileStream)) {
                            vfmSerializer.Serialize(archiveData.Value, writer);
                            commandList.Add(commandFactory.CreateFileRemappingCommand(archiveData.Key.DatFilePath, vfmFileStream.Name));
                        }
                    logger?.Info("Wrote VFM " + vfmFileName + " to " + tempDir);

                    // Serialize the RAF
                    var rafFileName = versionString + "/" + archiveFileName;
                    var rafPath     = temporaryFileService.AllocateTemporaryFile(tempDir, rafFileName);
                    using (var rafFileStream = File.Open(rafPath, FileMode.Create, FileAccess.Write, FileShare.None))
                        using (var writer = new BinaryWriter(rafFileStream)) {
                            writer.Write(archiveData.Key.GetDirectoryFile().GetBytes());
                            commandList.Add(commandFactory.CreateFileRedirectionCommand(archiveData.Key.RAFFilePath, rafFileStream.Name));
                        }
                    logger?.Info("Wrote RAF " + rafFileName + " to " + tempDir);
                }
            }

            // Serialize the Release Manifest
            var manifestPath = temporaryFileService.AllocateTemporaryFile(tempDir, "releasemanifest");

            using (var manifestFileStream = File.Open(manifestPath, FileMode.Create, FileAccess.Write, FileShare.None))
                using (var writer = new BinaryWriter(manifestFileStream)) {
                    new ReleaseManifestWriter(gameManifest).Save(writer);
                    commandList.Add(commandFactory.CreateFileRedirectionCommand(gameManifest.Path, manifestFileStream.Name));
                }
            logger?.Info("Wrote release manifest to " + tempDir);
            return(commandList);
        }