internal static bool BuildAll(string[] modFolders, IBuildStatus status) { var modList = new List <LoadingMod>(); //read mod sources folder foreach (var modFolder in modFolders) { var mod = ReadProperties(modFolder, status); if (mod == null) { return(false); } modList.Add(mod); } //figure out which of the installed mods are required for building var installedMods = FindMods() .Where(mod => !modList.Exists(m => m.Name == mod.name)) .Select(mod => new LoadingMod(mod, BuildProperties.ReadModFile(mod))) .ToList(); var requiredFromInstall = new HashSet <LoadingMod>(); Action <LoadingMod> require = null; require = (mod) => { foreach (var dep in mod.properties.RefNames(true)) { var depMod = installedMods.SingleOrDefault(m => m.Name == dep); if (depMod != null && requiredFromInstall.Add(depMod)) { require(depMod); } } }; foreach (var mod in modList) { require(mod); } modList.AddRange(requiredFromInstall); //sort and version check List <BuildingMod> modsToBuild; try { EnsureDependenciesExist(modList, true); EnsureTargetVersionsMet(modList); var sortedModList = Sort(modList); modsToBuild = sortedModList.OfType <BuildingMod>().ToList(); } catch (ModSortingException e) { ErrorLogger.LogDependencyError(e.Message); return(false); } //build int num = 0; foreach (var mod in modsToBuild) { status.SetProgress(num++, modsToBuild.Count); if (!Build(mod, status)) { return(false); } } return(true); }
private static bool Build(BuildingMod mod, IBuildStatus status) { byte[] winDLL = null; byte[] monoDLL = null; byte[] winPDB = null; if (mod.properties.noCompile) { winDLL = monoDLL = ReadIfExists(Path.Combine(mod.path, "All.dll")); winPDB = ReadIfExists(Path.Combine(mod.path, "All.pdb")); if (winDLL == null) { winDLL = ReadIfExists(Path.Combine(mod.path, "Windows.dll")); monoDLL = ReadIfExists(Path.Combine(mod.path, "Mono.dll")); winPDB = ReadIfExists(Path.Combine(mod.path, "Windows.pdb")); } if (winDLL == null || monoDLL == null) { ErrorLogger.LogDllBuildError(mod.path); return(false); } } else { var refMods = FindReferencedMods(mod.properties); if (refMods == null) { return(false); } if (Program.LaunchParameters.ContainsKey("-eac")) { if (!windows) { ErrorLogger.LogBuildError("Edit and continue is only supported on windows"); return(false); } try { status.SetStatus("Loading pre-compiled Windows.dll with edit and continue support"); var winPath = Program.LaunchParameters["-eac"]; var pdbPath = Path.ChangeExtension(winPath, "pdb"); winDLL = File.ReadAllBytes(winPath); winPDB = File.ReadAllBytes(pdbPath); mod.properties.editAndContinue = true; } catch (Exception e) { ErrorLogger.LogBuildError("Failed to load pre-compiled edit and continue dll " + e); return(false); } } else { status.SetStatus("Compiling " + mod + " for Windows..."); status.SetProgress(0, 2); CompileMod(mod, refMods, true, ref winDLL, ref winPDB); } if (winDLL == null) { return(false); } status.SetStatus("Compiling " + mod + " for Mono..."); status.SetProgress(1, 2); CompileMod(mod, refMods, false, ref monoDLL, ref winPDB); //the pdb reference won't actually be written to if (monoDLL == null) { return(false); } } if (!VerifyName(mod.Name, winDLL) || !VerifyName(mod.Name, monoDLL)) { return(false); } status.SetStatus("Building " + mod + "..."); status.SetProgress(0, 1); mod.modFile.AddFile("Info", mod.properties.ToBytes()); if (Equal(winDLL, monoDLL)) { mod.modFile.AddFile("All.dll", winDLL); if (winPDB != null) { mod.modFile.AddFile("All.pdb", winPDB); } } else { mod.modFile.AddFile("Windows.dll", winDLL); mod.modFile.AddFile("Mono.dll", monoDLL); if (winPDB != null) { mod.modFile.AddFile("Windows.pdb", winPDB); } } foreach (var resource in Directory.GetFiles(mod.path, "*", SearchOption.AllDirectories)) { var relPath = resource.Substring(mod.path.Length + 1); if (mod.properties.ignoreFile(relPath) || relPath == "build.txt" || !mod.properties.includeSource && sourceExtensions.Contains(Path.GetExtension(resource)) || Path.GetFileName(resource) == "Thumbs.db") { continue; } mod.modFile.AddFile(relPath, File.ReadAllBytes(resource)); } WAVCacheIO.ClearCache(mod.Name); mod.modFile.Save(); EnableMod(mod.modFile); ActivateExceptionReporting(); return(true); }
private static void CompileMod(BuildingMod mod, List <LoadingMod> refMods, bool forWindows, ref byte[] dll, ref byte[] pdb) { LoadReferences(); bool generatePDB = mod.properties.includePDB && forWindows; if (generatePDB && !windows) { Console.WriteLine("PDB files can only be generated for windows, on windows."); generatePDB = false; } //collect all dll references var tempDir = Path.Combine(ModPath, "compile_temp"); Directory.CreateDirectory(tempDir); var refs = new List <string>(); //everything used to compile the tModLoader for the target platform refs.AddRange(GetTerrariaReferences(tempDir, forWindows)); //libs added by the mod refs.AddRange(mod.properties.dllReferences.Select(refDll => Path.Combine(mod.path, "lib/" + refDll + ".dll"))); //all dlls included in all referenced mods foreach (var refMod in refMods) { var path = Path.Combine(tempDir, refMod + ".dll"); File.WriteAllBytes(path, refMod.modFile.GetMainAssembly(forWindows)); refs.Add(path); foreach (var refDll in refMod.properties.dllReferences) { path = Path.Combine(tempDir, refDll + ".dll"); File.WriteAllBytes(path, refMod.modFile.GetFile("lib/" + refDll + ".dll")); refs.Add(path); } } var compileOptions = new CompilerParameters { OutputAssembly = Path.Combine(tempDir, mod + ".dll"), GenerateExecutable = false, GenerateInMemory = false, TempFiles = new TempFileCollection(tempDir, true), IncludeDebugInformation = generatePDB }; compileOptions.ReferencedAssemblies.AddRange(refs.ToArray()); var files = Directory.GetFiles(mod.path, "*.cs", SearchOption.AllDirectories).Where(file => !mod.properties.ignoreFile(file.Substring(mod.path.Length + 1))).ToArray(); try { CompilerResults results; if (mod.properties.languageVersion == 6) { if (Environment.Version.Revision < 10000) { ErrorLogger.LogBuildError(".NET Framework 4.5 must be installed to compile C# 6.0"); return; } results = RoslynCompile(compileOptions, files); } else { var options = new Dictionary <string, string> { { "CompilerVersion", "v" + mod.properties.languageVersion + ".0" } }; results = new CSharpCodeProvider(options).CompileAssemblyFromFile(compileOptions, files); } if (results.Errors.HasErrors) { ErrorLogger.LogCompileErrors(results.Errors, forWindows); return; } dll = File.ReadAllBytes(compileOptions.OutputAssembly); dll = PostProcess(dll, forWindows); if (generatePDB) { pdb = File.ReadAllBytes(Path.Combine(tempDir, mod + ".pdb")); } } finally { int numTries = 10; while (numTries > 0) { try { Directory.Delete(tempDir, true); numTries = 0; } catch { System.Threading.Thread.Sleep(1); numTries--; } } } }
internal static List <Mod> InstantiateMods(List <LocalMod> modsToLoad) { var modList = new List <LoadedMod>(); foreach (var loading in modsToLoad) { if (!loadedMods.TryGetValue(loading.Name, out LoadedMod mod)) { mod = loadedMods[loading.Name] = new LoadedMod(); } mod.SetMod(loading); modList.Add(mod); } RecalculateReferences(); if (Debugger.IsAttached) { ModLoader.isModder = true; foreach (var mod in modList.Where(mod => mod.properties.editAndContinue && mod.CanEaC)) { mod.EnableEaC(); } } if (ModLoader.alwaysLogExceptions) { ModCompile.ActivateExceptionReporting(); } try { //load all the assemblies in parallel. Interface.loadMods.SetLoadStage("tModLoader.MSSandboxing", modsToLoad.Count); int i = 0; Parallel.ForEach(modList, mod => { Interface.loadMods.SetCurrentMod(i++, mod.Name); mod.LoadAssemblies(); }); Interface.loadMods.SetLoadStage("tModLoader.MSInstantiating"); //Assemblies must be loaded before any instantiation occurs to satisfy dependencies return(modList.Select(Instantiate).ToList()); } catch (AggregateException ae) { ErrorLogger.LogMulti(ae.InnerExceptions.Select(e => new Action(() => { var mod = modList.Single(m => m.Name == (string)e.Data["mod"]); ModLoader.DisableMod(mod.Name); ErrorLogger.LogLoadingError(mod.Name, mod.modFile.tModLoaderVersion, e); }))); Main.menuMode = Interface.errorMessageID; return(null); } catch (Exception e) { var mod = modList.Single(m => m.Name == (string)e.Data["mod"]); ModLoader.DisableMod(mod.Name); ErrorLogger.LogLoadingError(mod.Name, mod.modFile.tModLoaderVersion, e); Main.menuMode = Interface.errorMessageID; return(null); } }
private static bool LoadMods() { //load all referenced assemblies before mods for compiling ModCompile.LoadReferences(); if (!CommandLineModPackOverride()) { return(false); } Interface.loadMods.SetProgressFinding(); var modsToLoad = FindMods() .Where(IsEnabled) .Select(mod => new LoadingMod(mod, BuildProperties.ReadModFile(mod))) .Where(mod => LoadSide(mod.properties.side)) .ToList(); // Press shift while starting up tModLoader or while trapped in a reload cycle to skip loading all mods. if (Main.oldKeyState.PressingShift()) { modsToLoad.Clear(); } if (!VerifyNames(modsToLoad)) { return(false); } try { EnsureDependenciesExist(modsToLoad, false); EnsureTargetVersionsMet(modsToLoad); modsToLoad = Sort(modsToLoad); } catch (ModSortingException e) { foreach (var mod in e.errored) { DisableMod(mod.modFile); } ErrorLogger.LogDependencyError(e.Message); return(false); } var modInstances = AssemblyManager.InstantiateMods(modsToLoad); if (modInstances == null) { return(false); } modInstances.Insert(0, new ModLoaderMod()); loadedMods = modInstances.ToArray(); foreach (var mod in modInstances) { loadOrder.Push(mod.Name); mods[mod.Name] = mod; } return(true); }
private static void do_Load(object threadContext) { if (!LoadMods()) { Main.menuMode = Interface.errorMessageID; return; } int num = 0; foreach (Mod mod in mods.Values) { Interface.loadMods.SetProgressInit(mod.Name, num, mods.Count); try { mod.Autoload(); mod.Load(); } catch (Exception e) { DisableMod(mod.file); ErrorLogger.LogLoadingError(mod.file, e); Main.menuMode = Interface.errorMessageID; return; } num++; } Interface.loadMods.SetProgressSetup(0f); ResizeArrays(); num = 0; foreach (Mod mod in mods.Values) { Interface.loadMods.SetProgressLoad(mod.Name, num, mods.Count); try { mod.SetupContent(); } catch (Exception e) { DisableMod(mod.file); ErrorLogger.LogLoadingError(mod.file, e); Main.menuMode = Interface.errorMessageID; return; } num++; } Interface.loadMods.SetProgressRecipes(); for (int k = 0; k < Recipe.maxRecipes; k++) { Main.recipe[k] = new Recipe(); } Recipe.numRecipes = 0; try { CraftGroup.ResetVanillaGroups(); AddCraftGroups(); Recipe.SetupRecipes(); } catch (Exception e) { ErrorLogger.LogLoadingError("recipes", e); Main.menuMode = Interface.errorMessageID; return; } Main.menuMode = 0; }
internal static void do_Load(object threadContext) { if (!LoadMods()) { Main.menuMode = Interface.errorMessageID; return; } if (Main.dedServ) { Console.WriteLine("Adding mod content..."); } int num = 0; foreach (Mod mod in mods.Values) { Interface.loadMods.SetProgressInit(mod.Name, num, mods.Count); try { mod.loading = true; mod.File?.Read(TmodFile.LoadedState.Streaming, mod.LoadResourceFromStream); mod.Autoload(); Interface.loadMods.SetSubProgressInit(""); mod.Load(); mod.loading = false; } catch (Exception e) { DisableMod(mod.Name); ErrorLogger.LogLoadingError(mod.Name, mod.tModLoaderVersion, e); Main.menuMode = Interface.errorMessageID; return; } num++; } Interface.loadMods.SetProgressSetup(0f); ResizeArrays(); RecipeGroupHelper.FixRecipeGroupLookups(); num = 0; foreach (Mod mod in mods.Values) { Interface.loadMods.SetProgressLoad(mod.Name, num, mods.Count); try { mod.SetupContent(); mod.PostSetupContent(); mod.File?.UnloadAssets(); } catch (Exception e) { DisableMod(mod.Name); ErrorLogger.LogLoadingError(mod.Name, mod.tModLoaderVersion, e); Main.menuMode = Interface.errorMessageID; return; } num++; } RefreshModLanguage(Language.ActiveCulture); if (Main.dedServ) { ModNet.AssignNetIDs(); //Main.player[0] = new Player(); } Main.player[255] = new Player(false); // setup inventory is unnecessary MapLoader.SetupModMap(); ItemSorting.SetupWhiteLists(); Interface.loadMods.SetProgressRecipes(); for (int k = 0; k < Recipe.maxRecipes; k++) { Main.recipe[k] = new Recipe(); } Recipe.numRecipes = 0; RecipeGroupHelper.ResetRecipeGroups(); try { Recipe.SetupRecipes(); } catch (AddRecipesException e) { ErrorLogger.LogLoadingError(e.modName, version, e.InnerException, true); Main.menuMode = Interface.errorMessageID; return; } if (PostLoad != null) { PostLoad(); PostLoad = null; } else { Main.menuMode = 0; } GameInput.PlayerInput.ReInitialize(); }
internal static void ReceiveMod(BinaryReader reader) { if (downloadingMod == null) { return; } try { if (downloadingFile == null) { Interface.downloadMod.SetDownloading(reader.ReadString()); Interface.downloadMod.SetCancel(() => { downloadingFile?.Close(); downloadingMod = null; Netplay.disconnect = true; Main.menuMode = 0; }); Main.menuMode = Interface.downloadModID; downloadingLength = reader.ReadInt64(); downloadingFile = new FileStream(downloadingMod.path, FileMode.Create); return; } var bytes = reader.ReadBytes((int)Math.Min(downloadingLength - downloadingFile.Position, CHUNK_SIZE)); downloadingFile.Write(bytes, 0, bytes.Length); Interface.downloadMod.SetProgress(downloadingFile.Position, downloadingLength); if (downloadingFile.Position == downloadingLength) { downloadingFile.Close(); var mod = new TmodFile(downloadingMod.path); mod.Read(); var ex = mod.ValidMod(); if (ex != null) { throw ex; } if (!downloadingMod.Matches(mod)) { throw new Exception("Hash mismatch"); } if (downloadingMod.signed && !mod.ValidModBrowserSignature) { throw new Exception("Mod was not signed by the Mod Browser"); } ModLoader.EnableMod(mod); if (downloadQueue.Count > 0) { DownloadNextMod(); } else { OnModsDownloaded(true); } } } catch (Exception e) { try { downloadingFile?.Close(); } catch { } File.Delete(downloadingMod.path); ErrorLogger.LogException(e, "An error occured while downloading " + downloadingMod.name); downloadingMod = null; } }
internal static void SyncClientMods(BinaryReader reader) { AllowVanillaClients = reader.ReadBoolean(); Main.statusText = "Syncing Mods"; var clientMods = ModLoader.LoadedMods; var modFiles = ModLoader.FindMods(); var needsReload = false; downloadQueue.Clear(); var syncSet = new HashSet <string>(); var blockedList = new List <ModHeader>(); int n = reader.ReadInt32(); for (int i = 0; i < n; i++) { var header = new ModHeader(reader.ReadString(), new Version(reader.ReadString()), reader.ReadBytes(20), reader.ReadBoolean()); syncSet.Add(header.name); var clientMod = clientMods.SingleOrDefault(m => m.Name == header.name); if (clientMod != null) { if (header.Matches(clientMod.File)) { continue; } header.path = clientMod.File.path; } else { var disabledVersions = modFiles.Where(m => m.name == header.name).ToArray(); var matching = disabledVersions.FirstOrDefault(header.Matches); if (matching != null) { ModLoader.EnableMod(matching); needsReload = true; continue; } if (disabledVersions.Length > 0) { header.path = disabledVersions[0].path; } } if (downloadModsFromServers && (header.signed || !onlyDownloadSignedMods)) { downloadQueue.Enqueue(header); } else { blockedList.Add(header); } } foreach (var mod in clientMods) { if (mod.Side == ModSide.Both && !syncSet.Contains(mod.Name)) { ModLoader.DisableMod(mod.File); needsReload = true; } } if (blockedList.Count > 0) { var msg = "The following mods are installed on the server but cannot be downloaded "; msg += downloadModsFromServers ? "because you only accept mods signed by the mod browser" : "because you have disabled automatic mod downloading"; msg += ".\nYou will need to change your settings or acquire the mods from the server owner.\n"; foreach (var mod in blockedList) { msg += "\n " + mod; } ErrorLogger.LogMissingMods(msg); return; } if (downloadQueue.Count > 0) { DownloadNextMod(); } else { OnModsDownloaded(needsReload); } }
internal static bool do_BuildMod(object threadContext) { Interface.buildMod.SetReading(); BuildProperties properties = BuildProperties.ReadBuildFile(modToBuild); if (!CreateModReferenceDlls(properties)) { if (!buildAll) { Main.menuMode = Interface.errorMessageID; } return(false); } LoadReferences(); byte[] windowsData; byte[] otherData; if (properties.noCompile) { string modDir = modToBuild + Path.DirectorySeparatorChar; if (File.Exists(modDir + "All.dll")) { windowsData = File.ReadAllBytes(modDir + "All.dll"); otherData = File.ReadAllBytes(modDir + "All.dll"); } else if (File.Exists(modDir + "Windows.dll") && File.Exists(modDir + "Other.dll")) { windowsData = File.ReadAllBytes(modDir + "Windows.dll"); otherData = File.ReadAllBytes(modDir + "Other.dll"); } else { ErrorLogger.LogDllBuildError(modToBuild); if (!buildAll) { Main.menuMode = Interface.errorMessageID; } return(false); } } else { Interface.buildMod.SetCompiling(0); windowsData = CompileMod(modToBuild, properties, true); Interface.buildMod.SetCompiling(1); otherData = CompileMod(modToBuild, properties, false); if (windowsData == null || otherData == null) { if (!buildAll) { Main.menuMode = Interface.errorMessageID; } return(false); } } Interface.buildMod.SetBuildText(); string file = ModPath + Path.DirectorySeparatorChar + Path.GetFileName(modToBuild) + ".tmod"; byte[] propertiesData = properties.ToBytes(); TmodFile modFile = new TmodFile(file); using (MemoryStream memoryStream = new MemoryStream()) { using (BinaryWriter writer = new BinaryWriter(memoryStream)) { writer.Write(version); writer.Write(propertiesData.Length); writer.Write(propertiesData); writer.Flush(); modFile.AddFile("Info", memoryStream.ToArray()); } } using (MemoryStream memoryStream = new MemoryStream()) { using (BinaryWriter writer = new BinaryWriter(memoryStream)) { writer.Write(Path.GetFileName(modToBuild)); string[] resources = Directory.GetFiles(modToBuild, "*", SearchOption.AllDirectories); foreach (string resource in resources) { if (properties.ignoreFile(resource.Replace(modToBuild + Path.DirectorySeparatorChar, null))) { continue; } if (Path.GetExtension(resource) == ".cs" && !properties.includeSource) { continue; } if (Path.GetFileName(resource) == "Thumbs.db") { continue; } if (resource.Substring(modToBuild.Length + 1) == "build.txt") { continue; } string resourcePath = resource.Replace(ModSourcePath + Path.DirectorySeparatorChar, null); resourcePath = resourcePath.Replace(Path.DirectorySeparatorChar, '/'); byte[] buffer = File.ReadAllBytes(resource); writer.Write(resourcePath); writer.Write(buffer.Length); writer.Write(buffer); } writer.Write("end"); writer.Flush(); modFile.AddFile("Resources", memoryStream.ToArray()); } } bool same = windowsData.Length == otherData.Length; if (same) { for (int k = 0; k < windowsData.Length; k++) { if (windowsData[k] != otherData[k]) { same = false; break; } } } if (same) { modFile.AddFile("All", windowsData); } else { modFile.AddFile("Windows", windowsData); modFile.AddFile("Other", otherData); } modFile.Save(); WAVCacheIO.ClearCache(modFile.Name); EnableMod(file); if (!buildAll) { Main.menuMode = reloadAfterBuild ? Interface.reloadModsID : 0; } return(true); }
private static byte[] CompileMod(string modDir, BuildProperties properties, bool forWindows) { CompilerParameters compileOptions = new CompilerParameters(); compileOptions.GenerateExecutable = false; compileOptions.GenerateInMemory = false; string outFile = ModPath + Path.DirectorySeparatorChar + Path.GetFileName(modDir) + ".dll"; compileOptions.OutputAssembly = outFile; bool flag = false; foreach (string reference in buildReferences) { if (forWindows) { if (reference.IndexOf("FNA.dll") >= 0) { compileOptions.ReferencedAssemblies.Add("Microsoft.Xna.Framework.dll"); compileOptions.ReferencedAssemblies.Add("Microsoft.Xna.Framework.Game.dll"); compileOptions.ReferencedAssemblies.Add("Microsoft.Xna.Framework.Graphics.dll"); compileOptions.ReferencedAssemblies.Add("Microsoft.Xna.Framework.Xact.dll"); continue; } else if (!windows && reference.IndexOf("Terraria.exe") >= 0) { compileOptions.ReferencedAssemblies.Add("TerrariaWindows.exe"); continue; } } else { if (reference.IndexOf("Microsoft.Xna.Framework") >= 0) { if (!flag) { compileOptions.ReferencedAssemblies.Add("FNA.dll"); flag = true; } continue; } else if (windows && reference.IndexOf(System.AppDomain.CurrentDomain.FriendlyName) >= 0) { compileOptions.ReferencedAssemblies.Add("TerrariaMac.exe"); continue; } } compileOptions.ReferencedAssemblies.Add(reference); } Directory.CreateDirectory(DllPath); foreach (string reference in properties.dllReferences) { compileOptions.ReferencedAssemblies.Add(DllPath + Path.DirectorySeparatorChar + reference + ".dll"); } foreach (string reference in properties.modReferences) { string refFile = ModSourcePath + Path.DirectorySeparatorChar + reference; string realRefFile = refFile + ".dll"; refFile += forWindows ? "1.dll" : "2.dll"; if (File.Exists(realRefFile)) { File.Delete(realRefFile); } File.Move(refFile, realRefFile); compileOptions.ReferencedAssemblies.Add(realRefFile); } var options = new Dictionary <string, string> { { "CompilerVersion", "v4.0" } }; CodeDomProvider codeProvider = new CSharpCodeProvider(options); CompilerResults results = codeProvider.CompileAssemblyFromFile(compileOptions, Directory.GetFiles(modDir, "*.cs", SearchOption.AllDirectories)); CompilerErrorCollection errors = results.Errors; foreach (string reference in properties.modReferences) { File.Delete(ModSourcePath + Path.DirectorySeparatorChar + reference + ".dll"); } if (errors.HasErrors) { ErrorLogger.LogCompileErrors(errors); return(null); } byte[] data = File.ReadAllBytes(outFile); File.Delete(outFile); return(data); }
private static bool LoadMods() { Interface.loadMods.SetProgressFinding(); TmodFile[] modFiles = FindMods(); List <TmodFile> enabledMods = new List <TmodFile>(); foreach (TmodFile modFile in modFiles) { if (IsEnabled(modFile.Name)) { enabledMods.Add(modFile); } } IDictionary <string, BuildProperties> properties = new Dictionary <string, BuildProperties>(); List <TmodFile> modsToLoad = new List <TmodFile>(); foreach (TmodFile modFile in enabledMods) { properties[modFile.Name] = BuildProperties.ReadModFile(modFile); modsToLoad.Add(modFile); } int previousCount = 0; int num = 0; Mod defaultMod = new ModLoaderMod(); defaultMod.Init(); mods[defaultMod.Name] = defaultMod; loadedMods.Add(defaultMod.Name); while (modsToLoad.Count > 0 && modsToLoad.Count != previousCount) { previousCount = modsToLoad.Count; int k = 0; while (k < modsToLoad.Count) { bool canLoad = true; foreach (string reference in properties[modsToLoad[k].Name].modReferences) { if (!ModLoaded(ModPath + Path.DirectorySeparatorChar + reference + ".tmod")) { canLoad = false; break; } } if (canLoad) { Interface.loadMods.SetProgressCompatibility(Path.GetFileNameWithoutExtension(modsToLoad[k].Name), num, enabledMods.Count); try { LoadMod(modsToLoad[k], properties[modsToLoad[k].Name]); } catch (Exception e) { DisableMod(modsToLoad[k].Name); ErrorLogger.LogLoadingError(modsToLoad[k].Name, properties[modsToLoad[k].Name].modBuildVersion, e); return(false); } loadedMods.Add(modsToLoad[k].Name); num++; modsToLoad.RemoveAt(k); } else { k++; } } } if (modsToLoad.Count > 0) { foreach (TmodFile modFile in modsToLoad) { DisableMod(modFile.Name); } ErrorLogger.LogMissingLoadReference(modsToLoad); return(false); } return(true); }
internal static void do_Load(object threadContext) { if (!LoadMods()) { Main.menuMode = Interface.errorMessageID; return; } if (Main.dedServ) { Console.WriteLine("Adding mod content..."); } int num = 0; foreach (Mod mod in mods.Values) { Interface.loadMods.SetProgressInit(mod.Name, num, mods.Count); try { mod.Autoload(); mod.Load(); } catch (Exception e) { DisableMod(mod.file); ErrorLogger.LogLoadingError(mod.file, mod.buildVersion, e); Main.menuMode = Interface.errorMessageID; return; } num++; } Interface.loadMods.SetProgressSetup(0f); ResizeArrays(); num = 0; foreach (Mod mod in mods.Values) { Interface.loadMods.SetProgressLoad(mod.Name, num, mods.Count); try { mod.SetupContent(); mod.PostSetupContent(); } catch (Exception e) { DisableMod(mod.file); ErrorLogger.LogLoadingError(mod.file, mod.buildVersion, e); Main.menuMode = Interface.errorMessageID; return; } num++; } MapLoader.SetupModMap(); Interface.loadMods.SetProgressRecipes(); for (int k = 0; k < Recipe.maxRecipes; k++) { Main.recipe[k] = new Recipe(); } Recipe.numRecipes = 0; try { CraftGroup.ResetVanillaGroups(); AddCraftGroups(); Recipe.SetupRecipes(); } catch (Exception e) { ErrorLogger.LogLoadingError("recipes", version, e); Main.menuMode = Interface.errorMessageID; return; } Main.menuMode = 0; numLoads++; }
private static BuildProperties ReadBuildProperties(string modDir) { string propertiesFile = modDir + Path.DirectorySeparatorChar + "build.txt"; BuildProperties properties = new BuildProperties(); if (!File.Exists(propertiesFile)) { return(properties); } string[] lines = File.ReadAllLines(propertiesFile); foreach (string line in lines) { if (line.Length == 0) { continue; } int split = line.IndexOf('='); string property = line.Substring(0, split).Trim(); string value = line.Substring(split + 1).Trim(); if (value.Length == 0) { continue; } switch (property) { case "dllReferences": string[] dllReferences = value.Split(','); for (int k = 0; k < dllReferences.Length; k++) { string dllReference = dllReferences[k].Trim(); if (dllReference.Length > 0) { dllReferences[k] = dllReference; } } properties.dllReferences = dllReferences; break; case "modReferences": string[] modReferences = value.Split(','); for (int k = 0; k < modReferences.Length; k++) { string modReference = modReferences[k].Trim(); if (modReference.Length > 0) { modReferences[k] = modReference; } } properties.modReferences = modReferences; break; case "author": properties.author = value; break; case "version": properties.version = value; break; case "displayName": properties.displayName = value; break; } } foreach (string modReference in properties.modReferences) { string path = ModPath + Path.DirectorySeparatorChar + modReference + ".tmod"; if (!File.Exists(path)) { ErrorLogger.LogModReferenceError(modReference); return(null); } byte[] data; using (FileStream fileStream = File.OpenRead(path)) { using (BinaryReader reader = new BinaryReader(fileStream)) { fileStream.Seek(reader.ReadInt32(), SeekOrigin.Current); data = reader.ReadBytes(reader.ReadInt32()); } } using (FileStream writeStream = File.Create(ModSourcePath + Path.DirectorySeparatorChar + modReference + ".dll")) { using (BinaryWriter writer = new BinaryWriter(writeStream)) { writer.Write(data); } } } return(properties); }
internal static List <Mod> InstantiateMods(List <ModLoader.LoadingMod> modsToLoad) { var modList = new List <LoadedMod>(); foreach (var loading in modsToLoad) { LoadedMod mod; if (!loadedMods.TryGetValue(loading.Name, out mod)) { mod = loadedMods[loading.Name] = new LoadedMod(); } mod.SetMod(loading); modList.Add(mod); } RecalculateReferences(); if (Debugger.IsAttached) { ModLoader.isModder = true; foreach (var mod in modList.Where(mod => mod.properties.editAndContinue && mod.CanEaC)) { mod.EnableEaC(); } } if (ModLoader.alwaysLogExceptions) { ModCompile.ActivateExceptionReporting(); } var modInstances = new List <Mod>(); int i = 0; foreach (var mod in modList) { Interface.loadMods.SetProgressCompatibility(mod.Name, i++, modsToLoad.Count); try { Interface.loadMods.SetProgressReading(mod.Name, 0, 1); mod.LoadAssemblies(); Interface.loadMods.SetProgressReading(mod.Name, 1, 2); Type modType; try { modType = mod.assembly.GetTypes().Single(t => t.IsSubclassOf(typeof(Mod))); } catch (Exception e) { throw new Exception("It looks like this mod doesn't have a class extending Mod. Mods need a Mod class to function.", e) { HelpLink = "https://github.com/blushiemagic/tModLoader/wiki/Basic-tModLoader-Modding-FAQ#sequence-contains-no-matching-element-error" }; } var m = (Mod)Activator.CreateInstance(modType); m.File = mod.modFile; m.Code = mod.assembly; m.Side = mod.properties.side; m.DisplayName = mod.properties.displayName; modInstances.Add(m); } catch (Exception e) { ModLoader.DisableMod(mod.modFile); ErrorLogger.LogLoadingError(mod.Name, mod.modFile.tModLoaderVersion, e); return(null); } } return(modInstances); }
private static void CompileMod(BuildingMod mod, List <LoadingMod> refMods, bool forWindows, ref byte[] dll, ref byte[] pdb) { LoadReferences(); var terrariaModule = Assembly.GetExecutingAssembly(); bool generatePDB = mod.properties.includePDB && forWindows; if (generatePDB && !windows) { Console.WriteLine("PDB files can only be generated for windows, on windows."); generatePDB = false; } var refs = new List <string>(terrariaReferences); if (forWindows == windows) { refs.Add(terrariaModule.Location); } else { refs = refs.Where(path => { var name = Path.GetFileName(path); return(name != "FNA.dll" && !name.StartsWith("Microsoft.Xna.Framework")); }).ToList(); var names = forWindows ? new[] { "tModLoaderWindows.exe", "Microsoft.Xna.Framework.dll", "Microsoft.Xna.Framework.Game.dll", "Microsoft.Xna.Framework.Graphics.dll", "Microsoft.Xna.Framework.Xact.dll" } : new[] { "tModLoaderMac.exe", "FNA.dll" }; refs.AddRange(names.Select(f => Path.Combine(modCompileDir, f))); } refs.AddRange(mod.properties.dllReferences.Select(refDll => Path.Combine(mod.path, "lib/" + refDll + ".dll"))); var tempDir = Path.Combine(ModPath, "compile_temp"); Directory.CreateDirectory(tempDir); foreach (var resName in terrariaModule.GetManifestResourceNames().Where(n => n.EndsWith(".dll"))) { var path = Path.Combine(tempDir, Path.GetFileName(resName)); using (Stream res = terrariaModule.GetManifestResourceStream(resName), file = File.Create(path)) res.CopyTo(file); refs.Add(path); } foreach (var refMod in refMods) { var path = Path.Combine(tempDir, refMod.Name + ".dll"); File.WriteAllBytes(path, refMod.modFile.GetMainAssembly(forWindows)); refs.Add(path); foreach (var refDll in refMod.properties.dllReferences) { path = Path.Combine(tempDir, refDll + ".dll"); File.WriteAllBytes(path, refMod.modFile.GetFile("lib/" + refDll + ".dll")); refs.Add(path); } } var compileOptions = new CompilerParameters { OutputAssembly = Path.Combine(tempDir, mod.Name + ".dll"), GenerateExecutable = false, GenerateInMemory = false, TempFiles = new TempFileCollection(tempDir, true), IncludeDebugInformation = generatePDB }; compileOptions.ReferencedAssemblies.AddRange(refs.ToArray()); var files = Directory.GetFiles(mod.path, "*.cs", SearchOption.AllDirectories); try { CompilerResults results; if (mod.properties.languageVersion == 6) { if (Environment.Version.Revision < 10000) { ErrorLogger.LogBuildError(".NET Framework 4.5 must be installed to compile C# 6.0"); return; } results = RoslynCompile(compileOptions, files); } else { var options = new Dictionary <string, string> { { "CompilerVersion", "v" + mod.properties.languageVersion + ".0" } }; results = new CSharpCodeProvider(options).CompileAssemblyFromFile(compileOptions, files); } if (results.Errors.HasErrors) { ErrorLogger.LogCompileErrors(results.Errors); return; } dll = File.ReadAllBytes(compileOptions.OutputAssembly); if (generatePDB) { pdb = File.ReadAllBytes(Path.Combine(tempDir, mod.Name + ".pdb")); } } finally { int numTries = 10; while (numTries > 0) { try { Directory.Delete(tempDir, true); numTries = 0; } catch { System.Threading.Thread.Sleep(1); numTries--; } } } }
internal static void do_Load(object threadContext) { if (!LoadMods()) { Main.menuMode = Interface.errorMessageID; return; } if (Main.dedServ) { Console.WriteLine("Adding mod content..."); } int num = 0; foreach (Mod mod in mods.Values) { Interface.loadMods.SetProgressInit(mod.Name, num, mods.Count); try { mod.Autoload(); mod.Load(); } catch (Exception e) { DisableMod(mod.File); ErrorLogger.LogLoadingError(mod.Name, mod.tModLoaderVersion, e); Main.menuMode = Interface.errorMessageID; return; } num++; } Interface.loadMods.SetProgressSetup(0f); ResizeArrays(); num = 0; foreach (Mod mod in mods.Values) { Interface.loadMods.SetProgressLoad(mod.Name, num, mods.Count); try { mod.SetupContent(); mod.PostSetupContent(); } catch (Exception e) { DisableMod(mod.File); ErrorLogger.LogLoadingError(mod.Name, mod.tModLoaderVersion, e); Main.menuMode = Interface.errorMessageID; return; } num++; } if (Main.dedServ) { ModNet.AssignNetIDs(); } MapLoader.SetupModMap(); ItemSorting.SetupWhiteLists(); Interface.loadMods.SetProgressRecipes(); for (int k = 0; k < Recipe.maxRecipes; k++) { Main.recipe[k] = new Recipe(); } Recipe.numRecipes = 0; RecipeGroupHelper.ResetRecipeGroups(); try { Recipe.SetupRecipes(); } catch (AddRecipesException e) { ErrorLogger.LogLoadingError(e.modName, version, e.InnerException, true); Main.menuMode = Interface.errorMessageID; return; } if (PostLoad != null) { PostLoad(); PostLoad = null; } else { Main.menuMode = 0; } GameInput.PlayerInput.ReInitialize(); }
internal static void SyncClientMods(BinaryReader reader) { AllowVanillaClients = reader.ReadBoolean(); Main.statusText = Language.GetTextValue("tModLoader.MPSyncingMods"); var clientMods = ModLoader.Mods; var modFiles = ModOrganizer.FindMods(); var needsReload = false; downloadQueue.Clear(); var syncSet = new HashSet <string>(); var blockedList = new List <ModHeader>(); int n = reader.ReadInt32(); for (int i = 0; i < n; i++) { var header = new ModHeader(reader.ReadString(), new Version(reader.ReadString()), reader.ReadBytes(20), reader.ReadBoolean()); syncSet.Add(header.name); var clientMod = clientMods.SingleOrDefault(m => m.Name == header.name); if (clientMod != null) { if (header.Matches(clientMod.File)) { continue; } header.path = clientMod.File.path; } else { var disabledVersions = modFiles.Where(m => m.Name == header.name).ToArray(); var matching = disabledVersions.FirstOrDefault(mod => header.Matches(mod.modFile)); if (matching != null) { matching.Enabled = true; needsReload = true; continue; } if (disabledVersions.Length > 0) { header.path = disabledVersions[0].modFile.path; } } if (downloadModsFromServers && (header.signed || !onlyDownloadSignedMods)) { downloadQueue.Enqueue(header); } else { blockedList.Add(header); } } foreach (var mod in clientMods) { if (mod.Side == ModSide.Both && !syncSet.Contains(mod.Name)) { ModLoader.DisableMod(mod.Name); needsReload = true; } } if (blockedList.Count > 0) { var msg = Language.GetTextValue("tModLoader.MPServerModsCantDownload"); msg += downloadModsFromServers ? Language.GetTextValue("tModLoader.MPServerModsCantDownloadReasonSigned") : Language.GetTextValue("tModLoader.MPServerModsCantDownloadReasonAutomaticDownloadDisabled"); msg += ".\n" + Language.GetTextValue("tModLoader.MPServerModsCantDownloadChangeSettingsHint") + "\n"; foreach (var mod in blockedList) { msg += "\n " + mod; } ErrorLogger.LogMissingMods(msg); return; } if (downloadQueue.Count > 0) { DownloadNextMod(); } else { OnModsDownloaded(needsReload); } }