public void Create(ProgressHandler progress) { string modFilePath = GetFolderPath() + System.IO.Path.DirectorySeparatorChar + "Mod" + System.IO.Path.DirectorySeparatorChar + this.ID + ".dll"; if (!System.IO.File.Exists(modFilePath)) { Debug.Log("Mod: "+ID, "Couldn't find the compiled mod dll at \""+modFilePath+"\".", Debug.Type.ERROR); SetProgress(progress, "Error.FileNotFound"); return; } string modInfoPath = GetFolderPath() + System.IO.Path.DirectorySeparatorChar + "ModInfo.xml"; if (!System.IO.File.Exists(modInfoPath)) { Debug.Log("Mod: "+ID, "Couldn't find the mod configuration at \""+modInfoPath+"\".", Debug.Type.ERROR); SetProgress(progress, "Error.FileNotFound"); return; } string libraryFolder = Game.ModLibrary.GetLibraryFolder(); string baseModLibPath = libraryFolder + System.IO.Path.DirectorySeparatorChar + "BaseModLib.dll"; if (!System.IO.File.Exists(baseModLibPath)) { Debug.Log("Mod: "+ID, "Couldn't find BaseModLib.dll at \""+baseModLibPath+"\".", Debug.Type.ERROR); SetProgress(progress, "Error.FileNotFound"); return; } ModuleDefinition modModule; ModuleDefinition baseModLib; try { SetProgress(progress, 0f, "Preparing"); baseModLib = ModuleDefinition.ReadModule(baseModLibPath); SetProgress(progress, 5f); modModule = ModuleDefinition.ReadModule(modFilePath); SetProgress(progress, 10f); } catch (Exception e) { Debug.Log("Mod: "+ID, "One of the assemblies is corrupted: "+e.ToString(), Debug.Type.ERROR); SetProgress(progress, "Error.CorruptAssembly"); return; } Mod mod = new Mod(this.Game, ""); mod.header = new Mod.Header(mod, System.IO.File.ReadAllText(modInfoPath)); mod.module = modModule; MemoryStream stream = new MemoryStream(); mod.module.Write(stream); stream.Position = 0; mod.originalModule = ModuleDefinition.ReadModule(stream); SetProgress(progress, 15f); try { Dictionary<MethodReference, MethodReference> baseModLibRemap = new Dictionary<MethodReference, MethodReference>(); foreach (TypeDefinition baseModLibType in baseModLib.Types) { foreach (MethodDefinition method in baseModLibType.Methods) { if (method.HasCustomAttributes && method.CustomAttributes[0].AttributeType.Name == "AddModname") { foreach (MethodDefinition method2 in baseModLibType.Methods) { if (!method2.HasCustomAttributes && method2.Name == method.Name && method2.Parameters.Count > method.Parameters.Count) { bool add = true; for (int i = 0; i < method.Parameters.Count; i++) { ParameterDefinition param = method.Parameters[i]; if (param.ParameterType.FullName != method2.Parameters[i].ParameterType.FullName) add = false; } if (add) { baseModLibRemap.Add(method, method2); } } } } } } SetProgress(progress, 20f, "FetchingTypes"); Dictionary<string, string> injectableClasses = new Dictionary<string, string>(); Dictionary<string, Dictionary<string, TypeDefinition>> assemblyTypes = new Dictionary<string, Dictionary<string, TypeDefinition>>(); for (int i = 0; i < Game.GameConfiguration.IncludeAssemblies.Count; i++) { string assembly = libraryFolder + System.IO.Path.DirectorySeparatorChar + Game.ParsePath(Game.GameConfiguration.IncludeAssemblies[i]); ModuleDefinition module = ModuleDefinition.ReadModule(assembly); string key = System.IO.Path.GetFileNameWithoutExtension(assembly); assemblyTypes.Add(key, new Dictionary<string, TypeDefinition>()); foreach (TypeDefinition type in module.Types) { if (!ModLib.CheckName(type.Namespace, Game.GameConfiguration.ExcludeNamespaces) && !ModLib.CheckName(type.FullName, Game.GameConfiguration.ExcludeTypes) && !ModLib.CheckName(type.FullName, Game.GameConfiguration.NoFamily)) { assemblyTypes[key].Add(type.FullName, type); if (!injectableClasses.ContainsKey(type.FullName)) { injectableClasses.Add(type.FullName, key); } } } SetProgress(progress, 20f + ((float)i / (float)Game.GameConfiguration.IncludeAssemblies.Count) * 30f); } SetProgress(progress, 50f, "ConvertingClasses"); Dictionary<string, TypeDefinition> newClasses = new Dictionary<string, TypeDefinition>(); for (int i = 0; i < modModule.Types.Count; i++) { TypeDefinition type = modModule.Types[i]; if (type.FullName == "<Module>") continue; foreach (MethodDefinition method in type.Methods) { if (method != null && method.Body != null) { for (int j = 0; j < method.Body.Instructions.Count; j++) { ILProcessor methodIL = method.Body.GetILProcessor(); Instruction instruction = method.Body.Instructions[j]; if (instruction.OpCode == OpCodes.Call && instruction.Operand != null) { foreach (KeyValuePair<MethodReference, MethodReference> map in baseModLibRemap) { if (((MethodReference)instruction.Operand).FullName == map.Key.FullName) { instruction.Operand = type.Module.Import(map.Value); Instruction newInstruction = methodIL.Create(OpCodes.Ldstr, ID); methodIL.InsertBefore(instruction, newInstruction); } } } } } } string assemblyName = ""; if (type.BaseType != null && injectableClasses.ContainsKey(type.BaseType.FullName)) assemblyName = injectableClasses[type.BaseType.FullName]; if (assemblyName == "" || !assemblyTypes[assemblyName].ContainsKey(type.BaseType.FullName)) { Mod.Header.AddClass addClass = new Mod.Header.AddClass(mod); addClass.Type = type; mod.header.AddAddClass(addClass); } else { foreach (Mono.Cecil.FieldDefinition field in type.Fields) { Mod.Header.AddField addField = new Mod.Header.AddField(mod); addField.Field = field; addField.AssemblyName = assemblyName; mod.header.AddAddField(addField); } foreach (MethodDefinition method in type.Methods) { if (method == null) continue; int priority = int.MaxValue; if (method.CustomAttributes != null) { foreach (CustomAttribute attribute in method.CustomAttributes) { if (attribute.AttributeType.Name == "Priority") { priority = (int)attribute.ConstructorArguments[0].Value; } } } bool inject = false; if (method.IsVirtual || method.IsStatic || method.IsConstructor) { foreach (MethodDefinition _m in assemblyTypes[assemblyName][type.BaseType.FullName].Methods) { if (_m.Name == method.Name) { if ((_m.IsStatic && method.IsStatic) || (_m.IsConstructor && method.IsConstructor)) { if (method.Parameters.Count == _m.Parameters.Count) { bool ok = true; for (int pi = 0; pi < _m.Parameters.Count; pi++) { ParameterDefinition param = _m.Parameters[pi]; if (param.ParameterType.FullName != method.Parameters[pi].ParameterType.FullName) { ok = false; break; } } if (ok) { inject = true; } } } else if (!_m.IsStatic && !method.IsStatic) inject = true; break; } } } if (inject) { Mod.Header.InjectInto injectInto = new Mod.Header.InjectInto(mod); injectInto.Method = method; injectInto.Priority = priority; injectInto.AssemblyName = assemblyName; mod.header.AddInjectInto(injectInto); } else { Mod.Header.AddMethod addMethod = new Mod.Header.AddMethod(mod); addMethod.Method = method; addMethod.AssemblyName = assemblyName; mod.header.AddAddMethod(addMethod); } } } SetProgress(progress, 50f + ((float)i / (float)modModule.Types.Count) * 30f); } foreach (AssemblyNameReference aref in modModule.AssemblyReferences) { if (aref.Name == "mscorlib" || aref.Name == "System") { aref.Version = new System.Version("2.0.0.0"); aref.PublicKeyToken = new byte[] { 0xB7, 0x7A, 0x5C, 0x56, 0x19, 0x34, 0xE0, 0x89 }; } if (aref.Name == "System.Core") { aref.Version = new System.Version("3.5.0.0"); aref.PublicKeyToken = new byte[] { 0xB7, 0x7A, 0x5C, 0x56, 0x19, 0x34, 0xE0, 0x89 }; } if (aref.Name == "System.Xml") { aref.Version = new System.Version("2.0.0.0"); aref.PublicKeyToken = new byte[] { 0xB7, 0x7A, 0x5C, 0x56, 0x19, 0x34, 0xE0, 0x89 }; } } } catch (Exception e) { Debug.Log("Mod: "+ID, "An unexpected error occured while parsing the assembly: "+e.ToString(), Debug.Type.ERROR); SetProgress(progress, "Error.UnexpectedError"); return; } string modResourcesPath = GetFolderPath() + System.IO.Path.DirectorySeparatorChar + "Resources/"; if (!System.IO.Directory.Exists(modResourcesPath)) { System.IO.Directory.CreateDirectory(modResourcesPath); } if (System.IO.Directory.GetFiles(modResourcesPath).Length > 0 || System.IO.Directory.GetDirectories(modResourcesPath).Length > 0) { ZipFile newZipFile = new ZipFile(); newZipFile.AddDirectory(modResourcesPath); newZipFile.Comment = "Automaticlly created resources zip file."; mod.Resources = newZipFile; } try { SetProgress(progress, 90f, "SavingMod"); string modFolder = System.IO.Path.GetFullPath(Configuration.GetPath("mods") + System.IO.Path.DirectorySeparatorChar + Game.GameConfiguration.ID); if (!System.IO.Directory.Exists(modFolder)) System.IO.Directory.CreateDirectory(modFolder); mod.FileName = System.IO.Path.GetFullPath(modFolder + System.IO.Path.DirectorySeparatorChar + mod.UniqueID + ".mod"); if (mod.Save()) { string key = mod.ID + "-" + mod.header.GetVersion(); if (Mod.Mods.ContainsKey(key)) { if (Mod.Mods[key].FileName != mod.FileName) Mod.Mods[key].Remove(); //Mod.Mods[key] = mod; } /*else { Mod.Mods.Add(key, mod); }*/ SetProgress(progress, 100f, "Finish"); } else { Debug.Log("Mod: "+ID, "Could not save the mod.", Debug.Type.ERROR); SetProgress(progress, "Error.Save"); } } catch (Exception e) { Debug.Log("Mod: "+ID, "An error occured while saving the mod: "+e.ToString(), Debug.Type.ERROR); SetProgress(progress, "Error.Save"); } }
internal static void Add(Mod mod, string path, Texture2D texture) { string key = mod.ID + "::" + path.ToLower(); if (!TextureResources.ContainsKey(key)) TextureResources.Add(key, texture); }
public static void Initialize() { if (!Initialized) { Initialized = true; ModsFolder = System.IO.Path.GetFullPath(Application.dataPath + "/../Mods") + System.IO.Path.DirectorySeparatorChar; try { XDocument configuration = XDocument.Load(ModsFolder + "RuntimeConfiguration.xml"); foreach (XElement modConfiguration in configuration.Root.Elements("Mod")) { try { Mod newMod = new Mod(modConfiguration); if (newMod.ID != "") Mods.Add(newMod.ID, newMod); newMod.Assembly = Assembly.Load(new AssemblyName(newMod.ID)); ModAPI.Mods.Add(newMod); } catch (Exception e) { XAttribute idAttribute = modConfiguration.Attribute("ID"); string ID = "Core"; if (idAttribute != null) ID = idAttribute.Value; Log.Write("Something went wrong while initializing a mod: " + e.ToString(), ID); } } foreach (XElement ExecuteEveryFrame in configuration.Root.Elements("ExecuteEveryFrame")) { MethodInfo m = FindMethod(ExecuteEveryFrame.Value.ToString()); if (m != null) { string OnlyInGame = ExecuteEveryFrame.Attribute("OnlyInGame").Value; if (OnlyInGame == "true") BaseSystem.ExecuteEveryFrameInGame.Add(new Execution() { Method = m, ModID = ExecuteEveryFrame.Attribute("ModID").Value }); else BaseSystem.ExecuteEveryFrame.Add(new Execution() { Method = m, ModID = ExecuteEveryFrame.Attribute("ModID").Value }); } else { Log.Write("Could not find method for execute every frame: " + ExecuteEveryFrame.Value.ToString(), "Core"); } } foreach (XElement ExecuteOnApplicationStart in configuration.Root.Elements("ExecuteOnApplicationStart")) { MethodInfo m = FindMethod(ExecuteOnApplicationStart.Value.ToString()); if (m != null) { BaseSystem.ExecuteOnApplicationStart.Add(new Execution() { Method = m, ModID = ExecuteOnApplicationStart.Attribute("ModID").Value }); } else { Log.Write("Could not find method for execute on application start: " + ExecuteOnApplicationStart.Value.ToString(), "Core"); } } foreach (XElement ExecuteOnGameStart in configuration.Root.Elements("ExecuteOnGameStart")) { MethodInfo m = FindMethod(ExecuteOnGameStart.Value.ToString()); if (m != null) { BaseSystem.ExecuteOnGameStart.Add(new Execution() { Method = m, ModID = ExecuteOnGameStart.Attribute("ModID").Value }); } else { Log.Write("Could not find method for execute on game start: " + ExecuteOnGameStart.Value.ToString(), "Core"); } } WWW www = new WWW("file://" + ModsFolder + "GUI.assetbundle"); while (www.progress < 1) { } if ((www.error == "" || www.error == null) && www.assetBundle != null) { ModAPI.GUI.Skin = (GUISkin)www.assetBundle.mainAsset; } } catch (Exception e) { Log.Write("Something went wrong while initializing: " + e.ToString(), "Core"); } } if (SystemObject == null) { ModAPI.Log.Write(Application.loadedLevel + "", "Core"); SystemObject = new GameObject("__ModAPISystem__"); ; Input.Initialize(SystemObject); Console.Initialize(SystemObject); if (SystemObject.GetComponent<BaseSystem>() == null) SystemObject.AddComponent<BaseSystem>(); if (SystemObject.GetComponent<LiveInspector>() == null) SystemObject.AddComponent<LiveInspector>(); if (Application.loadedLevel > 0) { Execute(BaseSystem.ExecuteOnGameStart); } else { Execute(BaseSystem.ExecuteOnApplicationStart); } } }
public static void Add(Mod mod) { LoadedMods.Add(mod.ID, mod); }