diff --git a/Plugin.ClientModLoader/ModInjector.cs b/Plugin.ClientModLoader/ModInjector.cs index 0c969b0..b2fdbb3 100644 --- a/Plugin.ClientModLoader/ModInjector.cs +++ b/Plugin.ClientModLoader/ModInjector.cs @@ -1,4 +1,5 @@ -using System.Reflection.Emit; +using System.Collections.Immutable; +using System.Reflection.Emit; using HarmonyLib; using Sandbox.Definitions; using Sandbox.Engine.Networking; @@ -26,7 +27,31 @@ internal static class ModInjector [HarmonyPostfix] private static void DownloadModsBlockingPostfix(List mods, List __state) { - foreach (var mod in mods) + var worldMods = __state.Select(b => b.PublishedFileId).ToImmutableHashSet(); + var resolvedMods = mods.ToImmutableDictionary(b => b.PublishedFileId); + + // list of selected mods which are resolved + var requestedMods = mods.IntersectBy(Mods, b => b.PublishedFileId) + .ToDictionary(b => b.PublishedFileId); + + // add dependencies of requested mods + // but skip if those are also requested by world we're loading in + foreach (var dependency in requestedMods.Values + .SelectMany(b => b.GetModData().Dependencies) + .Distinct().ToArray()) + { + if (worldMods.Contains(dependency)) + continue; + + requestedMods.TryAdd(dependency, resolvedMods[dependency]); + } + + // add resolved client mods and their exclusive dependencies + AdditionalFilledModItems.AddRange(requestedMods.Values); + + // upsert world mods by resolved ones excluding our client ones and their exclusive dependencies + // so world mods is only populated by dependencies of original world mods + foreach (var mod in mods.ExceptBy(requestedMods.Keys, b => b.PublishedFileId)) { var index = __state.FindIndex(b => b.PublishedFileId == mod.PublishedFileId && b.PublishedServiceName == mod.PublishedServiceName); @@ -37,8 +62,6 @@ internal static class ModInjector stateMod.SetModData(mod.GetModData()); __state[index] = stateMod; } - else if (Mods.Contains(mod.PublishedFileId)) - AdditionalFilledModItems.Add(mod); else __state.Add(mod); } @@ -104,7 +127,7 @@ internal static class ModInjector foreach (var mod in Mods) { //avoid duplicates - if (mods.FindIndex(m => m.PublishedFileId == mod) != -1) + if (mods.Exists(m => m.PublishedFileId == mod)) continue; mods.Add(new MyObjectBuilder_Checkpoint.ModItem(mod, "Steam"));