Ejemplo n.º 1
0
        static void Stub2()
        {
            OMOD             omod            = null;
            IScriptFunctions scriptFunctions = null;

            Rtf.ToHtml("");
        }
Ejemplo n.º 2
0
        private static async Task <Dictionary <RelativePath, T> > GatheringExtractWithOMOD <T>(Stream archive, Predicate <RelativePath> shouldExtract, Func <RelativePath, IStreamFactory, ValueTask <T> > mapfn)
        {
            var tmpFile = new TempFile();
            await tmpFile.Path.WriteAllAsync(archive);

            var dest = await TempFolder.Create();

            Utils.Log($"Extracting {(string)tmpFile.Path}");

            Framework.Settings.TempPath     = (string)dest.Dir;
            Framework.Settings.CodeProgress = new OMODProgress();

            var omod = new OMOD((string)tmpFile.Path);

            omod.GetDataFiles();
            omod.GetPlugins();

            var results = new Dictionary <RelativePath, T>();

            foreach (var file in dest.Dir.EnumerateFiles())
            {
                var path = file.RelativeTo(dest.Dir);
                if (!shouldExtract(path))
                {
                    continue;
                }

                var result = await mapfn(path, new NativeFileStreamFactory(file, path));

                results.Add(path, result);
            }

            return(results);
        }
Ejemplo n.º 3
0
        internal AScriptHandler(OMOD omod, string script, OMODScriptSettings settings, string?extractionFolder)
        {
            ScriptSettings = settings;

            OMOD   = omod;
            Script = script;

            var guid = Guid.NewGuid();

            ExtractionFolder = extractionFolder ?? Path.Combine(Path.GetTempPath(), "OMODFramework", guid.ToString("D"));

            DataFolder    = Path.Combine(ExtractionFolder, "data");
            PluginsFolder = Path.Combine(ExtractionFolder, "plugins");

            if (!settings.DryRun)
            {
                Directory.CreateDirectory(DataFolder);
                Directory.CreateDirectory(PluginsFolder);

                omod.ExtractFilesParallel(DataFolder, 4);
                if (omod.HasEntryFile(OMODEntryFileType.Plugins))
                {
                    omod.ExtractFiles(false, PluginsFolder);
                }
            }

            ScriptReturnData = new ScriptReturnData(DataFolder, PluginsFolder);
            ScriptFunctions  = new ScriptFunctions(ScriptSettings, omod, ScriptReturnData);
        }
Ejemplo n.º 4
0
        public CSharpScriptHandler(OMOD omod, string script, OMODScriptSettings settings, string?extractionFolder)
            : base(omod, script, settings, extractionFolder)
        {
            var scriptBytes = Encoding.UTF8.GetBytes(script);

            ScriptCRC = Crc32Algorithm.Compute(scriptBytes, 0, scriptBytes.Length);
        }
Ejemplo n.º 5
0
        public async void TestOMODExtractionParallel()
        {
            var file = Path.Combine("files", "test.omod");

            using var omod = new OMOD(file);

            const string outputDir = @"output-extraction-parallel";

            if (Directory.Exists(outputDir))
            {
                Directory.Delete(outputDir, true);
            }
            Directory.CreateDirectory(outputDir);

            var files = omod.GetFilesFromCRC(true);

            Assert.NotEmpty(files);

            omod.ExtractFilesParallel(outputDir, 4, 2, true);

            foreach (var outputPath in files.Select(compressedFile => Path.Combine(outputDir, compressedFile.Name)))
            {
                Assert.True(File.Exists(outputPath), $"File does not exist: {outputPath}");
            }
        }
Ejemplo n.º 6
0
        private static string ExtractAllWithOMOD(string source, string dest)
        {
            Utils.Log($"Extracting {Path.GetFileName(source)}");
            var omod = new OMOD(source);

            omod.ExtractDataFiles();
            omod.ExtractPlugins();
            return(dest);
        }
Ejemplo n.º 7
0
        public void TestOMOD()
        {
            Files.Do(f =>
            {
                var omod = new OMOD(f.FileName);

                Assert.IsNotNull(omod);
            });
        }
Ejemplo n.º 8
0
        private static void ExtractAllWithOMOD(string source, string dest)
        {
            Utils.Log($"Extracting {Path.GetFileName(source)}");
            var f = new Framework();

            f.SetTempDirectory(dest);
            var omod = new OMOD(source, ref f);

            omod.ExtractDataFiles();
            omod.ExtractPlugins();
        }
Ejemplo n.º 9
0
        private static void ExtractAllWithOMOD(AbsolutePath source, AbsolutePath dest)
        {
            Utils.Log($"Extracting {(string)source.FileName}");

            Framework.Settings.TempPath     = (string)dest;
            Framework.Settings.CodeProgress = new OMODProgress();

            var omod = new OMOD((string)source);

            omod.GetDataFiles();
            omod.GetPlugins();
        }
Ejemplo n.º 10
0
        private static void ExtractAllWithOMOD(string source, string dest)
        {
            Utils.Log($"Extracting {Path.GetFileName(source)}");

            Framework.Settings.TempPath     = dest;
            Framework.Settings.CodeProgress = new OMODProgress();

            var omod = new OMOD(source);

            omod.GetDataFiles();
            omod.GetPlugins();
        }
Ejemplo n.º 11
0
        //[TestMethod]
        public void TestCSharpScript()
        {
            Files.Do(f =>
            {
                var omod = new OMOD(f.FileName);

                Assert.IsNotNull(omod);

                var scriptFunctions = new ScriptFunctions();

                ScriptRunner.RunScript(omod, scriptFunctions);
            });
        }
Ejemplo n.º 12
0
        private static async Task <ExtractedFiles> ExtractAllWithOMOD(AbsolutePath source)
        {
            var dest = await TempFolder.Create();

            Utils.Log($"Extracting {(string)source.FileName}");

            Framework.Settings.TempPath     = (string)dest.Dir;
            Framework.Settings.CodeProgress = new OMODProgress();

            var omod = new OMOD((string)source);

            omod.GetDataFiles();
            omod.GetPlugins();

            return(new ExtractedFiles(dest));
        }
Ejemplo n.º 13
0
        public void TestExtraction()
        {
            Files.Do(f =>
            {
                var omod = new OMOD(f.FileName);

                Assert.IsNotNull(omod);

                var data = omod.GetDataFiles();
                Assert.IsNotNull(data);

                var plugins = omod.GetPlugins();
                Assert.IsTrue(omod.AllPlugins.Count == 0 && plugins == null ||
                              omod.AllPlugins.Count >= 1 && plugins != null);
            });
        }
Ejemplo n.º 14
0
        /// <summary>
        /// The ScriptRunner is responsible for running a script inside an OMOD
        /// </summary>
        /// <param name="omod">The OMOD with the script to be executed</param>
        /// <param name="scriptRunnerFunctions">All callback functions for execution</param>
        public ScriptRunner(ref OMOD omod, IScriptRunnerFunctions scriptRunnerFunctions)
        {
            OMOD = omod;
            ScriptRunnerFunctions = scriptRunnerFunctions;
            script = omod.GetScript();
            if ((byte)script[0] >= (byte)ScriptType.Count)
            {
                type = ScriptType.obmmScript;
            }
            else
            {
                type   = (ScriptType)script[0];
                script = script.Substring(1);
            }

            DataPath    = omod.ExtractDataFiles();
            PluginsPath = omod.ExtractPlugins();
        }
Ejemplo n.º 15
0
 private static bool CompareCreationToFile(ref OMODCreationOptions ops, ref OMOD omod)
 {
     if (ops.Name != omod.ModName)
     {
         return(false);
     }
     if (ops.Author != omod.Author)
     {
         return(false);
     }
     if (ops.Email != omod.Email)
     {
         return(false);
     }
     if (ops.Website != omod.Website)
     {
         return(false);
     }
     if (ops.Description != omod.Description)
     {
         return(false);
     }
     if (ops.MajorVersion != omod.MajorVersion)
     {
         return(false);
     }
     if (ops.MinorVersion != omod.MinorVersion)
     {
         return(false);
     }
     if (ops.BuildVersion != omod.BuildVersion)
     {
         return(false);
     }
     if (ops.CompressionType != omod.Compression)
     {
         return(false);
     }
     return(true);
 }
Ejemplo n.º 16
0
        public void TestCSharpScript(string fileName, long expectedFileLength, uint scriptCRC)
        {
            var file = Path.Combine("files", "csharp-scripting", fileName);

            if (!File.Exists(file))
            {
                return;
            }

            var fi = new FileInfo(file);
            var actualFileLength = fi.Length;

            Assert.Equal(expectedFileLength, actualFileLength);

            using var omod = new OMOD(file);

            var script = omod.GetScript();
            var crc    = Crc32Algorithm.Compute(Encoding.UTF8.GetBytes(script));

            Assert.Equal(scriptCRC, crc);

            //TODO: set this variable back to false once done testing locally
            const bool runScript = false;

            if (!runScript)
            {
                return;
            }
#pragma warning disable 162
            if (TestUtils.IsCI)
            {
                throw new Exception($"Someone forgot to change the runScript variable back to false before commiting!");
            }
            var scriptFunctions = new ExternalScriptFunctionsForTesting();
            var srd             = OMODScriptRunner.RunScript(omod, new OMODScriptSettings(scriptFunctions));

            Directory.Delete(srd.DataFolder);
            Directory.Delete(srd.PluginsFolder);
#pragma warning restore 162
        }
Ejemplo n.º 17
0
        public void TestScriptExecution(string fileName, long expectedFileLength)
        {
            /*
             * Get the mods listed above and put them into the OMODFramework.Test/files/obmm-scripting folder. They
             * will be copied to the output folder post build. I don't want to download those mods in the CI so this
             * test can only be run locally.
             */

            //TODO: make this run on the CI without having to download the mods (use data+plugin files index)

            var file = Path.Combine("files", "obmm-scripting", fileName);

            if (!File.Exists(file))
            {
                return;
            }

            var fi = new FileInfo(file);
            var actualFileLength = fi.Length;

            Assert.Equal(expectedFileLength, actualFileLength);

            var resultsFile = Path.Combine("files", "obmm-scripting", fileName + "-Results.txt");

            Assert.True(File.Exists(resultsFile));

            using var omod = new OMOD(file);

            var externalScriptFunctions = new ExternalScriptFunctionsForTesting(resultsFile, fileName);
            var settings = new OMODScriptSettings(externalScriptFunctions)
            {
                DryRun             = true,
                UseBitmapOverloads = false
            };

            var srd = OMODScriptRunner.RunScript(omod, settings);

            VerifyFiles(externalScriptFunctions.DataFiles, srd.DataFiles);
            VerifyFiles(externalScriptFunctions.PluginFiles, srd.PluginFiles);
        }
Ejemplo n.º 18
0
        public void TestOBMMScript()
        {
            Files.Do(f =>
            {
                var omod = new OMOD(f.FileName);

                Assert.IsNotNull(omod);

                var data    = omod.GetDataFiles();
                var plugins = omod.GetPlugins();

                var scriptFunctions = new ScriptFunctions();

                var srd = ScriptRunner.RunScript(omod, scriptFunctions, data, plugins);

                Assert.IsNotNull(srd);
                Assert.IsTrue(!srd.CancelInstall);

                srd.Pretty(omod, data, plugins);

                Assert.IsNotNull(srd.InstallFiles);
            });
        }
Ejemplo n.º 19
0
        /// <summary>
        /// Run the script inside an OMOD.
        /// </summary>
        /// <param name="omod">The OMOD with the script to run.</param>
        /// <param name="settings">The settings to use during Script Execution.</param>
        /// <param name="extractionFolder">The folder to extract the data and plugin files to. Defaults to a path
        /// inside the users temp folder if set to null.</param>
        /// <returns></returns>
        /// <exception cref="ArgumentException">The omod does not have a script.</exception>
        /// <exception cref="NotImplementedException">The script is of type <see cref="OMODScriptType.Python"/> or
        /// <see cref="OMODScriptType.VisualBasic"/>.</exception>
        /// <exception cref="ArgumentOutOfRangeException">The script has an unknown script type.</exception>
        public static ScriptReturnData RunScript(OMOD omod, OMODScriptSettings settings, string?extractionFolder = null)
        {
            if (!omod.HasEntryFile(OMODEntryFileType.Script))
            {
                throw new ArgumentException("OMOD does not have a script!", nameof(omod));
            }

            var script = omod.GetScript(out var scriptType);

            AScriptHandler handler = scriptType switch
            {
                OMODScriptType.OBMMScript => new OBMMScriptHandler(omod, script, settings, extractionFolder),
                OMODScriptType.CSharp => new CSharpScriptHandler(omod, script, settings, extractionFolder),
#pragma warning disable 618
                OMODScriptType.Python => throw new NotImplementedException(),
                      OMODScriptType.VisualBasic => throw new NotImplementedException(),
#pragma warning restore 618
                            _ => throw new ArgumentOutOfRangeException(nameof(scriptType), scriptType.ToString(),
                                                                       "Unknown script type")
            };

            return(handler.RunScript());
        }
    }
Ejemplo n.º 20
0
 internal ScriptFunctions(OMODScriptSettings settings, OMOD omod, ScriptReturnData srd)
 {
     _settings = settings;
     _omod     = omod;
     _srd      = srd;
 }
Ejemplo n.º 21
0
        public void TestCreation()
        {
            if (File.Exists("test.omod"))
            {
                File.Delete("test.omod");
            }
            Directory.CreateDirectory(Path.Combine(Framework.Settings.TempPath, "text_files"));

            var file1 = Path.Combine(Framework.Settings.TempPath, "file.txt");
            var file2 = Path.Combine(Framework.Settings.TempPath, "file2.txt");
            var file3 = Path.Combine(Framework.Settings.TempPath, "text_files", "file3.txt");

            var text1 = "This is some text";
            var text2 = "This is more text";
            var text3 = "MORE TEXT !!!!!!!!";

            File.WriteAllText(file1, text1);
            File.WriteAllText(file2, text2);
            File.WriteAllText(file3, text3);

            var ops = new OMODCreationOptions
            {
                Name                     = "Test OMOD",
                Author                   = "erri120",
                Email                    = "*****@*****.**",
                Website                  = "https://github.com/erri120",
                Description              = "The best OMOD you can find on the internet!",
                Image                    = "",
                MajorVersion             = 1,
                MinorVersion             = 0,
                BuildVersion             = 0,
                CompressionType          = CompressionType.SevenZip,
                DataFileCompressionLevel = CompressionLevel.Medium,
                OMODCompressionLevel     = CompressionLevel.Medium,
                ESPs                     = new List <string>(0),
                ESPPaths                 = new List <string>(0),
                DataFiles                = new List <string>
                {
                    file1,
                    file2,
                    file3
                },
                DataFilePaths = new List <string>
                {
                    "file.txt",
                    "file2.txt",
                    "text_files\\file3.txt"
                },
                Readme = "",
                Script = ""
            };

            OMOD.CreateOMOD(ops, "test.omod");

            Assert.IsTrue(File.Exists("test.omod"));

            var omod = new OMOD("test.omod");

            Assert.IsNotNull(omod);

            Assert.IsTrue(omod.ModName == ops.Name);
            Assert.IsTrue(omod.Author == ops.Author);
            Assert.IsTrue(omod.AllPlugins.Count == ops.ESPs.Count);
            Assert.IsTrue(omod.AllDataFiles.Count == ops.DataFiles.Count);

            var data = omod.GetDataFiles();

            Directory.EnumerateFiles(data, "*", SearchOption.AllDirectories).Do(file =>
            {
                var contents = File.ReadAllText(file);
                Assert.IsTrue(contents == text1 || contents == text2 || contents == text3);
            });
        }
Ejemplo n.º 22
0
        internal static OMODCompressedFile GetPluginFile(this OMOD omod, string file)
        {
            var compressedFile = omod.GetPluginFiles().First(x => x.Name.Equals(file.MakePath(), StringComparison.OrdinalIgnoreCase));

            return(compressedFile);
        }
Ejemplo n.º 23
0
        internal static PluginFile GetOrAddPluginFile(this ScriptReturnData srd, string file, OMOD omod, bool byInput = true)
        {
            var filePath   = file.MakePath();
            var pluginFile = srd.PluginFiles.FirstOrDefault(x => byInput
                ? x.Input.Name.Equals(filePath, StringComparison.OrdinalIgnoreCase)
                : x.Output.Equals(filePath, StringComparison.OrdinalIgnoreCase));

            if (pluginFile != null)
            {
                return(pluginFile);
            }

            var compressedFile = GetPluginFile(omod, filePath);

            pluginFile = new PluginFile(compressedFile);
            srd.PluginFiles.Add(pluginFile);

            return(pluginFile);
        }
Ejemplo n.º 24
0
 public static ScriptReturnData RunScript(OMOD omod, IScriptFunctions scriptFunctions, string data, string plugin)
 {
     return(ExecuteScript(omod.GetScript(), data, plugin, scriptFunctions));
 }
Ejemplo n.º 25
0
 public static ScriptReturnData RunScript(OMOD omod, IScriptFunctions scriptFunctions)
 {
     return(ExecuteScript(omod.GetScript(), omod.GetDataFiles(), omod.GetPlugins(), scriptFunctions));
 }
Ejemplo n.º 26
0
        public async void TestOMOD()
        {
            var file = Path.Combine("files", "test.omod");

            using var omod = new OMOD(file);
        }
Ejemplo n.º 27
0
        public void EndToEnd()
        {
            // Creation

            var ops = new OMODCreationOptions
            {
                Name                     = "I love, love... moist towelettes",
                Author                   = "erri120",
                Email                    = "*****@*****.**",
                Website                  = "https://github.com/erri120",
                Description              = "The best OMOD you can find on the internet!",
                Image                    = "",
                MajorVersion             = 6,
                MinorVersion             = 6,
                BuildVersion             = 6,
                CompressionType          = CompressionType.SevenZip,
                DataFileCompressionLevel = CompressionLevel.High,
                OMODCompressionLevel     = CompressionLevel.Medium,
                ESPs                     = new List <string>(0),
                ESPPaths                 = new List <string>(0),
                DataFiles                = ModFiles,
                DataFilePaths            = FolderStructure,
                Readme                   = Readme,
                Script                   = Script
            };

            OMOD.CreateOMOD(ops, OMODFile);

            Assert.IsTrue(File.Exists(OMODFile));

            // Test parsing

            var omod = new OMOD(OMODFile);

            Assert.IsNotNull(omod);
            Assert.IsTrue(CompareCreationToFile(ref ops, ref omod));

            // Test extraction

            var data = omod.GetDataFiles();

            var fList1 = new List <FileInfo>();
            var fList2 = new List <FileInfo>();

            Directory.GetFiles("files", "*", SearchOption.AllDirectories).Do(f =>
            {
                fList1.Add(new FileInfo(f));
            });

            Directory.GetFiles(data, "*", SearchOption.AllDirectories).Do(f =>
            {
                fList2.Add(new FileInfo(f));
            });

            Assert.IsTrue(fList1.Count == fList2.Count);

            for (var i = 0; i < fList1.Count; i++)
            {
                var f1 = fList1[i];
                var f2 = fList2[i];

                Assert.IsTrue(Equals(f1, f2, Path.GetFullPath("files"), data));
            }

            // Test scripting

            var scriptFunctions = new ScriptFunctions();

            var srd = ScriptRunner.RunScript(omod, scriptFunctions, data);

            Assert.IsNotNull(srd);
            Assert.IsTrue(!srd.CancelInstall);
            Assert.IsTrue(srd.CopyDataFiles.Count == 1 && srd.CopyDataFiles.TryGetValue(new ScriptCopyDataFile("A\\A.txt", "meshes\\a.txt"), out _));
            Assert.IsTrue(srd.InstallData.Contains("something.txt"));
        }
Ejemplo n.º 28
0
        public void TestOMODCreation()
        {
            var imageFile = Path.Combine("files", "image.png");

            Assert.True(File.Exists(imageFile));
            using var bitmap = (Bitmap)Image.FromFile(imageFile);

            var dataFile   = Path.Combine("files", "data.txt");
            var pluginFile = Path.Combine("files", "plugin.esp");

            Assert.True(File.Exists(dataFile));
            Assert.True(File.Exists(pluginFile));

            var options = new OMODCreationOptions(new Version(1, 2, 3))
            {
                Name                 = "erri120's Mod",
                Author               = "erri120",
                Email                = "*****@*****.**",
                Description          = "The best mod in existence",
                Website              = "https://github.com/erri120/OMODFramework",
                CompressionType      = CompressionType.SevenZip,
                OMODCompressionLevel = CompressionLevel.Optimal,
                Readme               = "This mod is very nice.",
                Script               = "Some script",
                Image                = bitmap,

                DataFiles = new List <OMODCreationFile>
                {
                    new OMODCreationFile(dataFile, "data.txt")
                },

                PluginFiles = new List <OMODCreationFile>
                {
                    new OMODCreationFile(pluginFile, "plugin.esp")
                }
            };

            using var ms   = OMODCreation.CreateOMOD(options);
            using var omod = new OMOD(ms);

            Assert.Equal(options.Name, omod.Config.Name);
            Assert.Equal(options.Author, omod.Config.Author);
            Assert.Equal(options.Email, omod.Config.Email);
            Assert.Equal(options.Description, omod.Config.Description);
            Assert.Equal(options.Website, omod.Config.Website);
            Assert.Equal(options.CompressionType, omod.Config.CompressionType);
            Assert.Equal(options.Version, omod.Config.Version);

            var readme = omod.GetReadme();

            Assert.Equal(options.Readme, readme);

            var script = omod.GetScript();

            Assert.Equal(options.Script, script);

            var image = omod.GetImage();

            Assert.Equal(options.Image.Size, image.Size);
            options.Image.Dispose();

            var dataFiles   = omod.GetDataFiles();
            var pluginFiles = omod.GetPluginFiles();

            Assert.Single(dataFiles);
            Assert.Single(pluginFiles);
        }
Ejemplo n.º 29
0
        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]));
                }
            }
        }