Compare commits

..

No commits in common. "debug" and "master" have entirely different histories.

6 changed files with 56 additions and 372 deletions

2
.gitignore vendored
View file

@ -34,5 +34,3 @@ sysinfo.txt
# Builds
*.apk
*.unitypackage
bin/

View file

@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
@ -7,7 +7,7 @@
<OutputType>Library</OutputType>
<RootNamespace>BWModLoader</RootNamespace>
<AssemblyName>BWModLoader</AssemblyName>
<TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
<TargetFrameworkVersion>v4.7</TargetFrameworkVersion>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
@ -35,13 +35,13 @@
<ItemGroup>
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="src\Loader.cs" />
<Compile Include="src\ModLogger.cs" />
<Compile Include="src\ModGUI.cs" />
<Compile Include="src\ModLoader.cs" />
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />
</ItemGroup>
<ItemGroup />
<ItemGroup>
<Folder Include="src\" />
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
</Project>

View file

@ -1,49 +1,73 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using UnityEngine;
namespace BWModLoader
namespace ModLoader
{
public static class Loader
{
public static void Log(string output)
{
Console.WriteLine("[BWML]" + output);
//UnityEngine.Debug.Log("[BWML]" + output);
}
public static void Load()
{
string logfile = null;
#if DEBUG
logfile = ModLoader.LogPath + "\\modloader.log";
#endif
ModLogger logger = new ModLogger("[BWML]", logfile);
logger.ClearLog();
logger.Log("Starting mod loader...");
logger.DebugLog("Mods dir: " + ModLoader.ModsPath);
Log("Starting mod loader...");
if (!Directory.Exists(ModLoader.ModsPath))
string dllpath = new System.Uri(System.Reflection.Assembly.GetExecutingAssembly().CodeBase).LocalPath;
string Path = new FileInfo(dllpath).Directory.FullName;
string modsPath = Path + "\\Mods";
string assetsPath = modsPath + "\\Assets";
Log("Dll dir: "+Path);
Log("Mods dir: "+modsPath);
if (!Directory.Exists(modsPath))
{
Directory.CreateDirectory(ModLoader.ModsPath);
Directory.CreateDirectory(modsPath);
}
if (!Directory.Exists(ModLoader.AssetsPath))
if (!Directory.Exists(assetsPath))
{
Directory.CreateDirectory(ModLoader.AssetsPath);
Directory.CreateDirectory(assetsPath);
}
DirectoryInfo d = new DirectoryInfo(modsPath);
GameObject modObjects = new GameObject();
//For each DLL in "Blackwake/Blackwake_Data/Managed/Mods/"
//Open them, Get the mod class, then add it in the game.
ModLoader loader = new ModLoader(logger);
ModLoader.Instance = loader;
loader.RefreshModFiles();
foreach (FileInfo file in loader.GetAllMods().Keys)
foreach (var file in d.GetFiles("*.dll"))
{
loader.Load(file);
try
{
Assembly modDll = Assembly.LoadFrom(modsPath + "/" + file.Name);
Type[] modType = modDll.GetTypes();
foreach (Type t in modType)
{
Log("Found type in " + file.Name + ": " + t.Name);
if (t.IsClass && t.IsSubclassOf(typeof(MonoBehaviour)))
{
modObjects.AddComponent(t);
Log("Loaded '" + t.Name + "' in " + file.Name);
}
}
}
catch (Exception e)
{
Log("Exception raised while loading mod " + file.Name);
Log(e.Message);
Log("Skipped loading this mod");
}
}
logger.Log("All Mods have been Loaded!");
loader.ModObjects.AddComponent<ModGUI.ModGUI>();
logger.Log("GUI has been loaded");
Log("All Mods have been Loaded!");
modObjects.AddComponent<ModGUI.ModGUI>();
Log("GUI has been loaded");
//Keep mods active
UnityEngine.Object.DontDestroyOnLoad(loader.ModObjects);
UnityEngine.Object.DontDestroyOnLoad(modObjects);
}
}
}

View file

@ -1,143 +1,14 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using UnityEngine;
namespace BWModLoader.ModGUI
namespace ModGUI
{
public enum ScreenType
{
MOD,
LOG
}
/// <summary>
/// Manages contents and behaviour of the Debug Window
/// </summary>
public class ModGUI : MonoBehaviour
{
static bool debugEnabled;
static int currentScreen;
static Vector2 scrollPosition;
static Vector2 size;
static Vector2 position;
void Start()
{
currentScreen = (int)ScreenType.MOD;
scrollPosition = Vector2.zero;
debugEnabled = false;
size = new Vector2(1000, 1000);
position = new Vector2((Screen.width / 2) - (size.x / 2),
(Screen.height / 2) - (size.x / 2));
}
/// <summary>
/// Toggles the Window when the Hotkey is pressed
/// </summary>
void Update()
{
if (Input.GetKeyUp("insert"))
{
debugEnabled = !debugEnabled;
}
}
/// <summary>
/// Code that executes if the window was opened
/// </summary>
void OnGUI()
{
if (debugEnabled)
{
GUI.ModalWindow(0, new Rect(position, size), DebugWindow, "[BWML]Debug Menu");
}
}
/// <summary>
/// Manages contents of the window
/// </summary>
/// <param name="windowID">ID of the Debug Window</param>
void DebugWindow(int windowID)
{
GUI.DragWindow(new Rect(0, 0, 10000, 20));
currentScreen = GUI.SelectionGrid(new Rect(25, 25, size.x - 50, 75), currentScreen,
new string[] { "Mods", "Logs" }, 2);
if (currentScreen == (int)ScreenType.MOD)
{
ModWindow();
}
else
{
LogWindow();
}
}
/// <summary>
/// Logging window content
/// </summary>
void LogWindow()
{
GUI.Label(new Rect(0, 100, 100, 25), "LogWindow");
int logNum = 0;
if (ModLoader.Instance.Logger.Logs.Any())
{
scrollPosition = GUI.BeginScrollView(new Rect(0, 100, size.x, size.y - 100), scrollPosition, new Rect(0, 0, size.x, 50));
foreach (string log in ModLoader.Instance.Logger.Logs)
{
logNum++;
GUI.Label(new Rect(0, 25 * logNum, 1000, 25), log);
}
GUI.EndScrollView();
}
}
/// <summary>
/// Mod window content
/// </summary>
void ModWindow()
{
if (GUI.Button(new Rect(0, 100, 100, 25), "Reload all mods"))
{
ModLoader.Instance.RefreshModFiles();
}
scrollPosition = GUI.BeginScrollView(new Rect(0, 100, size.x, size.y - 100), scrollPosition, new Rect(0, 0, size.x, 50));
int modNum = 0;
var allmods = ModLoader.Instance.GetAllMods();
foreach (FileInfo file in allmods.Keys)
{
foreach (Type mod in allmods[file])
{
modNum++;
//GUI.Label(new Rect(0, modNum * 25, 100, 25), mod.Name);
//GUI.Toggle(new Rect(0, modNum * 25, 100, 25), ModLoader.Instance.IsLoaded(mod), mod.Name);
bool newCheckboxStatus = GUI.Toggle(new Rect(20, modNum * 25, 100, 25), ModLoader.Instance.IsLoaded(mod), mod.Name);
if (newCheckboxStatus)
{
if (!ModLoader.Instance.IsLoaded(mod))
{
ModLoader.Instance.Load(file);
}
}
else
{
if (ModLoader.Instance.IsLoaded(mod))
{
ModLoader.Instance.Unload(file);
}
}
// Reload the respective Mod
if (GUI.Button(new Rect(200, modNum * 25, 100, 25), "Reload"))
{
ModLoader.Instance.RefreshModFiles();
}
}
}
GUI.EndScrollView();
GUI.color = Color.red;
GUI.Label(new Rect(5f, 0f, 200f, 20f), "ModLoader v0.3");
}
}
}

View file

@ -1,141 +0,0 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using UnityEngine;
namespace BWModLoader
{
public class ModLoader
{
public static ModLoader Instance { get; internal set; }
private static readonly string dllpath = new Uri(Assembly.GetExecutingAssembly().CodeBase).LocalPath;
private static readonly string folderPath = Path.GetDirectoryName(dllpath);
public static string ModsPath => folderPath + "\\Mods";
public static string AssetsPath => ModsPath + "\\Assets";
public static string LogPath => ModsPath + "\\Logs";
public ModLogger Logger;
/// <summary>
/// All known mods files
/// </summary>
private readonly Dictionary<FileInfo, List<Type>> allMods = new Dictionary<FileInfo, List<Type>>();
/// <summary>
/// Gets all known mods files
/// </summary>
/// Prevent modification from outside by making copy
public Dictionary<FileInfo, List<Type>> GetAllMods() => new Dictionary<FileInfo, List<Type>>(allMods);
/// <summary>
/// GameObject that holds our mods
/// </summary>
public GameObject ModObjects { get; } = new GameObject();
public ModLoader(ModLogger logger)
{
this.Logger = logger;
}
/// <summary>
/// Checks if a mod is loaded
/// </summary>
/// <param name="mod"></param>
/// <returns></returns>
public bool IsLoaded(Type mod)
{
return ModObjects.GetComponent(mod) != null;
}
/// <summary>
/// Refresh all known mods
/// </summary>
public void RefreshModFiles()
{
DirectoryInfo dir = new DirectoryInfo(ModsPath);
//Unloads & clears known mods
foreach (var mod in allMods)
{
Unload(mod.Key);
}
allMods.Clear();
//Find all files to refresh
foreach (FileInfo file in dir.GetFiles("*.dll"))
{
//Save mod types and file path
allMods.Add(file, LoadModTypes(file));
Logger.Log("Found dll: " + file.Name);
}
}
/// <summary>
/// Finds and loads all mod classes in a file
/// </summary>
/// <param name="file">The file to load</param>
/// <returns></returns>
private List<Type> LoadModTypes(FileInfo file)
{
List<Type> mods = new List<Type>();
try
{
Assembly modDll = Assembly.LoadFrom(file.FullName);
Type[] modType = modDll.GetTypes();
foreach (Type t in modType)
{
Logger.Log("Found type in " + file.Name + ": " + t.Name);
if (t.IsClass && typeof(MonoBehaviour).IsAssignableFrom(t) && !t.IsAbstract && t.IsPublic)
{
mods.Add(t);
}
}
}
catch (Exception e)
{
Logger.Log("Exception raised while loading mod " + file.Name);
Logger.Log(e.Message);
Logger.Log("Skipped loading this mod");
}
return mods;
}
/// <summary>
/// will load a mod from memory
/// </summary>
/// <param name="file"></param>
public void Load(FileInfo file)
{
if (allMods.TryGetValue(file, out var types))
{
foreach (Type mod in types)
{
//if mod is not loaded
if (!IsLoaded(mod))
{
ModObjects.AddComponent(mod);
Logger.Log("Loaded: " + mod.Name + " From file: " + file.Name);
}
}
}
}
//Unloads a mod from game
public void Unload(FileInfo file)
{
if (allMods.TryGetValue(file, out var types))
{
foreach (Type mod in types)
{
//if mod is loaded
if (IsLoaded(mod))
{
UnityEngine.Object.Destroy(ModObjects.GetComponent(mod));
Logger.Log("Unloaded: " + mod.Name + " From file: " + file.Name);
}
}
}
}
}
}

View file

@ -1,68 +0,0 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
namespace BWModLoader
{
/// <summary>
/// Handles logging
/// </summary>
public class ModLogger
{
string prefix;
string file;
/// <summary>
/// Log history
/// </summary>
public List<string> Logs { get; } = new List<string>();
public ModLogger(string prefix, string file = null)
{
this.prefix = prefix;
this.file = file;
if (!string.IsNullOrEmpty(file) && !File.Exists(file))
{
Directory.CreateDirectory(Path.GetDirectoryName(file));
File.WriteAllText(file, "");
}
}
/// <summary>
/// Clears ingame log and log files
/// </summary>
public void ClearLog()
{
Logs.Clear();
if (!string.IsNullOrEmpty(file) && File.Exists(file))
{
File.Delete(file);
}
}
/// <summary>
/// Log to debugger and output.txt
/// </summary>
public void Log(string output)
{
Console.WriteLine(prefix + output);
Logs.Add(prefix + output);
if (!string.IsNullOrEmpty(file))
{
File.AppendAllText(file, prefix + output + Environment.NewLine);
}
}
/// <summary>
/// Only logs messages in Debug builds of the modloader
/// </summary>
public void DebugLog(string output)
{
#if DEBUG
Log(output);
#endif // DEBUG
}
}
}