From 66202af53af29f0d7aa3f891c2292b42abc75144 Mon Sep 17 00:00:00 2001 From: Mister_Nebula <41904486+misternebula@users.noreply.github.com> Date: Sat, 25 Apr 2020 22:26:03 +0100 Subject: [PATCH 01/36] Implemented load order --- OWML.Common/IModManifest.cs | 1 + OWML.Common/OWML.Common.csproj | 29 +++-- OWML.Common/packages.config | 3 +- OWML.Common/readme.txt | 2 + .../OWML.ModHelper.Assets.csproj | 29 +++-- OWML.ModHelper.Assets/packages.config | 3 +- OWML.ModHelper.Assets/readme.txt | 2 + .../OWML.ModHelper.Events.csproj | 29 +++-- OWML.ModHelper.Events/packages.config | 3 +- OWML.ModHelper.Events/readme.txt | 2 + .../OWML.ModHelper.Menus.csproj | 26 +++-- OWML.ModHelper.Menus/packages.config | 2 +- OWML.ModHelper.Menus/readme.txt | 2 + OWML.ModHelper/ModManifest.cs | 3 + OWML.ModHelper/OWML.ModHelper.csproj | 26 +++-- OWML.ModHelper/packages.config | 2 +- OWML.ModHelper/readme.txt | 2 + OWML.ModLoader/ModSorter.cs | 101 ++++++++++++++++++ OWML.ModLoader/OWML.ModLoader.csproj | 27 +++-- OWML.ModLoader/Owo.cs | 7 +- OWML.ModLoader/packages.config | 2 +- OWML.ModLoader/readme.txt | 2 + .../OWML.EnableDebugMode.csproj | 29 +++-- .../OWML.EnableDebugMode/manifest.json | 1 + .../OWML.EnableDebugMode/packages.config | 3 +- .../OWML.EnableDebugMode/readme.txt | 2 + .../OWML.LoadCustomAssets.csproj | 24 +++-- .../OWML.LoadCustomAssets/manifest.json | 1 + .../OWML.LoadCustomAssets/packages.config | 2 +- .../OWML.LoadCustomAssets/readme.txt | 2 + 30 files changed, 280 insertions(+), 89 deletions(-) create mode 100644 OWML.Common/readme.txt create mode 100644 OWML.ModHelper.Assets/readme.txt create mode 100644 OWML.ModHelper.Events/readme.txt create mode 100644 OWML.ModHelper.Menus/readme.txt create mode 100644 OWML.ModHelper/readme.txt create mode 100644 OWML.ModLoader/ModSorter.cs create mode 100644 OWML.ModLoader/readme.txt create mode 100644 OWML.SampleMods/OWML.EnableDebugMode/readme.txt create mode 100644 OWML.SampleMods/OWML.LoadCustomAssets/readme.txt diff --git a/OWML.Common/IModManifest.cs b/OWML.Common/IModManifest.cs index 976396b61..8c1ded4c3 100644 --- a/OWML.Common/IModManifest.cs +++ b/OWML.Common/IModManifest.cs @@ -13,5 +13,6 @@ public interface IModManifest string UniqueName { get; } string ModFolderPath { get; set; } Dictionary AppIds { get; } + string Dependency { get; } } } diff --git a/OWML.Common/OWML.Common.csproj b/OWML.Common/OWML.Common.csproj index c4ad68673..ebb5c5137 100644 --- a/OWML.Common/OWML.Common.csproj +++ b/OWML.Common/OWML.Common.csproj @@ -33,32 +33,38 @@ - ..\packages\OW.Unity.Dlls.1.0.2\lib\net35\Assembly-CSharp.dll + ..\packages\OW.Unity.Dlls.1.0.4\lib\net35\Assembly-CSharp.dll - - ..\packages\OW.Unity.Dlls.1.0.2\lib\net35\OW.Unity.Dlls.dll + + ..\packages\Json.Net.Unity3D.9.0.1\lib\net35\Newtonsoft.Json.dll + + + ..\packages\OW.Unity.Dlls.1.0.4\lib\net35\OW.Unity.Dlls.dll - ..\packages\OW.Unity.Dlls.1.0.2\lib\net35\UnityEngine.dll + ..\packages\OW.Unity.Dlls.1.0.4\lib\net35\UnityEngine.dll - ..\packages\OW.Unity.Dlls.1.0.2\lib\net35\UnityEngine.AudioModule.dll + ..\packages\OW.Unity.Dlls.1.0.4\lib\net35\UnityEngine.AudioModule.dll - ..\packages\OW.Unity.Dlls.1.0.2\lib\net35\UnityEngine.CoreModule.dll + ..\packages\OW.Unity.Dlls.1.0.4\lib\net35\UnityEngine.CoreModule.dll + + + ..\packages\OW.Unity.Dlls.1.0.4\lib\net35\UnityEngine.IMGUIModule.dll - ..\packages\OW.Unity.Dlls.1.0.2\lib\net35\UnityEngine.PhysicsModule.dll + ..\packages\OW.Unity.Dlls.1.0.4\lib\net35\UnityEngine.PhysicsModule.dll - ..\packages\OW.Unity.Dlls.1.0.2\lib\net35\UnityEngine.UI.dll + ..\packages\OW.Unity.Dlls.1.0.4\lib\net35\UnityEngine.UI.dll - ..\packages\OW.Unity.Dlls.1.0.2\lib\net35\UnityEngine.UIModule.dll + ..\packages\OW.Unity.Dlls.1.0.4\lib\net35\UnityEngine.UIModule.dll - ..\packages\OW.Unity.Dlls.1.0.2\lib\net35\UnityEngine.UnityWebRequestWWWModule.dll + ..\packages\OW.Unity.Dlls.1.0.4\lib\net35\UnityEngine.UnityWebRequestWWWModule.dll @@ -100,5 +106,8 @@ + + + \ No newline at end of file diff --git a/OWML.Common/packages.config b/OWML.Common/packages.config index bfe552ebf..074e374a8 100644 --- a/OWML.Common/packages.config +++ b/OWML.Common/packages.config @@ -1,4 +1,5 @@  - + + \ No newline at end of file diff --git a/OWML.Common/readme.txt b/OWML.Common/readme.txt new file mode 100644 index 000000000..d3d7dc6a3 --- /dev/null +++ b/OWML.Common/readme.txt @@ -0,0 +1,2 @@ +nuget pack +nuget.exe push -Source "OW" -ApiKey az OW.Unity.Dlls.1.0.0.1.nupkg \ No newline at end of file diff --git a/OWML.ModHelper.Assets/OWML.ModHelper.Assets.csproj b/OWML.ModHelper.Assets/OWML.ModHelper.Assets.csproj index 9b72e1ef9..fc1e5939e 100644 --- a/OWML.ModHelper.Assets/OWML.ModHelper.Assets.csproj +++ b/OWML.ModHelper.Assets/OWML.ModHelper.Assets.csproj @@ -34,35 +34,41 @@ - ..\packages\OW.Unity.Dlls.1.0.2\lib\net35\Assembly-CSharp.dll + ..\packages\OW.Unity.Dlls.1.0.4\lib\net35\Assembly-CSharp.dll NAudio-Unity\NAudio-Unity.dll - - ..\packages\OW.Unity.Dlls.1.0.2\lib\net35\OW.Unity.Dlls.dll + + ..\packages\Json.Net.Unity3D.9.0.1\lib\net35\Newtonsoft.Json.dll + + + ..\packages\OW.Unity.Dlls.1.0.4\lib\net35\OW.Unity.Dlls.dll - ..\packages\OW.Unity.Dlls.1.0.2\lib\net35\UnityEngine.dll + ..\packages\OW.Unity.Dlls.1.0.4\lib\net35\UnityEngine.dll - ..\packages\OW.Unity.Dlls.1.0.2\lib\net35\UnityEngine.AudioModule.dll + ..\packages\OW.Unity.Dlls.1.0.4\lib\net35\UnityEngine.AudioModule.dll - ..\packages\OW.Unity.Dlls.1.0.2\lib\net35\UnityEngine.CoreModule.dll + ..\packages\OW.Unity.Dlls.1.0.4\lib\net35\UnityEngine.CoreModule.dll + + + ..\packages\OW.Unity.Dlls.1.0.4\lib\net35\UnityEngine.IMGUIModule.dll - ..\packages\OW.Unity.Dlls.1.0.2\lib\net35\UnityEngine.PhysicsModule.dll + ..\packages\OW.Unity.Dlls.1.0.4\lib\net35\UnityEngine.PhysicsModule.dll - ..\packages\OW.Unity.Dlls.1.0.2\lib\net35\UnityEngine.UI.dll + ..\packages\OW.Unity.Dlls.1.0.4\lib\net35\UnityEngine.UI.dll - ..\packages\OW.Unity.Dlls.1.0.2\lib\net35\UnityEngine.UIModule.dll + ..\packages\OW.Unity.Dlls.1.0.4\lib\net35\UnityEngine.UIModule.dll - ..\packages\OW.Unity.Dlls.1.0.2\lib\net35\UnityEngine.UnityWebRequestWWWModule.dll + ..\packages\OW.Unity.Dlls.1.0.4\lib\net35\UnityEngine.UnityWebRequestWWWModule.dll @@ -88,5 +94,8 @@ + + + \ No newline at end of file diff --git a/OWML.ModHelper.Assets/packages.config b/OWML.ModHelper.Assets/packages.config index bfe552ebf..074e374a8 100644 --- a/OWML.ModHelper.Assets/packages.config +++ b/OWML.ModHelper.Assets/packages.config @@ -1,4 +1,5 @@  - + + \ No newline at end of file diff --git a/OWML.ModHelper.Assets/readme.txt b/OWML.ModHelper.Assets/readme.txt new file mode 100644 index 000000000..d3d7dc6a3 --- /dev/null +++ b/OWML.ModHelper.Assets/readme.txt @@ -0,0 +1,2 @@ +nuget pack +nuget.exe push -Source "OW" -ApiKey az OW.Unity.Dlls.1.0.0.1.nupkg \ No newline at end of file diff --git a/OWML.ModHelper.Events/OWML.ModHelper.Events.csproj b/OWML.ModHelper.Events/OWML.ModHelper.Events.csproj index 96642f4c9..7d1b123f8 100644 --- a/OWML.ModHelper.Events/OWML.ModHelper.Events.csproj +++ b/OWML.ModHelper.Events/OWML.ModHelper.Events.csproj @@ -36,32 +36,38 @@ ..\packages\Lib.Harmony.1.2.0.1\lib\net35\0Harmony.dll - ..\packages\OW.Unity.Dlls.1.0.2\lib\net35\Assembly-CSharp.dll + ..\packages\OW.Unity.Dlls.1.0.4\lib\net35\Assembly-CSharp.dll - - ..\packages\OW.Unity.Dlls.1.0.2\lib\net35\OW.Unity.Dlls.dll + + ..\packages\Json.Net.Unity3D.9.0.1\lib\net35\Newtonsoft.Json.dll + + + ..\packages\OW.Unity.Dlls.1.0.4\lib\net35\OW.Unity.Dlls.dll - ..\packages\OW.Unity.Dlls.1.0.2\lib\net35\UnityEngine.dll + ..\packages\OW.Unity.Dlls.1.0.4\lib\net35\UnityEngine.dll - ..\packages\OW.Unity.Dlls.1.0.2\lib\net35\UnityEngine.AudioModule.dll + ..\packages\OW.Unity.Dlls.1.0.4\lib\net35\UnityEngine.AudioModule.dll - ..\packages\OW.Unity.Dlls.1.0.2\lib\net35\UnityEngine.CoreModule.dll + ..\packages\OW.Unity.Dlls.1.0.4\lib\net35\UnityEngine.CoreModule.dll + + + ..\packages\OW.Unity.Dlls.1.0.4\lib\net35\UnityEngine.IMGUIModule.dll - ..\packages\OW.Unity.Dlls.1.0.2\lib\net35\UnityEngine.PhysicsModule.dll + ..\packages\OW.Unity.Dlls.1.0.4\lib\net35\UnityEngine.PhysicsModule.dll - ..\packages\OW.Unity.Dlls.1.0.2\lib\net35\UnityEngine.UI.dll + ..\packages\OW.Unity.Dlls.1.0.4\lib\net35\UnityEngine.UI.dll - ..\packages\OW.Unity.Dlls.1.0.2\lib\net35\UnityEngine.UIModule.dll + ..\packages\OW.Unity.Dlls.1.0.4\lib\net35\UnityEngine.UIModule.dll - ..\packages\OW.Unity.Dlls.1.0.2\lib\net35\UnityEngine.UnityWebRequestWWWModule.dll + ..\packages\OW.Unity.Dlls.1.0.4\lib\net35\UnityEngine.UnityWebRequestWWWModule.dll @@ -80,5 +86,8 @@ OWML.Common + + + \ No newline at end of file diff --git a/OWML.ModHelper.Events/packages.config b/OWML.ModHelper.Events/packages.config index f9b9c8a24..5f0a66ab7 100644 --- a/OWML.ModHelper.Events/packages.config +++ b/OWML.ModHelper.Events/packages.config @@ -1,5 +1,6 @@  + - + \ No newline at end of file diff --git a/OWML.ModHelper.Events/readme.txt b/OWML.ModHelper.Events/readme.txt new file mode 100644 index 000000000..d3d7dc6a3 --- /dev/null +++ b/OWML.ModHelper.Events/readme.txt @@ -0,0 +1,2 @@ +nuget pack +nuget.exe push -Source "OW" -ApiKey az OW.Unity.Dlls.1.0.0.1.nupkg \ No newline at end of file diff --git a/OWML.ModHelper.Menus/OWML.ModHelper.Menus.csproj b/OWML.ModHelper.Menus/OWML.ModHelper.Menus.csproj index 944907bf3..7fc6d847c 100644 --- a/OWML.ModHelper.Menus/OWML.ModHelper.Menus.csproj +++ b/OWML.ModHelper.Menus/OWML.ModHelper.Menus.csproj @@ -32,13 +32,13 @@ - ..\packages\OW.Unity.Dlls.1.0.2\lib\net35\Assembly-CSharp.dll + ..\packages\OW.Unity.Dlls.1.0.4\lib\net35\Assembly-CSharp.dll ..\packages\Json.Net.Unity3D.9.0.1\lib\net35\Newtonsoft.Json.dll - - ..\packages\OW.Unity.Dlls.1.0.2\lib\net35\OW.Unity.Dlls.dll + + ..\packages\OW.Unity.Dlls.1.0.4\lib\net35\OW.Unity.Dlls.dll @@ -47,25 +47,28 @@ - ..\packages\OW.Unity.Dlls.1.0.2\lib\net35\UnityEngine.dll + ..\packages\OW.Unity.Dlls.1.0.4\lib\net35\UnityEngine.dll - ..\packages\OW.Unity.Dlls.1.0.2\lib\net35\UnityEngine.AudioModule.dll + ..\packages\OW.Unity.Dlls.1.0.4\lib\net35\UnityEngine.AudioModule.dll - ..\packages\OW.Unity.Dlls.1.0.2\lib\net35\UnityEngine.CoreModule.dll + ..\packages\OW.Unity.Dlls.1.0.4\lib\net35\UnityEngine.CoreModule.dll + + + ..\packages\OW.Unity.Dlls.1.0.4\lib\net35\UnityEngine.IMGUIModule.dll - ..\packages\OW.Unity.Dlls.1.0.2\lib\net35\UnityEngine.PhysicsModule.dll + ..\packages\OW.Unity.Dlls.1.0.4\lib\net35\UnityEngine.PhysicsModule.dll - ..\packages\OW.Unity.Dlls.1.0.2\lib\net35\UnityEngine.UI.dll + ..\packages\OW.Unity.Dlls.1.0.4\lib\net35\UnityEngine.UI.dll - ..\packages\OW.Unity.Dlls.1.0.2\lib\net35\UnityEngine.UIModule.dll + ..\packages\OW.Unity.Dlls.1.0.4\lib\net35\UnityEngine.UIModule.dll - ..\packages\OW.Unity.Dlls.1.0.2\lib\net35\UnityEngine.UnityWebRequestWWWModule.dll + ..\packages\OW.Unity.Dlls.1.0.4\lib\net35\UnityEngine.UnityWebRequestWWWModule.dll @@ -105,5 +108,8 @@ + + + \ No newline at end of file diff --git a/OWML.ModHelper.Menus/packages.config b/OWML.ModHelper.Menus/packages.config index 9cdd28f36..074e374a8 100644 --- a/OWML.ModHelper.Menus/packages.config +++ b/OWML.ModHelper.Menus/packages.config @@ -1,5 +1,5 @@  - + \ No newline at end of file diff --git a/OWML.ModHelper.Menus/readme.txt b/OWML.ModHelper.Menus/readme.txt new file mode 100644 index 000000000..d3d7dc6a3 --- /dev/null +++ b/OWML.ModHelper.Menus/readme.txt @@ -0,0 +1,2 @@ +nuget pack +nuget.exe push -Source "OW" -ApiKey az OW.Unity.Dlls.1.0.0.1.nupkg \ No newline at end of file diff --git a/OWML.ModHelper/ModManifest.cs b/OWML.ModHelper/ModManifest.cs index 955a4c3f7..4376fb21b 100644 --- a/OWML.ModHelper/ModManifest.cs +++ b/OWML.ModHelper/ModManifest.cs @@ -24,6 +24,9 @@ public class ModManifest : IModManifest [JsonProperty("owmlVersion")] public string OWMLVersion { get; private set; } + [JsonProperty("dependency")] + public string Dependency { get; private set; } + [JsonIgnore] public string ModFolderPath { get; set; } diff --git a/OWML.ModHelper/OWML.ModHelper.csproj b/OWML.ModHelper/OWML.ModHelper.csproj index 97293f4ee..884cc7f92 100644 --- a/OWML.ModHelper/OWML.ModHelper.csproj +++ b/OWML.ModHelper/OWML.ModHelper.csproj @@ -33,35 +33,38 @@ - ..\packages\OW.Unity.Dlls.1.0.2\lib\net35\Assembly-CSharp.dll + ..\packages\OW.Unity.Dlls.1.0.4\lib\net35\Assembly-CSharp.dll ..\packages\Json.Net.Unity3D.9.0.1\lib\net35\Newtonsoft.Json.dll - - ..\packages\OW.Unity.Dlls.1.0.2\lib\net35\OW.Unity.Dlls.dll + + ..\packages\OW.Unity.Dlls.1.0.4\lib\net35\OW.Unity.Dlls.dll - ..\packages\OW.Unity.Dlls.1.0.2\lib\net35\UnityEngine.dll + ..\packages\OW.Unity.Dlls.1.0.4\lib\net35\UnityEngine.dll - ..\packages\OW.Unity.Dlls.1.0.2\lib\net35\UnityEngine.AudioModule.dll + ..\packages\OW.Unity.Dlls.1.0.4\lib\net35\UnityEngine.AudioModule.dll - ..\packages\OW.Unity.Dlls.1.0.2\lib\net35\UnityEngine.CoreModule.dll + ..\packages\OW.Unity.Dlls.1.0.4\lib\net35\UnityEngine.CoreModule.dll + + + ..\packages\OW.Unity.Dlls.1.0.4\lib\net35\UnityEngine.IMGUIModule.dll - ..\packages\OW.Unity.Dlls.1.0.2\lib\net35\UnityEngine.PhysicsModule.dll + ..\packages\OW.Unity.Dlls.1.0.4\lib\net35\UnityEngine.PhysicsModule.dll - ..\packages\OW.Unity.Dlls.1.0.2\lib\net35\UnityEngine.UI.dll + ..\packages\OW.Unity.Dlls.1.0.4\lib\net35\UnityEngine.UI.dll - ..\packages\OW.Unity.Dlls.1.0.2\lib\net35\UnityEngine.UIModule.dll + ..\packages\OW.Unity.Dlls.1.0.4\lib\net35\UnityEngine.UIModule.dll - ..\packages\OW.Unity.Dlls.1.0.2\lib\net35\UnityEngine.UnityWebRequestWWWModule.dll + ..\packages\OW.Unity.Dlls.1.0.4\lib\net35\UnityEngine.UnityWebRequestWWWModule.dll @@ -91,5 +94,8 @@ OWML.ModHelper.Events + + + \ No newline at end of file diff --git a/OWML.ModHelper/packages.config b/OWML.ModHelper/packages.config index 9cdd28f36..074e374a8 100644 --- a/OWML.ModHelper/packages.config +++ b/OWML.ModHelper/packages.config @@ -1,5 +1,5 @@  - + \ No newline at end of file diff --git a/OWML.ModHelper/readme.txt b/OWML.ModHelper/readme.txt new file mode 100644 index 000000000..d3d7dc6a3 --- /dev/null +++ b/OWML.ModHelper/readme.txt @@ -0,0 +1,2 @@ +nuget pack +nuget.exe push -Source "OW" -ApiKey az OW.Unity.Dlls.1.0.0.1.nupkg \ No newline at end of file diff --git a/OWML.ModLoader/ModSorter.cs b/OWML.ModLoader/ModSorter.cs new file mode 100644 index 000000000..7db59be68 --- /dev/null +++ b/OWML.ModLoader/ModSorter.cs @@ -0,0 +1,101 @@ +using OWML.Common; +using System; +using System.Collections.Generic; +using System.Linq; + +namespace OWML.ModLoader +{ + class ModSorter + { + public static IList SortMods(IList mods) + { + List modList = new List(); + foreach (var mod in mods) + { + if (mod.Manifest.Dependency != "None" && mod.Manifest.Dependency != null) + { + modList.Add(new ModDep(mod.Manifest.Name, mod, mod.Manifest.Dependency)); + } + else + { + modList.Add(new ModDep(mod.Manifest.Name, mod)); + } + } + + return Sort(modList, x => x.Dependencies, x => x.Name); + } + + private static IList Sort(IEnumerable source, Func> getDependencies) + { + var sorted = new List(); + var visited = new Dictionary(); + + foreach (var item in source) + { + Visit(item, getDependencies, sorted, visited); + } + + return sorted; + } + + private static void Visit(T item, Func> getDependencies, List sorted, Dictionary visited) + { + bool inProcess; + var alreadyVisited = visited.TryGetValue(item, out inProcess); + + if (alreadyVisited) + { + if (inProcess) + { + throw new ArgumentException("Cyclic dependency found."); + } + } + else + { + visited[item] = true; + + var dependencies = getDependencies(item); + if (dependencies != null) + { + foreach (var dependency in dependencies) + { + Visit(dependency, getDependencies, sorted, visited); + } + } + + visited[item] = false; + sorted.Add(item); + } + } + + private static Func> RemapDependencies(IEnumerable source, Func> getDependencies, Func getKey) + { + var map = source.ToDictionary(getKey); + return item => + { + var dependencies = getDependencies(item); + return dependencies != null ? dependencies.Select(key => map[key]) : null; + }; + } + + private static IList Sort(IEnumerable source, Func> getDependencies, Func getKey) + { + return Sort(source, RemapDependencies(source, getDependencies, getKey)); + } + } + + public class ModDep + { + public string Name { get; private set; } + public string[] Dependencies { get; private set; } + + public IModData Data { get; private set; } + + public ModDep(string name, IModData data, params string[] dependencies) + { + Name = name; + Data = data; + Dependencies = dependencies; + } + } +} diff --git a/OWML.ModLoader/OWML.ModLoader.csproj b/OWML.ModLoader/OWML.ModLoader.csproj index b0db9c3d6..5ed832e21 100644 --- a/OWML.ModLoader/OWML.ModLoader.csproj +++ b/OWML.ModLoader/OWML.ModLoader.csproj @@ -33,41 +33,45 @@ - ..\packages\OW.Unity.Dlls.1.0.2\lib\net35\Assembly-CSharp.dll + ..\packages\OW.Unity.Dlls.1.0.4\lib\net35\Assembly-CSharp.dll ..\packages\Json.Net.Unity3D.9.0.1\lib\net35\Newtonsoft.Json.dll - - ..\packages\OW.Unity.Dlls.1.0.2\lib\net35\OW.Unity.Dlls.dll + + ..\packages\OW.Unity.Dlls.1.0.4\lib\net35\OW.Unity.Dlls.dll - ..\packages\OW.Unity.Dlls.1.0.2\lib\net35\UnityEngine.dll + ..\packages\OW.Unity.Dlls.1.0.4\lib\net35\UnityEngine.dll - ..\packages\OW.Unity.Dlls.1.0.2\lib\net35\UnityEngine.AudioModule.dll + ..\packages\OW.Unity.Dlls.1.0.4\lib\net35\UnityEngine.AudioModule.dll - ..\packages\OW.Unity.Dlls.1.0.2\lib\net35\UnityEngine.CoreModule.dll + ..\packages\OW.Unity.Dlls.1.0.4\lib\net35\UnityEngine.CoreModule.dll + + + ..\packages\OW.Unity.Dlls.1.0.4\lib\net35\UnityEngine.IMGUIModule.dll - ..\packages\OW.Unity.Dlls.1.0.2\lib\net35\UnityEngine.PhysicsModule.dll + ..\packages\OW.Unity.Dlls.1.0.4\lib\net35\UnityEngine.PhysicsModule.dll - ..\packages\OW.Unity.Dlls.1.0.2\lib\net35\UnityEngine.UI.dll + ..\packages\OW.Unity.Dlls.1.0.4\lib\net35\UnityEngine.UI.dll - ..\packages\OW.Unity.Dlls.1.0.2\lib\net35\UnityEngine.UIModule.dll + ..\packages\OW.Unity.Dlls.1.0.4\lib\net35\UnityEngine.UIModule.dll - ..\packages\OW.Unity.Dlls.1.0.2\lib\net35\UnityEngine.UnityWebRequestWWWModule.dll + ..\packages\OW.Unity.Dlls.1.0.4\lib\net35\UnityEngine.UnityWebRequestWWWModule.dll + @@ -96,5 +100,8 @@ + + + \ No newline at end of file diff --git a/OWML.ModLoader/Owo.cs b/OWML.ModLoader/Owo.cs index 065bee814..360743579 100644 --- a/OWML.ModLoader/Owo.cs +++ b/OWML.ModLoader/Owo.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using System.Linq; using System.Reflection; using OWML.Common; @@ -38,8 +39,12 @@ public void LoadMods() Application.logMessageReceived += OnLogMessageReceived; } var mods = _modFinder.GetMods(); - foreach (var modData in mods) + + var sortedMods = ModSorter.SortMods(mods); + + foreach (var modDep in sortedMods) { + var modData = modDep.Data; var modType = LoadMod(modData); if (modType == null) { diff --git a/OWML.ModLoader/packages.config b/OWML.ModLoader/packages.config index 9cdd28f36..074e374a8 100644 --- a/OWML.ModLoader/packages.config +++ b/OWML.ModLoader/packages.config @@ -1,5 +1,5 @@  - + \ No newline at end of file diff --git a/OWML.ModLoader/readme.txt b/OWML.ModLoader/readme.txt new file mode 100644 index 000000000..d3d7dc6a3 --- /dev/null +++ b/OWML.ModLoader/readme.txt @@ -0,0 +1,2 @@ +nuget pack +nuget.exe push -Source "OW" -ApiKey az OW.Unity.Dlls.1.0.0.1.nupkg \ No newline at end of file diff --git a/OWML.SampleMods/OWML.EnableDebugMode/OWML.EnableDebugMode.csproj b/OWML.SampleMods/OWML.EnableDebugMode/OWML.EnableDebugMode.csproj index 2c260c025..2ae09ea5c 100644 --- a/OWML.SampleMods/OWML.EnableDebugMode/OWML.EnableDebugMode.csproj +++ b/OWML.SampleMods/OWML.EnableDebugMode/OWML.EnableDebugMode.csproj @@ -32,32 +32,38 @@ - ..\..\packages\OW.Unity.Dlls.1.0.2\lib\net35\Assembly-CSharp.dll + ..\..\packages\OW.Unity.Dlls.1.0.4\lib\net35\Assembly-CSharp.dll - - ..\..\packages\OW.Unity.Dlls.1.0.2\lib\net35\OW.Unity.Dlls.dll + + ..\..\packages\Json.Net.Unity3D.9.0.1\lib\net35\Newtonsoft.Json.dll + + + ..\..\packages\OW.Unity.Dlls.1.0.4\lib\net35\OW.Unity.Dlls.dll - ..\..\packages\OW.Unity.Dlls.1.0.2\lib\net35\UnityEngine.dll + ..\..\packages\OW.Unity.Dlls.1.0.4\lib\net35\UnityEngine.dll - ..\..\packages\OW.Unity.Dlls.1.0.2\lib\net35\UnityEngine.AudioModule.dll + ..\..\packages\OW.Unity.Dlls.1.0.4\lib\net35\UnityEngine.AudioModule.dll - ..\..\packages\OW.Unity.Dlls.1.0.2\lib\net35\UnityEngine.CoreModule.dll + ..\..\packages\OW.Unity.Dlls.1.0.4\lib\net35\UnityEngine.CoreModule.dll + + + ..\..\packages\OW.Unity.Dlls.1.0.4\lib\net35\UnityEngine.IMGUIModule.dll - ..\..\packages\OW.Unity.Dlls.1.0.2\lib\net35\UnityEngine.PhysicsModule.dll + ..\..\packages\OW.Unity.Dlls.1.0.4\lib\net35\UnityEngine.PhysicsModule.dll - ..\..\packages\OW.Unity.Dlls.1.0.2\lib\net35\UnityEngine.UI.dll + ..\..\packages\OW.Unity.Dlls.1.0.4\lib\net35\UnityEngine.UI.dll - ..\..\packages\OW.Unity.Dlls.1.0.2\lib\net35\UnityEngine.UIModule.dll + ..\..\packages\OW.Unity.Dlls.1.0.4\lib\net35\UnityEngine.UIModule.dll - ..\..\packages\OW.Unity.Dlls.1.0.2\lib\net35\UnityEngine.UnityWebRequestWWWModule.dll + ..\..\packages\OW.Unity.Dlls.1.0.4\lib\net35\UnityEngine.UnityWebRequestWWWModule.dll @@ -87,6 +93,9 @@ OWML.ModHelper + + + diff --git a/OWML.SampleMods/OWML.EnableDebugMode/manifest.json b/OWML.SampleMods/OWML.EnableDebugMode/manifest.json index 825827758..7ccb182c6 100644 --- a/OWML.SampleMods/OWML.EnableDebugMode/manifest.json +++ b/OWML.SampleMods/OWML.EnableDebugMode/manifest.json @@ -5,5 +5,6 @@ "uniqueName": "Alek.EnableDebugMode", "version": "0.2", "owmlVersion": "0.3.46", + "dependency": "LoadCustomAssets", "description": "Enables the debug mode in Outer Wilds" } \ No newline at end of file diff --git a/OWML.SampleMods/OWML.EnableDebugMode/packages.config b/OWML.SampleMods/OWML.EnableDebugMode/packages.config index bfe552ebf..074e374a8 100644 --- a/OWML.SampleMods/OWML.EnableDebugMode/packages.config +++ b/OWML.SampleMods/OWML.EnableDebugMode/packages.config @@ -1,4 +1,5 @@  - + + \ No newline at end of file diff --git a/OWML.SampleMods/OWML.EnableDebugMode/readme.txt b/OWML.SampleMods/OWML.EnableDebugMode/readme.txt new file mode 100644 index 000000000..d3d7dc6a3 --- /dev/null +++ b/OWML.SampleMods/OWML.EnableDebugMode/readme.txt @@ -0,0 +1,2 @@ +nuget pack +nuget.exe push -Source "OW" -ApiKey az OW.Unity.Dlls.1.0.0.1.nupkg \ No newline at end of file diff --git a/OWML.SampleMods/OWML.LoadCustomAssets/OWML.LoadCustomAssets.csproj b/OWML.SampleMods/OWML.LoadCustomAssets/OWML.LoadCustomAssets.csproj index c3fae5bbe..7f737895b 100644 --- a/OWML.SampleMods/OWML.LoadCustomAssets/OWML.LoadCustomAssets.csproj +++ b/OWML.SampleMods/OWML.LoadCustomAssets/OWML.LoadCustomAssets.csproj @@ -32,35 +32,38 @@ - ..\..\packages\OW.Unity.Dlls.1.0.2\lib\net35\Assembly-CSharp.dll + ..\..\packages\OW.Unity.Dlls.1.0.4\lib\net35\Assembly-CSharp.dll ..\..\packages\Json.Net.Unity3D.9.0.1\lib\net35\Newtonsoft.Json.dll - - ..\..\packages\OW.Unity.Dlls.1.0.2\lib\net35\OW.Unity.Dlls.dll + + ..\..\packages\OW.Unity.Dlls.1.0.4\lib\net35\OW.Unity.Dlls.dll - ..\..\packages\OW.Unity.Dlls.1.0.2\lib\net35\UnityEngine.dll + ..\..\packages\OW.Unity.Dlls.1.0.4\lib\net35\UnityEngine.dll - ..\..\packages\OW.Unity.Dlls.1.0.2\lib\net35\UnityEngine.AudioModule.dll + ..\..\packages\OW.Unity.Dlls.1.0.4\lib\net35\UnityEngine.AudioModule.dll - ..\..\packages\OW.Unity.Dlls.1.0.2\lib\net35\UnityEngine.CoreModule.dll + ..\..\packages\OW.Unity.Dlls.1.0.4\lib\net35\UnityEngine.CoreModule.dll + + + ..\..\packages\OW.Unity.Dlls.1.0.4\lib\net35\UnityEngine.IMGUIModule.dll - ..\..\packages\OW.Unity.Dlls.1.0.2\lib\net35\UnityEngine.PhysicsModule.dll + ..\..\packages\OW.Unity.Dlls.1.0.4\lib\net35\UnityEngine.PhysicsModule.dll - ..\..\packages\OW.Unity.Dlls.1.0.2\lib\net35\UnityEngine.UI.dll + ..\..\packages\OW.Unity.Dlls.1.0.4\lib\net35\UnityEngine.UI.dll - ..\..\packages\OW.Unity.Dlls.1.0.2\lib\net35\UnityEngine.UIModule.dll + ..\..\packages\OW.Unity.Dlls.1.0.4\lib\net35\UnityEngine.UIModule.dll - ..\..\packages\OW.Unity.Dlls.1.0.2\lib\net35\UnityEngine.UnityWebRequestWWWModule.dll + ..\..\packages\OW.Unity.Dlls.1.0.4\lib\net35\UnityEngine.UnityWebRequestWWWModule.dll @@ -96,6 +99,7 @@ Always + Always diff --git a/OWML.SampleMods/OWML.LoadCustomAssets/manifest.json b/OWML.SampleMods/OWML.LoadCustomAssets/manifest.json index 53694b1c6..a632629ec 100644 --- a/OWML.SampleMods/OWML.LoadCustomAssets/manifest.json +++ b/OWML.SampleMods/OWML.LoadCustomAssets/manifest.json @@ -5,5 +5,6 @@ "uniqueName": "Alek.LoadCustomAssets", "version": "0.5", "owmlVersion": "0.3.46", + "dependency": "None", "description": "A mod for testing loading of custom assets" } \ No newline at end of file diff --git a/OWML.SampleMods/OWML.LoadCustomAssets/packages.config b/OWML.SampleMods/OWML.LoadCustomAssets/packages.config index 9cdd28f36..074e374a8 100644 --- a/OWML.SampleMods/OWML.LoadCustomAssets/packages.config +++ b/OWML.SampleMods/OWML.LoadCustomAssets/packages.config @@ -1,5 +1,5 @@  - + \ No newline at end of file diff --git a/OWML.SampleMods/OWML.LoadCustomAssets/readme.txt b/OWML.SampleMods/OWML.LoadCustomAssets/readme.txt new file mode 100644 index 000000000..d3d7dc6a3 --- /dev/null +++ b/OWML.SampleMods/OWML.LoadCustomAssets/readme.txt @@ -0,0 +1,2 @@ +nuget pack +nuget.exe push -Source "OW" -ApiKey az OW.Unity.Dlls.1.0.0.1.nupkg \ No newline at end of file From e1b2093bfef189aea807a6313ca2298cce42a0aa Mon Sep 17 00:00:00 2001 From: Mister_Nebula <41904486+misternebula@users.noreply.github.com> Date: Sun, 26 Apr 2020 09:55:44 +0100 Subject: [PATCH 02/36] Support for multiple dependencies --- OWML.Common/IModManifest.cs | 4 +++- OWML.ModHelper/ModManifest.cs | 7 ++++++- OWML.ModLoader/ModSorter.cs | 9 +++++++-- OWML.SampleMods/OWML.EnableDebugMode/manifest.json | 2 +- OWML.SampleMods/OWML.LoadCustomAssets/manifest.json | 1 - 5 files changed, 17 insertions(+), 6 deletions(-) diff --git a/OWML.Common/IModManifest.cs b/OWML.Common/IModManifest.cs index 8c1ded4c3..3332542a8 100644 --- a/OWML.Common/IModManifest.cs +++ b/OWML.Common/IModManifest.cs @@ -13,6 +13,8 @@ public interface IModManifest string UniqueName { get; } string ModFolderPath { get; set; } Dictionary AppIds { get; } - string Dependency { get; } + string[] Dependencies { get; } + + void SetDependencies(params string[] dependencies); } } diff --git a/OWML.ModHelper/ModManifest.cs b/OWML.ModHelper/ModManifest.cs index 4376fb21b..d696962b1 100644 --- a/OWML.ModHelper/ModManifest.cs +++ b/OWML.ModHelper/ModManifest.cs @@ -25,7 +25,7 @@ public class ModManifest : IModManifest public string OWMLVersion { get; private set; } [JsonProperty("dependency")] - public string Dependency { get; private set; } + public string[] Dependencies { get; private set; } [JsonIgnore] public string ModFolderPath { get; set; } @@ -35,5 +35,10 @@ public class ModManifest : IModManifest [JsonIgnore] public string AssemblyPath => ModFolderPath + Filename; + + public void SetDependencies(params string[] dependencies) + { + Dependencies = dependencies; + } } } diff --git a/OWML.ModLoader/ModSorter.cs b/OWML.ModLoader/ModSorter.cs index 7db59be68..3e1d3d50a 100644 --- a/OWML.ModLoader/ModSorter.cs +++ b/OWML.ModLoader/ModSorter.cs @@ -12,9 +12,14 @@ public static IList SortMods(IList mods) List modList = new List(); foreach (var mod in mods) { - if (mod.Manifest.Dependency != "None" && mod.Manifest.Dependency != null) + if (mod.Manifest.Dependencies == null) { - modList.Add(new ModDep(mod.Manifest.Name, mod, mod.Manifest.Dependency)); + mod.Manifest.SetDependencies(new[] { "None" }); + } + + if (mod.Manifest.Dependencies.First() != "None") + { + modList.Add(new ModDep(mod.Manifest.Name, mod, mod.Manifest.Dependencies)); } else { diff --git a/OWML.SampleMods/OWML.EnableDebugMode/manifest.json b/OWML.SampleMods/OWML.EnableDebugMode/manifest.json index 7ccb182c6..dfef39b3f 100644 --- a/OWML.SampleMods/OWML.EnableDebugMode/manifest.json +++ b/OWML.SampleMods/OWML.EnableDebugMode/manifest.json @@ -5,6 +5,6 @@ "uniqueName": "Alek.EnableDebugMode", "version": "0.2", "owmlVersion": "0.3.46", - "dependency": "LoadCustomAssets", + "dependency": [ "LoadCustomAssets" ], "description": "Enables the debug mode in Outer Wilds" } \ No newline at end of file diff --git a/OWML.SampleMods/OWML.LoadCustomAssets/manifest.json b/OWML.SampleMods/OWML.LoadCustomAssets/manifest.json index a632629ec..53694b1c6 100644 --- a/OWML.SampleMods/OWML.LoadCustomAssets/manifest.json +++ b/OWML.SampleMods/OWML.LoadCustomAssets/manifest.json @@ -5,6 +5,5 @@ "uniqueName": "Alek.LoadCustomAssets", "version": "0.5", "owmlVersion": "0.3.46", - "dependency": "None", "description": "A mod for testing loading of custom assets" } \ No newline at end of file From 5c8b2d3e31536944ec085988810d894b79c94240 Mon Sep 17 00:00:00 2001 From: Mister_Nebula <41904486+misternebula@users.noreply.github.com> Date: Sun, 26 Apr 2020 10:11:28 +0100 Subject: [PATCH 03/36] code cleanup --- OWML.ModLoader/ModSorter.cs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/OWML.ModLoader/ModSorter.cs b/OWML.ModLoader/ModSorter.cs index 3e1d3d50a..85673b4c6 100644 --- a/OWML.ModLoader/ModSorter.cs +++ b/OWML.ModLoader/ModSorter.cs @@ -45,8 +45,7 @@ private static IList Sort(IEnumerable source, Func> g private static void Visit(T item, Func> getDependencies, List sorted, Dictionary visited) { - bool inProcess; - var alreadyVisited = visited.TryGetValue(item, out inProcess); + var alreadyVisited = visited.TryGetValue(item, out bool inProcess); if (alreadyVisited) { @@ -79,7 +78,7 @@ private static Func> RemapDependencies(IEnumerable return item => { var dependencies = getDependencies(item); - return dependencies != null ? dependencies.Select(key => map[key]) : null; + return dependencies?.Select(key => map[key]); }; } From b385e04459f74d94f677f67cc95e1315b154c789 Mon Sep 17 00:00:00 2001 From: Mister_Nebula <41904486+misternebula@users.noreply.github.com> Date: Sun, 26 Apr 2020 15:05:24 +0100 Subject: [PATCH 04/36] Added interaction methods --- OWML.Common/IModHelper.cs | 1 + OWML.Common/IModInteraction.cs | 15 +++ OWML.Common/OWML.Common.csproj | 1 + OWML.ModHelper.Interaction/ModInteraction.cs | 43 +++++++++ .../OWML.ModHelper.Interaction.csproj | 96 +++++++++++++++++++ .../Properties/AssemblyInfo.cs | 36 +++++++ OWML.ModHelper.Interaction/packages.config | 4 + OWML.ModHelper.Interaction/readme.txt | 2 + OWML.ModHelper/ModHelper.cs | 4 +- OWML.ModLoader/OWML.ModLoader.csproj | 4 + OWML.ModLoader/Owo.cs | 7 +- OWML.Nuget/OWML.Nuget.csproj | 4 + OWML.Nuget/OWML.Nuget.nuspec | 1 + OWML.Patcher/OWPatcher.cs | 2 +- OWML.sln | 6 ++ createrelease.bat | 1 + 16 files changed, 224 insertions(+), 3 deletions(-) create mode 100644 OWML.Common/IModInteraction.cs create mode 100644 OWML.ModHelper.Interaction/ModInteraction.cs create mode 100644 OWML.ModHelper.Interaction/OWML.ModHelper.Interaction.csproj create mode 100644 OWML.ModHelper.Interaction/Properties/AssemblyInfo.cs create mode 100644 OWML.ModHelper.Interaction/packages.config create mode 100644 OWML.ModHelper.Interaction/readme.txt diff --git a/OWML.Common/IModHelper.cs b/OWML.Common/IModHelper.cs index d25e1c2f8..7de23a2f4 100644 --- a/OWML.Common/IModHelper.cs +++ b/OWML.Common/IModHelper.cs @@ -14,5 +14,6 @@ public interface IModHelper IModManifest Manifest { get; } IModConfig Config { get; } IOwmlConfig OwmlConfig { get; } + IModInteraction ModInteraction { get; } } } diff --git a/OWML.Common/IModInteraction.cs b/OWML.Common/IModInteraction.cs new file mode 100644 index 000000000..b59e05b0c --- /dev/null +++ b/OWML.Common/IModInteraction.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace OWML.Common +{ + public interface IModInteraction + { + IList GetMods(); + bool ModExists(string uniqueName); + T InvokeMethod(string uniqueName, string methodName, params object[] parameters); + void SetVariableValue(string uniqueName, string variableName, object value); + } +} diff --git a/OWML.Common/OWML.Common.csproj b/OWML.Common/OWML.Common.csproj index ebb5c5137..eb82d290a 100644 --- a/OWML.Common/OWML.Common.csproj +++ b/OWML.Common/OWML.Common.csproj @@ -73,6 +73,7 @@ + diff --git a/OWML.ModHelper.Interaction/ModInteraction.cs b/OWML.ModHelper.Interaction/ModInteraction.cs new file mode 100644 index 000000000..9d3815472 --- /dev/null +++ b/OWML.ModHelper.Interaction/ModInteraction.cs @@ -0,0 +1,43 @@ +using OWML.Common; +using OWML.ModHelper.Events; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using UnityEngine; + +namespace OWML.ModHelper.Interaction +{ + public class ModInteraction : IModInteraction + { + private readonly List _modList = new List(); + private readonly IModFinder _finder; + public ModInteraction(List list, IModFinder finder) + { + _modList = list; + _finder = finder; + } + + public IList GetMods() + { + return _finder.GetMods(); + } + + public bool ModExists(string uniqueName) + { + return _finder.GetMods().Where(m => m.Manifest.UniqueName == uniqueName).Count() != 0; + } + + public T InvokeMethod(string uniqueName, string methodName, params object[] parameters) + { + var mod = _modList.Where(m => m.ModHelper.Manifest.UniqueName == uniqueName).First(); + return (T)mod.GetType().GetMethod(methodName).Invoke(mod, parameters); + } + + public void SetVariableValue(string uniqueName, string variableName, object value) + { + var mod = _modList.Where(m => m.ModHelper.Manifest.UniqueName == uniqueName).First(); + mod.GetType().SetValue(variableName, value); + } + } +} diff --git a/OWML.ModHelper.Interaction/OWML.ModHelper.Interaction.csproj b/OWML.ModHelper.Interaction/OWML.ModHelper.Interaction.csproj new file mode 100644 index 000000000..2a50c0bd1 --- /dev/null +++ b/OWML.ModHelper.Interaction/OWML.ModHelper.Interaction.csproj @@ -0,0 +1,96 @@ + + + + + Debug + AnyCPU + {3212C570-D4C3-4083-A3DB-616F80BA5DAB} + Library + Properties + OWML.ModHelper.Interaction + OWML.ModHelper.Interaction + v3.5 + 512 + true + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + ..\packages\OW.Unity.Dlls.1.0.4\lib\net35\Assembly-CSharp.dll + + + ..\packages\OW.Unity.Dlls.1.0.4\lib\net35\OW.Unity.Dlls.dll + + + + + + + + + ..\packages\OW.Unity.Dlls.1.0.4\lib\net35\UnityEngine.dll + + + ..\packages\OW.Unity.Dlls.1.0.4\lib\net35\UnityEngine.AudioModule.dll + + + ..\packages\OW.Unity.Dlls.1.0.4\lib\net35\UnityEngine.CoreModule.dll + + + ..\packages\OW.Unity.Dlls.1.0.4\lib\net35\UnityEngine.IMGUIModule.dll + + + ..\packages\OW.Unity.Dlls.1.0.4\lib\net35\UnityEngine.PhysicsModule.dll + + + ..\packages\OW.Unity.Dlls.1.0.4\lib\net35\UnityEngine.UI.dll + + + ..\packages\OW.Unity.Dlls.1.0.4\lib\net35\UnityEngine.UIModule.dll + + + ..\packages\OW.Unity.Dlls.1.0.4\lib\net35\UnityEngine.UnityWebRequestWWWModule.dll + + + + + + + + + {3C00626F-B688-4F32-B493-5B7EC1C879A0} + OWML.Common + + + {B771615E-6B51-44F8-B862-D7543C12C0FF} + OWML.ModHelper.Events + + + {cb57bab8-d70e-4fce-9bf1-328a924173a7} + OWML.ModHelper + + + + + + + + + + \ No newline at end of file diff --git a/OWML.ModHelper.Interaction/Properties/AssemblyInfo.cs b/OWML.ModHelper.Interaction/Properties/AssemblyInfo.cs new file mode 100644 index 000000000..7fb177fa7 --- /dev/null +++ b/OWML.ModHelper.Interaction/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("OWML.ModInteraction")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("OWML.ModInteraction")] +[assembly: AssemblyCopyright("Copyright © 2020")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("3212c570-d4c3-4083-a3db-616f80ba5dab")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/OWML.ModHelper.Interaction/packages.config b/OWML.ModHelper.Interaction/packages.config new file mode 100644 index 000000000..8288b7a49 --- /dev/null +++ b/OWML.ModHelper.Interaction/packages.config @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/OWML.ModHelper.Interaction/readme.txt b/OWML.ModHelper.Interaction/readme.txt new file mode 100644 index 000000000..d3d7dc6a3 --- /dev/null +++ b/OWML.ModHelper.Interaction/readme.txt @@ -0,0 +1,2 @@ +nuget pack +nuget.exe push -Source "OW" -ApiKey az OW.Unity.Dlls.1.0.0.1.nupkg \ No newline at end of file diff --git a/OWML.ModHelper/ModHelper.cs b/OWML.ModHelper/ModHelper.cs index e36a9bd4f..0ccf013df 100644 --- a/OWML.ModHelper/ModHelper.cs +++ b/OWML.ModHelper/ModHelper.cs @@ -16,9 +16,10 @@ public class ModHelper : IModHelper public IModManifest Manifest { get; } public IModConfig Config { get; } public IOwmlConfig OwmlConfig { get; } + public IModInteraction ModInteraction { get; } public ModHelper(IModLogger logger, IModConsole console, IHarmonyHelper harmonyHelper, IModEvents events, - IModAssets assets, IModStorage storage, IModMenus menus, IModManifest manifest, IModConfig config, IOwmlConfig owmlConfig) + IModAssets assets, IModStorage storage, IModMenus menus, IModManifest manifest, IModConfig config, IOwmlConfig owmlConfig, IModInteraction interaction) { Logger = logger; Console = console; @@ -30,6 +31,7 @@ public ModHelper(IModLogger logger, IModConsole console, IHarmonyHelper harmonyH Manifest = manifest; Config = config; OwmlConfig = owmlConfig; + ModInteraction = interaction; } } diff --git a/OWML.ModLoader/OWML.ModLoader.csproj b/OWML.ModLoader/OWML.ModLoader.csproj index 5ed832e21..feb210e44 100644 --- a/OWML.ModLoader/OWML.ModLoader.csproj +++ b/OWML.ModLoader/OWML.ModLoader.csproj @@ -88,6 +88,10 @@ {B771615E-6B51-44F8-B862-D7543C12C0FF} OWML.ModHelper.Events + + {3212C570-D4C3-4083-A3DB-616F80BA5DAB} + OWML.ModHelper.Interaction + {b874cc24-8340-4238-ac9d-1bfb41186bb5} OWML.ModHelper.Menus diff --git a/OWML.ModLoader/Owo.cs b/OWML.ModLoader/Owo.cs index 360743579..69a95f41e 100644 --- a/OWML.ModLoader/Owo.cs +++ b/OWML.ModLoader/Owo.cs @@ -7,6 +7,7 @@ using OWML.ModHelper; using OWML.ModHelper.Assets; using OWML.ModHelper.Events; +using OWML.ModHelper.Interaction; using UnityEngine; namespace OWML.ModLoader @@ -20,6 +21,8 @@ internal class Owo private readonly IModMenus _menus; private readonly IHarmonyHelper _harmonyHelper; + List _modList = new List(); + public Owo(IModFinder modFinder, IModLogger logger, IModConsole console, IOwmlConfig owmlConfig, IModMenus menus, IHarmonyHelper harmonyHelper) { @@ -55,6 +58,7 @@ public void LoadMods() var helper = CreateModHelper(modData); var mod = InitializeMod(modType, helper); _menus.ModsMenu.AddMod(modData, mod); + _modList.Add(mod as ModBehaviour); } } @@ -94,8 +98,9 @@ private IModHelper CreateModHelper(IModData modData) var assets = new ModAssets(console, modData.Manifest); var storage = new ModStorage(console, modData.Manifest); var events = new ModEvents(logger, console, _harmonyHelper); + var interaction = new ModInteraction(_modList, _modFinder); return new ModHelper.ModHelper(logger, console, _harmonyHelper, - events, assets, storage, _menus, modData.Manifest, modData.Config, _owmlConfig); + events, assets, storage, _menus, modData.Manifest, modData.Config, _owmlConfig, interaction); } private IModBehaviour InitializeMod(Type modType, IModHelper helper) diff --git a/OWML.Nuget/OWML.Nuget.csproj b/OWML.Nuget/OWML.Nuget.csproj index 718cbad66..bef0fa152 100644 --- a/OWML.Nuget/OWML.Nuget.csproj +++ b/OWML.Nuget/OWML.Nuget.csproj @@ -58,6 +58,10 @@ {b771615e-6b51-44f8-b862-d7543c12c0ff} OWML.ModHelper.Events + + {3212c570-d4c3-4083-a3db-616f80ba5dab} + OWML.ModHelper.Interaction + {b874cc24-8340-4238-ac9d-1bfb41186bb5} OWML.ModHelper.Menus diff --git a/OWML.Nuget/OWML.Nuget.nuspec b/OWML.Nuget/OWML.Nuget.nuspec index a55fa9d0f..fa2943c00 100644 --- a/OWML.Nuget/OWML.Nuget.nuspec +++ b/OWML.Nuget/OWML.Nuget.nuspec @@ -25,6 +25,7 @@ + diff --git a/OWML.Patcher/OWPatcher.cs b/OWML.Patcher/OWPatcher.cs index b8f631127..a4b55daed 100644 --- a/OWML.Patcher/OWPatcher.cs +++ b/OWML.Patcher/OWPatcher.cs @@ -34,7 +34,7 @@ private void CopyFiles() var filesToCopy = new[] { "OWML.ModLoader.dll", "OWML.Common.dll", "OWML.ModHelper.dll", "OWML.ModHelper.Events.dll", "OWML.ModHelper.Assets.dll", "OWML.ModHelper.Menus.dll", "Newtonsoft.Json.dll", "System.Runtime.Serialization.dll", "0Harmony.dll", "NAudio-Unity.dll", - "OWML.Manifest.json" }; + "OWML.Manifest.json", "OWML.ModHelper.Interaction.dll" }; foreach (var filename in filesToCopy) { File.Copy(filename, $"{_owmlConfig.ManagedPath}/{filename}", true); diff --git a/OWML.sln b/OWML.sln index 54f169daf..eae2490e5 100644 --- a/OWML.sln +++ b/OWML.sln @@ -27,6 +27,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OWML.Nuget", "OWML.Nuget\OW EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OWML.ModHelper.Menus", "OWML.ModHelper.Menus\OWML.ModHelper.Menus.csproj", "{B874CC24-8340-4238-AC9D-1BFB41186BB5}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OWML.ModHelper.Interaction", "OWML.ModHelper.Interaction\OWML.ModHelper.Interaction.csproj", "{3212C570-D4C3-4083-A3DB-616F80BA5DAB}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -77,6 +79,10 @@ Global {B874CC24-8340-4238-AC9D-1BFB41186BB5}.Debug|Any CPU.Build.0 = Debug|Any CPU {B874CC24-8340-4238-AC9D-1BFB41186BB5}.Release|Any CPU.ActiveCfg = Release|Any CPU {B874CC24-8340-4238-AC9D-1BFB41186BB5}.Release|Any CPU.Build.0 = Release|Any CPU + {3212C570-D4C3-4083-A3DB-616F80BA5DAB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {3212C570-D4C3-4083-A3DB-616F80BA5DAB}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3212C570-D4C3-4083-A3DB-616F80BA5DAB}.Release|Any CPU.ActiveCfg = Release|Any CPU + {3212C570-D4C3-4083-A3DB-616F80BA5DAB}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/createrelease.bat b/createrelease.bat index b12d30015..8782db912 100644 --- a/createrelease.bat +++ b/createrelease.bat @@ -21,6 +21,7 @@ copy "OWML.Nuget\bin\Debug\OWML.Common.dll" "Release\OWML.Common.dll" copy "OWML.Nuget\bin\Debug\OWML.ModHelper.dll" "Release\OWML.ModHelper.dll" copy "OWML.Nuget\bin\Debug\OWML.ModHelper.Events.dll" "Release\OWML.ModHelper.Events.dll" copy "OWML.Nuget\bin\Debug\OWML.ModHelper.Assets.dll" "Release\OWML.ModHelper.Assets.dll" +copy "OWML.Nuget\bin\Debug\OWML.ModHelper.Interaction.dll" "Release\OWML.ModHelper.Interaction.dll" copy "OWML.Nuget\bin\Debug\OWML.ModHelper.Menus.dll" "Release\OWML.ModHelper.Menus.dll" copy "OWML.Nuget\bin\Debug\0Harmony.dll" "Release\0Harmony.dll" copy "OWML.Nuget\bin\Debug\Newtonsoft.Json.dll" "Release\Newtonsoft.Json.dll" From 1861d013437d104c3c6cdb35d488dba5967202bd Mon Sep 17 00:00:00 2001 From: Mister_Nebula <41904486+misternebula@users.noreply.github.com> Date: Sun, 26 Apr 2020 15:07:22 +0100 Subject: [PATCH 05/36] cleanup --- OWML.Common/readme.txt | 2 -- OWML.ModHelper.Assets/readme.txt | 2 -- OWML.ModHelper.Events/readme.txt | 2 -- OWML.ModHelper.Interaction/readme.txt | 2 -- OWML.ModHelper.Menus/readme.txt | 2 -- OWML.ModLoader/readme.txt | 2 -- 6 files changed, 12 deletions(-) delete mode 100644 OWML.Common/readme.txt delete mode 100644 OWML.ModHelper.Assets/readme.txt delete mode 100644 OWML.ModHelper.Events/readme.txt delete mode 100644 OWML.ModHelper.Interaction/readme.txt delete mode 100644 OWML.ModHelper.Menus/readme.txt delete mode 100644 OWML.ModLoader/readme.txt diff --git a/OWML.Common/readme.txt b/OWML.Common/readme.txt deleted file mode 100644 index d3d7dc6a3..000000000 --- a/OWML.Common/readme.txt +++ /dev/null @@ -1,2 +0,0 @@ -nuget pack -nuget.exe push -Source "OW" -ApiKey az OW.Unity.Dlls.1.0.0.1.nupkg \ No newline at end of file diff --git a/OWML.ModHelper.Assets/readme.txt b/OWML.ModHelper.Assets/readme.txt deleted file mode 100644 index d3d7dc6a3..000000000 --- a/OWML.ModHelper.Assets/readme.txt +++ /dev/null @@ -1,2 +0,0 @@ -nuget pack -nuget.exe push -Source "OW" -ApiKey az OW.Unity.Dlls.1.0.0.1.nupkg \ No newline at end of file diff --git a/OWML.ModHelper.Events/readme.txt b/OWML.ModHelper.Events/readme.txt deleted file mode 100644 index d3d7dc6a3..000000000 --- a/OWML.ModHelper.Events/readme.txt +++ /dev/null @@ -1,2 +0,0 @@ -nuget pack -nuget.exe push -Source "OW" -ApiKey az OW.Unity.Dlls.1.0.0.1.nupkg \ No newline at end of file diff --git a/OWML.ModHelper.Interaction/readme.txt b/OWML.ModHelper.Interaction/readme.txt deleted file mode 100644 index d3d7dc6a3..000000000 --- a/OWML.ModHelper.Interaction/readme.txt +++ /dev/null @@ -1,2 +0,0 @@ -nuget pack -nuget.exe push -Source "OW" -ApiKey az OW.Unity.Dlls.1.0.0.1.nupkg \ No newline at end of file diff --git a/OWML.ModHelper.Menus/readme.txt b/OWML.ModHelper.Menus/readme.txt deleted file mode 100644 index d3d7dc6a3..000000000 --- a/OWML.ModHelper.Menus/readme.txt +++ /dev/null @@ -1,2 +0,0 @@ -nuget pack -nuget.exe push -Source "OW" -ApiKey az OW.Unity.Dlls.1.0.0.1.nupkg \ No newline at end of file diff --git a/OWML.ModLoader/readme.txt b/OWML.ModLoader/readme.txt deleted file mode 100644 index d3d7dc6a3..000000000 --- a/OWML.ModLoader/readme.txt +++ /dev/null @@ -1,2 +0,0 @@ -nuget pack -nuget.exe push -Source "OW" -ApiKey az OW.Unity.Dlls.1.0.0.1.nupkg \ No newline at end of file From ee9fded76228ae8b20cf24a4454dda35eb466a6d Mon Sep 17 00:00:00 2001 From: Mister_Nebula <41904486+misternebula@users.noreply.github.com> Date: Sun, 26 Apr 2020 15:11:32 +0100 Subject: [PATCH 06/36] remove unneeded references --- OWML.ModHelper.Interaction/ModInteraction.cs | 3 --- OWML.ModHelper.Interaction/OWML.ModHelper.Interaction.csproj | 3 --- 2 files changed, 6 deletions(-) diff --git a/OWML.ModHelper.Interaction/ModInteraction.cs b/OWML.ModHelper.Interaction/ModInteraction.cs index 9d3815472..9baec8938 100644 --- a/OWML.ModHelper.Interaction/ModInteraction.cs +++ b/OWML.ModHelper.Interaction/ModInteraction.cs @@ -1,10 +1,7 @@ using OWML.Common; using OWML.ModHelper.Events; -using System; using System.Collections.Generic; using System.Linq; -using System.Text; -using UnityEngine; namespace OWML.ModHelper.Interaction { diff --git a/OWML.ModHelper.Interaction/OWML.ModHelper.Interaction.csproj b/OWML.ModHelper.Interaction/OWML.ModHelper.Interaction.csproj index 2a50c0bd1..30fb88bbc 100644 --- a/OWML.ModHelper.Interaction/OWML.ModHelper.Interaction.csproj +++ b/OWML.ModHelper.Interaction/OWML.ModHelper.Interaction.csproj @@ -52,9 +52,6 @@ ..\packages\OW.Unity.Dlls.1.0.4\lib\net35\UnityEngine.CoreModule.dll - - ..\packages\OW.Unity.Dlls.1.0.4\lib\net35\UnityEngine.IMGUIModule.dll - ..\packages\OW.Unity.Dlls.1.0.4\lib\net35\UnityEngine.PhysicsModule.dll From cc10d08e4e1b869cd65af648f75076b4f9513a31 Mon Sep 17 00:00:00 2001 From: Mister_Nebula <41904486+misternebula@users.noreply.github.com> Date: Sun, 26 Apr 2020 15:19:45 +0100 Subject: [PATCH 07/36] Update Readme.md --- Readme.md | 1 + 1 file changed, 1 insertion(+) diff --git a/Readme.md b/Readme.md index 512a1f6ce..91da362ba 100644 --- a/Readme.md +++ b/Readme.md @@ -69,6 +69,7 @@ Each mod is defined in a manifest.json file: |uniqueName|Usually {author}.{uniqueName}.| |version|The version number.| |owmlVersion|The version of OWML the mod was built for.| +|dependencies|\[ Dependency mod 1 name, Dependency mod 2 name, etc. \]| Each mod can be configured with an **optional** config.json file: From 3f23a05a522129ad08b4735c4e5f660d74e57dbe Mon Sep 17 00:00:00 2001 From: Mister_Nebula <41904486+misternebula@users.noreply.github.com> Date: Sun, 26 Apr 2020 15:21:12 +0100 Subject: [PATCH 08/36] Changed "dependency" to "dependencies" in ModManifest --- OWML.ModHelper/ModManifest.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OWML.ModHelper/ModManifest.cs b/OWML.ModHelper/ModManifest.cs index d696962b1..a2246e0c5 100644 --- a/OWML.ModHelper/ModManifest.cs +++ b/OWML.ModHelper/ModManifest.cs @@ -24,7 +24,7 @@ public class ModManifest : IModManifest [JsonProperty("owmlVersion")] public string OWMLVersion { get; private set; } - [JsonProperty("dependency")] + [JsonProperty("dependencies")] public string[] Dependencies { get; private set; } [JsonIgnore] From f09f02ec854c0a11cb71ad7fc52e898dbd65c122 Mon Sep 17 00:00:00 2001 From: Mister_Nebula <41904486+misternebula@users.noreply.github.com> Date: Sun, 26 Apr 2020 17:00:15 +0100 Subject: [PATCH 09/36] Cleanup and dependency warning --- OWML.ModHelper/readme.txt | 2 -- OWML.ModLoader/OWML.ModLoader.csproj | 3 --- OWML.ModLoader/Owo.cs | 16 ++++++++++++++++ 3 files changed, 16 insertions(+), 5 deletions(-) delete mode 100644 OWML.ModHelper/readme.txt diff --git a/OWML.ModHelper/readme.txt b/OWML.ModHelper/readme.txt deleted file mode 100644 index d3d7dc6a3..000000000 --- a/OWML.ModHelper/readme.txt +++ /dev/null @@ -1,2 +0,0 @@ -nuget pack -nuget.exe push -Source "OW" -ApiKey az OW.Unity.Dlls.1.0.0.1.nupkg \ No newline at end of file diff --git a/OWML.ModLoader/OWML.ModLoader.csproj b/OWML.ModLoader/OWML.ModLoader.csproj index feb210e44..82122e79d 100644 --- a/OWML.ModLoader/OWML.ModLoader.csproj +++ b/OWML.ModLoader/OWML.ModLoader.csproj @@ -104,8 +104,5 @@ - - - \ No newline at end of file diff --git a/OWML.ModLoader/Owo.cs b/OWML.ModLoader/Owo.cs index 69a95f41e..3ac2b67ab 100644 --- a/OWML.ModLoader/Owo.cs +++ b/OWML.ModLoader/Owo.cs @@ -45,8 +45,24 @@ public void LoadMods() var sortedMods = ModSorter.SortMods(mods); + var modNames = new List(); + foreach (var mod in mods) + { + if (mod.Config.Enabled == true) + { + modNames.Add(mod.Manifest.Name); + } + } + foreach (var modDep in sortedMods) { + foreach (var dep in modDep.Dependencies) + { + if (!modNames.Contains(dep) && dep != "None") + { + _console.WriteLine("Error! " + modDep.Name + " needs " + dep + ", but it's disabled!"); + } + } var modData = modDep.Data; var modType = LoadMod(modData); if (modType == null) From c02369f57b08ba316c9f6837c7e9a48131c1cf24 Mon Sep 17 00:00:00 2001 From: Mister_Nebula <41904486+misternebula@users.noreply.github.com> Date: Sun, 26 Apr 2020 20:18:51 +0100 Subject: [PATCH 10/36] Added more helper methods --- OWML.Common/IModInteraction.cs | 3 ++ OWML.Common/OWML.Common.csproj | 3 -- .../OWML.ModHelper.Assets.csproj | 3 -- .../OWML.ModHelper.Events.csproj | 3 -- OWML.ModHelper.Interaction/ModInteraction.cs | 35 +++++++++++++++++++ .../OWML.ModHelper.Interaction.csproj | 3 -- .../OWML.ModHelper.Menus.csproj | 3 -- OWML.ModHelper/OWML.ModHelper.csproj | 3 -- 8 files changed, 38 insertions(+), 18 deletions(-) diff --git a/OWML.Common/IModInteraction.cs b/OWML.Common/IModInteraction.cs index b59e05b0c..b1fe5fdc6 100644 --- a/OWML.Common/IModInteraction.cs +++ b/OWML.Common/IModInteraction.cs @@ -8,8 +8,11 @@ namespace OWML.Common public interface IModInteraction { IList GetMods(); + IList GetDependants(string dependencyName); bool ModExists(string uniqueName); T InvokeMethod(string uniqueName, string methodName, params object[] parameters); + void InvokeMethod(string uniqueName, string methodName, params object[] parameters); void SetVariableValue(string uniqueName, string variableName, object value); + T GetVariableValue(string uniqueName, string variableName); } } diff --git a/OWML.Common/OWML.Common.csproj b/OWML.Common/OWML.Common.csproj index eb82d290a..59fa3b1ca 100644 --- a/OWML.Common/OWML.Common.csproj +++ b/OWML.Common/OWML.Common.csproj @@ -107,8 +107,5 @@ - - - \ No newline at end of file diff --git a/OWML.ModHelper.Assets/OWML.ModHelper.Assets.csproj b/OWML.ModHelper.Assets/OWML.ModHelper.Assets.csproj index fc1e5939e..0cb35780c 100644 --- a/OWML.ModHelper.Assets/OWML.ModHelper.Assets.csproj +++ b/OWML.ModHelper.Assets/OWML.ModHelper.Assets.csproj @@ -94,8 +94,5 @@ - - - \ No newline at end of file diff --git a/OWML.ModHelper.Events/OWML.ModHelper.Events.csproj b/OWML.ModHelper.Events/OWML.ModHelper.Events.csproj index 7d1b123f8..21efc69ef 100644 --- a/OWML.ModHelper.Events/OWML.ModHelper.Events.csproj +++ b/OWML.ModHelper.Events/OWML.ModHelper.Events.csproj @@ -86,8 +86,5 @@ OWML.Common - - - \ No newline at end of file diff --git a/OWML.ModHelper.Interaction/ModInteraction.cs b/OWML.ModHelper.Interaction/ModInteraction.cs index 9baec8938..89306df16 100644 --- a/OWML.ModHelper.Interaction/ModInteraction.cs +++ b/OWML.ModHelper.Interaction/ModInteraction.cs @@ -9,10 +9,28 @@ public class ModInteraction : IModInteraction { private readonly List _modList = new List(); private readonly IModFinder _finder; + private readonly Dictionary> dependantDict = new Dictionary>(); + public ModInteraction(List list, IModFinder finder) { _modList = list; _finder = finder; + // Creates dictionary of key [Dependency] and value [Mods that depend on that dependency] + foreach (var mod in _finder.GetMods()) + { + List temp = new List(); + foreach (var mod2 in _finder.GetMods()) + { + if (mod2.Manifest.Dependencies != null) + { + if (mod2.Manifest.Dependencies.Contains(mod.Manifest.Name)) + { + temp.Add(mod2); + } + } + } + dependantDict.Add(mod, temp); + } } public IList GetMods() @@ -20,6 +38,11 @@ public IList GetMods() return _finder.GetMods(); } + public IList GetDependants(string dependencyName) + { + return dependantDict.Where(x => x.Key.Manifest.UniqueName == dependencyName).FirstOrDefault().Value; + } + public bool ModExists(string uniqueName) { return _finder.GetMods().Where(m => m.Manifest.UniqueName == uniqueName).Count() != 0; @@ -31,10 +54,22 @@ public T InvokeMethod(string uniqueName, string methodName, params object[] p return (T)mod.GetType().GetMethod(methodName).Invoke(mod, parameters); } + public void InvokeMethod(string uniqueName, string methodName, params object[] parameters) + { + var mod = _modList.Where(m => m.ModHelper.Manifest.UniqueName == uniqueName).First(); + mod.GetType().GetMethod(methodName).Invoke(mod, parameters); + } + public void SetVariableValue(string uniqueName, string variableName, object value) { var mod = _modList.Where(m => m.ModHelper.Manifest.UniqueName == uniqueName).First(); mod.GetType().SetValue(variableName, value); } + + public T GetVariableValue(string uniqueName, string variableName) + { + var mod = _modList.Where(m => m.ModHelper.Manifest.UniqueName == uniqueName).First(); + return mod.GetType().GetValue(variableName); + } } } diff --git a/OWML.ModHelper.Interaction/OWML.ModHelper.Interaction.csproj b/OWML.ModHelper.Interaction/OWML.ModHelper.Interaction.csproj index 30fb88bbc..9bfbd1642 100644 --- a/OWML.ModHelper.Interaction/OWML.ModHelper.Interaction.csproj +++ b/OWML.ModHelper.Interaction/OWML.ModHelper.Interaction.csproj @@ -83,9 +83,6 @@ OWML.ModHelper - - - diff --git a/OWML.ModHelper.Menus/OWML.ModHelper.Menus.csproj b/OWML.ModHelper.Menus/OWML.ModHelper.Menus.csproj index 7fc6d847c..8c33f2196 100644 --- a/OWML.ModHelper.Menus/OWML.ModHelper.Menus.csproj +++ b/OWML.ModHelper.Menus/OWML.ModHelper.Menus.csproj @@ -108,8 +108,5 @@ - - - \ No newline at end of file diff --git a/OWML.ModHelper/OWML.ModHelper.csproj b/OWML.ModHelper/OWML.ModHelper.csproj index 884cc7f92..bf2f66a0f 100644 --- a/OWML.ModHelper/OWML.ModHelper.csproj +++ b/OWML.ModHelper/OWML.ModHelper.csproj @@ -94,8 +94,5 @@ OWML.ModHelper.Events - - - \ No newline at end of file From 8eb9dfcad5451be595fa96ee7198495b3ceb23d0 Mon Sep 17 00:00:00 2001 From: Mister_Nebula <41904486+misternebula@users.noreply.github.com> Date: Sun, 26 Apr 2020 22:41:41 +0100 Subject: [PATCH 11/36] cleanup --- OWML.ModHelper.Interaction/ModInteraction.cs | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/OWML.ModHelper.Interaction/ModInteraction.cs b/OWML.ModHelper.Interaction/ModInteraction.cs index 89306df16..a67c95107 100644 --- a/OWML.ModHelper.Interaction/ModInteraction.cs +++ b/OWML.ModHelper.Interaction/ModInteraction.cs @@ -15,18 +15,15 @@ public ModInteraction(List list, IModFinder finder) { _modList = list; _finder = finder; - // Creates dictionary of key [Dependency] and value [Mods that depend on that dependency] + foreach (var mod in _finder.GetMods()) { List temp = new List(); foreach (var mod2 in _finder.GetMods()) { - if (mod2.Manifest.Dependencies != null) + if (mod2.Manifest.Dependencies != null && mod2.Manifest.Dependencies.Contains(mod.Manifest.Name)) { - if (mod2.Manifest.Dependencies.Contains(mod.Manifest.Name)) - { - temp.Add(mod2); - } + temp.Add(mod2); } } dependantDict.Add(mod, temp); From a16189ee0a32d198a78b444f1d4935d14ef7b895 Mon Sep 17 00:00:00 2001 From: Mister_Nebula <41904486+misternebula@users.noreply.github.com> Date: Mon, 27 Apr 2020 14:43:51 +0100 Subject: [PATCH 12/36] Clarify parameter name --- OWML.ModHelper.Interaction/ModInteraction.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/OWML.ModHelper.Interaction/ModInteraction.cs b/OWML.ModHelper.Interaction/ModInteraction.cs index a67c95107..7922a662b 100644 --- a/OWML.ModHelper.Interaction/ModInteraction.cs +++ b/OWML.ModHelper.Interaction/ModInteraction.cs @@ -35,9 +35,9 @@ public IList GetMods() return _finder.GetMods(); } - public IList GetDependants(string dependencyName) + public IList GetDependants(string dependencyUniqueName) { - return dependantDict.Where(x => x.Key.Manifest.UniqueName == dependencyName).FirstOrDefault().Value; + return dependantDict.Where(x => x.Key.Manifest.UniqueName == dependencyUniqueName).FirstOrDefault().Value; } public bool ModExists(string uniqueName) From d0a4fe1e7282818f7ceba2540aa0e4920f69b2d8 Mon Sep 17 00:00:00 2001 From: Mister_Nebula <41904486+misternebula@users.noreply.github.com> Date: Mon, 27 Apr 2020 14:48:23 +0100 Subject: [PATCH 13/36] Cleanup --- OWML.SampleMods/OWML.EnableDebugMode/manifest.json | 1 - OWML.SampleMods/OWML.EnableDebugMode/readme.txt | 2 -- .../OWML.LoadCustomAssets/OWML.LoadCustomAssets.csproj | 1 - OWML.SampleMods/OWML.LoadCustomAssets/readme.txt | 2 -- 4 files changed, 6 deletions(-) delete mode 100644 OWML.SampleMods/OWML.EnableDebugMode/readme.txt delete mode 100644 OWML.SampleMods/OWML.LoadCustomAssets/readme.txt diff --git a/OWML.SampleMods/OWML.EnableDebugMode/manifest.json b/OWML.SampleMods/OWML.EnableDebugMode/manifest.json index dfef39b3f..825827758 100644 --- a/OWML.SampleMods/OWML.EnableDebugMode/manifest.json +++ b/OWML.SampleMods/OWML.EnableDebugMode/manifest.json @@ -5,6 +5,5 @@ "uniqueName": "Alek.EnableDebugMode", "version": "0.2", "owmlVersion": "0.3.46", - "dependency": [ "LoadCustomAssets" ], "description": "Enables the debug mode in Outer Wilds" } \ No newline at end of file diff --git a/OWML.SampleMods/OWML.EnableDebugMode/readme.txt b/OWML.SampleMods/OWML.EnableDebugMode/readme.txt deleted file mode 100644 index d3d7dc6a3..000000000 --- a/OWML.SampleMods/OWML.EnableDebugMode/readme.txt +++ /dev/null @@ -1,2 +0,0 @@ -nuget pack -nuget.exe push -Source "OW" -ApiKey az OW.Unity.Dlls.1.0.0.1.nupkg \ No newline at end of file diff --git a/OWML.SampleMods/OWML.LoadCustomAssets/OWML.LoadCustomAssets.csproj b/OWML.SampleMods/OWML.LoadCustomAssets/OWML.LoadCustomAssets.csproj index 7f737895b..3e65f717f 100644 --- a/OWML.SampleMods/OWML.LoadCustomAssets/OWML.LoadCustomAssets.csproj +++ b/OWML.SampleMods/OWML.LoadCustomAssets/OWML.LoadCustomAssets.csproj @@ -99,7 +99,6 @@ Always - Always diff --git a/OWML.SampleMods/OWML.LoadCustomAssets/readme.txt b/OWML.SampleMods/OWML.LoadCustomAssets/readme.txt deleted file mode 100644 index d3d7dc6a3..000000000 --- a/OWML.SampleMods/OWML.LoadCustomAssets/readme.txt +++ /dev/null @@ -1,2 +0,0 @@ -nuget pack -nuget.exe push -Source "OW" -ApiKey az OW.Unity.Dlls.1.0.0.1.nupkg \ No newline at end of file From 3fbac47015284cc89dd2d69dd88caf6fba1d9bc4 Mon Sep 17 00:00:00 2001 From: Mister_Nebula <41904486+misternebula@users.noreply.github.com> Date: Mon, 27 Apr 2020 17:04:38 +0100 Subject: [PATCH 14/36] remove more readme.txts... --- .../OWML.EnableDebugMode/OWML.EnableDebugMode.csproj | 3 --- 1 file changed, 3 deletions(-) diff --git a/OWML.SampleMods/OWML.EnableDebugMode/OWML.EnableDebugMode.csproj b/OWML.SampleMods/OWML.EnableDebugMode/OWML.EnableDebugMode.csproj index 2ae09ea5c..a9080156c 100644 --- a/OWML.SampleMods/OWML.EnableDebugMode/OWML.EnableDebugMode.csproj +++ b/OWML.SampleMods/OWML.EnableDebugMode/OWML.EnableDebugMode.csproj @@ -93,9 +93,6 @@ OWML.ModHelper - - - From da62d3ab8486342de1111f9ac198c8939cd8f52c Mon Sep 17 00:00:00 2001 From: Mister_Nebula <41904486+misternebula@users.noreply.github.com> Date: Mon, 27 Apr 2020 18:04:41 +0100 Subject: [PATCH 15/36] Changes based on PR responses - Added null checker to method invoke - Split ModDep into seperate file - Made ModSorter non-static --- OWML.ModHelper.Interaction/ModInteraction.cs | 25 ++++++++++++++---- OWML.ModLoader/ModDep.cs | 23 +++++++++++++++++ OWML.ModLoader/ModLoader.cs | 3 ++- OWML.ModLoader/ModSorter.cs | 27 +++++--------------- OWML.ModLoader/Owo.cs | 6 +++-- 5 files changed, 55 insertions(+), 29 deletions(-) create mode 100644 OWML.ModLoader/ModDep.cs diff --git a/OWML.ModHelper.Interaction/ModInteraction.cs b/OWML.ModHelper.Interaction/ModInteraction.cs index 7922a662b..dd23999ad 100644 --- a/OWML.ModHelper.Interaction/ModInteraction.cs +++ b/OWML.ModHelper.Interaction/ModInteraction.cs @@ -30,6 +30,11 @@ public ModInteraction(List list, IModFinder finder) } } + private ModBehaviour GetModFromName(string uniqueName) + { + return _modList.First(m => m.ModHelper.Manifest.UniqueName == uniqueName); + } + public IList GetMods() { return _finder.GetMods(); @@ -42,30 +47,40 @@ public IList GetDependants(string dependencyUniqueName) public bool ModExists(string uniqueName) { - return _finder.GetMods().Where(m => m.Manifest.UniqueName == uniqueName).Count() != 0; + return _finder.GetMods().Count(m => m.Manifest.UniqueName == uniqueName) != 0; } public T InvokeMethod(string uniqueName, string methodName, params object[] parameters) { - var mod = _modList.Where(m => m.ModHelper.Manifest.UniqueName == uniqueName).First(); + var mod = GetModFromName(uniqueName); + if (mod.GetType().GetMethod(methodName) == null) + { + ModConsole.Instance.WriteLine("Tried to invoke method " + methodName + " in mod " + uniqueName + " but it could not be found."); + return default; + } return (T)mod.GetType().GetMethod(methodName).Invoke(mod, parameters); } public void InvokeMethod(string uniqueName, string methodName, params object[] parameters) { - var mod = _modList.Where(m => m.ModHelper.Manifest.UniqueName == uniqueName).First(); + var mod = GetModFromName(uniqueName); + if (mod.GetType().GetMethod(methodName) == null) + { + ModConsole.Instance.WriteLine("Tried to invoke method " + methodName + " in mod " + uniqueName + " but it could not be found."); + return; + } mod.GetType().GetMethod(methodName).Invoke(mod, parameters); } public void SetVariableValue(string uniqueName, string variableName, object value) { - var mod = _modList.Where(m => m.ModHelper.Manifest.UniqueName == uniqueName).First(); + var mod = GetModFromName(uniqueName); mod.GetType().SetValue(variableName, value); } public T GetVariableValue(string uniqueName, string variableName) { - var mod = _modList.Where(m => m.ModHelper.Manifest.UniqueName == uniqueName).First(); + var mod = GetModFromName(uniqueName); return mod.GetType().GetValue(variableName); } } diff --git a/OWML.ModLoader/ModDep.cs b/OWML.ModLoader/ModDep.cs new file mode 100644 index 000000000..2df954ce0 --- /dev/null +++ b/OWML.ModLoader/ModDep.cs @@ -0,0 +1,23 @@ +using OWML.Common; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace OWML.ModLoader +{ + public class ModDep + { + public string Name { get; private set; } + public string[] Dependencies { get; private set; } + + public IModData Data { get; private set; } + + public ModDep(string name, IModData data, params string[] dependencies) + { + Name = name; + Data = data; + Dependencies = dependencies; + } + } +} diff --git a/OWML.ModLoader/ModLoader.cs b/OWML.ModLoader/ModLoader.cs index 60951195e..63eb6036d 100644 --- a/OWML.ModLoader/ModLoader.cs +++ b/OWML.ModLoader/ModLoader.cs @@ -28,11 +28,12 @@ public static void LoadMods() logger.Log("Got config!"); var console = new ModConsole(owmlConfig, logger, owmlManifest); console.WriteLine("Mod loader has been initialized."); + var modSorter = new ModSorter(); var modFinder = new ModFinder(owmlConfig, console); var harmonyHelper = new HarmonyHelper(logger, console); var events = new ModEvents(logger, console, harmonyHelper); var menus = new ModMenus(logger, console, events); - var owo = new Owo(modFinder, logger, console, owmlConfig, menus, harmonyHelper); + var owo = new Owo(modFinder, logger, console, owmlConfig, menus, harmonyHelper, modSorter); owo.LoadMods(); } diff --git a/OWML.ModLoader/ModSorter.cs b/OWML.ModLoader/ModSorter.cs index 85673b4c6..5b053d35b 100644 --- a/OWML.ModLoader/ModSorter.cs +++ b/OWML.ModLoader/ModSorter.cs @@ -7,9 +7,9 @@ namespace OWML.ModLoader { class ModSorter { - public static IList SortMods(IList mods) + public IList SortMods(IList mods) { - List modList = new List(); + var modList = new List(); foreach (var mod in mods) { if (mod.Manifest.Dependencies == null) @@ -30,7 +30,7 @@ public static IList SortMods(IList mods) return Sort(modList, x => x.Dependencies, x => x.Name); } - private static IList Sort(IEnumerable source, Func> getDependencies) + private IList Sort(IEnumerable source, Func> getDependencies) { var sorted = new List(); var visited = new Dictionary(); @@ -43,7 +43,7 @@ private static IList Sort(IEnumerable source, Func> g return sorted; } - private static void Visit(T item, Func> getDependencies, List sorted, Dictionary visited) + private void Visit(T item, Func> getDependencies, List sorted, Dictionary visited) { var alreadyVisited = visited.TryGetValue(item, out bool inProcess); @@ -72,7 +72,7 @@ private static void Visit(T item, Func> getDependencies, Li } } - private static Func> RemapDependencies(IEnumerable source, Func> getDependencies, Func getKey) + private Func> RemapDependencies(IEnumerable source, Func> getDependencies, Func getKey) { var map = source.ToDictionary(getKey); return item => @@ -82,24 +82,9 @@ private static Func> RemapDependencies(IEnumerable }; } - private static IList Sort(IEnumerable source, Func> getDependencies, Func getKey) + private IList Sort(IEnumerable source, Func> getDependencies, Func getKey) { return Sort(source, RemapDependencies(source, getDependencies, getKey)); } } - - public class ModDep - { - public string Name { get; private set; } - public string[] Dependencies { get; private set; } - - public IModData Data { get; private set; } - - public ModDep(string name, IModData data, params string[] dependencies) - { - Name = name; - Data = data; - Dependencies = dependencies; - } - } } diff --git a/OWML.ModLoader/Owo.cs b/OWML.ModLoader/Owo.cs index 3ac2b67ab..829722aa5 100644 --- a/OWML.ModLoader/Owo.cs +++ b/OWML.ModLoader/Owo.cs @@ -20,11 +20,12 @@ internal class Owo private readonly IOwmlConfig _owmlConfig; private readonly IModMenus _menus; private readonly IHarmonyHelper _harmonyHelper; + private readonly ModSorter _sorter; List _modList = new List(); public Owo(IModFinder modFinder, IModLogger logger, IModConsole console, - IOwmlConfig owmlConfig, IModMenus menus, IHarmonyHelper harmonyHelper) + IOwmlConfig owmlConfig, IModMenus menus, IHarmonyHelper harmonyHelper, ModSorter sorter) { _modFinder = modFinder; _logger = logger; @@ -32,6 +33,7 @@ public Owo(IModFinder modFinder, IModLogger logger, IModConsole console, _owmlConfig = owmlConfig; _menus = menus; _harmonyHelper = harmonyHelper; + _sorter = sorter; } public void LoadMods() @@ -43,7 +45,7 @@ public void LoadMods() } var mods = _modFinder.GetMods(); - var sortedMods = ModSorter.SortMods(mods); + var sortedMods = _sorter.SortMods(mods); var modNames = new List(); foreach (var mod in mods) From d910e72b9467ebcd0861baf66d45ebce82ad3960 Mon Sep 17 00:00:00 2001 From: Mister_Nebula <41904486+misternebula@users.noreply.github.com> Date: Mon, 27 Apr 2020 19:04:39 +0100 Subject: [PATCH 16/36] Refactor - Removed invoke and set/get value, as they already exist... - Added GetDependants() to ModBehaviour - Added GetMod() to make mods simpler, with interface counterpart. - Added a return-able version of Invoke. --- OWML.Common/IModBehaviour.cs | 6 ++- OWML.Common/IModInteraction.cs | 8 ++- OWML.ModHelper.Events/TypeExtensions.cs | 6 +++ OWML.ModHelper.Interaction/ModInteraction.cs | 54 +++++--------------- OWML.ModHelper/ModBehaviour.cs | 6 +++ OWML.ModLoader/OWML.ModLoader.csproj | 1 + 6 files changed, 34 insertions(+), 47 deletions(-) diff --git a/OWML.Common/IModBehaviour.cs b/OWML.Common/IModBehaviour.cs index 2623d27d3..8b1603a46 100644 --- a/OWML.Common/IModBehaviour.cs +++ b/OWML.Common/IModBehaviour.cs @@ -1,8 +1,12 @@ -namespace OWML.Common +using System.Collections.Generic; + +namespace OWML.Common { public interface IModBehaviour { IModHelper ModHelper { get; } void Configure(IModConfig config); + + List GetDependants(); } } diff --git a/OWML.Common/IModInteraction.cs b/OWML.Common/IModInteraction.cs index b1fe5fdc6..4a5ca886d 100644 --- a/OWML.Common/IModInteraction.cs +++ b/OWML.Common/IModInteraction.cs @@ -8,11 +8,9 @@ namespace OWML.Common public interface IModInteraction { IList GetMods(); - IList GetDependants(string dependencyName); + List GetDependants(string dependencyUniqueName); + IModBehaviour GetMod(string uniqueName); + T GetMod(string uniqueName) where T : IModBehaviour; bool ModExists(string uniqueName); - T InvokeMethod(string uniqueName, string methodName, params object[] parameters); - void InvokeMethod(string uniqueName, string methodName, params object[] parameters); - void SetVariableValue(string uniqueName, string variableName, object value); - T GetVariableValue(string uniqueName, string variableName); } } diff --git a/OWML.ModHelper.Events/TypeExtensions.cs b/OWML.ModHelper.Events/TypeExtensions.cs index b4684f378..73c108f1b 100644 --- a/OWML.ModHelper.Events/TypeExtensions.cs +++ b/OWML.ModHelper.Events/TypeExtensions.cs @@ -67,5 +67,11 @@ public static void Invoke(this object obj, string name, params object[] paramete method?.Invoke(obj, parameters); } + public static T Invoke(this object obj, string name, params object[] parameters) + { + var type = obj.GetType(); + var method = type.GetAnyMethod(name); + return (T)method?.Invoke(obj, parameters); + } } } \ No newline at end of file diff --git a/OWML.ModHelper.Interaction/ModInteraction.cs b/OWML.ModHelper.Interaction/ModInteraction.cs index dd23999ad..486e9c5c3 100644 --- a/OWML.ModHelper.Interaction/ModInteraction.cs +++ b/OWML.ModHelper.Interaction/ModInteraction.cs @@ -9,7 +9,7 @@ public class ModInteraction : IModInteraction { private readonly List _modList = new List(); private readonly IModFinder _finder; - private readonly Dictionary> dependantDict = new Dictionary>(); + private readonly Dictionary> _dependantDict = new Dictionary>(); public ModInteraction(List list, IModFinder finder) { @@ -26,62 +26,34 @@ public ModInteraction(List list, IModFinder finder) temp.Add(mod2); } } - dependantDict.Add(mod, temp); + _dependantDict.Add(mod, temp); } } - private ModBehaviour GetModFromName(string uniqueName) + public List GetDependants(string dependencyUniqueName) { - return _modList.First(m => m.ModHelper.Manifest.UniqueName == uniqueName); - } - - public IList GetMods() - { - return _finder.GetMods(); + return _dependantDict.Where(x => x.Key.Manifest.UniqueName == dependencyUniqueName).FirstOrDefault().Value; } - public IList GetDependants(string dependencyUniqueName) + public IModBehaviour GetMod(string uniqueName) { - return dependantDict.Where(x => x.Key.Manifest.UniqueName == dependencyUniqueName).FirstOrDefault().Value; - } - - public bool ModExists(string uniqueName) - { - return _finder.GetMods().Count(m => m.Manifest.UniqueName == uniqueName) != 0; - } - - public T InvokeMethod(string uniqueName, string methodName, params object[] parameters) - { - var mod = GetModFromName(uniqueName); - if (mod.GetType().GetMethod(methodName) == null) - { - ModConsole.Instance.WriteLine("Tried to invoke method " + methodName + " in mod " + uniqueName + " but it could not be found."); - return default; - } - return (T)mod.GetType().GetMethod(methodName).Invoke(mod, parameters); + return _modList.First(m => m.ModHelper.Manifest.UniqueName == uniqueName); } - public void InvokeMethod(string uniqueName, string methodName, params object[] parameters) + public T GetMod(string uniqueName) where T : IModBehaviour { - var mod = GetModFromName(uniqueName); - if (mod.GetType().GetMethod(methodName) == null) - { - ModConsole.Instance.WriteLine("Tried to invoke method " + methodName + " in mod " + uniqueName + " but it could not be found."); - return; - } - mod.GetType().GetMethod(methodName).Invoke(mod, parameters); + var mod = GetMod(uniqueName); + return (T)mod; } - public void SetVariableValue(string uniqueName, string variableName, object value) + public IList GetMods() { - var mod = GetModFromName(uniqueName); - mod.GetType().SetValue(variableName, value); + return _finder.GetMods(); } - public T GetVariableValue(string uniqueName, string variableName) + public bool ModExists(string uniqueName) { - var mod = GetModFromName(uniqueName); - return mod.GetType().GetValue(variableName); + return _finder.GetMods().Count(m => m.Manifest.UniqueName == uniqueName) != 0; } } } diff --git a/OWML.ModHelper/ModBehaviour.cs b/OWML.ModHelper/ModBehaviour.cs index e71d1f89c..d7a09fa49 100644 --- a/OWML.ModHelper/ModBehaviour.cs +++ b/OWML.ModHelper/ModBehaviour.cs @@ -1,4 +1,6 @@ using OWML.Common; +using OWML.ModHelper.Events; +using System.Collections.Generic; using UnityEngine; namespace OWML.ModHelper @@ -18,5 +20,9 @@ public virtual void Configure(IModConfig config) { } + public List GetDependants() + { + return ModHelper.ModInteraction.GetDependants(ModHelper.Manifest.UniqueName); + } } } diff --git a/OWML.ModLoader/OWML.ModLoader.csproj b/OWML.ModLoader/OWML.ModLoader.csproj index 82122e79d..fe5873ca9 100644 --- a/OWML.ModLoader/OWML.ModLoader.csproj +++ b/OWML.ModLoader/OWML.ModLoader.csproj @@ -69,6 +69,7 @@ + From e92ffefde8ad8a6c649f9240c7f59fef460df6ff Mon Sep 17 00:00:00 2001 From: Mister_Nebula <41904486+misternebula@users.noreply.github.com> Date: Mon, 27 Apr 2020 19:54:25 +0100 Subject: [PATCH 17/36] Responses to PR - Changed ModInteraction to Interaction - Removed "None" feature of dependencies --- OWML.Common/IModHelper.cs | 2 +- OWML.Common/IModManifest.cs | 2 -- OWML.ModHelper/ModBehaviour.cs | 2 +- OWML.ModHelper/ModHelper.cs | 4 ++-- OWML.ModHelper/ModManifest.cs | 7 +------ OWML.ModLoader/ModSorter.cs | 14 +------------- OWML.ModLoader/Owo.cs | 16 +++------------- 7 files changed, 9 insertions(+), 38 deletions(-) diff --git a/OWML.Common/IModHelper.cs b/OWML.Common/IModHelper.cs index 7de23a2f4..fa1f15bd8 100644 --- a/OWML.Common/IModHelper.cs +++ b/OWML.Common/IModHelper.cs @@ -14,6 +14,6 @@ public interface IModHelper IModManifest Manifest { get; } IModConfig Config { get; } IOwmlConfig OwmlConfig { get; } - IModInteraction ModInteraction { get; } + IModInteraction Interaction { get; } } } diff --git a/OWML.Common/IModManifest.cs b/OWML.Common/IModManifest.cs index 3332542a8..9863d5566 100644 --- a/OWML.Common/IModManifest.cs +++ b/OWML.Common/IModManifest.cs @@ -14,7 +14,5 @@ public interface IModManifest string ModFolderPath { get; set; } Dictionary AppIds { get; } string[] Dependencies { get; } - - void SetDependencies(params string[] dependencies); } } diff --git a/OWML.ModHelper/ModBehaviour.cs b/OWML.ModHelper/ModBehaviour.cs index d7a09fa49..09f85b488 100644 --- a/OWML.ModHelper/ModBehaviour.cs +++ b/OWML.ModHelper/ModBehaviour.cs @@ -22,7 +22,7 @@ public virtual void Configure(IModConfig config) public List GetDependants() { - return ModHelper.ModInteraction.GetDependants(ModHelper.Manifest.UniqueName); + return ModHelper.Interaction.GetDependants(ModHelper.Manifest.UniqueName); } } } diff --git a/OWML.ModHelper/ModHelper.cs b/OWML.ModHelper/ModHelper.cs index 0ccf013df..8c89c2b1e 100644 --- a/OWML.ModHelper/ModHelper.cs +++ b/OWML.ModHelper/ModHelper.cs @@ -16,7 +16,7 @@ public class ModHelper : IModHelper public IModManifest Manifest { get; } public IModConfig Config { get; } public IOwmlConfig OwmlConfig { get; } - public IModInteraction ModInteraction { get; } + public IModInteraction Interaction { get; } public ModHelper(IModLogger logger, IModConsole console, IHarmonyHelper harmonyHelper, IModEvents events, IModAssets assets, IModStorage storage, IModMenus menus, IModManifest manifest, IModConfig config, IOwmlConfig owmlConfig, IModInteraction interaction) @@ -31,7 +31,7 @@ public ModHelper(IModLogger logger, IModConsole console, IHarmonyHelper harmonyH Manifest = manifest; Config = config; OwmlConfig = owmlConfig; - ModInteraction = interaction; + Interaction = interaction; } } diff --git a/OWML.ModHelper/ModManifest.cs b/OWML.ModHelper/ModManifest.cs index a2246e0c5..f8a386cf4 100644 --- a/OWML.ModHelper/ModManifest.cs +++ b/OWML.ModHelper/ModManifest.cs @@ -25,7 +25,7 @@ public class ModManifest : IModManifest public string OWMLVersion { get; private set; } [JsonProperty("dependencies")] - public string[] Dependencies { get; private set; } + public string[] Dependencies { get; private set; } = new string[] { }; [JsonIgnore] public string ModFolderPath { get; set; } @@ -35,10 +35,5 @@ public class ModManifest : IModManifest [JsonIgnore] public string AssemblyPath => ModFolderPath + Filename; - - public void SetDependencies(params string[] dependencies) - { - Dependencies = dependencies; - } } } diff --git a/OWML.ModLoader/ModSorter.cs b/OWML.ModLoader/ModSorter.cs index 5b053d35b..11cbd61f8 100644 --- a/OWML.ModLoader/ModSorter.cs +++ b/OWML.ModLoader/ModSorter.cs @@ -12,19 +12,7 @@ public IList SortMods(IList mods) var modList = new List(); foreach (var mod in mods) { - if (mod.Manifest.Dependencies == null) - { - mod.Manifest.SetDependencies(new[] { "None" }); - } - - if (mod.Manifest.Dependencies.First() != "None") - { - modList.Add(new ModDep(mod.Manifest.Name, mod, mod.Manifest.Dependencies)); - } - else - { - modList.Add(new ModDep(mod.Manifest.Name, mod)); - } + modList.Add(new ModDep(mod.Manifest.Name, mod, mod.Manifest.Dependencies)); } return Sort(modList, x => x.Dependencies, x => x.Name); diff --git a/OWML.ModLoader/Owo.cs b/OWML.ModLoader/Owo.cs index 829722aa5..721f9b80e 100644 --- a/OWML.ModLoader/Owo.cs +++ b/OWML.ModLoader/Owo.cs @@ -44,25 +44,15 @@ public void LoadMods() Application.logMessageReceived += OnLogMessageReceived; } var mods = _modFinder.GetMods(); - var sortedMods = _sorter.SortMods(mods); - - var modNames = new List(); - foreach (var mod in mods) - { - if (mod.Config.Enabled == true) - { - modNames.Add(mod.Manifest.Name); - } - } - + var modNames = mods.Where(mod => mod.Config.Enabled).Select(mod => mod.Manifest.Name); foreach (var modDep in sortedMods) { foreach (var dep in modDep.Dependencies) { - if (!modNames.Contains(dep) && dep != "None") + if (!modNames.Contains(dep)) { - _console.WriteLine("Error! " + modDep.Name + " needs " + dep + ", but it's disabled!"); + _console.WriteLine($"Error! {modDep.Name} needs {dep}, but it's disabled!"); } } var modData = modDep.Data; From 3be8de33eb9bb2b2e2771856b58ff83b2ef3dbdd Mon Sep 17 00:00:00 2001 From: Mister_Nebula <41904486+misternebula@users.noreply.github.com> Date: Mon, 27 Apr 2020 20:48:42 +0100 Subject: [PATCH 18/36] Change most IModData to IModBehaviour, remove unneeded references --- OWML.Common/IModBehaviour.cs | 3 +- OWML.Common/IModInteraction.cs | 4 +-- OWML.Common/OWML.Common.csproj | 4 --- OWML.Common/packages.config | 1 - OWML.Launcher/packages.config | 2 +- .../OWML.ModHelper.Assets.csproj | 3 -- OWML.ModHelper.Assets/packages.config | 1 - .../OWML.ModHelper.Events.csproj | 3 -- OWML.ModHelper.Events/packages.config | 1 - OWML.ModHelper.Interaction/ModInteraction.cs | 28 +++++++++---------- OWML.ModHelper/ModBehaviour.cs | 2 +- OWML.ModLoader/Owo.cs | 2 +- .../OWML.EnableDebugMode.csproj | 3 -- .../OWML.EnableDebugMode/packages.config | 1 - .../OWML.LoadCustomAssets.csproj | 3 -- .../OWML.LoadCustomAssets/packages.config | 1 - 16 files changed, 19 insertions(+), 43 deletions(-) diff --git a/OWML.Common/IModBehaviour.cs b/OWML.Common/IModBehaviour.cs index 8b1603a46..e470cd7ce 100644 --- a/OWML.Common/IModBehaviour.cs +++ b/OWML.Common/IModBehaviour.cs @@ -6,7 +6,6 @@ public interface IModBehaviour { IModHelper ModHelper { get; } void Configure(IModConfig config); - - List GetDependants(); + IList GetDependants(); } } diff --git a/OWML.Common/IModInteraction.cs b/OWML.Common/IModInteraction.cs index 4a5ca886d..e58c7b673 100644 --- a/OWML.Common/IModInteraction.cs +++ b/OWML.Common/IModInteraction.cs @@ -7,8 +7,8 @@ namespace OWML.Common { public interface IModInteraction { - IList GetMods(); - List GetDependants(string dependencyUniqueName); + IList GetMods(); + IList GetDependants(string dependencyUniqueName); IModBehaviour GetMod(string uniqueName); T GetMod(string uniqueName) where T : IModBehaviour; bool ModExists(string uniqueName); diff --git a/OWML.Common/OWML.Common.csproj b/OWML.Common/OWML.Common.csproj index 59fa3b1ca..6269eed8c 100644 --- a/OWML.Common/OWML.Common.csproj +++ b/OWML.Common/OWML.Common.csproj @@ -35,13 +35,9 @@ ..\packages\OW.Unity.Dlls.1.0.4\lib\net35\Assembly-CSharp.dll - - ..\packages\Json.Net.Unity3D.9.0.1\lib\net35\Newtonsoft.Json.dll - ..\packages\OW.Unity.Dlls.1.0.4\lib\net35\OW.Unity.Dlls.dll - ..\packages\OW.Unity.Dlls.1.0.4\lib\net35\UnityEngine.dll diff --git a/OWML.Common/packages.config b/OWML.Common/packages.config index 074e374a8..8288b7a49 100644 --- a/OWML.Common/packages.config +++ b/OWML.Common/packages.config @@ -1,5 +1,4 @@  - \ No newline at end of file diff --git a/OWML.Launcher/packages.config b/OWML.Launcher/packages.config index eceb5e431..8ab0a407c 100644 --- a/OWML.Launcher/packages.config +++ b/OWML.Launcher/packages.config @@ -1,4 +1,4 @@  - + \ No newline at end of file diff --git a/OWML.ModHelper.Assets/OWML.ModHelper.Assets.csproj b/OWML.ModHelper.Assets/OWML.ModHelper.Assets.csproj index 0cb35780c..7178b702e 100644 --- a/OWML.ModHelper.Assets/OWML.ModHelper.Assets.csproj +++ b/OWML.ModHelper.Assets/OWML.ModHelper.Assets.csproj @@ -39,9 +39,6 @@ NAudio-Unity\NAudio-Unity.dll - - ..\packages\Json.Net.Unity3D.9.0.1\lib\net35\Newtonsoft.Json.dll - ..\packages\OW.Unity.Dlls.1.0.4\lib\net35\OW.Unity.Dlls.dll diff --git a/OWML.ModHelper.Assets/packages.config b/OWML.ModHelper.Assets/packages.config index 074e374a8..8288b7a49 100644 --- a/OWML.ModHelper.Assets/packages.config +++ b/OWML.ModHelper.Assets/packages.config @@ -1,5 +1,4 @@  - \ No newline at end of file diff --git a/OWML.ModHelper.Events/OWML.ModHelper.Events.csproj b/OWML.ModHelper.Events/OWML.ModHelper.Events.csproj index 21efc69ef..aa6000d1b 100644 --- a/OWML.ModHelper.Events/OWML.ModHelper.Events.csproj +++ b/OWML.ModHelper.Events/OWML.ModHelper.Events.csproj @@ -38,9 +38,6 @@ ..\packages\OW.Unity.Dlls.1.0.4\lib\net35\Assembly-CSharp.dll - - ..\packages\Json.Net.Unity3D.9.0.1\lib\net35\Newtonsoft.Json.dll - ..\packages\OW.Unity.Dlls.1.0.4\lib\net35\OW.Unity.Dlls.dll diff --git a/OWML.ModHelper.Events/packages.config b/OWML.ModHelper.Events/packages.config index 5f0a66ab7..2dec3d558 100644 --- a/OWML.ModHelper.Events/packages.config +++ b/OWML.ModHelper.Events/packages.config @@ -1,6 +1,5 @@  - \ No newline at end of file diff --git a/OWML.ModHelper.Interaction/ModInteraction.cs b/OWML.ModHelper.Interaction/ModInteraction.cs index 486e9c5c3..faae54192 100644 --- a/OWML.ModHelper.Interaction/ModInteraction.cs +++ b/OWML.ModHelper.Interaction/ModInteraction.cs @@ -8,31 +8,29 @@ namespace OWML.ModHelper.Interaction public class ModInteraction : IModInteraction { private readonly List _modList = new List(); - private readonly IModFinder _finder; - private readonly Dictionary> _dependantDict = new Dictionary>(); + private readonly Dictionary> _dependantDict = new Dictionary>(); - public ModInteraction(List list, IModFinder finder) + public ModInteraction(List list) { _modList = list; - _finder = finder; - foreach (var mod in _finder.GetMods()) + foreach (var mod in _modList) { - List temp = new List(); - foreach (var mod2 in _finder.GetMods()) + var dependants = new List(); + foreach (var dependency in _modList) { - if (mod2.Manifest.Dependencies != null && mod2.Manifest.Dependencies.Contains(mod.Manifest.Name)) + if (dependency.ModHelper.Manifest.Dependencies != new string[] { } && dependency.ModHelper.Manifest.Dependencies.Contains(mod.ModHelper.Manifest.Name)) { - temp.Add(mod2); + dependants.Add(dependency); } } - _dependantDict.Add(mod, temp); + _dependantDict.Add(mod, dependants); } } - public List GetDependants(string dependencyUniqueName) + public IList GetDependants(string dependencyUniqueName) { - return _dependantDict.Where(x => x.Key.Manifest.UniqueName == dependencyUniqueName).FirstOrDefault().Value; + return _dependantDict.Where(x => x.Key.ModHelper.Manifest.UniqueName == dependencyUniqueName).FirstOrDefault().Value; } public IModBehaviour GetMod(string uniqueName) @@ -46,14 +44,14 @@ public T GetMod(string uniqueName) where T : IModBehaviour return (T)mod; } - public IList GetMods() + public IList GetMods() { - return _finder.GetMods(); + return _modList as IList; } public bool ModExists(string uniqueName) { - return _finder.GetMods().Count(m => m.Manifest.UniqueName == uniqueName) != 0; + return _modList.Count(m => m.ModHelper.Manifest.UniqueName == uniqueName) != 0; } } } diff --git a/OWML.ModHelper/ModBehaviour.cs b/OWML.ModHelper/ModBehaviour.cs index 09f85b488..ce677c389 100644 --- a/OWML.ModHelper/ModBehaviour.cs +++ b/OWML.ModHelper/ModBehaviour.cs @@ -20,7 +20,7 @@ public virtual void Configure(IModConfig config) { } - public List GetDependants() + public IList GetDependants() { return ModHelper.Interaction.GetDependants(ModHelper.Manifest.UniqueName); } diff --git a/OWML.ModLoader/Owo.cs b/OWML.ModLoader/Owo.cs index 721f9b80e..62ccbfb44 100644 --- a/OWML.ModLoader/Owo.cs +++ b/OWML.ModLoader/Owo.cs @@ -106,7 +106,7 @@ private IModHelper CreateModHelper(IModData modData) var assets = new ModAssets(console, modData.Manifest); var storage = new ModStorage(console, modData.Manifest); var events = new ModEvents(logger, console, _harmonyHelper); - var interaction = new ModInteraction(_modList, _modFinder); + var interaction = new ModInteraction(_modList); return new ModHelper.ModHelper(logger, console, _harmonyHelper, events, assets, storage, _menus, modData.Manifest, modData.Config, _owmlConfig, interaction); } diff --git a/OWML.SampleMods/OWML.EnableDebugMode/OWML.EnableDebugMode.csproj b/OWML.SampleMods/OWML.EnableDebugMode/OWML.EnableDebugMode.csproj index a9080156c..5dc3f8726 100644 --- a/OWML.SampleMods/OWML.EnableDebugMode/OWML.EnableDebugMode.csproj +++ b/OWML.SampleMods/OWML.EnableDebugMode/OWML.EnableDebugMode.csproj @@ -34,9 +34,6 @@ ..\..\packages\OW.Unity.Dlls.1.0.4\lib\net35\Assembly-CSharp.dll - - ..\..\packages\Json.Net.Unity3D.9.0.1\lib\net35\Newtonsoft.Json.dll - ..\..\packages\OW.Unity.Dlls.1.0.4\lib\net35\OW.Unity.Dlls.dll diff --git a/OWML.SampleMods/OWML.EnableDebugMode/packages.config b/OWML.SampleMods/OWML.EnableDebugMode/packages.config index 074e374a8..8288b7a49 100644 --- a/OWML.SampleMods/OWML.EnableDebugMode/packages.config +++ b/OWML.SampleMods/OWML.EnableDebugMode/packages.config @@ -1,5 +1,4 @@  - \ No newline at end of file diff --git a/OWML.SampleMods/OWML.LoadCustomAssets/OWML.LoadCustomAssets.csproj b/OWML.SampleMods/OWML.LoadCustomAssets/OWML.LoadCustomAssets.csproj index 3e65f717f..0f031eab6 100644 --- a/OWML.SampleMods/OWML.LoadCustomAssets/OWML.LoadCustomAssets.csproj +++ b/OWML.SampleMods/OWML.LoadCustomAssets/OWML.LoadCustomAssets.csproj @@ -34,9 +34,6 @@ ..\..\packages\OW.Unity.Dlls.1.0.4\lib\net35\Assembly-CSharp.dll - - ..\..\packages\Json.Net.Unity3D.9.0.1\lib\net35\Newtonsoft.Json.dll - ..\..\packages\OW.Unity.Dlls.1.0.4\lib\net35\OW.Unity.Dlls.dll diff --git a/OWML.SampleMods/OWML.LoadCustomAssets/packages.config b/OWML.SampleMods/OWML.LoadCustomAssets/packages.config index 074e374a8..8288b7a49 100644 --- a/OWML.SampleMods/OWML.LoadCustomAssets/packages.config +++ b/OWML.SampleMods/OWML.LoadCustomAssets/packages.config @@ -1,5 +1,4 @@  - \ No newline at end of file From 12ba6942b3502d8535c184d57140eed13b1e7122 Mon Sep 17 00:00:00 2001 From: Mister_Nebula <41904486+misternebula@users.noreply.github.com> Date: Tue, 28 Apr 2020 11:38:50 +0100 Subject: [PATCH 19/36] Updated manifest dependencies to use uniqueName --- OWML.ModLoader/ModSorter.cs | 2 +- OWML.ModLoader/Owo.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/OWML.ModLoader/ModSorter.cs b/OWML.ModLoader/ModSorter.cs index 11cbd61f8..fbde2eabf 100644 --- a/OWML.ModLoader/ModSorter.cs +++ b/OWML.ModLoader/ModSorter.cs @@ -12,7 +12,7 @@ public IList SortMods(IList mods) var modList = new List(); foreach (var mod in mods) { - modList.Add(new ModDep(mod.Manifest.Name, mod, mod.Manifest.Dependencies)); + modList.Add(new ModDep(mod.Manifest.UniqueName, mod, mod.Manifest.Dependencies)); } return Sort(modList, x => x.Dependencies, x => x.Name); diff --git a/OWML.ModLoader/Owo.cs b/OWML.ModLoader/Owo.cs index 62ccbfb44..4d6e3c294 100644 --- a/OWML.ModLoader/Owo.cs +++ b/OWML.ModLoader/Owo.cs @@ -45,7 +45,7 @@ public void LoadMods() } var mods = _modFinder.GetMods(); var sortedMods = _sorter.SortMods(mods); - var modNames = mods.Where(mod => mod.Config.Enabled).Select(mod => mod.Manifest.Name); + var modNames = mods.Where(mod => mod.Config.Enabled).Select(mod => mod.Manifest.UniqueName); foreach (var modDep in sortedMods) { foreach (var dep in modDep.Dependencies) From 4ef71247bd2b11acb347e9c9dbdc66354368b499 Mon Sep 17 00:00:00 2001 From: Mister_Nebula <41904486+misternebula@users.noreply.github.com> Date: Tue, 28 Apr 2020 11:40:25 +0100 Subject: [PATCH 20/36] Added missing reference --- .../OWML.LoadCustomAssets/OWML.LoadCustomAssets.csproj | 3 +++ OWML.SampleMods/OWML.LoadCustomAssets/packages.config | 1 + 2 files changed, 4 insertions(+) diff --git a/OWML.SampleMods/OWML.LoadCustomAssets/OWML.LoadCustomAssets.csproj b/OWML.SampleMods/OWML.LoadCustomAssets/OWML.LoadCustomAssets.csproj index 0f031eab6..3e65f717f 100644 --- a/OWML.SampleMods/OWML.LoadCustomAssets/OWML.LoadCustomAssets.csproj +++ b/OWML.SampleMods/OWML.LoadCustomAssets/OWML.LoadCustomAssets.csproj @@ -34,6 +34,9 @@ ..\..\packages\OW.Unity.Dlls.1.0.4\lib\net35\Assembly-CSharp.dll + + ..\..\packages\Json.Net.Unity3D.9.0.1\lib\net35\Newtonsoft.Json.dll + ..\..\packages\OW.Unity.Dlls.1.0.4\lib\net35\OW.Unity.Dlls.dll diff --git a/OWML.SampleMods/OWML.LoadCustomAssets/packages.config b/OWML.SampleMods/OWML.LoadCustomAssets/packages.config index 8288b7a49..074e374a8 100644 --- a/OWML.SampleMods/OWML.LoadCustomAssets/packages.config +++ b/OWML.SampleMods/OWML.LoadCustomAssets/packages.config @@ -1,4 +1,5 @@  + \ No newline at end of file From 5a622c45e010122c628e6d82962b67d2f85d756a Mon Sep 17 00:00:00 2001 From: Mister_Nebula <41904486+misternebula@users.noreply.github.com> Date: Tue, 28 Apr 2020 12:25:05 +0100 Subject: [PATCH 21/36] Added priority mod loading option --- OWML.Common/IModManifest.cs | 1 + OWML.ModHelper/ModManifest.cs | 3 +++ OWML.ModLoader/Owo.cs | 13 ++++++++++--- 3 files changed, 14 insertions(+), 3 deletions(-) diff --git a/OWML.Common/IModManifest.cs b/OWML.Common/IModManifest.cs index 9863d5566..0a2c664e8 100644 --- a/OWML.Common/IModManifest.cs +++ b/OWML.Common/IModManifest.cs @@ -14,5 +14,6 @@ public interface IModManifest string ModFolderPath { get; set; } Dictionary AppIds { get; } string[] Dependencies { get; } + bool PriorityLoad { get; } } } diff --git a/OWML.ModHelper/ModManifest.cs b/OWML.ModHelper/ModManifest.cs index f8a386cf4..50e022706 100644 --- a/OWML.ModHelper/ModManifest.cs +++ b/OWML.ModHelper/ModManifest.cs @@ -27,6 +27,9 @@ public class ModManifest : IModManifest [JsonProperty("dependencies")] public string[] Dependencies { get; private set; } = new string[] { }; + [JsonProperty("priorityLoad")] + public bool PriorityLoad { get; private set; } = false; + [JsonIgnore] public string ModFolderPath { get; set; } diff --git a/OWML.ModLoader/Owo.cs b/OWML.ModLoader/Owo.cs index 4d6e3c294..8259a5dd1 100644 --- a/OWML.ModLoader/Owo.cs +++ b/OWML.ModLoader/Owo.cs @@ -43,9 +43,16 @@ public void LoadMods() _console.WriteLine("Verbose mode is enabled"); Application.logMessageReceived += OnLogMessageReceived; } - var mods = _modFinder.GetMods(); - var sortedMods = _sorter.SortMods(mods); - var modNames = mods.Where(mod => mod.Config.Enabled).Select(mod => mod.Manifest.UniqueName); + var normalMods = _modFinder.GetMods().Where(mod => !mod.Manifest.PriorityLoad).ToList(); + var sortedNormal = _sorter.SortMods(normalMods); + + var priorityMods = _modFinder.GetMods().Where(mod => mod.Manifest.PriorityLoad).ToList(); + var sortedPriority = _sorter.SortMods(priorityMods); + + var modNames = _modFinder.GetMods().Where(mod => mod.Config.Enabled).Select(mod => mod.Manifest.UniqueName); + + var sortedMods = Enumerable.Concat(sortedPriority, sortedNormal); + foreach (var modDep in sortedMods) { foreach (var dep in modDep.Dependencies) From 70239db564e9caafa8781668e5f17dc3396d6c71 Mon Sep 17 00:00:00 2001 From: Mister_Nebula <41904486+misternebula@users.noreply.github.com> Date: Tue, 28 Apr 2020 21:49:32 +0100 Subject: [PATCH 22/36] Added GetDependencies() and fixed null-dict issue --- OWML.Common/IModBehaviour.cs | 1 + OWML.Common/IModInteraction.cs | 1 + OWML.ModHelper.Interaction/ModInteraction.cs | 40 +++++++++++++++----- OWML.ModHelper/ModBehaviour.cs | 5 +++ 4 files changed, 38 insertions(+), 9 deletions(-) diff --git a/OWML.Common/IModBehaviour.cs b/OWML.Common/IModBehaviour.cs index e470cd7ce..c9e6bf20c 100644 --- a/OWML.Common/IModBehaviour.cs +++ b/OWML.Common/IModBehaviour.cs @@ -7,5 +7,6 @@ public interface IModBehaviour IModHelper ModHelper { get; } void Configure(IModConfig config); IList GetDependants(); + IList GetDependencies(); } } diff --git a/OWML.Common/IModInteraction.cs b/OWML.Common/IModInteraction.cs index e58c7b673..03431a784 100644 --- a/OWML.Common/IModInteraction.cs +++ b/OWML.Common/IModInteraction.cs @@ -9,6 +9,7 @@ public interface IModInteraction { IList GetMods(); IList GetDependants(string dependencyUniqueName); + IList GetDependencies(string uniqueName); IModBehaviour GetMod(string uniqueName); T GetMod(string uniqueName) where T : IModBehaviour; bool ModExists(string uniqueName); diff --git a/OWML.ModHelper.Interaction/ModInteraction.cs b/OWML.ModHelper.Interaction/ModInteraction.cs index faae54192..dda27ba5c 100644 --- a/OWML.ModHelper.Interaction/ModInteraction.cs +++ b/OWML.ModHelper.Interaction/ModInteraction.cs @@ -1,36 +1,58 @@ using OWML.Common; -using OWML.ModHelper.Events; using System.Collections.Generic; using System.Linq; +using UnityEngine; namespace OWML.ModHelper.Interaction { public class ModInteraction : IModInteraction { - private readonly List _modList = new List(); - private readonly Dictionary> _dependantDict = new Dictionary>(); + private readonly IList _modList; + private Dictionary> _dependantDict = new Dictionary>(); + private Dictionary> _dependencyDict = new Dictionary>(); - public ModInteraction(List list) + public ModInteraction(IList list) { _modList = list; + RegenDicts(); + } + + private void RegenDicts() + { + _dependantDict = new Dictionary>(); + _dependencyDict = new Dictionary>(); foreach (var mod in _modList) { - var dependants = new List(); + var dependants = new List(); + var dependencies = new List(); foreach (var dependency in _modList) - { - if (dependency.ModHelper.Manifest.Dependencies != new string[] { } && dependency.ModHelper.Manifest.Dependencies.Contains(mod.ModHelper.Manifest.Name)) + { + if (dependency.ModHelper.Manifest.Dependencies != new string[] { } && dependency.ModHelper.Manifest.Dependencies.Contains(mod.ModHelper.Manifest.UniqueName)) { dependants.Add(dependency); } + + if (mod.ModHelper.Manifest.Dependencies.Contains(dependency.ModHelper.Manifest.UniqueName)) + { + dependencies.Add(dependency); + } } _dependantDict.Add(mod, dependants); + _dependencyDict.Add(mod, dependencies); } } public IList GetDependants(string dependencyUniqueName) { - return _dependantDict.Where(x => x.Key.ModHelper.Manifest.UniqueName == dependencyUniqueName).FirstOrDefault().Value; + RegenDicts(); + return _dependantDict.Where(x => x.Key.ModHelper.Manifest.UniqueName == dependencyUniqueName).FirstOrDefault().Value.Cast().ToList(); + } + + public IList GetDependencies(string uniqueName) + { + RegenDicts(); + return _dependencyDict.Where(x => x.Key.ModHelper.Manifest.UniqueName == uniqueName).FirstOrDefault().Value.Cast().ToList(); } public IModBehaviour GetMod(string uniqueName) @@ -46,7 +68,7 @@ public T GetMod(string uniqueName) where T : IModBehaviour public IList GetMods() { - return _modList as IList; + return _modList.Cast().ToList(); } public bool ModExists(string uniqueName) diff --git a/OWML.ModHelper/ModBehaviour.cs b/OWML.ModHelper/ModBehaviour.cs index ce677c389..7297860ac 100644 --- a/OWML.ModHelper/ModBehaviour.cs +++ b/OWML.ModHelper/ModBehaviour.cs @@ -24,5 +24,10 @@ public IList GetDependants() { return ModHelper.Interaction.GetDependants(ModHelper.Manifest.UniqueName); } + + public IList GetDependencies() + { + return ModHelper.Interaction.GetDependencies(ModHelper.Manifest.UniqueName); + } } } From 0f901819f20973406232120ffbdec1ba1d5c8404 Mon Sep 17 00:00:00 2001 From: Mister_Nebula <41904486+misternebula@users.noreply.github.com> Date: Tue, 28 Apr 2020 22:31:06 +0100 Subject: [PATCH 23/36] Changed ModBehaviour to IModBehaviour --- OWML.ModHelper.Interaction/ModInteraction.cs | 24 ++++++++++---------- OWML.ModLoader/Owo.cs | 4 ++-- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/OWML.ModHelper.Interaction/ModInteraction.cs b/OWML.ModHelper.Interaction/ModInteraction.cs index dda27ba5c..cfcba0623 100644 --- a/OWML.ModHelper.Interaction/ModInteraction.cs +++ b/OWML.ModHelper.Interaction/ModInteraction.cs @@ -7,11 +7,11 @@ namespace OWML.ModHelper.Interaction { public class ModInteraction : IModInteraction { - private readonly IList _modList; - private Dictionary> _dependantDict = new Dictionary>(); - private Dictionary> _dependencyDict = new Dictionary>(); + private readonly IList _modList; + private Dictionary> _dependantDict = new Dictionary>(); + private Dictionary> _dependencyDict = new Dictionary>(); - public ModInteraction(IList list) + public ModInteraction(IList list) { _modList = list; @@ -20,15 +20,15 @@ public ModInteraction(IList list) private void RegenDicts() { - _dependantDict = new Dictionary>(); - _dependencyDict = new Dictionary>(); + _dependantDict = new Dictionary>(); + _dependencyDict = new Dictionary>(); foreach (var mod in _modList) { - var dependants = new List(); - var dependencies = new List(); + var dependants = new List(); + var dependencies = new List(); foreach (var dependency in _modList) { - if (dependency.ModHelper.Manifest.Dependencies != new string[] { } && dependency.ModHelper.Manifest.Dependencies.Contains(mod.ModHelper.Manifest.UniqueName)) + if (dependency.ModHelper.Manifest.Dependencies.Any() && dependency.ModHelper.Manifest.Dependencies.Contains(mod.ModHelper.Manifest.UniqueName)) { dependants.Add(dependency); } @@ -46,13 +46,13 @@ private void RegenDicts() public IList GetDependants(string dependencyUniqueName) { RegenDicts(); - return _dependantDict.Where(x => x.Key.ModHelper.Manifest.UniqueName == dependencyUniqueName).FirstOrDefault().Value.Cast().ToList(); + return _dependantDict.Where(x => x.Key.ModHelper.Manifest.UniqueName == dependencyUniqueName).FirstOrDefault().Value; } public IList GetDependencies(string uniqueName) { RegenDicts(); - return _dependencyDict.Where(x => x.Key.ModHelper.Manifest.UniqueName == uniqueName).FirstOrDefault().Value.Cast().ToList(); + return _dependencyDict.Where(x => x.Key.ModHelper.Manifest.UniqueName == uniqueName).FirstOrDefault().Value; } public IModBehaviour GetMod(string uniqueName) @@ -68,7 +68,7 @@ public T GetMod(string uniqueName) where T : IModBehaviour public IList GetMods() { - return _modList.Cast().ToList(); + return _modList; } public bool ModExists(string uniqueName) diff --git a/OWML.ModLoader/Owo.cs b/OWML.ModLoader/Owo.cs index 8259a5dd1..bb1fe072b 100644 --- a/OWML.ModLoader/Owo.cs +++ b/OWML.ModLoader/Owo.cs @@ -22,7 +22,7 @@ internal class Owo private readonly IHarmonyHelper _harmonyHelper; private readonly ModSorter _sorter; - List _modList = new List(); + List _modList = new List(); public Owo(IModFinder modFinder, IModLogger logger, IModConsole console, IOwmlConfig owmlConfig, IModMenus menus, IHarmonyHelper harmonyHelper, ModSorter sorter) @@ -73,7 +73,7 @@ public void LoadMods() var helper = CreateModHelper(modData); var mod = InitializeMod(modType, helper); _menus.ModsMenu.AddMod(modData, mod); - _modList.Add(mod as ModBehaviour); + _modList.Add(mod); } } From d3182f9a2c1aed0037a0f7bfb2bbb93a6e5eb422 Mon Sep 17 00:00:00 2001 From: Mister_Nebula <41904486+misternebula@users.noreply.github.com> Date: Wed, 29 Apr 2020 13:07:45 +0100 Subject: [PATCH 24/36] Rewrote sorting code to be more readable --- OWML.ModLoader/ModDep.cs | 4 +- OWML.ModLoader/ModSorter.cs | 124 ++++++++++++++++++++++++------------ OWML.ModLoader/Owo.cs | 19 +++--- 3 files changed, 95 insertions(+), 52 deletions(-) diff --git a/OWML.ModLoader/ModDep.cs b/OWML.ModLoader/ModDep.cs index 2df954ce0..527be0876 100644 --- a/OWML.ModLoader/ModDep.cs +++ b/OWML.ModLoader/ModDep.cs @@ -6,14 +6,14 @@ namespace OWML.ModLoader { - public class ModDep + public class Mod { public string Name { get; private set; } public string[] Dependencies { get; private set; } public IModData Data { get; private set; } - public ModDep(string name, IModData data, params string[] dependencies) + public Mod(string name, IModData data, params string[] dependencies) { Name = name; Data = data; diff --git a/OWML.ModLoader/ModSorter.cs b/OWML.ModLoader/ModSorter.cs index fbde2eabf..ad8c99662 100644 --- a/OWML.ModLoader/ModSorter.cs +++ b/OWML.ModLoader/ModSorter.cs @@ -7,72 +7,116 @@ namespace OWML.ModLoader { class ModSorter { - public IList SortMods(IList mods) + public IList SortMods(IList mods) { - var modList = new List(); - foreach (var mod in mods) + // Make dict of uniqueName to IModData + var modDict = new Dictionary(); + foreach (var item in mods) { - modList.Add(new ModDep(mod.Manifest.UniqueName, mod, mod.Manifest.Dependencies)); + modDict.Add(item.Manifest.UniqueName, item); } - return Sort(modList, x => x.Dependencies, x => x.Name); - } - - private IList Sort(IEnumerable source, Func> getDependencies) - { - var sorted = new List(); - var visited = new Dictionary(); + // Make list of uniqueNames + var modList = new List(); + foreach (var mod in mods) + { + modList.Add(mod.Manifest.UniqueName); + } - foreach (var item in source) + // Make hashset of tuples of Dependant : Dependency + HashSet> set = new HashSet>(); + foreach (var mod in mods) { - Visit(item, getDependencies, sorted, visited); + foreach (var dep in mod.Manifest.Dependencies) + { + set.Add(new Tuple(mod.Manifest.UniqueName, dep)); + } } - return sorted; + // Sort the mods + var ret = TopologicalSort( + new HashSet(modList), + new HashSet>(set) + ); + + // Reverse the list + ret.Reverse(); + + // Get the IModData back by looking up uniqueName in dict + var returnList = new List(); + ret.ForEach(x => returnList.Add(modDict[x])); + + return returnList; } - private void Visit(T item, Func> getDependencies, List sorted, Dictionary visited) + // Thanks to https://gist.github.com/Sup3rc4l1fr4g1l1571c3xp14l1d0c10u5/3341dba6a53d7171fe3397d13d00ee3f + + static List TopologicalSort(HashSet nodes, HashSet> edges) { - var alreadyVisited = visited.TryGetValue(item, out bool inProcess); + // Empty list that will contain the sorted elements + var sortedList = new List(); - if (alreadyVisited) - { - if (inProcess) - { - throw new ArgumentException("Cyclic dependency found."); - } - } - else + // Set of all nodes with no incoming edges + var nodesWithNoEdges = new HashSet(nodes.Where(n => edges.All(e => e.Item2.Equals(n) == false))); + + // while nodesWithNoEdges is non-empty do + while (nodesWithNoEdges.Any()) { - visited[item] = true; + // remove a node from nodesWithNoEdges + var node = nodesWithNoEdges.First(); + nodesWithNoEdges.Remove(node); + + // add node to tail of sortedList + sortedList.Add(node); - var dependencies = getDependencies(item); - if (dependencies != null) + // for each node m with an edge e from n to m do + foreach (var e in edges.Where(e => e.Item1.Equals(node)).ToList()) { - foreach (var dependency in dependencies) + var m = e.Item2; + + // remove edge e from the graph + edges.Remove(e); + + // if m has no other incoming edges then + if (edges.All(me => me.Item2.Equals(m) == false)) { - Visit(dependency, getDependencies, sorted, visited); + // insert m into nodesWithNoEdges + nodesWithNoEdges.Add(m); } } + } - visited[item] = false; - sorted.Add(item); + // if graph has edges then + if (edges.Any()) + { + // return error (graph has at least one cycle) + return null; + } + else + { + // return sortedList (a topologically sorted order) + return sortedList; } } + } - private Func> RemapDependencies(IEnumerable source, Func> getDependencies, Func getKey) + public class Tuple + { + public T1 Item1 { get; private set; } + public T2 Item2 { get; private set; } + internal Tuple(T1 first, T2 second) { - var map = source.ToDictionary(getKey); - return item => - { - var dependencies = getDependencies(item); - return dependencies?.Select(key => map[key]); - }; + Item1 = first; + Item2 = second; } + } - private IList Sort(IEnumerable source, Func> getDependencies, Func getKey) + public static class Tuple + { + public static Tuple New(T1 first, T2 second) { - return Sort(source, RemapDependencies(source, getDependencies, getKey)); + var tuple = new Tuple(first, second); + return tuple; } } } diff --git a/OWML.ModLoader/Owo.cs b/OWML.ModLoader/Owo.cs index bb1fe072b..f9c0ac262 100644 --- a/OWML.ModLoader/Owo.cs +++ b/OWML.ModLoader/Owo.cs @@ -53,27 +53,26 @@ public void LoadMods() var sortedMods = Enumerable.Concat(sortedPriority, sortedNormal); - foreach (var modDep in sortedMods) + foreach (var mod in sortedMods) { - foreach (var dep in modDep.Dependencies) + foreach (var dep in mod.Manifest.Dependencies) { if (!modNames.Contains(dep)) { - _console.WriteLine($"Error! {modDep.Name} needs {dep}, but it's disabled!"); + _console.WriteLine($"Error! {mod.Manifest.UniqueName} needs {dep}, but it's disabled!"); } } - var modData = modDep.Data; - var modType = LoadMod(modData); + var modType = LoadMod(mod); if (modType == null) { _logger.Log("Mod type is null, skipping"); - _menus.ModsMenu.AddMod(modData, null); + _menus.ModsMenu.AddMod(mod, null); continue; } - var helper = CreateModHelper(modData); - var mod = InitializeMod(modType, helper); - _menus.ModsMenu.AddMod(modData, mod); - _modList.Add(mod); + var helper = CreateModHelper(mod); + var initMod = InitializeMod(modType, helper); + _menus.ModsMenu.AddMod(mod, initMod); + _modList.Add(initMod); } } From a49f1cb2f2c5b50d680a91b2c412b9ce402ff1df Mon Sep 17 00:00:00 2001 From: Mister_Nebula <41904486+misternebula@users.noreply.github.com> Date: Wed, 29 Apr 2020 13:12:51 +0100 Subject: [PATCH 25/36] Update Readme.md --- Readme.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Readme.md b/Readme.md index 91da362ba..70cfe8497 100644 --- a/Readme.md +++ b/Readme.md @@ -69,7 +69,7 @@ Each mod is defined in a manifest.json file: |uniqueName|Usually {author}.{uniqueName}.| |version|The version number.| |owmlVersion|The version of OWML the mod was built for.| -|dependencies|\[ Dependency mod 1 name, Dependency mod 2 name, etc. \]| +|dependencies|\Array of dependency names. Make sure to use the unique name.| Each mod can be configured with an **optional** config.json file: From dafaa86c17e7d872208217c4193d96c061450d26 Mon Sep 17 00:00:00 2001 From: Mister_Nebula <41904486+misternebula@users.noreply.github.com> Date: Wed, 29 Apr 2020 21:06:06 +0100 Subject: [PATCH 26/36] Improved clarity in ModSorter, Owo and ModDependency --- .../{ModDep.cs => ModDependency.cs} | 4 +- OWML.ModLoader/ModSorter.cs | 89 +++++++++---------- OWML.ModLoader/OWML.ModLoader.csproj | 2 +- OWML.ModLoader/Owo.cs | 6 +- 4 files changed, 50 insertions(+), 51 deletions(-) rename OWML.ModLoader/{ModDep.cs => ModDependency.cs} (78%) diff --git a/OWML.ModLoader/ModDep.cs b/OWML.ModLoader/ModDependency.cs similarity index 78% rename from OWML.ModLoader/ModDep.cs rename to OWML.ModLoader/ModDependency.cs index 527be0876..c3639d402 100644 --- a/OWML.ModLoader/ModDep.cs +++ b/OWML.ModLoader/ModDependency.cs @@ -6,14 +6,14 @@ namespace OWML.ModLoader { - public class Mod + public class ModDependency { public string Name { get; private set; } public string[] Dependencies { get; private set; } public IModData Data { get; private set; } - public Mod(string name, IModData data, params string[] dependencies) + public ModDependency(string name, IModData data, params string[] dependencies) { Name = name; Data = data; diff --git a/OWML.ModLoader/ModSorter.cs b/OWML.ModLoader/ModSorter.cs index ad8c99662..807f5aa78 100644 --- a/OWML.ModLoader/ModSorter.cs +++ b/OWML.ModLoader/ModSorter.cs @@ -9,79 +9,78 @@ class ModSorter { public IList SortMods(IList mods) { - // Make dict of uniqueName to IModData + var modDict = new Dictionary(); - foreach (var item in mods) - { - modDict.Add(item.Manifest.UniqueName, item); - } - - // Make list of uniqueNames var modList = new List(); + HashSet> set = new HashSet>(); foreach (var mod in mods) { - modList.Add(mod.Manifest.UniqueName); - } + // Add to dict of (uniqueName, IModData) + modDict.Add(mod.Manifest.UniqueName, mod); - // Make hashset of tuples of Dependant : Dependency - HashSet> set = new HashSet>(); - foreach (var mod in mods) - { - foreach (var dep in mod.Manifest.Dependencies) + // Add to list of uniqueNames + modList.Add(mod.Manifest.UniqueName); + + // Add to hashset of tuples (Dependant : Dependency) + foreach (var dependency in mod.Manifest.Dependencies) { - set.Add(new Tuple(mod.Manifest.UniqueName, dep)); + set.Add(new Edge(mod.Manifest.UniqueName, dependency)); } } - // Sort the mods - var ret = TopologicalSort( + var sortedList = TopologicalSort( new HashSet(modList), - new HashSet>(set) + new HashSet>(set) ); - // Reverse the list - ret.Reverse(); + if (sortedList == null) + { + // Sorting has failed, return the original mod list + return mods; + } + + sortedList.Reverse(); // Get the IModData back by looking up uniqueName in dict var returnList = new List(); - ret.ForEach(x => returnList.Add(modDict[x])); + sortedList.ForEach(mod => returnList.Add(modDict[mod])); return returnList; } // Thanks to https://gist.github.com/Sup3rc4l1fr4g1l1571c3xp14l1d0c10u5/3341dba6a53d7171fe3397d13d00ee3f - static List TopologicalSort(HashSet nodes, HashSet> edges) + static List TopologicalSort(HashSet nodes, HashSet> edges) { // Empty list that will contain the sorted elements - var sortedList = new List(); + var sortedList = new List(); // Set of all nodes with no incoming edges - var nodesWithNoEdges = new HashSet(nodes.Where(n => edges.All(e => e.Item2.Equals(n) == false))); + var nodesWithNoEdges = new HashSet(nodes.Where(node => edges.All(edge => edge.Second.Equals(node) == false))); // while nodesWithNoEdges is non-empty do while (nodesWithNoEdges.Any()) { // remove a node from nodesWithNoEdges - var node = nodesWithNoEdges.First(); - nodesWithNoEdges.Remove(node); + var firstNode = nodesWithNoEdges.First(); + nodesWithNoEdges.Remove(firstNode); // add node to tail of sortedList - sortedList.Add(node); + sortedList.Add(firstNode); - // for each node m with an edge e from n to m do - foreach (var e in edges.Where(e => e.Item1.Equals(node)).ToList()) + // for each node secondNode with an edge from firstNode to secondNode do + foreach (var edge in edges.Where(e => e.First.Equals(firstNode)).ToList()) { - var m = e.Item2; + var secondNode = edge.Second; // remove edge e from the graph - edges.Remove(e); + edges.Remove(edge); - // if m has no other incoming edges then - if (edges.All(me => me.Item2.Equals(m) == false)) + // if secondNode has no other incoming edges then + if (edges.All(mEdge => mEdge.Second.Equals(secondNode) == false)) { - // insert m into nodesWithNoEdges - nodesWithNoEdges.Add(m); + // insert secondNode into nodesWithNoEdges + nodesWithNoEdges.Add(secondNode); } } } @@ -89,7 +88,7 @@ static List TopologicalSort(HashSet nodes, HashSet> edges) // if graph has edges then if (edges.Any()) { - // return error (graph has at least one cycle) + // This will be caught and handled in the caller method return null; } else @@ -100,22 +99,22 @@ static List TopologicalSort(HashSet nodes, HashSet> edges) } } - public class Tuple + public class Edge { - public T1 Item1 { get; private set; } - public T2 Item2 { get; private set; } - internal Tuple(T1 first, T2 second) + public string First { get; private set; } + public string Second { get; private set; } + internal Edge(string first, string second) { - Item1 = first; - Item2 = second; + this.First = first; + this.Second = second; } } - public static class Tuple + public static class Edge { - public static Tuple New(T1 first, T2 second) + public static Edge New(string first, string second) { - var tuple = new Tuple(first, second); + var tuple = new Edge(first, second); return tuple; } } diff --git a/OWML.ModLoader/OWML.ModLoader.csproj b/OWML.ModLoader/OWML.ModLoader.csproj index fe5873ca9..6bdbfb6e2 100644 --- a/OWML.ModLoader/OWML.ModLoader.csproj +++ b/OWML.ModLoader/OWML.ModLoader.csproj @@ -69,7 +69,7 @@ - + diff --git a/OWML.ModLoader/Owo.cs b/OWML.ModLoader/Owo.cs index f9c0ac262..1e2df086d 100644 --- a/OWML.ModLoader/Owo.cs +++ b/OWML.ModLoader/Owo.cs @@ -55,11 +55,11 @@ public void LoadMods() foreach (var mod in sortedMods) { - foreach (var dep in mod.Manifest.Dependencies) + foreach (var dependency in mod.Manifest.Dependencies) { - if (!modNames.Contains(dep)) + if (!modNames.Contains(dependency)) { - _console.WriteLine($"Error! {mod.Manifest.UniqueName} needs {dep}, but it's disabled!"); + _console.WriteLine($"Error! {mod.Manifest.UniqueName} needs {dependency}, but it's disabled!"); } } var modType = LoadMod(mod); From 7a09d7ca844082a4faa980babcf199b03765d24a Mon Sep 17 00:00:00 2001 From: Mister_Nebula <41904486+misternebula@users.noreply.github.com> Date: Wed, 29 Apr 2020 21:35:52 +0100 Subject: [PATCH 27/36] Responses to PR - changed edge hashset declaration to use var - added "public" to ModSorter - removed false from ModManifest --- OWML.ModHelper/ModManifest.cs | 2 +- OWML.ModLoader/ModSorter.cs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/OWML.ModHelper/ModManifest.cs b/OWML.ModHelper/ModManifest.cs index 50e022706..9dbb840b0 100644 --- a/OWML.ModHelper/ModManifest.cs +++ b/OWML.ModHelper/ModManifest.cs @@ -28,7 +28,7 @@ public class ModManifest : IModManifest public string[] Dependencies { get; private set; } = new string[] { }; [JsonProperty("priorityLoad")] - public bool PriorityLoad { get; private set; } = false; + public bool PriorityLoad { get; private set; } [JsonIgnore] public string ModFolderPath { get; set; } diff --git a/OWML.ModLoader/ModSorter.cs b/OWML.ModLoader/ModSorter.cs index 807f5aa78..fd70ff512 100644 --- a/OWML.ModLoader/ModSorter.cs +++ b/OWML.ModLoader/ModSorter.cs @@ -5,14 +5,14 @@ namespace OWML.ModLoader { - class ModSorter + public class ModSorter { public IList SortMods(IList mods) { var modDict = new Dictionary(); var modList = new List(); - HashSet> set = new HashSet>(); + var set = new HashSet>(); foreach (var mod in mods) { // Add to dict of (uniqueName, IModData) From 1a30e49cad66009260bd17aef5442f66e66fb56e Mon Sep 17 00:00:00 2001 From: Mister_Nebula <41904486+misternebula@users.noreply.github.com> Date: Thu, 30 Apr 2020 10:06:14 +0100 Subject: [PATCH 28/36] Reworked dictionaries and removed unneeded types --- OWML.ModHelper.Interaction/ModInteraction.cs | 16 ++++++++-------- OWML.ModLoader/ModSorter.cs | 19 +++++-------------- 2 files changed, 13 insertions(+), 22 deletions(-) diff --git a/OWML.ModHelper.Interaction/ModInteraction.cs b/OWML.ModHelper.Interaction/ModInteraction.cs index cfcba0623..01e569cfe 100644 --- a/OWML.ModHelper.Interaction/ModInteraction.cs +++ b/OWML.ModHelper.Interaction/ModInteraction.cs @@ -8,8 +8,8 @@ namespace OWML.ModHelper.Interaction public class ModInteraction : IModInteraction { private readonly IList _modList; - private Dictionary> _dependantDict = new Dictionary>(); - private Dictionary> _dependencyDict = new Dictionary>(); + private Dictionary> _dependantDict = new Dictionary>(); + private Dictionary> _dependencyDict = new Dictionary>(); public ModInteraction(IList list) { @@ -20,8 +20,8 @@ public ModInteraction(IList list) private void RegenDicts() { - _dependantDict = new Dictionary>(); - _dependencyDict = new Dictionary>(); + _dependantDict = new Dictionary>(); + _dependencyDict = new Dictionary>(); foreach (var mod in _modList) { var dependants = new List(); @@ -38,21 +38,21 @@ private void RegenDicts() dependencies.Add(dependency); } } - _dependantDict.Add(mod, dependants); - _dependencyDict.Add(mod, dependencies); + _dependantDict.Add(mod.ModHelper.Manifest.UniqueName, dependants); + _dependencyDict.Add(mod.ModHelper.Manifest.UniqueName, dependencies); } } public IList GetDependants(string dependencyUniqueName) { RegenDicts(); - return _dependantDict.Where(x => x.Key.ModHelper.Manifest.UniqueName == dependencyUniqueName).FirstOrDefault().Value; + return _dependantDict[dependencyUniqueName]; } public IList GetDependencies(string uniqueName) { RegenDicts(); - return _dependencyDict.Where(x => x.Key.ModHelper.Manifest.UniqueName == uniqueName).FirstOrDefault().Value; + return _dependencyDict[uniqueName]; } public IModBehaviour GetMod(string uniqueName) diff --git a/OWML.ModLoader/ModSorter.cs b/OWML.ModLoader/ModSorter.cs index fd70ff512..2b6c98144 100644 --- a/OWML.ModLoader/ModSorter.cs +++ b/OWML.ModLoader/ModSorter.cs @@ -12,7 +12,7 @@ public IList SortMods(IList mods) var modDict = new Dictionary(); var modList = new List(); - var set = new HashSet>(); + var set = new HashSet(); foreach (var mod in mods) { // Add to dict of (uniqueName, IModData) @@ -24,13 +24,13 @@ public IList SortMods(IList mods) // Add to hashset of tuples (Dependant : Dependency) foreach (var dependency in mod.Manifest.Dependencies) { - set.Add(new Edge(mod.Manifest.UniqueName, dependency)); + set.Add(new Edge(mod.Manifest.UniqueName, dependency)); } } var sortedList = TopologicalSort( new HashSet(modList), - new HashSet>(set) + new HashSet(set) ); if (sortedList == null) @@ -50,7 +50,7 @@ public IList SortMods(IList mods) // Thanks to https://gist.github.com/Sup3rc4l1fr4g1l1571c3xp14l1d0c10u5/3341dba6a53d7171fe3397d13d00ee3f - static List TopologicalSort(HashSet nodes, HashSet> edges) + static List TopologicalSort(HashSet nodes, HashSet edges) { // Empty list that will contain the sorted elements var sortedList = new List(); @@ -99,7 +99,7 @@ static List TopologicalSort(HashSet nodes, HashSet + public class Edge { public string First { get; private set; } public string Second { get; private set; } @@ -109,13 +109,4 @@ internal Edge(string first, string second) this.Second = second; } } - - public static class Edge - { - public static Edge New(string first, string second) - { - var tuple = new Edge(first, second); - return tuple; - } - } } From 4531b4187974b072dd4ff21d214c8eff6488bcd8 Mon Sep 17 00:00:00 2001 From: Mister_Nebula <41904486+misternebula@users.noreply.github.com> Date: Thu, 30 Apr 2020 10:09:42 +0100 Subject: [PATCH 29/36] Added console log to cyclic dependency --- OWML.ModLoader/ModLoader.cs | 2 +- OWML.ModLoader/ModSorter.cs | 8 +++++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/OWML.ModLoader/ModLoader.cs b/OWML.ModLoader/ModLoader.cs index 63eb6036d..e893a1c01 100644 --- a/OWML.ModLoader/ModLoader.cs +++ b/OWML.ModLoader/ModLoader.cs @@ -28,7 +28,7 @@ public static void LoadMods() logger.Log("Got config!"); var console = new ModConsole(owmlConfig, logger, owmlManifest); console.WriteLine("Mod loader has been initialized."); - var modSorter = new ModSorter(); + var modSorter = new ModSorter(console); var modFinder = new ModFinder(owmlConfig, console); var harmonyHelper = new HarmonyHelper(logger, console); var events = new ModEvents(logger, console, harmonyHelper); diff --git a/OWML.ModLoader/ModSorter.cs b/OWML.ModLoader/ModSorter.cs index 2b6c98144..5e2709c29 100644 --- a/OWML.ModLoader/ModSorter.cs +++ b/OWML.ModLoader/ModSorter.cs @@ -7,6 +7,11 @@ namespace OWML.ModLoader { public class ModSorter { + private readonly IModConsole _console; + public ModSorter(IModConsole console) + { + _console = console; + } public IList SortMods(IList mods) { @@ -28,7 +33,7 @@ public IList SortMods(IList mods) } } - var sortedList = TopologicalSort( + var sortedList = TopologicalSort( new HashSet(modList), new HashSet(set) ); @@ -36,6 +41,7 @@ public IList SortMods(IList mods) if (sortedList == null) { // Sorting has failed, return the original mod list + _console.WriteLine("Error - Cyclic dependency found."); return mods; } From 846204657c96393d82a28ccff051d1ebf9f82f36 Mon Sep 17 00:00:00 2001 From: Mister_Nebula <41904486+misternebula@users.noreply.github.com> Date: Thu, 30 Apr 2020 10:36:26 +0100 Subject: [PATCH 30/36] Added check for priority mod needed a normal mod --- OWML.ModLoader/ModSorter.cs | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/OWML.ModLoader/ModSorter.cs b/OWML.ModLoader/ModSorter.cs index 5e2709c29..9a52ad726 100644 --- a/OWML.ModLoader/ModSorter.cs +++ b/OWML.ModLoader/ModSorter.cs @@ -14,25 +14,39 @@ public ModSorter(IModConsole console) } public IList SortMods(IList mods) { - var modDict = new Dictionary(); var modList = new List(); var set = new HashSet(); + foreach (var mod in mods) { - // Add to dict of (uniqueName, IModData) - modDict.Add(mod.Manifest.UniqueName, mod); - // Add to list of uniqueNames modList.Add(mod.Manifest.UniqueName); + } + + foreach (var mod in mods) + { + // Add to dict of (uniqueName, IModData) + modDict.Add(mod.Manifest.UniqueName, mod); // Add to hashset of tuples (Dependant : Dependency) foreach (var dependency in mod.Manifest.Dependencies) { - set.Add(new Edge(mod.Manifest.UniqueName, dependency)); + if (mod.Manifest.PriorityLoad && !modList.Contains(dependency)) + { + _console.WriteLine($"Error! {mod.Manifest.UniqueName} (priority load) depends on a normal mod! Removing from load..."); + mods.Remove(mod); + modDict.Remove(mod.Manifest.UniqueName); + modList.Remove(mod.Manifest.UniqueName); + } + else + { + set.Add(new Edge(mod.Manifest.UniqueName, dependency)); + } } } + var sortedList = TopologicalSort( new HashSet(modList), new HashSet(set) From 4f52e23dcdf90723711a8f4a07fdc1dd55e442a3 Mon Sep 17 00:00:00 2001 From: Mister_Nebula <41904486+misternebula@users.noreply.github.com> Date: Thu, 30 Apr 2020 11:00:33 +0100 Subject: [PATCH 31/36] Update mod removal code to not cause a enumeration error --- OWML.ModLoader/ModSorter.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/OWML.ModLoader/ModSorter.cs b/OWML.ModLoader/ModSorter.cs index 9a52ad726..904967056 100644 --- a/OWML.ModLoader/ModSorter.cs +++ b/OWML.ModLoader/ModSorter.cs @@ -12,6 +12,7 @@ public ModSorter(IModConsole console) { _console = console; } + public IList SortMods(IList mods) { var modDict = new Dictionary(); @@ -35,7 +36,6 @@ public IList SortMods(IList mods) if (mod.Manifest.PriorityLoad && !modList.Contains(dependency)) { _console.WriteLine($"Error! {mod.Manifest.UniqueName} (priority load) depends on a normal mod! Removing from load..."); - mods.Remove(mod); modDict.Remove(mod.Manifest.UniqueName); modList.Remove(mod.Manifest.UniqueName); } @@ -55,7 +55,7 @@ public IList SortMods(IList mods) if (sortedList == null) { // Sorting has failed, return the original mod list - _console.WriteLine("Error - Cyclic dependency found."); + _console.WriteLine("Error - Cyclic dependency found. Returning original load order..."); return mods; } From 51cabf86e2af5c01ab5aed533b56ffb36005a2c3 Mon Sep 17 00:00:00 2001 From: Mister_Nebula <41904486+misternebula@users.noreply.github.com> Date: Thu, 30 Apr 2020 22:13:38 +0100 Subject: [PATCH 32/36] Update Readme.md --- Readme.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Readme.md b/Readme.md index 70cfe8497..106ef63dd 100644 --- a/Readme.md +++ b/Readme.md @@ -69,7 +69,7 @@ Each mod is defined in a manifest.json file: |uniqueName|Usually {author}.{uniqueName}.| |version|The version number.| |owmlVersion|The version of OWML the mod was built for.| -|dependencies|\Array of dependency names. Make sure to use the unique name.| +|dependencies|Array of dependency names. Make sure to use the unique name.| Each mod can be configured with an **optional** config.json file: From 7dc13f69a36c90bcdeae5578a3495a26ea18e9a7 Mon Sep 17 00:00:00 2001 From: Mister_Nebula <41904486+misternebula@users.noreply.github.com> Date: Thu, 30 Apr 2020 22:46:57 +0100 Subject: [PATCH 33/36] Made RegenDicts() be called less and improved clarity --- OWML.ModHelper.Interaction/ModInteraction.cs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/OWML.ModHelper.Interaction/ModInteraction.cs b/OWML.ModHelper.Interaction/ModInteraction.cs index 01e569cfe..b22cde7ed 100644 --- a/OWML.ModHelper.Interaction/ModInteraction.cs +++ b/OWML.ModHelper.Interaction/ModInteraction.cs @@ -51,7 +51,10 @@ public IList GetDependants(string dependencyUniqueName) public IList GetDependencies(string uniqueName) { - RegenDicts(); + if (_dependantDict.Count != _modList.Count) + { + RegenDicts(); + } return _dependencyDict[uniqueName]; } @@ -73,7 +76,7 @@ public IList GetMods() public bool ModExists(string uniqueName) { - return _modList.Count(m => m.ModHelper.Manifest.UniqueName == uniqueName) != 0; + return _modList.Any(m => m.ModHelper.Manifest.UniqueName == uniqueName); } } } From 81674e0569de339c74a9d4e23dfd7dd28eab469d Mon Sep 17 00:00:00 2001 From: Mister_Nebula <41904486+misternebula@users.noreply.github.com> Date: Thu, 30 Apr 2020 23:02:38 +0100 Subject: [PATCH 34/36] Remove unneeded comments --- OWML.ModLoader/ModSorter.cs | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/OWML.ModLoader/ModSorter.cs b/OWML.ModLoader/ModSorter.cs index 904967056..6d9ba5f97 100644 --- a/OWML.ModLoader/ModSorter.cs +++ b/OWML.ModLoader/ModSorter.cs @@ -21,16 +21,13 @@ public IList SortMods(IList mods) foreach (var mod in mods) { - // Add to list of uniqueNames modList.Add(mod.Manifest.UniqueName); } foreach (var mod in mods) { - // Add to dict of (uniqueName, IModData) modDict.Add(mod.Manifest.UniqueName, mod); - // Add to hashset of tuples (Dependant : Dependency) foreach (var dependency in mod.Manifest.Dependencies) { if (mod.Manifest.PriorityLoad && !modList.Contains(dependency)) @@ -61,7 +58,6 @@ public IList SortMods(IList mods) sortedList.Reverse(); - // Get the IModData back by looking up uniqueName in dict var returnList = new List(); sortedList.ForEach(mod => returnList.Add(modDict[mod])); @@ -72,40 +68,30 @@ public IList SortMods(IList mods) static List TopologicalSort(HashSet nodes, HashSet edges) { - // Empty list that will contain the sorted elements var sortedList = new List(); - // Set of all nodes with no incoming edges var nodesWithNoEdges = new HashSet(nodes.Where(node => edges.All(edge => edge.Second.Equals(node) == false))); - // while nodesWithNoEdges is non-empty do while (nodesWithNoEdges.Any()) { - // remove a node from nodesWithNoEdges var firstNode = nodesWithNoEdges.First(); nodesWithNoEdges.Remove(firstNode); - // add node to tail of sortedList sortedList.Add(firstNode); - // for each node secondNode with an edge from firstNode to secondNode do foreach (var edge in edges.Where(e => e.First.Equals(firstNode)).ToList()) { var secondNode = edge.Second; - // remove edge e from the graph edges.Remove(edge); - // if secondNode has no other incoming edges then if (edges.All(mEdge => mEdge.Second.Equals(secondNode) == false)) { - // insert secondNode into nodesWithNoEdges nodesWithNoEdges.Add(secondNode); } } } - // if graph has edges then if (edges.Any()) { // This will be caught and handled in the caller method @@ -113,7 +99,6 @@ static List TopologicalSort(HashSet nodes, HashSet edges) } else { - // return sortedList (a topologically sorted order) return sortedList; } } From ad9549caad7ebf7e259ca638027b02085f65e4c4 Mon Sep 17 00:00:00 2001 From: Mister_Nebula <41904486+misternebula@users.noreply.github.com> Date: Sun, 3 May 2020 14:06:34 +0100 Subject: [PATCH 35/36] Readability and duplicate mod protection --- OWML.ModHelper.Interaction/ModInteraction.cs | 11 +++++++---- OWML.ModLoader/ModSorter.cs | 6 ++---- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/OWML.ModHelper.Interaction/ModInteraction.cs b/OWML.ModHelper.Interaction/ModInteraction.cs index b22cde7ed..74971f0e0 100644 --- a/OWML.ModHelper.Interaction/ModInteraction.cs +++ b/OWML.ModHelper.Interaction/ModInteraction.cs @@ -28,7 +28,7 @@ private void RegenDicts() var dependencies = new List(); foreach (var dependency in _modList) { - if (dependency.ModHelper.Manifest.Dependencies.Any() && dependency.ModHelper.Manifest.Dependencies.Contains(mod.ModHelper.Manifest.UniqueName)) + if (dependency.ModHelper.Manifest.Dependencies.Contains(mod.ModHelper.Manifest.UniqueName)) { dependants.Add(dependency); } @@ -38,14 +38,17 @@ private void RegenDicts() dependencies.Add(dependency); } } - _dependantDict.Add(mod.ModHelper.Manifest.UniqueName, dependants); - _dependencyDict.Add(mod.ModHelper.Manifest.UniqueName, dependencies); + _dependantDict[mod.ModHelper.Manifest.UniqueName] = dependants; + _dependencyDict[mod.ModHelper.Manifest.UniqueName] = dependencies; } } public IList GetDependants(string dependencyUniqueName) { - RegenDicts(); + if (_dependantDict.Count != _modList.Count) + { + RegenDicts(); + } return _dependantDict[dependencyUniqueName]; } diff --git a/OWML.ModLoader/ModSorter.cs b/OWML.ModLoader/ModSorter.cs index 6d9ba5f97..f8712705a 100644 --- a/OWML.ModLoader/ModSorter.cs +++ b/OWML.ModLoader/ModSorter.cs @@ -8,6 +8,7 @@ namespace OWML.ModLoader public class ModSorter { private readonly IModConsole _console; + public ModSorter(IModConsole console) { _console = console; @@ -58,10 +59,7 @@ public IList SortMods(IList mods) sortedList.Reverse(); - var returnList = new List(); - sortedList.ForEach(mod => returnList.Add(modDict[mod])); - - return returnList; + return sortedList.Select(mod => modDict[mod]).ToList(); } // Thanks to https://gist.github.com/Sup3rc4l1fr4g1l1571c3xp14l1d0c10u5/3341dba6a53d7171fe3397d13d00ee3f From 005110b881ae8f826a8a36d01ed8d9f4ba7c2929 Mon Sep 17 00:00:00 2001 From: Mister_Nebula <41904486+misternebula@users.noreply.github.com> Date: Wed, 6 May 2020 10:50:35 +0100 Subject: [PATCH 36/36] bump version --- OWML.Launcher/OWML.Manifest.json | 2 +- OWML.SampleMods/OWML.EnableDebugMode/manifest.json | 2 +- OWML.SampleMods/OWML.LoadCustomAssets/manifest.json | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/OWML.Launcher/OWML.Manifest.json b/OWML.Launcher/OWML.Manifest.json index e3a167a6a..6e98989c8 100644 --- a/OWML.Launcher/OWML.Manifest.json +++ b/OWML.Launcher/OWML.Manifest.json @@ -2,6 +2,6 @@ "author": "Alek", "name": "OWML", "uniqueName": "Alek.OWML", - "version": "0.3.46", + "version": "0.3.47", "description": "The mod loader and mod framework for Outer Wilds" } \ No newline at end of file diff --git a/OWML.SampleMods/OWML.EnableDebugMode/manifest.json b/OWML.SampleMods/OWML.EnableDebugMode/manifest.json index 825827758..310addc8b 100644 --- a/OWML.SampleMods/OWML.EnableDebugMode/manifest.json +++ b/OWML.SampleMods/OWML.EnableDebugMode/manifest.json @@ -4,6 +4,6 @@ "name": "EnableDebugMode", "uniqueName": "Alek.EnableDebugMode", "version": "0.2", - "owmlVersion": "0.3.46", + "owmlVersion": "0.3.47", "description": "Enables the debug mode in Outer Wilds" } \ No newline at end of file diff --git a/OWML.SampleMods/OWML.LoadCustomAssets/manifest.json b/OWML.SampleMods/OWML.LoadCustomAssets/manifest.json index 53694b1c6..b49be46d7 100644 --- a/OWML.SampleMods/OWML.LoadCustomAssets/manifest.json +++ b/OWML.SampleMods/OWML.LoadCustomAssets/manifest.json @@ -4,6 +4,6 @@ "name": "LoadCustomAssets", "uniqueName": "Alek.LoadCustomAssets", "version": "0.5", - "owmlVersion": "0.3.46", + "owmlVersion": "0.3.47", "description": "A mod for testing loading of custom assets" } \ No newline at end of file