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)); }
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); } } }
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); }