From 9f2894d2ba8d1521f25b712eb095e1e2406a1726 Mon Sep 17 00:00:00 2001 From: S K Date: Mon, 20 Jan 2020 01:10:10 +0100 Subject: [PATCH 1/2] * Added ModManager as main unit for mod managment. * Added a few classes and interfaces for the ModManager. * Added activation support for mods. The mod list is now a button list and the mods can be activated or deactivated by clicking. - Coloring green/gray. - Excluded Framework mod from actions. * Changed ModLoader and more to support ModManager. * Changed ModBase to support Cleanup on deactivation. * Added de language. * Tested. TODOs: - Maybe changing the Patcher for a better ModManger support. - Rewrite the ModListGameState --- FrameworkMod.cs | 7 +- GuiRenderer.cs | 25 ++++ IModConfig.cs | 79 ++++++++++++ IModLoader.cs | 32 +++++ IModMetaData.cs | 65 ++++++++++ ModBase.cs | 3 + ModListGameState.cs | 45 +++++-- ModManager.cs | 152 +++++++++++++++++++++++ Modloader.cs | 37 ++++-- Patches/Planetbase/GameManager/Update.cs | 3 +- PlanetbaseFramework.csproj | 18 ++- PlanetbaseFramework.csproj.user | 4 + assets/strings/framework_de.xml | 5 + assets/strings/framework_en.xml | 2 +- 14 files changed, 451 insertions(+), 26 deletions(-) create mode 100644 GuiRenderer.cs create mode 100644 IModConfig.cs create mode 100644 IModLoader.cs create mode 100644 IModMetaData.cs create mode 100644 ModManager.cs create mode 100644 assets/strings/framework_de.xml diff --git a/FrameworkMod.cs b/FrameworkMod.cs index 4ec8fb7..2480727 100644 --- a/FrameworkMod.cs +++ b/FrameworkMod.cs @@ -5,15 +5,16 @@ namespace PlanetbaseFramework { public class FrameworkMod : ModBase { - public const string AssemblyVersion = "2.2.2.0"; + public const string AssemblyVersion = "2.3.2.0"; public new static readonly Version ModVersion = new Version(AssemblyVersion); + public const string DefaultModName = "Planetbase Framework"; public FrameworkMod() { Utils.ErrorTexture = ModTextures.Find(x => x.name.Equals("error.png")); } - public override string ModName { get; } = "Planetbase Framework"; + public override string ModName { get; } = DefaultModName; public override void Init() { @@ -24,7 +25,7 @@ public override void Init() private class ModTitleButton : TitleButton { - public ModTitleButton() : base("mod_titlemenu") { } + public ModTitleButton() : base("fmod_titlemenu") { } public override void HandleAction(GameStateTitle gst) { diff --git a/GuiRenderer.cs b/GuiRenderer.cs new file mode 100644 index 0000000..c32bdcb --- /dev/null +++ b/GuiRenderer.cs @@ -0,0 +1,25 @@ +using System; +using UnityEngine; +using Planetbase; + +namespace PlanetbaseFramework { + class GuiRenderer : Planetbase.GuiRenderer { + + public bool renderBigButton(Rect rect, string text, FontSize fontSize, GUIStyle style, SoundDefinition sound = null) { + if (style == null) { + float aspect = rect.width / rect.height; + style = (aspect <= 1.5f) ? Singleton.getInstance().getBigButtonStyle(fontSize, aspect) : Singleton.getInstance().getBigTextButtonStyle(fontSize, aspect); + } + if (!GUI.Button(rect, text, style)) { + return false; + } + Singleton.getInstance().play((sound != null) ? sound : SoundListMenu.getInstance().ButtonClick, null); + return true; + } + + public bool renderTitleButton(Rect rect, string text, FontSize fontSize, GUIStyle style, bool playSound = false) { + return this.renderBigButton(rect, text, fontSize, style, null); + } + + } +} diff --git a/IModConfig.cs b/IModConfig.cs new file mode 100644 index 0000000..c25c409 --- /dev/null +++ b/IModConfig.cs @@ -0,0 +1,79 @@ +using System; +using System.Collections.Generic; +using System.Collections; +using System.Linq; +using System.Text; +using System.Text.RegularExpressions; + +namespace PlanetbaseFramework { + + public interface IModConfig { + + bool isActive(string modName); + void setActive(string modName, bool state); + + } + + public class SimpleFileBasedModConfig : IModConfig { + + private string configFile; + private Dictionary modConfigMap = null; + + public SimpleFileBasedModConfig(string configFile) { + this.configFile = configFile; + } + + private void loadConfig() { + modConfigMap = new Dictionary(); + if (!System.IO.File.Exists(configFile)) { + Console.WriteLine("Config file {0} not found. empty config.."); + return; + } + System.IO.StreamReader reader = new System.IO.StreamReader(configFile); + String line = null; + while ((line = reader.ReadLine()) != null) { + Regex commentRegex = new Regex(@"^#.*"); + Regex propertyRegex = new Regex(@".+=.*"); + if (commentRegex.Match(line).Success || !propertyRegex.Match(line).Success) + continue; + + String[] parts = line.Split(new char[] { '=' }, 2); + modConfigMap.Add(parts[0], (parts.Length > 1) ? parts[1] : ""); + } + reader.Close(); + } + + private void saveConfig() { + System.IO.StreamWriter writer = new System.IO.StreamWriter(configFile, false); + + foreach (KeyValuePair entry in modConfigMap) { + writer.WriteLine("{0}={1}", entry.Key, entry.Value); + } + writer.Flush(); + writer.Close(); + } + + public bool isActive(string modName) { + if (modConfigMap == null) + loadConfig(); + return (modConfigMap.ContainsKey(modName) && modConfigMap[modName].Equals("1")); + } + + public void setActive(string modName, bool state) { + if (modConfigMap == null) + loadConfig(); + + if (state) { + if (!modConfigMap.ContainsKey(modName)) + modConfigMap.Add(modName, "1"); + } + else { + if (modConfigMap.ContainsKey(modName)) + modConfigMap.Remove(modName); + } + saveConfig(); + } + + } + +} diff --git a/IModLoader.cs b/IModLoader.cs new file mode 100644 index 0000000..6b533d5 --- /dev/null +++ b/IModLoader.cs @@ -0,0 +1,32 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace PlanetbaseFramework { + + /// + ///Loads all mods from the mods directory + /// + public interface IModLoader { + + void setModDirectory(string path); + List loadAll(); + + } + + /* + public class OldModLoaderWrapper : ModLoader, IModLoader { + + public List loadAll() { + List list = new List(); + ModLoader.LoadAll(); + return ModLoader.ModList; + } + + public void setModDirectory(string path) { + throw new NotSupportedException(); + } + + }*/ +} diff --git a/IModMetaData.cs b/IModMetaData.cs new file mode 100644 index 0000000..aceb5ef --- /dev/null +++ b/IModMetaData.cs @@ -0,0 +1,65 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Collections; +using UnityEngine; + +namespace PlanetbaseFramework { + + + public interface IModMetaData { + + string GetName(); + Version GetVersion(); + string GetRootPath(); + ModBase GetMod(); + List GetTextures(); + List GetObjects(); + + // TODO: dependencies + + } + + public class SelfModMetaData : IModMetaData { + + private ModBase mod; + + public SelfModMetaData(ModBase mod) { + this.mod = mod; + } + + public ModBase GetMod() { + return mod; + } + + public string GetName() { + return mod.ModName; + } + + public Version GetVersion() { + return mod.ModVersion; + } + + public string GetRootPath() { + return mod.ModPath; + } + + public List GetTextures() { + return mod.ModTextures; + } + + public List GetObjects() { + return mod.ModObjects; + } + + + } + + /* + // TODO: implement xml based meta data + public class XmlModMetaData { + + } + */ +} diff --git a/ModBase.cs b/ModBase.cs index d0cf23f..3fbf294 100644 --- a/ModBase.cs +++ b/ModBase.cs @@ -15,6 +15,7 @@ public abstract class ModBase public List ModTextures { get; protected set; } public List ModObjects { get; protected set; } + public virtual Version ModVersion => new Version(0, 0, 0, 0); private HarmonyInstance Harmony { get; set; } @@ -130,6 +131,8 @@ public virtual void Update() { } + public virtual void Cleanup() {} + public int LoadAllStrings(string subfolder = null) { var files = GetAssetsMatchingFileType("xml", subfolder); diff --git a/ModListGameState.cs b/ModListGameState.cs index ff80bb3..8c6afce 100644 --- a/ModListGameState.cs +++ b/ModListGameState.cs @@ -1,9 +1,11 @@ using Planetbase; using UnityEngine; +using System.Collections.Generic; namespace PlanetbaseFramework { //This class was thrown together fairly quickly, but should be a decent example on making new gamestates. + //qp: followed instructions above.. public class ModListGameState : GameState { private GuiRenderer Renderer { get; } = new GuiRenderer(); @@ -20,10 +22,16 @@ public override void onGui() return; } + List datas = ModManager.getInstance().GetMetaDatas(); PrintLine("Loaded Mods:", 0); - for(var i = 0; i < ModLoader.ModList.Count; i++) + for(var i = 0; i < datas.Count; i++) { - PrintLine(ModLoader.ModList[i].ModName, i + 1); + string name = datas[i].GetName(); + string text = string.Format("{0} - ({1})", name, datas[i].GetVersion().ToString()); + if (name.Equals(Utils.GetFrameworkMod().ModName)) + PrintLine(text, i + 1, (ModManager.getInstance().isModActive(name)) ? Color.green : Color.red, FontSize.Normal); + else + PrintLine(text, i + 1, (ModManager.getInstance().isModActive(name)) ? Color.green : Color.gray, FontSize.Normal, name); } if (Renderer.renderBackButton( @@ -37,15 +45,34 @@ public override void onGui() } } - private void PrintLine(string text, int lineNumber) - { - Vector2 textLocation = new Vector2(50, 80); - GUIStyle labelStyle = Renderer.getLabelStyle(FontSize.Huge, FontStyle.Bold, TextAnchor.LowerLeft, FontType.Title); - labelStyle.normal.textColor = Color.blue; + private void PrintLine(string text, int lineNumber) { + PrintLine(text, lineNumber, Color.blue); + } - GUI.Label(new Rect(textLocation.x, textLocation.y + (GuiRenderer.getMenuButtonSize(FontSize.Huge).y )* lineNumber, Screen.width, GuiRenderer.getMenuButtonSize(FontSize.Huge).y - 30), text, labelStyle); + private void PrintLine(string text, int lineNumber, Color color, FontSize size = FontSize.Huge, string modName = null) + { + float deltaY = (GuiRenderer.getMenuButtonSize(FontSize.Huge).y); + + if (modName != null) { + Vector2 startLocation = new Vector2(50, 200); + Rect rect = new Rect(startLocation.x, startLocation.y + deltaY * lineNumber, GuiRenderer.getMenuButtonSize(FontSize.Huge).x - 30, GuiRenderer.getMenuButtonSize(FontSize.Huge).y - 30); + float aspect = rect.width / rect.height; + GUIStyle btnStyle = Singleton.getInstance().getBigTextButtonStyle(FontSize.Normal, aspect); + Color c = btnStyle.normal.textColor; + btnStyle.normal.textColor = color; + if (Renderer.renderTitleButton(rect, text, FontSize.Normal)) { + ModManager.getInstance().setModActive(modName, !(color == Color.green)); + } + btnStyle.normal.textColor = c; + } + else { + Vector2 startLocation = new Vector2(55, 200); + GUIStyle labelStyle = Renderer.getLabelStyle(size, FontStyle.Bold, TextAnchor.LowerLeft, FontType.Title); + labelStyle.normal.textColor = color; + GUI.Label(new Rect(startLocation.x, startLocation.y + deltaY * lineNumber, Screen.width, GuiRenderer.getMenuButtonSize(FontSize.Huge).y - 30), text, labelStyle); - labelStyle.normal.textColor = Color.white; + labelStyle.normal.textColor = Color.white; + } } } } \ No newline at end of file diff --git a/ModManager.cs b/ModManager.cs new file mode 100644 index 0000000..d94e64f --- /dev/null +++ b/ModManager.cs @@ -0,0 +1,152 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Collections; +using Planetbase; +using UnityEngine; + +namespace PlanetbaseFramework { + + + + public class ModManager { + + private static ModManager instance = null; + + public static ModManager getInstance() { + if (instance == null) { + instance = new ModManager(); + } + return instance; + } + + + + private Dictionary modMetaDatas = new Dictionary(); + + private Dictionary mods = new Dictionary(); + private Dictionary activeMods = new Dictionary(); + + private IModConfig modConfig; + //private IModLoader modLoader; + + public ModManager() { + init(); + } + + + private void init() { + modConfig = new SimpleFileBasedModConfig(ModBase.BasePath+"/"+FrameworkMod.DefaultModName+"/.mods.cfg"); + + // register framework mod + FrameworkMod mod = new FrameworkMod(); + RegisterMod(new SelfModMetaData(mod), mod); + //leagcy support + ModLoader.ModList.Add(mod); + } + + /// + /// Set the implementation to use. + /// + /// The mod config implementation. + public void setModConfig(IModConfig modConfig) { + this.modConfig = modConfig; + } + + + /// + /// Registering a mod to the ModManager. + /// If the mod is newer + /// + /// + /// + public bool RegisterMod(IModMetaData metaData, ModBase mod) { + string name = metaData.GetName(); + if (modMetaDatas.ContainsKey(name)) { + /// TODO: Can't get the original version?! always 0.0.0.0 on both sides.. + Debug.Log($"{modMetaDatas[name].GetVersion()} <> {metaData.GetVersion()} = {modMetaDatas[name].GetVersion().CompareTo(metaData.GetVersion())}"); + if (modMetaDatas[name].GetVersion().CompareTo(metaData.GetVersion()) >= 0) { + Debug.Log($"Newer or equal version ({modMetaDatas[name].GetVersion()} <- {metaData.GetVersion()}) of mod {name} already exists , skipping registration."); + return false; + } + Debug.Log($"Older version of mod {name} already exists, removing.."); + if (isModActive(name)) { + cleanupMod(mods[name]); + activeMods.Remove(name); + } + modMetaDatas.Remove(name); + mods.Remove(name); + } + modMetaDatas[name] = metaData; + mods[name] = mod; + Debug.Log($"Mod {name} registered with version {metaData.GetVersion()}"); + if (mod.GetType() == typeof(FrameworkMod) || modConfig.isActive(name)) { + activeMods[name] = mod; + initMod(mod); + Debug.Log($"Mod {name} auto activated."); + } + return true; + } + + private void initMod(ModBase mod) { + try { + mod.Init(); + } catch (Exception e) { + Debug.Log($"Error initializing mod \"{mod.ModName}\""); + Utils.LogException(e); + } + } + + private void cleanupMod(ModBase mod) { + try { + mod.Cleanup(); + } + catch (Exception e) { + Debug.Log($"Error cleanup mod \"{mod.ModName}\""); + Utils.LogException(e); + } + } + /// + /// Update hook for the mods. + /// TODO: Changing patcher, called from , can be direct. + /// + // copied from ModLoader + public void UpdateMods() { + foreach (ModBase mod in activeMods.Values) { + try { + mod.Update(); + } + catch (Exception e) { + Debug.Log($"Error updating mod {mod.ModName}"); + Utils.LogException(e); + } + } + } + + + public List GetMetaDatas() { + return new List(modMetaDatas.Values); + } + + public bool isModActive(string name) { + return (activeMods.ContainsKey(name)); + } + + public void setModActive(string modName, bool state = true) { + ModBase mod = mods[modName]; + if (state) { + initMod(mod); + activeMods.Add(modName, mod); + } + else { + activeMods.Remove(modName); + cleanupMod(mod); + } + modConfig.setActive(modName, state); + } + + } + + +} diff --git a/Modloader.cs b/Modloader.cs index 2ec665b..3104532 100644 --- a/Modloader.cs +++ b/Modloader.cs @@ -21,8 +21,12 @@ public class ModLoader /// /// Called by the game manager on startup to load in mods /// - public static void LoadMods() - { + public static void LoadMods() { + /* ModManager.getInstance().loadMods(); + } + + public static void LoadAll() + {*/ Debug.Log("Loading mods..."); var modDLLs = new List(); @@ -31,7 +35,9 @@ public static void LoadMods() if (Directory.Exists(ModBase.BasePath)) { - modDLLs.AddRange(Directory.GetFiles(ModBase.BasePath, "*.dll")); + foreach (string dir in Directory.GetDirectories(ModBase.BasePath)) { + modDLLs.AddRange(Directory.GetFiles(dir, "*.dll")); + } } else { @@ -100,9 +106,12 @@ public static void LoadMods() try { - mod.Init(); - ModList.Add(mod); - Debug.Log($"Loaded mod \"{modName}\""); + // nope, just load.. + //mod.Init(); + if (ModManager.getInstance().RegisterMod(createMetaData(mod), mod)) { + ModList.Add(mod); + Debug.Log($"Loaded mod \"{modName}\""); + } } catch (Exception e) { @@ -122,10 +131,22 @@ public static void LoadMods() Debug.Log($"Successfully loaded {modDLLs.Count} mods"); } + /// + /// Give a chance to override the implementation by other implementations. + /// + /// The mod + /// A implementation of the given mod. + static internal IModMetaData createMetaData(ModBase mod) { + return new SelfModMetaData(mod); + } + /// /// Update the mods in the order they were loaded on each game tick. /// - public static void UpdateMods() + public static void UpdateMods() { + ModManager.getInstance().UpdateMods(); + } + /* { foreach(var mod in ModList) { @@ -139,7 +160,7 @@ public static void UpdateMods() Utils.LogException(e); } } - } + }*/ /// /// Utility method to get mods that match the provided type diff --git a/Patches/Planetbase/GameManager/Update.cs b/Patches/Planetbase/GameManager/Update.cs index 1bde001..22ac82f 100644 --- a/Patches/Planetbase/GameManager/Update.cs +++ b/Patches/Planetbase/GameManager/Update.cs @@ -8,7 +8,8 @@ public class Update { public static void Postfix() { - ModLoader.UpdateMods(); + //ModLoader.UpdateMods(); + ModManager.getInstance().UpdateMods(); } } } \ No newline at end of file diff --git a/PlanetbaseFramework.csproj b/PlanetbaseFramework.csproj index beab27b..fd4c340 100644 --- a/PlanetbaseFramework.csproj +++ b/PlanetbaseFramework.csproj @@ -20,7 +20,7 @@ true full false - bin\Debug\ + ..\..\games\steam\steamapps\common\Planetbase\Planetbase_Data\Managed\ DEBUG;TRACE prompt 4 @@ -51,24 +51,33 @@ - packages\Lib.Harmony.1.2.0.1\lib\net35\0Harmony.dll + ..\..\games\steam\steamapps\common\Planetbase\Planetbase_Data\Managed\0Harmony.dll + False False - ..\..\..\..\..\Program Files (x86)\Steam\steamapps\common\Planetbase\Planetbase_Data\Managed\Assembly-CSharp.dll + ..\..\games\steam\steamapps\common\Planetbase\Planetbase_Data\Managed\Assembly-CSharp.dll + False packages\SharpZipLib.0.86.0\lib\20\ICSharpCode.SharpZipLib.dll + False - ..\..\..\..\..\Program Files (x86)\Steam\steamapps\common\Planetbase\Planetbase_Data\Managed\UnityEngine.dll + ..\..\games\steam\steamapps\common\Planetbase\Planetbase_Data\Managed\UnityEngine.dll + False + + + + + @@ -99,6 +108,7 @@ + diff --git a/PlanetbaseFramework.csproj.user b/PlanetbaseFramework.csproj.user index ca1d04b..1764eb9 100644 --- a/PlanetbaseFramework.csproj.user +++ b/PlanetbaseFramework.csproj.user @@ -3,4 +3,8 @@ ProjectFiles + + Program + D:\games\steam\steamapps\common\Planetbase\Planetbase.exe + \ No newline at end of file diff --git a/assets/strings/framework_de.xml b/assets/strings/framework_de.xml new file mode 100644 index 0000000..ed610af --- /dev/null +++ b/assets/strings/framework_de.xml @@ -0,0 +1,5 @@ + + + Mod Liste + + \ No newline at end of file diff --git a/assets/strings/framework_en.xml b/assets/strings/framework_en.xml index c794f6d..efe9074 100644 --- a/assets/strings/framework_en.xml +++ b/assets/strings/framework_en.xml @@ -1,5 +1,5 @@ - Mod List + Mod List \ No newline at end of file From 5250747de1419ab20c9407cf7fc99df2a4ae0e58 Mon Sep 17 00:00:00 2001 From: S K Date: Mon, 20 Jan 2020 15:59:52 +0100 Subject: [PATCH 2/2] * Formatted code to project style. * Added legacy load functionality * Removed unused imports --- GuiRenderer.cs | 20 +++++--- IModConfig.cs | 47 +++++++++++-------- IModLoader.cs | 32 ------------- IModMetaData.cs | 33 ++++++++------ ModBase.cs | 6 +-- ModListGameState.cs | 16 ++++--- ModManager.cs | 93 ++++++++++++++++++++++++-------------- Modloader.cs | 42 ++++++----------- PlanetbaseFramework.csproj | 1 - 9 files changed, 150 insertions(+), 140 deletions(-) delete mode 100644 IModLoader.cs diff --git a/GuiRenderer.cs b/GuiRenderer.cs index c32bdcb..db9b66b 100644 --- a/GuiRenderer.cs +++ b/GuiRenderer.cs @@ -2,24 +2,32 @@ using UnityEngine; using Planetbase; -namespace PlanetbaseFramework { - class GuiRenderer : Planetbase.GuiRenderer { +namespace PlanetbaseFramework +{ + class GuiRenderer : Planetbase.GuiRenderer + { - public bool renderBigButton(Rect rect, string text, FontSize fontSize, GUIStyle style, SoundDefinition sound = null) { - if (style == null) { + public bool renderBigButton(Rect rect, string text, FontSize fontSize, GUIStyle style, SoundDefinition sound = null) + { + if (style == null) + { float aspect = rect.width / rect.height; style = (aspect <= 1.5f) ? Singleton.getInstance().getBigButtonStyle(fontSize, aspect) : Singleton.getInstance().getBigTextButtonStyle(fontSize, aspect); } - if (!GUI.Button(rect, text, style)) { + if (!GUI.Button(rect, text, style)) + { return false; } Singleton.getInstance().play((sound != null) ? sound : SoundListMenu.getInstance().ButtonClick, null); return true; } - public bool renderTitleButton(Rect rect, string text, FontSize fontSize, GUIStyle style, bool playSound = false) { + public bool renderTitleButton(Rect rect, string text, FontSize fontSize, GUIStyle style, bool playSound = false) + { return this.renderBigButton(rect, text, fontSize, style, null); } } } + + diff --git a/IModConfig.cs b/IModConfig.cs index c25c409..d58e888 100644 --- a/IModConfig.cs +++ b/IModConfig.cs @@ -1,37 +1,42 @@ using System; using System.Collections.Generic; -using System.Collections; -using System.Linq; -using System.Text; using System.Text.RegularExpressions; +using UnityEngine; -namespace PlanetbaseFramework { +namespace PlanetbaseFramework +{ - public interface IModConfig { + public interface IModConfig + { bool isActive(string modName); void setActive(string modName, bool state); } - public class SimpleFileBasedModConfig : IModConfig { + public class SimpleFileBasedModConfig : IModConfig + { private string configFile; private Dictionary modConfigMap = null; - public SimpleFileBasedModConfig(string configFile) { + public SimpleFileBasedModConfig(string configFile) + { this.configFile = configFile; } - private void loadConfig() { + private void loadConfig() + { modConfigMap = new Dictionary(); - if (!System.IO.File.Exists(configFile)) { - Console.WriteLine("Config file {0} not found. empty config.."); + if (!System.IO.File.Exists(configFile)) + { + Debug.Log("Config file {0} not found. empty config.."); return; } System.IO.StreamReader reader = new System.IO.StreamReader(configFile); String line = null; - while ((line = reader.ReadLine()) != null) { + while ((line = reader.ReadLine()) != null) + { Regex commentRegex = new Regex(@"^#.*"); Regex propertyRegex = new Regex(@".+=.*"); if (commentRegex.Match(line).Success || !propertyRegex.Match(line).Success) @@ -43,31 +48,37 @@ private void loadConfig() { reader.Close(); } - private void saveConfig() { + private void saveConfig() + { System.IO.StreamWriter writer = new System.IO.StreamWriter(configFile, false); - - foreach (KeyValuePair entry in modConfigMap) { + + foreach (KeyValuePair entry in modConfigMap) + { writer.WriteLine("{0}={1}", entry.Key, entry.Value); } writer.Flush(); writer.Close(); } - public bool isActive(string modName) { + public bool isActive(string modName) + { if (modConfigMap == null) loadConfig(); return (modConfigMap.ContainsKey(modName) && modConfigMap[modName].Equals("1")); } - public void setActive(string modName, bool state) { + public void setActive(string modName, bool state) + { if (modConfigMap == null) loadConfig(); - if (state) { + if (state) + { if (!modConfigMap.ContainsKey(modName)) modConfigMap.Add(modName, "1"); } - else { + else + { if (modConfigMap.ContainsKey(modName)) modConfigMap.Remove(modName); } diff --git a/IModLoader.cs b/IModLoader.cs deleted file mode 100644 index 6b533d5..0000000 --- a/IModLoader.cs +++ /dev/null @@ -1,32 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; - -namespace PlanetbaseFramework { - - /// - ///Loads all mods from the mods directory - /// - public interface IModLoader { - - void setModDirectory(string path); - List loadAll(); - - } - - /* - public class OldModLoaderWrapper : ModLoader, IModLoader { - - public List loadAll() { - List list = new List(); - ModLoader.LoadAll(); - return ModLoader.ModList; - } - - public void setModDirectory(string path) { - throw new NotSupportedException(); - } - - }*/ -} diff --git a/IModMetaData.cs b/IModMetaData.cs index aceb5ef..3669c56 100644 --- a/IModMetaData.cs +++ b/IModMetaData.cs @@ -1,14 +1,13 @@ using System; using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Collections; using UnityEngine; -namespace PlanetbaseFramework { +namespace PlanetbaseFramework +{ - public interface IModMetaData { + public interface IModMetaData + { string GetName(); Version GetVersion(); @@ -21,35 +20,43 @@ public interface IModMetaData { } - public class SelfModMetaData : IModMetaData { + public class SelfModMetaData : IModMetaData + { private ModBase mod; - public SelfModMetaData(ModBase mod) { + public SelfModMetaData(ModBase mod) + { this.mod = mod; } - public ModBase GetMod() { + public ModBase GetMod() + { return mod; } - public string GetName() { + public string GetName() + { return mod.ModName; } - public Version GetVersion() { + public Version GetVersion() + { return mod.ModVersion; } - public string GetRootPath() { + public string GetRootPath() + { return mod.ModPath; } - public List GetTextures() { + public List GetTextures() + { return mod.ModTextures; } - public List GetObjects() { + public List GetObjects() + { return mod.ModObjects; } diff --git a/ModBase.cs b/ModBase.cs index 3fbf294..13137c3 100644 --- a/ModBase.cs +++ b/ModBase.cs @@ -15,7 +15,7 @@ public abstract class ModBase public List ModTextures { get; protected set; } public List ModObjects { get; protected set; } - + public virtual Version ModVersion => new Version(0, 0, 0, 0); private HarmonyInstance Harmony { get; set; } @@ -101,7 +101,7 @@ protected ModBase() { ModObjects = LoadAllObjs("obj"); - if(ModObjects.Count > 0) + if (ModObjects.Count > 0) { Debug.Log($"Successfully loaded {ModObjects.Count} object(s)"); } @@ -131,7 +131,7 @@ public virtual void Update() { } - public virtual void Cleanup() {} + public virtual void Cleanup() { } public int LoadAllStrings(string subfolder = null) { diff --git a/ModListGameState.cs b/ModListGameState.cs index 8c6afce..a9a1086 100644 --- a/ModListGameState.cs +++ b/ModListGameState.cs @@ -24,7 +24,7 @@ public override void onGui() List datas = ModManager.getInstance().GetMetaDatas(); PrintLine("Loaded Mods:", 0); - for(var i = 0; i < datas.Count; i++) + for (var i = 0; i < datas.Count; i++) { string name = datas[i].GetName(); string text = string.Format("{0} - ({1})", name, datas[i].GetVersion().ToString()); @@ -45,27 +45,31 @@ public override void onGui() } } - private void PrintLine(string text, int lineNumber) { + private void PrintLine(string text, int lineNumber) + { PrintLine(text, lineNumber, Color.blue); } private void PrintLine(string text, int lineNumber, Color color, FontSize size = FontSize.Huge, string modName = null) { float deltaY = (GuiRenderer.getMenuButtonSize(FontSize.Huge).y); - - if (modName != null) { + + if (modName != null) + { Vector2 startLocation = new Vector2(50, 200); Rect rect = new Rect(startLocation.x, startLocation.y + deltaY * lineNumber, GuiRenderer.getMenuButtonSize(FontSize.Huge).x - 30, GuiRenderer.getMenuButtonSize(FontSize.Huge).y - 30); float aspect = rect.width / rect.height; GUIStyle btnStyle = Singleton.getInstance().getBigTextButtonStyle(FontSize.Normal, aspect); Color c = btnStyle.normal.textColor; btnStyle.normal.textColor = color; - if (Renderer.renderTitleButton(rect, text, FontSize.Normal)) { + if (Renderer.renderTitleButton(rect, text, FontSize.Normal)) + { ModManager.getInstance().setModActive(modName, !(color == Color.green)); } btnStyle.normal.textColor = c; } - else { + else + { Vector2 startLocation = new Vector2(55, 200); GUIStyle labelStyle = Renderer.getLabelStyle(size, FontStyle.Bold, TextAnchor.LowerLeft, FontType.Title); labelStyle.normal.textColor = color; diff --git a/ModManager.cs b/ModManager.cs index d94e64f..76fd4e1 100644 --- a/ModManager.cs +++ b/ModManager.cs @@ -1,21 +1,22 @@ using System; using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Collections; -using Planetbase; using UnityEngine; +using Planetbase; -namespace PlanetbaseFramework { +namespace PlanetbaseFramework +{ - public class ModManager { + public class ModManager + { private static ModManager instance = null; - public static ModManager getInstance() { - if (instance == null) { + public static ModManager getInstance() + { + if (instance == null) + { instance = new ModManager(); } return instance; @@ -31,13 +32,15 @@ public static ModManager getInstance() { private IModConfig modConfig; //private IModLoader modLoader; - public ModManager() { + public ModManager() + { init(); } - private void init() { - modConfig = new SimpleFileBasedModConfig(ModBase.BasePath+"/"+FrameworkMod.DefaultModName+"/.mods.cfg"); + private void init() + { + modConfig = new SimpleFileBasedModConfig(ModBase.BasePath + "/" + FrameworkMod.DefaultModName + "/.mods.cfg"); // register framework mod FrameworkMod mod = new FrameworkMod(); @@ -50,10 +53,11 @@ private void init() { /// Set the implementation to use. /// /// The mod config implementation. - public void setModConfig(IModConfig modConfig) { + public void setModConfig(IModConfig modConfig) + { this.modConfig = modConfig; } - + /// /// Registering a mod to the ModManager. @@ -61,17 +65,21 @@ public void setModConfig(IModConfig modConfig) { /// /// /// - public bool RegisterMod(IModMetaData metaData, ModBase mod) { + public bool RegisterMod(IModMetaData metaData, ModBase mod) + { string name = metaData.GetName(); - if (modMetaDatas.ContainsKey(name)) { + if (modMetaDatas.ContainsKey(name)) + { /// TODO: Can't get the original version?! always 0.0.0.0 on both sides.. Debug.Log($"{modMetaDatas[name].GetVersion()} <> {metaData.GetVersion()} = {modMetaDatas[name].GetVersion().CompareTo(metaData.GetVersion())}"); - if (modMetaDatas[name].GetVersion().CompareTo(metaData.GetVersion()) >= 0) { + if (modMetaDatas[name].GetVersion().CompareTo(metaData.GetVersion()) >= 0) + { Debug.Log($"Newer or equal version ({modMetaDatas[name].GetVersion()} <- {metaData.GetVersion()}) of mod {name} already exists , skipping registration."); return false; } Debug.Log($"Older version of mod {name} already exists, removing.."); - if (isModActive(name)) { + if (isModActive(name)) + { cleanupMod(mods[name]); activeMods.Remove(name); } @@ -81,7 +89,8 @@ public bool RegisterMod(IModMetaData metaData, ModBase mod) { modMetaDatas[name] = metaData; mods[name] = mod; Debug.Log($"Mod {name} registered with version {metaData.GetVersion()}"); - if (mod.GetType() == typeof(FrameworkMod) || modConfig.isActive(name)) { + if (mod.GetType() == typeof(FrameworkMod) || modConfig.isActive(name)) + { activeMods[name] = mod; initMod(mod); Debug.Log($"Mod {name} auto activated."); @@ -89,20 +98,27 @@ public bool RegisterMod(IModMetaData metaData, ModBase mod) { return true; } - private void initMod(ModBase mod) { - try { + private void initMod(ModBase mod) + { + try + { mod.Init(); - } catch (Exception e) { + } + catch (Exception e) + { Debug.Log($"Error initializing mod \"{mod.ModName}\""); Utils.LogException(e); } } - private void cleanupMod(ModBase mod) { - try { + private void cleanupMod(ModBase mod) + { + try + { mod.Cleanup(); } - catch (Exception e) { + catch (Exception e) + { Debug.Log($"Error cleanup mod \"{mod.ModName}\""); Utils.LogException(e); } @@ -112,12 +128,16 @@ private void cleanupMod(ModBase mod) { /// TODO: Changing patcher, called from , can be direct. /// // copied from ModLoader - public void UpdateMods() { - foreach (ModBase mod in activeMods.Values) { - try { + public void UpdateMods() + { + foreach (ModBase mod in activeMods.Values) + { + try + { mod.Update(); } - catch (Exception e) { + catch (Exception e) + { Debug.Log($"Error updating mod {mod.ModName}"); Utils.LogException(e); } @@ -125,21 +145,26 @@ public void UpdateMods() { } - public List GetMetaDatas() { + public List GetMetaDatas() + { return new List(modMetaDatas.Values); } - public bool isModActive(string name) { + public bool isModActive(string name) + { return (activeMods.ContainsKey(name)); } - public void setModActive(string modName, bool state = true) { + public void setModActive(string modName, bool state = true) + { ModBase mod = mods[modName]; - if (state) { + if (state) + { initMod(mod); activeMods.Add(modName, mod); } - else { + else + { activeMods.Remove(modName); cleanupMod(mod); } @@ -148,5 +173,5 @@ public void setModActive(string modName, bool state = true) { } - + } diff --git a/Modloader.cs b/Modloader.cs index 3104532..9b5762c 100644 --- a/Modloader.cs +++ b/Modloader.cs @@ -21,12 +21,8 @@ public class ModLoader /// /// Called by the game manager on startup to load in mods /// - public static void LoadMods() { - /* ModManager.getInstance().loadMods(); - } - - public static void LoadAll() - {*/ + public static void LoadMods() + { Debug.Log("Loading mods..."); var modDLLs = new List(); @@ -35,7 +31,11 @@ public static void LoadAll() if (Directory.Exists(ModBase.BasePath)) { - foreach (string dir in Directory.GetDirectories(ModBase.BasePath)) { + //legacy support + modDLLs.AddRange(Directory.GetFiles(ModBase.BasePath, "*.dll")); + + foreach (string dir in Directory.GetDirectories(ModBase.BasePath)) + { modDLLs.AddRange(Directory.GetFiles(dir, "*.dll")); } } @@ -45,11 +45,11 @@ public static void LoadAll() Directory.CreateDirectory(ModBase.BasePath); //Create the planetbase mod folder and extract the assets - + } Debug.Log($"Found {modDLLs.Count} mods"); - + foreach (var file in modDLLs) { Type[] types; @@ -108,7 +108,8 @@ public static void LoadAll() { // nope, just load.. //mod.Init(); - if (ModManager.getInstance().RegisterMod(createMetaData(mod), mod)) { + if (ModManager.getInstance().RegisterMod(createMetaData(mod), mod)) + { ModList.Add(mod); Debug.Log($"Loaded mod \"{modName}\""); } @@ -136,31 +137,18 @@ public static void LoadAll() /// /// The mod /// A implementation of the given mod. - static internal IModMetaData createMetaData(ModBase mod) { + static internal IModMetaData createMetaData(ModBase mod) + { return new SelfModMetaData(mod); } /// /// Update the mods in the order they were loaded on each game tick. /// - public static void UpdateMods() { + public static void UpdateMods() + { ModManager.getInstance().UpdateMods(); } - /* - { - foreach(var mod in ModList) - { - try - { - mod.Update(); - } - catch (Exception e) - { - Debug.Log($"Error updating mod {mod.ModName}"); - Utils.LogException(e); - } - } - }*/ /// /// Utility method to get mods that match the provided type diff --git a/PlanetbaseFramework.csproj b/PlanetbaseFramework.csproj index fd4c340..69126a6 100644 --- a/PlanetbaseFramework.csproj +++ b/PlanetbaseFramework.csproj @@ -74,7 +74,6 @@ -