public MO2Compiler(AbsolutePath sourcePath, AbsolutePath downloadsPath, string mo2Profile, AbsolutePath outputFile) : base(21, mo2Profile, sourcePath, downloadsPath, outputFile) { MO2Profile = mo2Profile; MO2Ini = SourcePath.Combine("ModOrganizer.ini").LoadIniFile(); var mo2game = (string)MO2Ini.General.gameName; CompilingGame = GameRegistry.Games.First(g => g.Value.MO2Name == mo2game).Value; GamePath = CompilingGame.GameLocation(); }
protected override async Task <bool> _Begin(CancellationToken cancel) { await Metrics.Send("begin_compiling", MO2Profile ?? "unknown"); if (cancel.IsCancellationRequested) { return(false); } DesiredThreads.OnNext(DiskThreads); FileExtractor2.FavorPerfOverRAM = FavorPerfOverRam; UpdateTracker.Reset(); UpdateTracker.NextStep("Gathering information"); Utils.Log("Loading compiler Settings"); Settings = await CompilerSettings.Load(MO2ProfileDir); Settings.IncludedGames = Settings.IncludedGames.Add(CompilingGame.Game); Info("Looking for other profiles"); var otherProfilesPath = MO2ProfileDir.Combine("otherprofiles.txt"); SelectedProfiles = new HashSet <string>(); if (otherProfilesPath.Exists) { SelectedProfiles = (await otherProfilesPath.ReadAllLinesAsync()).ToHashSet(); } SelectedProfiles.Add(MO2Profile !); Info("Using Profiles: " + string.Join(", ", SelectedProfiles.OrderBy(p => p))); Utils.Log($"Compiling Game: {CompilingGame.Game}"); Utils.Log("Games from setting files:"); foreach (var game in Settings.IncludedGames) { Utils.Log($"- {game}"); } Utils.Log($"VFS File Location: {VFSCacheName}"); Utils.Log($"MO2 Folder: {SourcePath}"); Utils.Log($"Downloads Folder: {DownloadsPath}"); Utils.Log($"Game Folder: {GamePath}"); var watcher = new DiskSpaceWatcher(cancel, new[] { SourcePath, DownloadsPath, GamePath, AbsolutePath.EntryPoint }, (long)2 << 31, drive => { Utils.Log($"Aborting due to low space on {drive.Name}"); Abort(); }); var watcherTask = watcher.Start(); if (cancel.IsCancellationRequested) { return(false); } List <AbsolutePath> roots; if (UseGamePaths) { roots = new List <AbsolutePath> { SourcePath, GamePath, DownloadsPath }; roots.AddRange(Settings.IncludedGames.Select(g => g.MetaData().GameLocation())); } else { roots = new List <AbsolutePath> { SourcePath, DownloadsPath }; } // TODO: make this generic so we can add more paths var lootPath = (AbsolutePath)Path.Combine( Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "LOOT"); IEnumerable <RawSourceFile> lootFiles = new List <RawSourceFile>(); if (lootPath.Exists) { roots.Add(lootPath); } UpdateTracker.NextStep("Indexing folders"); if (cancel.IsCancellationRequested) { return(false); } await VFS.AddRoots(roots); if (lootPath.Exists) { if (CompilingGame.MO2Name == null) { throw new ArgumentException("Compiling game had no MO2 name specified."); } var lootGameDirs = new[] { CompilingGame.MO2Name, // most of the games use the MO2 name CompilingGame.MO2Name.Replace(" ", "") //eg: Fallout 4 -> Fallout4 }; var lootGameDir = lootGameDirs.Select(x => lootPath.Combine(x)) .FirstOrDefault(p => p.IsDirectory); if (lootGameDir != default) { Utils.Log($"Found LOOT game folder at {lootGameDir}"); lootFiles = lootGameDir.EnumerateFiles(false) .Where(p => p.FileName == (RelativePath)"userlist.yaml") .Where(p => p.IsFile) .Select(p => new RawSourceFile(VFS.Index.ByRootPath[p], Consts.LOOTFolderFilesDir.Combine(p.RelativeTo(lootPath)))); if (!lootFiles.Any()) { Utils.Log( $"Found no LOOT user data for {CompilingGame.HumanFriendlyGameName} at {lootGameDir}!"); } } } if (cancel.IsCancellationRequested) { return(false); } UpdateTracker.NextStep("Cleaning output folder"); await ModListOutputFolder.DeleteDirectory(); if (cancel.IsCancellationRequested) { return(false); } UpdateTracker.NextStep("Inferring metas for game file downloads"); await InferMetas(); if (cancel.IsCancellationRequested) { return(false); } UpdateTracker.NextStep("Reindexing downloads after meta inferring"); await VFS.AddRoot(DownloadsPath); if (cancel.IsCancellationRequested) { return(false); } UpdateTracker.NextStep("Pre-validating Archives"); // Find all Downloads IndexedArchives = (await DownloadsPath.EnumerateFiles() .Where(f => f.WithExtension(Consts.MetaFileExtension).Exists) .PMap(Queue, UpdateTracker, async f => new IndexedArchive(VFS.Index.ByRootPath[f]) { Name = (string)f.FileName, IniData = f.WithExtension(Consts.MetaFileExtension).LoadIniFile(), Meta = await f.WithExtension(Consts.MetaFileExtension).ReadAllTextAsync() })).ToList(); await IndexGameFileHashes(); IndexedArchives = IndexedArchives.DistinctBy(a => a.File.AbsoluteName).ToList(); await CleanInvalidArchivesAndFillState(); UpdateTracker.NextStep("Finding Install Files"); ModListOutputFolder.CreateDirectory(); var mo2Files = SourcePath.EnumerateFiles() .Where(p => p.IsFile) .Select(p => { if (!VFS.Index.ByRootPath.ContainsKey(p)) { Utils.Log($"WELL THERE'S YOUR PROBLEM: {p} {VFS.Index.ByRootPath.Count}"); } return(new RawSourceFile(VFS.Index.ByRootPath[p], p.RelativeTo(SourcePath))); }); // If Game Folder Files exists, ignore the game folder IndexedFiles = IndexedArchives.SelectMany(f => f.File.ThisAndAllChildren) .OrderBy(f => f.NestingFactor) .GroupBy(f => f.Hash) .ToDictionary(f => f.Key, f => f.AsEnumerable()); AllFiles.SetTo(mo2Files .Concat(lootFiles) .DistinctBy(f => f.Path)); Info($"Found {AllFiles.Count} files to build into mod list"); if (cancel.IsCancellationRequested) { return(false); } UpdateTracker.NextStep("Verifying destinations"); var dups = AllFiles.GroupBy(f => f.Path) .Where(fs => fs.Count() > 1) .Select(fs => { Utils.Log( $"Duplicate files installed to {fs.Key} from : {String.Join(", ", fs.Select(f => f.AbsolutePath))}"); return(fs); }).ToList(); if (dups.Count > 0) { Error($"Found {dups.Count} duplicates, exiting"); } if (cancel.IsCancellationRequested) { return(false); } UpdateTracker.NextStep("Loading INIs"); ModInis.SetTo(SourcePath.Combine(Consts.MO2ModFolderName) .EnumerateDirectories() .Select(f => { var modName = f.FileName; var metaPath = f.Combine("meta.ini"); return(metaPath.Exists ? (mod_name: f, metaPath.LoadIniFile()) : default);
protected void Construct(string name, bool isExe) { FileName = name + (isExe ? ".exe" : ".dll"); Framework.Add(c => ShouldTargetTinyCorlib(c, this), Bee.DotNet.Framework.FrameworkNone); References.Add(c => ShouldTargetTinyCorlib(c, this), Il2Cpp.TinyCorlib); Framework.Add(c => !ShouldTargetTinyCorlib(c, this), Bee.DotNet.Framework.Framework471); References.Add(c => !ShouldTargetTinyCorlib(c, this), new SystemReference("System")); ProjectFile.Path = new NPath(FileName).ChangeExtension(".csproj"); ProjectFile.ReferenceModeCallback = arg => { if (arg == Il2Cpp.TinyCorlib) { return(ProjectFile.ReferenceMode.ByCSProj); } //most projects are AsmDefBasedDotsRuntimeCSharpProgram. The remained are things like ZeroJobs. For them we'll look up their packagestatus by the fact that we know //it's in the same package as Unity.Entities.CPlusPlus var asmdefDotsProgram = (arg as AsmDefBasedDotsRuntimeCSharpProgram)?.AsmDefDescription ?? BuildProgramConfigFile.AsmDefDescriptionFor("Unity.Entities.CPlusPlus"); switch (asmdefDotsProgram.PackageSource) { case "NoPackage": case "Embedded": case "Local": return(ProjectFile.ReferenceMode.ByCSProj); default: return(ProjectFile.ReferenceMode.ByDotNetAssembly); } }; LanguageVersion = "7.3"; Defines.Add( "UNITY_2018_3_OR_NEWER", "UNITY_DOTSPLAYER", "UNITY_ZEROPLAYER", //<-- this was used for a while, let's keep it around to not break people's incoming PR's. "NET_TINY", "NET_DOTS", "UNITY_USE_TINYMATH", "UNITY_BINDGEM" ); Defines.Add(c => (c as DotsRuntimeCSharpProgramConfiguration)?.Platform is WebGLPlatform, "UNITY_WEBGL"); Defines.Add(c => (c as DotsRuntimeCSharpProgramConfiguration)?.Platform is WindowsPlatform, "UNITY_WINDOWS"); Defines.Add(c => (c as DotsRuntimeCSharpProgramConfiguration)?.Platform is MacOSXPlatform, "UNITY_MACOSX"); Defines.Add(c => (c as DotsRuntimeCSharpProgramConfiguration)?.Platform is LinuxPlatform, "UNITY_LINUX"); Defines.Add(c => (c as DotsRuntimeCSharpProgramConfiguration)?.Platform is IosPlatform, "UNITY_IOS"); Defines.Add(c => (c as DotsRuntimeCSharpProgramConfiguration)?.Platform is AndroidPlatform, "UNITY_ANDROID"); CopyReferencesNextToTarget = false; WarningsAsErrors = false; //hack, fix this in unity.mathematics if (SourcePath.FileName == "Unity.Mathematics") { Sources.Add(SourcePath.Files("*.cs", true).Where(f => f.FileName != "math_unity_conversion.cs" && f.FileName != "PropertyAttributes.cs")); } else { var csFilesForDirectory = CSFilesForDirectory(SourcePath).ToList(); if (csFilesForDirectory.Count == 0) { csFilesForDirectory.Add(BuildProgram.BeeRoot.Combine("CSharpSupport/PlaceHolderForEmptyProject.cs")); } Sources.Add(csFilesForDirectory); } var cppFolder = SourcePath.Combine("cpp~"); var prejsFolder = SourcePath.Combine("prejs~"); var jsFolder = SourcePath.Combine("js~"); var postjsFolder = SourcePath.Combine("postjs~"); var beeFolder = SourcePath.Combine("bee~"); var includeFolder = cppFolder.Combine("include"); NPath[] cppFiles = Array.Empty <NPath>(); if (cppFolder.DirectoryExists()) { cppFiles = cppFolder.Files("*.c*", true); ProjectFile.AdditionalFiles.AddRange(cppFolder.Files(true)); GetOrMakeNativeProgram().Sources.Add(cppFiles); } if (prejsFolder.DirectoryExists()) { var jsFiles = prejsFolder.Files("*.js", true); ProjectFile.AdditionalFiles.AddRange(prejsFolder.Files(true)); GetOrMakeNativeProgram().Libraries.Add(jsFiles.Select(jsFile => new PreJsLibrary(jsFile))); } //todo: get rid of having both a regular js and a prejs folder if (jsFolder.DirectoryExists()) { var jsFiles = jsFolder.Files("*.js", true); ProjectFile.AdditionalFiles.AddRange(jsFolder.Files(true)); GetOrMakeNativeProgram().Libraries.Add(jsFiles.Select(jsFile => new JavascriptLibrary(jsFile))); } if (postjsFolder.DirectoryExists()) { var jsFiles = postjsFolder.Files("*.js", true); ProjectFile.AdditionalFiles.AddRange(postjsFolder.Files(true)); GetOrMakeNativeProgram().Libraries.Add(jsFiles.Select(jsFile => new PostJsLibrary(jsFile))); } if (beeFolder.DirectoryExists()) { ProjectFile.AdditionalFiles.AddRange(beeFolder.Files("*.cs")); } if (includeFolder.DirectoryExists()) { GetOrMakeNativeProgram().PublicIncludeDirectories.Add(includeFolder); } SupportFiles.Add(SourcePath.Files().Where(f => f.HasExtension("jpg", "png", "wav", "mp3", "jpeg", "mp4", "webm", "ogg"))); Defines.Add(c => c.CodeGen == CSharpCodeGen.Debug, "DEBUG"); Defines.Add(c => ((DotsRuntimeCSharpProgramConfiguration)c).EnableUnityCollectionsChecks, "ENABLE_UNITY_COLLECTIONS_CHECKS"); Defines.Add( c => (c as DotsRuntimeCSharpProgramConfiguration)?.ScriptingBackend == ScriptingBackend.TinyIl2cpp, "UNITY_DOTSPLAYER_IL2CPP"); Defines.Add(c => (c as DotsRuntimeCSharpProgramConfiguration)?.ScriptingBackend == ScriptingBackend.Dotnet, "UNITY_DOTSPLAYER_DOTNET"); ProjectFile.RedirectMSBuildBuildTargetToBee = true; ProjectFile.AddCustomLinkRoot(SourcePath, "."); ProjectFile.RootNameSpace = ""; DotsRuntimeCSharpProgramCustomizer.RunAllCustomizersOn(this); }