static void Main(string[] args) { // BEFORE you checkout the example: // this example is not optimized, it is not intended to be used in production // this should be used for understanding how the Framework operates, what it // needs, what you can do with it and what it returns Framework f = new Framework(); // basic, do this or go home string temp = @"M:\Projects\omod\testDLL\temp"; string OutputDir = @"M:\Projects\omod\testDLL\output"; // check if the temp and output dir already exist and delete them if they do if (Directory.Exists(temp)) { DeleteDirectory(temp); } Directory.CreateDirectory(temp); if (Directory.Exists(OutputDir)) { DeleteDirectory(OutputDir); } Directory.CreateDirectory(OutputDir); f.SetOBMMVersion(1, 1, 12); // latest official obmm version use this unless you know what you're doing f.SetTempDirectory(temp); // setting the dll path is mostly used for debugging or if you execute the code from somewhere else // better safe than sorry just do this if f.SetDLLPath(@"M:\Projects\OMOD-Framework\OMOD-Framework\bin\Release\erri120.OMODFramework.dll"); // after everything is setup you can go ahead and grap the omod OMOD omod = new OMOD(@"M:\Projects\omod\testDLL\Robert Male Body Replacer v52 OMOD-40532-1.omod", ref f); // before you run the install script, extract the data files and plugins from the omod // ExtractDataFiles will always return something but ExtractPlugins can return null if there is no // plugins.crc in the OMOD string dataPath = omod.ExtractDataFiles(); //extracts all data files and returns the path to them string pluginsPath = omod.ExtractPlugins(); //extracts all plugins and returns the path to them // the interface IScriptRunnerFunctions should be implemented by something that you can pass on // as an argument, in this case I created an internal class called ScriptFunctions that implements // all functions from the interface ScriptFunctions a = new ScriptFunctions(); // the script runner can execute the script, return the script and/or script type ScriptRunner sr = new ScriptRunner(ref omod, a); //to get the type: //ScriptType scriptType = sr.GetScriptType(); //to get the entire script without the first byte: //String script = sr.GetScript(); // this will execute the script and return all information about what needs to be installed ScriptReturnData srd = sr.ExecuteScript(); // after the script executed go ahead and do whatever you want with the ScriptReturnData: // be sure to check if the installation is canceled or you will run into issues if (srd.CancelInstall) { Console.WriteLine("Installation canceled"); } // just for testing bool doPretty = true; if (doPretty) { // if you do not want the raw output but a more 'prettier' version, use this method // it will change the ScriptReturnData and will populate the InstallFiles list srd.Pretty(true, ref omod, ref pluginsPath, ref dataPath); // loop through the whole thing, do note the custom struct foreach (InstallFile file in srd.InstallFiles) { string s = Path.GetDirectoryName(file.InstallTo); if (!Directory.Exists(Path.Combine(OutputDir, s))) { Directory.CreateDirectory(Path.Combine(OutputDir, s)); } File.Move(file.InstallFrom, Path.Combine(OutputDir, file.InstallTo)); } } else { // in the following example I will create two lists, one for all data files and one for all // plugins that need to be installed // this may seem non-intuitive since the ScriptReturnData should return this list // the thing is that you have InstallAll, Install, Ignore and Copy operations // the install script in the omod decideds what is best for itself List <string> InstallPlugins = new List <string>(); List <string> InstallDataFiles = new List <string>(); // start by checking if you can install all plugins if (srd.InstallAllPlugins) { // simply get all plugin files from the omod and loop through them // the s.Contains is just a safety check foreach (string s in omod.GetPluginList()) { if (!s.Contains("\\")) { InstallPlugins.Add(s); } } } // if you can't install everything go and check the list called InstallPlugins // this list gets populated when InstallAllPlugins is false // the Framework comes with two utility functions that helps in creating the temp list: // strArrayContains and strArrayRemove foreach (string s in srd.InstallPlugins) { if (!Framework.strArrayContains(InstallPlugins, s)) { InstallPlugins.Add(s); } } // next up is removing all plugins that are set to be ignored: foreach (string s in srd.IgnorePlugins) { Framework.strArrayRemove(InstallPlugins, s); } // last is going through the CopyPlugins list // in case you ask why there is a CopyPlugins list and what is does: // (it makes more sense with data files but whatever) // if the omod has eg this folder structure: // // installfiles/ // Option1/ // Meshes/ // Textures/ // Option2/ // Meshes/ // Textures/ // this is nice for writing the installation script as you kan keep track of what option // has what files // Authors than call CopyPlugins/Data and move the files from the options folder to // the root folder: // // meshes/ // textures/ // installfiles/ // Option1/ // Meshes/ // Textures/ // Option2/ // Meshes/ // Textures/ foreach (ScriptCopyDataFile scd in srd.CopyPlugins) { // check if the file you want to copy actually exists if (!File.Exists(Path.Combine(pluginsPath, scd.CopyFrom))) { return; } else { // check if the mod author didnt make a mistake if (scd.CopyFrom != scd.CopyTo) { // unlikely but you never know if (File.Exists(Path.Combine(pluginsPath, scd.CopyTo))) { File.Delete(Path.Combine(pluginsPath, scd.CopyTo)); } File.Copy(Path.Combine(pluginsPath, scd.CopyFrom), Path.Combine(pluginsPath, scd.CopyTo)); } // important to add the file to the temp list or else it will not be installed if (!Framework.strArrayContains(InstallPlugins, scd.CopyTo)) { InstallPlugins.Add(scd.CopyTo); } } } // now do the same for the data files :) if (srd.InstallAllData) { foreach (string s in omod.GetDataFileList()) { InstallDataFiles.Add(s); } } foreach (string s in srd.InstallData) { if (!Framework.strArrayContains(InstallDataFiles, s)) { InstallDataFiles.Add(s); } } foreach (string s in srd.IgnoreData) { Framework.strArrayRemove(InstallDataFiles, s); } foreach (ScriptCopyDataFile scd in srd.CopyDataFiles) { if (!File.Exists(Path.Combine(dataPath, scd.CopyFrom))) { return; } else { if (scd.CopyFrom != scd.CopyTo) { // because data files can be in subdirectories we have to check if the folder actually exists string dirName = Path.GetDirectoryName(Path.Combine(dataPath, scd.CopyTo)); if (!Directory.Exists(dirName)) { Directory.CreateDirectory(dirName); } if (File.Exists(Path.Combine(dataPath, scd.CopyTo))) { File.Delete(Path.Combine(dataPath, scd.CopyTo)); } File.Copy(Path.Combine(dataPath, scd.CopyFrom), Path.Combine(dataPath, scd.CopyTo)); } if (!Framework.strArrayContains(InstallDataFiles, scd.CopyTo)) { InstallDataFiles.Add(scd.CopyTo); } } } // after everything is done some final checks for (int i = 0; i < InstallDataFiles.Count; i++) { // if the files have \\ at the start than Path.Combine wont work :( if (InstallDataFiles[i].StartsWith("\\")) { InstallDataFiles[i] = InstallDataFiles[i].Substring(1); } string currentFile = Path.Combine(dataPath, InstallDataFiles[i]); // also check if the file we want to install exists and is not in the 5th dimension eating lunch if (!File.Exists(currentFile)) { InstallDataFiles.RemoveAt(i--); } } for (int i = 0; i < InstallPlugins.Count; i++) { if (InstallPlugins[i].StartsWith("\\")) { InstallPlugins[i] = InstallPlugins[i].Substring(1); } string currentFile = Path.Combine(pluginsPath, InstallPlugins[i]); if (!File.Exists(currentFile)) { InstallPlugins.RemoveAt(i--); } } // now install for (int i = 0; i < InstallDataFiles.Count; i++) { // check if the folder exists before copying string s = Path.GetDirectoryName(InstallDataFiles[i]); if (!Directory.Exists(Path.Combine(OutputDir, s))) { Directory.CreateDirectory(Path.Combine(OutputDir, s)); } File.Move(Path.Combine(dataPath, InstallDataFiles[i]), Path.Combine(OutputDir, InstallDataFiles[i])); } for (int i = 0; i < InstallPlugins.Count; i++) { File.Move(Path.Combine(pluginsPath, InstallPlugins[i]), Path.Combine(OutputDir, InstallPlugins[i])); } } }