Beispiel #1
0
        public RiotProject LoadProject(RiotProjectType projectType, string projectPath)
        {
            // - Find the RADS Project's latest release directory ------------------------------------
            var versionStringParser = new VersionStringUtilities();
            var releasesPath        = Path.Combine(projectPath, "releases");
            var releases            = from releasePath in Directory.GetDirectories(releasesPath)
                                      let versionString = versionStringParser.GetVersionString(releasePath)
                                                          where !string.IsNullOrWhiteSpace(versionString)
                                                          let versionNumber = versionStringParser.GetVersionNumber(versionString)
                                                                              select new { ReleasePath = releasePath, VersionNumber = versionNumber };
            var latestRelease = releases.MaxBy((release) => release.VersionNumber);

            // - Load RADS Project Release Manifest and assign to RADS Project -----------------------
            var releaseManifestPath = Path.Combine(latestRelease.ReleasePath, "releasemanifest");
            var releaseManifest     = new ReleaseManifestLoader().LoadFile(releaseManifestPath);

            // - Project-Type-Specific Hacks ------------------------------------------------
            if (projectType == RiotProjectType.AirClient)
            {
                var rootEntry    = releaseManifest.Root;
                var overloadName = Path.Combine(latestRelease.ReleasePath, "deploy");
                var overload     = new ReleaseManifestRootDirectoryOverload((ReleaseManifestDirectoryEntry)rootEntry, overloadName);
                releaseManifest.Root = overload;
            }

            return(new RiotProject(projectType, releaseManifest, latestRelease.VersionNumber));
        }
Beispiel #2
0
        public RiotArchiveLoader(string solutionPath)
        {
            fileArchivesPath = Path.Combine(solutionPath, "projects", "lol_game_client", "filearchives");
            var parser = new VersionStringUtilities();

            foreach (var directory in Directory.EnumerateDirectories(fileArchivesPath))
            {
                var  name = Path.GetFileName(directory);
                uint versionNumber;
                if (parser.TryGetVersionNumber(name, out versionNumber))
                {
                    var files = Directory.EnumerateFiles(directory);
                    var pairs = new List <RafDatPair>();
                    foreach (var rafPath in files.Where((path) => path.EndsWith(".raf", StringComparison.OrdinalIgnoreCase)))
                    {
                        var datPath = rafPath + ".dat";
                        if (File.Exists(datPath))
                        {
                            pairs.Add(new RafDatPair(rafPath, datPath));
                        }
                    }
                    pairCollectionsById.Add(versionNumber, pairs);
                }
            }
        }
Beispiel #3
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);
        }