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. int i = 0; Parallel.ForEach(modList, mod => { Interface.loadMods.SetProgressCompatibility(mod.Name, i++, modsToLoad.Count); mod.LoadAssemblies(); }); //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); }))); 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); return(null); } }
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) { foreach (var mod in modList.Where(mod => mod.properties.editAndContinue && mod.CanEaC)) { mod.EnableEaC(); } } 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); var modType = mod.assembly.GetTypes().Single(t => t.IsSubclassOf(typeof(Mod))); 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); }
internal static void PostAddRecipes() { foreach (Mod mod in ModLoader.mods.Values) { try { mod.PostAddRecipes(); } catch (Exception e) { ModLoader.DisableMod(mod.Name); throw new AddRecipesException(mod, "An error occured after adding recipes for " + mod.Name, e); } } }
internal static void AddRecipeGroups() { foreach (Mod mod in ModLoader.mods.Values) { try { mod.AddRecipeGroups(); } catch (Exception e) { ModLoader.DisableMod(mod.File); throw new AddRecipesException(mod, "An error occured in adding recipe groups for " + mod.Name, e); } } }
internal static bool Load() { try { Interface.loadMods.SetLoadStage("tModLoader.MSIntializing", ModLoader.Mods.Length); LoadModContent(mod => { mod.loading = true; mod.File?.Read(TmodFile.LoadedState.Streaming, mod.LoadResourceFromStream); mod.Autoload(); mod.Load(); mod.loading = false; }); Interface.loadMods.SetLoadStage("tModLoader.MSSettingUp"); ResizeArrays(); RecipeGroupHelper.FixRecipeGroupLookups(); Interface.loadMods.SetLoadStage("tModLoader.MSLoading", ModLoader.Mods.Length); LoadModContent(mod => { mod.SetupContent(); mod.PostSetupContent(); mod.File?.UnloadAssets(); }); if (Main.dedServ) { ModNet.AssignNetIDs(); } Main.player[255] = new Player(false); // setup inventory is unnecessary RefreshModLanguage(Language.ActiveCulture); MapLoader.SetupModMap(); ItemSorting.SetupWhiteLists(); PlayerInput.ReInitialize(); SetupRecipes(); return(true); } catch (LoadingException e) { ModLoader.DisableMod(e.mod.Name); ErrorLogger.LogLoadingError(e.mod.Name, e.mod.Version, e.InnerException, e is AddRecipesException); Main.menuMode = Interface.errorMessageID; return(false); } }
internal static void AddRecipes() { foreach (Mod mod in ModLoader.mods.Values) { try { mod.AddRecipes(); foreach (ModItem item in mod.items.Values) { item.AddRecipes(); } } catch (Exception e) { ModLoader.DisableMod(mod.Name); throw new AddRecipesException(mod, "An error occured in adding recipes for " + mod.Name, e); } } }
//in Terraria.Item.SetDefaults get rid of type-too-high check //add near end of Terraria.Item.SetDefaults after setting netID //in Terraria.Item.SetDefaults move Lang stuff before SetupItem internal static void SetupItem(Item item) { if (IsModItem(item)) { GetItem(item.type).SetupItem(item); } foreach (GlobalItem globalItem in globalItems) { try { globalItem.SetDefaults(item); } catch { ModLoader.DisableMod(globalItem.mod.file); throw; } } }
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) { foreach (var mod in modList.Where(mod => mod.properties.editAndContinue && mod.CanEaC)) { mod.EnableEaC(); } } 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/bluemagic123/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); }
// This method is split so that the local variables aren't held by the GC when reloading internal static bool SyncClientMods(BinaryReader reader, out bool needsReload) { AllowVanillaClients = reader.ReadBoolean(); Logging.tML.Info($"Server reports AllowVanillaClients set to {AllowVanillaClients}"); Main.statusText = Language.GetTextValue("tModLoader.MPSyncingMods"); var clientMods = ModLoader.Mods; var modFiles = ModOrganizer.FindMods(); needsReload = false; downloadQueue.Clear(); pendingConfigs.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); int configCount = reader.ReadInt32(); for (int c = 0; c < configCount; c++) { pendingConfigs.Add(new NetConfig(header.name, reader.ReadString(), reader.ReadString())); } var clientMod = clientMods.SingleOrDefault(m => m.Name == header.name); if (clientMod != null && header.Matches(clientMod.File)) { continue; } needsReload = true; var localVersions = modFiles.Where(m => m.Name == header.name).ToArray(); var matching = Array.Find(localVersions, mod => header.Matches(mod.modFile)); if (matching != null) { matching.Enabled = true; continue; } // overwrite an existing version of the mod if there is one if (localVersions.Length > 0) { header.path = localVersions[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; } Logging.tML.Warn(msg); Interface.errorMessage.Show(msg, 0); return(false); } // ready to connect, apply configs. Config manager will apply the configs on reload automatically if (!needsReload) { foreach (var pendingConfig in pendingConfigs) { JsonConvert.PopulateObject(pendingConfig.json, ConfigManager.GetConfig(pendingConfig), ConfigManager.serializerSettingsCompact); } if (ConfigManager.AnyModNeedsReload()) { needsReload = true; } else { foreach (var pendingConfig in pendingConfigs) { ConfigManager.GetConfig(pendingConfig).OnChanged(); } } } return(true); }
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; } Logging.tML.Warn(msg); Interface.errorMessage.SetMessage(msg); Interface.errorMessage.SetGotoMenu(0); Main.gameMenu = true; Main.menuMode = Interface.errorMessageID; return; } if (downloadQueue.Count > 0) { DownloadNextMod(); } else { OnModsDownloaded(needsReload); } }
internal static void ServerModMenu() { bool exit = false; while (!exit) { Console.WriteLine("Terraria Server " + Main.versionNumber2 + " - " + ModLoader.versionedName); Console.WriteLine(); TmodFile[] mods = ModLoader.FindMods(); for (int k = 0; k < mods.Length; k++) { BuildProperties properties = BuildProperties.ReadModFile(mods[k]); string name = properties.displayName; name = mods[k].name; string line = (k + 1) + "\t\t" + name + "("; line += (ModLoader.IsEnabled(mods[k]) ? "enabled" : "disabled") + ")"; Console.WriteLine(line); } Console.WriteLine("e\t\tEnable All"); Console.WriteLine("d\t\tDisable All"); Console.WriteLine("r\t\tReload and return to world menu"); Console.WriteLine("Type a number to switch between enabled/disabled"); Console.WriteLine(); Console.WriteLine("Type a command: "); string command = Console.ReadLine(); if (command == null) { command = ""; } command = command.ToLower(); Console.Clear(); if (command == "e") { foreach (TmodFile mod in mods) { ModLoader.EnableMod(mod); } } else if (command == "d") { foreach (TmodFile mod in mods) { ModLoader.DisableMod(mod); } } else if (command == "r") { Console.WriteLine("Unloading mods..."); ModLoader.Unload(); ModLoader.do_Load(null); exit = true; } else { int value; if (Int32.TryParse(command, out value)) { value--; if (value >= 0 && value < mods.Length) { ModLoader.SetModActive(mods[value], !ModLoader.IsEnabled(mods[value])); } } } } }
internal static void ServerModMenu() { bool exit = false; while (!exit) { Console.WriteLine("Terraria Server " + Main.versionNumber2 + " - " + ModLoader.versionedName); Console.WriteLine(); TmodFile[] mods = ModLoader.FindMods(); for (int k = 0; k < mods.Length; k++) { BuildProperties properties = BuildProperties.ReadModFile(mods[k]); string name = properties.displayName; name = mods[k].name; string line = (k + 1) + "\t\t" + name + "("; line += (ModLoader.IsEnabled(mods[k]) ? "enabled" : "disabled") + ")"; Console.WriteLine(line); } if (mods.Length == 0) { Console.ForegroundColor = ConsoleColor.Yellow; Console.WriteLine($"No mods were found in: \"{ModLoader.ModPath}\"\nIf you are running a dedicated server, you may wish to use the 'modpath' command line switch or server config setting to specify a custom mods directory.\n"); Console.ResetColor(); } Console.WriteLine("e\t\tEnable All"); Console.WriteLine("d\t\tDisable All"); Console.WriteLine("r\t\tReload and return to world menu"); Console.WriteLine("Type a number to switch between enabled/disabled"); Console.WriteLine(); Console.WriteLine("Type a command: "); string command = Console.ReadLine(); if (command == null) { command = ""; } command = command.ToLower(); Console.Clear(); if (command == "e") { foreach (TmodFile mod in mods) { ModLoader.EnableMod(mod); } } else if (command == "d") { foreach (TmodFile mod in mods) { ModLoader.DisableMod(mod); } } else if (command == "r") { Console.WriteLine("Unloading mods..."); ModLoader.Unload(); ModLoader.do_Load(null); exit = true; } else { int value; if (Int32.TryParse(command, out value)) { value--; if (value >= 0 && value < mods.Length) { ModLoader.SetModActive(mods[value], !ModLoader.IsEnabled(mods[value])); } } } } }
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); } }