예제 #1
0
        private static List <LocalMod> AssertSortSatisfied(List <LocalMod> list)
        {
            var sorted   = ModOrganizer.Sort(list);
            var indexMap = sorted.ToDictionary(m => m.Name, sorted.IndexOf);

            foreach (var mod in list)
            {
                int index = indexMap[mod.Name];
                foreach (var dep in mod.properties.sortAfter)
                {
                    int i;
                    if (indexMap.TryGetValue(dep, out i) && i > index)
                    {
                        Assert.Fail(mod.Name + " sorted after " + dep);
                    }
                }
                foreach (var dep in mod.properties.sortBefore)
                {
                    int i;
                    if (indexMap.TryGetValue(dep, out i) && i < index)
                    {
                        Assert.Fail(mod.Name + " sorted before " + dep);
                    }
                }
            }

            return(sorted);
        }
예제 #2
0
        internal static void ServerModMenu()
        {
            bool exit = false;

            while (!exit)
            {
                Console.WriteLine("Terraria Server " + Main.versionNumber2 + " - " + ModLoader.versionedName);
                Console.WriteLine();
                var mods = ModOrganizer.FindMods();
                for (int k = 0; k < mods.Length; k++)
                {
                    Console.Write((k + 1) + "\t\t" + mods[k].DisplayName);
                    Console.WriteLine(" (" + (ModLoader.IsEnabled(mods[k].Name) ? "enabled" : "disabled") + ")");
                }
                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 (var mod in mods)
                    {
                        mod.Enabled = true;
                    }
                }
                else if (command == "d")
                {
                    foreach (var mod in mods)
                    {
                        mod.Enabled = false;
                    }
                }
                else if (command == "r")
                {
                    Console.WriteLine("Unloading mods...");
                    ModLoader.Unload();
                    ModLoader.Load();
                    exit = true;
                }
                else if (int.TryParse(command, out int value) && value > 0 && value <= mods.Length)
                {
                    mods[value - 1].Enabled ^= true;
                }
            }
        }
예제 #3
0
        private static bool CommandLineModPackOverride()
        {
            if (commandLineModPack == "")
            {
                return(true);
            }

            if (!commandLineModPack.EndsWith(".json"))
            {
                commandLineModPack += ".json";
            }

            string filePath = Path.Combine(UI.UIModPacks.ModListSaveDirectory, commandLineModPack);

            try
            {
                Directory.CreateDirectory(UI.UIModPacks.ModListSaveDirectory);

                Console.WriteLine(Language.GetTextValue("tModLoader.LoadingSpecifiedModPack", commandLineModPack) + "\n");
                var modSet = JsonConvert.DeserializeObject <HashSet <string> >(File.ReadAllText(filePath));
                foreach (var mod in ModOrganizer.FindMods())
                {
                    ModLoader.SetModEnabled(mod.Name, modSet.Contains(mod.Name));
                }

                return(true);
            }
            catch (Exception e)
            {
                string err;
                if (e is FileNotFoundException)
                {
                    err = Language.GetTextValue("tModLoader.ModPackDoesNotExist", filePath) + "\n";
                }
                else
                {
                    err = Language.GetTextValue("tModLoader.ModPackDoesNotExist", commandLineModPack, e.Message) + "\n";
                }

                if (Main.dedServ)
                {
                    Console.ForegroundColor = ConsoleColor.Red;
                    Console.WriteLine(err);
                    Console.ResetColor();
                }
                else
                {
                    Main.menuMode = Interface.errorMessageID;
                    Interface.errorMessage.SetMessage(err);
                }

                return(false);
            }
            finally
            {
                commandLineModPack = "";
            }
        }
예제 #4
0
        internal void BuildAll()
        {
            var modList = new List <LocalMod>();

            foreach (var modFolder in FindModSources())
            {
                modList.Add(ReadBuildInfo(modFolder));
            }

            //figure out which of the installed mods are required for building
            var installedMods = ModOrganizer.FindMods().Where(mod => !modList.Exists(m => m.Name == mod.Name)).ToList();

            var requiredFromInstall = new HashSet <LocalMod>();

            void Require(LocalMod mod, bool includeWeak)
            {
                foreach (var dep in mod.properties.RefNames(includeWeak))
                {
                    var depMod = installedMods.SingleOrDefault(m => m.Name == dep);
                    if (depMod != null && requiredFromInstall.Add(depMod))
                    {
                        Require(depMod, false);
                    }
                }
            }

            foreach (var mod in modList)
            {
                Require(mod, true);
            }

            modList.AddRange(requiredFromInstall);

            //sort and version check
            List <BuildingMod> modsToBuild;

            try {
                ModOrganizer.EnsureDependenciesExist(modList, true);
                ModOrganizer.EnsureTargetVersionsMet(modList);
                var sortedModList = ModOrganizer.Sort(modList);
                modsToBuild = sortedModList.OfType <BuildingMod>().ToList();
            }
            catch (ModSortingException e) {
                throw new BuildException(e.Message);
            }

            //build
            int num = 0;

            foreach (var mod in modsToBuild)
            {
                status.SetProgress(num++, modsToBuild.Count);
                Build(mod);
            }
        }
예제 #5
0
        // 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);
        }
예제 #6
0
        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);
            }
        }
예제 #7
0
        public void TestVersionRequirements()
        {
            //test version on missing mod
            var list1 = new List <LocalMod> {
                Make("A", refs: new[] { "[email protected]" })
            };

            ModOrganizer.EnsureTargetVersionsMet(list1);

            //test passed version check
            var list2 = new List <LocalMod> {
                Make("A", refs: new[] { "[email protected]" }),
                Make("B", version: "1.2")
            };

            ModOrganizer.EnsureTargetVersionsMet(list2);

            //test failed version check
            var list3 = new List <LocalMod> {
                Make("A", refs: new[] { "[email protected]" }),
                Make("B")
            };

            AssertModException(
                () => ModOrganizer.EnsureTargetVersionsMet(list3),
                new[] { "A" },
                "A requires version 1.2+ of B but version 1.0.0.0 is installed");

            //test one pass, two fail version check
            var list4 = new List <LocalMod> {
                Make("A"),
                Make("B", refs: new[] { "[email protected]" }),
                Make("C", refs: new[] { "[email protected]" }),
                Make("D", refs: new[] { "[email protected]" })
            };

            AssertModException(
                () => ModOrganizer.EnsureTargetVersionsMet(list4),
                new[] { "C", "D" },
                "C requires version 1.1+ of A but version 1.0.0.0 is installed\r\n" +
                "D requires version 1.0.0.1+ of A but version 1.0.0.0 is installed");

            //test weak version check (missing)
            var list5 = new List <LocalMod> {
                Make("A", weakRefs: new[] { "[email protected]" })
            };

            ModOrganizer.EnsureDependenciesExist(list5, false);
            ModOrganizer.EnsureTargetVersionsMet(list5);

            //test weak version check (too low)
            var list6 = new List <LocalMod> {
                Make("A", weakRefs: new[] { "[email protected]" }),
                Make("B")
            };

            AssertModException(
                () => ModOrganizer.EnsureTargetVersionsMet(list6),
                new[] { "A" },
                "A requires version 1.1+ of B but version 1.0.0.0 is installed");
        }
예제 #8
0
        public void TestDependenciesExist()
        {
            //test A -> B
            var list1 = new List <LocalMod> {
                Make("A", refs: new[] { "B" }),
                Make("B"),
            };

            ModOrganizer.EnsureDependenciesExist(list1, false);

            //test A -> B (missing)
            var list2 = new List <LocalMod> {
                Make("A", refs: new[] { "B" })
            };

            AssertModException(
                () => ModOrganizer.EnsureDependenciesExist(list2, false),
                new[] { "A" },
                "Missing mod: B required by A");

            //test multi reference
            var list3 = new List <LocalMod> {
                Make("A", refs: new[] { "B" }),
                Make("B"),
                Make("C", refs: new[] { "A" })
            };

            ModOrganizer.EnsureDependenciesExist(list3, false);

            //test one missing reference
            var list4 = new List <LocalMod> {
                Make("A", refs: new[] { "B" }),
                Make("B", refs: new[] { "C" })
            };

            AssertModException(
                () => ModOrganizer.EnsureDependenciesExist(list4, false),
                new[] { "B" },
                "Missing mod: C required by B");

            //test weak reference (missing)
            var list5 = new List <LocalMod> {
                Make("A", weakRefs: new[] { "B" })
            };

            ModOrganizer.EnsureDependenciesExist(list5, false);
            AssertModException(
                () => ModOrganizer.EnsureDependenciesExist(list5, true),
                new[] { "A" },
                "Missing mod: B required by A");

            //test weak reference (found)
            var list6 = new List <LocalMod> {
                Make("A", weakRefs: new[] { "B" }),
                Make("B")
            };

            ModOrganizer.EnsureDependenciesExist(list6, true);

            //test strong (found) and weak (missing)
            var list7 = new List <LocalMod> {
                Make("A", refs: new[] { "B" }),
                Make("B", weakRefs: new[] { "C" })
            };

            ModOrganizer.EnsureDependenciesExist(list7, false);
            AssertModException(
                () => ModOrganizer.EnsureDependenciesExist(list7, true),
                new[] { "B" },
                "Missing mod: C required by B");

            //multi test case (missing)
            var list8 = new List <LocalMod> {
                Make("A", refs: new[] { "X" }),
                Make("B", refs: new[] { "Y" }),
                Make("C", refs: new[] { "D" }),
                Make("D", weakRefs: new[] { "E" }),
                Make("E", weakRefs: new[] { "Z" }),
                Make("F", weakRefs: new[] { "Z" })
            };

            AssertModException(
                () => ModOrganizer.EnsureDependenciesExist(list8, false),
                new[] { "A", "B" },
                "Missing mod: X required by A\r\n" +
                "Missing mod: Y required by B");
            AssertModException(
                () => ModOrganizer.EnsureDependenciesExist(list8, true),
                new[] { "A", "B", "E", "F" },
                "Missing mod: X required by A\r\n" +
                "Missing mod: Y required by B\r\n" +
                "Missing mod: Z required by E\r\n" +
                "Missing mod: Z required by F");

            //multi test case (found)
            var list9 = new List <LocalMod> {
                Make("A", refs: new[] { "C" }),
                Make("B", refs: new[] { "C" }),
                Make("C", refs: new[] { "D" }),
                Make("D", weakRefs: new[] { "E" }),
                Make("E", weakRefs: new[] { "F" }),
                Make("F")
            };

            ModOrganizer.EnsureDependenciesExist(list9, false);
            ModOrganizer.EnsureDependenciesExist(list9, true);
        }
예제 #9
0
        internal bool BuildAll(string[] modFolders)
        {
            var modList = new List <LocalMod>();

            //read mod sources folder
            foreach (var modFolder in modFolders)
            {
                var mod = ReadProperties(modFolder);
                if (mod == null)
                {
                    return(false);
                }

                modList.Add(mod);
            }

            //figure out which of the installed mods are required for building
            var installedMods = ModOrganizer.FindMods().Where(mod => !modList.Exists(m => m.Name == mod.Name)).ToList();

            var requiredFromInstall = new HashSet <LocalMod>();

            void Require(LocalMod 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
            {
                ModOrganizer.EnsureDependenciesExist(modList, true);
                ModOrganizer.EnsureTargetVersionsMet(modList);
                var sortedModList = ModOrganizer.Sort(modList);
                modsToBuild = sortedModList.OfType <BuildingMod>().ToList();
            }
            catch (ModSortingException e)
            {
                status.LogError(null, e.Message);
                return(false);
            }

            //build
            int num = 0;

            foreach (var mod in modsToBuild)
            {
                status.SetProgress(num++, modsToBuild.Count);
                if (!Build(mod))
                {
                    return(false);
                }
            }

            return(true);
        }