public static CompilerException Compile(string modDirectory, string outputDirectory) { CommonToolUtilities.RefreshHashes(); string modName = Path.GetDirectoryName(modDirectory); string jsonFile, modInfo; CodeDomProvider cdcp = new CSharpCodeProvider(); string ext = "*.cs"; #region validating ModInfo.json jsonFile = modDirectory + "\\ModInfo.json"; if (!File.Exists(jsonFile)) { File.WriteAllText(jsonFile, "{\"name\":\"" + modName + "\",\"author\":\"<unknown>\"}"); Console.WriteLine("Warning: You do not have a ModInfo.json file.\n\tUsing the default ModInfo..."); } try { JsonData json = JsonMapper.ToObject(File.ReadAllText(jsonFile)); if (!json.Has("name")) { throw new CompilerException("Missing ModInfo filed 'name'"); } else { modName = (string)json["name"]; } if (!json.Has("author")) { throw new CompilerException("Missing ModInfo filed 'author'"); } if (json.Has("code")) { JsonData jCode = json["code"]; if (jCode.Has("codeType")) { switch (jCode["codeType"].ToString().ToLower().Trim()) { case "vb": case "vb.net": case "basic": case "basic.net": case "vbasic": case "vbasic.net": case "visualbasic": case "visualbasic.net": case "visual basic": case "visual basic.net": cdcp = new VBCodeProvider(); ext = "*.vb"; Console.WriteLine("Using Visual Basic.NET (VBCodeDomProvider)..."); break; case "js": case "js.net": case "jscript": case "jscript.net": case "javascript": case "javascript.net": cdcp = new JScriptCodeProvider(); ext = "*.js"; Console.WriteLine("Using JScript.NET (JScriptCodeProvider)..."); break; case "cs": case "c#": case "csharp": case "visual cs": case "visual c#": case "visual csharp": // inited as C# Console.WriteLine("Using C# (CSharpCodeProvider)..."); break; default: Console.WriteLine("Language not explicitely defined, using C# (CSharpCodeProvider)..."); break; } } } //if (!json.Has("version")) // throw new CompileException("Missing ModInfo field 'version'"); //if (!json.Has("info")) // throw new CompileException("Missing ModInfo field 'info'"); modInfo = (string)json; } catch (Exception e) { throw new CompilerException("Invalid file: ModInfo.json", e); } #endregion #region compile the code List <string> toCompile = new List <string>(); foreach (string file in Directory.EnumerateFiles(modDirectory, ext, SearchOption.AllDirectories)) { toCompile.Add(file); } CompilerParameters cp = new CompilerParameters() { GenerateExecutable = false, GenerateInMemory = false, OutputAssembly = outputDirectory + "\\" + modName + ".tapimod" }; string xna = Environment.GetEnvironmentVariable("XNAGSv4") + "\\References\\Windows\\x86\\", wpf = Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86) + "\\Reference Assemblies\\Microsoft\\Framework\\.NETFramework\\v4.0\\Profile\\Client\\", here = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); cp.ReferencedAssemblies.Add("tAPI.exe"); cp.ReferencedAssemblies.Add("Microsoft.JScript.dll"); cp.ReferencedAssemblies.Add("Microsoft.VisualBasic.dll"); cp.ReferencedAssemblies.Add("Microsoft.CSharp.dll"); cp.ReferencedAssemblies.Add("Accessibility.dll"); cp.ReferencedAssemblies.Add("mscorlib.dll"); cp.ReferencedAssemblies.Add("System.dll"); cp.ReferencedAssemblies.Add("System.Core.dll"); cp.ReferencedAssemblies.Add("System.Drawing.dll"); cp.ReferencedAssemblies.Add("System.Windows.Forms.dll"); cp.ReferencedAssemblies.Add("System.Numerics.dll"); cp.ReferencedAssemblies.Add("System.Xml.dll"); cp.ReferencedAssemblies.Add(wpf + "PresentationCore.dll"); cp.ReferencedAssemblies.Add(wpf + "PresentationFramework.dll"); cp.ReferencedAssemblies.Add(wpf + "WindowsBase.dll"); cp.ReferencedAssemblies.Add(xna + "Microsoft.Xna.Framework.dll"); cp.ReferencedAssemblies.Add(xna + "Microsoft.Xna.Framework.Xact.dll"); cp.ReferencedAssemblies.Add(xna + "Microsoft.Xna.Framework.Game.dll"); cp.ReferencedAssemblies.Add(xna + "Microsoft.Xna.Framework.Graphics.dll"); CompilerResults cr = cdcp.CompileAssemblyFromFile(cp, toCompile.ToArray()); if (cr.Errors.HasErrors) { return(CompilerException.CreateException(cr.Errors)); } #endregion #region save to .tapimod file /* * How a .tapimod file looks like: * * - version (uint) * * - modinfo (string) * * - file amount (int) * * files: * - file name (string) * - file data length (int) * * files: * - file data (byte[]) * * - assembly data */ // VBCodeProvider automatically adds '.dll' string mod = outputDirectory + (cdcp is VBCodeProvider ? ".tapimod.dll" : ".tapimod"); List <Tuple <string, byte[]> > files = new List <Tuple <string, byte[]> >(); foreach (string fileName in Directory.EnumerateFiles(modDirectory, "*.*", SearchOption.AllDirectories)) { if (!Path.GetExtension(fileName).EndsWith(ext.Substring(2))) { files.Add(new Tuple <string, byte[]>(fileName.Substring(modDirectory.Length + 1).Replace('\\', '/'), File.ReadAllBytes(fileName))); } } BinBuffer bb = new BinBuffer(); bb.Write(Constants.versionAssembly); bb.Write(modInfo); bb.Write(files.Count); foreach (Tuple <string, byte[]> pfile in files) { bb.Write(pfile.Item1); bb.Write(pfile.Item2.Length); } foreach (Tuple <string, byte[]> pfile in files) { bb.Write(pfile.Item2); } bb.Pos = 0; File.WriteAllBytes(cdcp is VBCodeProvider ? Path.ChangeExtension(mod, null) : mod, bb.ReadBytes(bb.GetSize())); // generate false hashes CommonToolUtilities.AddHashes(modName, modDirectory); #endregion return(null); }
public static void Decompile(string modFile) { CommonToolUtilities.RefreshHashes(); string modName = Path.GetFileNameWithoutExtension(modFile), decompPath = ModDecompiler.decompDir + "\\" + modName; // might be a good idea if (!Directory.Exists(decompPath)) { Directory.CreateDirectory(decompPath); } // where to store file data List <Tuple <string, byte[]> > files = new List <Tuple <string, byte[]> >(); List <Tuple <string, int> > reading = new List <Tuple <string, int> >(); // load data into buffer BinBuffer bb = new BinBuffer(new BinBufferByte(File.ReadAllBytes(modFile))); // first 4 bytes is the version uint versionAssembly = bb.ReadUInt(); // write tAPI version if (!File.Exists(decompPath + "\\tAPI r" + versionAssembly)) { File.Create(decompPath + "\\tAPI r" + versionAssembly); } // write modinfo File.WriteAllText(decompPath + "\\ModInfo.json", bb.ReadString()); // get file amount int filesNum = bb.ReadInt(); // read file name + length while (filesNum-- > 0) { reading.Add(new Tuple <string, int>(bb.ReadString(), bb.ReadInt())); } // read file data foreach (Tuple <string, int> read in reading) { files.Add(new Tuple <string, byte[]>(read.Item1, bb.ReadBytes(read.Item2))); } // write files foreach (Tuple <string, byte[]> pfile in files) { if (!Directory.Exists(Path.GetDirectoryName(decompPath + "\\" + pfile.Item1))) { Directory.CreateDirectory(Path.GetDirectoryName(decompPath + "\\" + pfile.Item1)); } File.WriteAllBytes(decompPath + "\\" + pfile.Item1, pfile.Item2); } // write assembly File.WriteAllBytes(decompPath + "\\" + modName + ".dll", bb.ReadBytes(bb.BytesLeft())); CommonToolUtilities.RefreshHashes(); }
public static void Compile(string dllFile) { CommonToolUtilities.RefreshHashes(); #region setup string modName = Path.GetFileNameWithoutExtension(dllFile), modPath = CommonToolUtilities.modsSrcDir + "\\" + modName, modFile = CommonToolUtilities.modsBinDir + "\\" + modName + ".tapimod"; if (File.Exists(modFile)) { File.Delete(modFile); } Assembly asm = Assembly.LoadFrom(dllFile); List <Tuple <string, byte[]> > files = new List <Tuple <string, byte[]> >(); #endregion string modInfo = null; #region load all resources into the list foreach (string res in asm.GetManifestResourceNames()) { using (Stream stream = asm.GetManifestResourceStream(res)) { MemoryStream ms = new MemoryStream(); stream.CopyTo(ms); bool foundExt = false; int index = 0; for (int i = res.Length - 1; i >= 0; i--) { // find file name if (res[i] == '.') { if (foundExt) { index = i + 1; break; } else { foundExt = true; } } } // not putting ModInfo.json in it if (res.Substring(index) != "ModInfo.json") { files.Add(new Tuple <string, byte[]>(res.Substring(index), ms.ToArray())); } else { StreamReader r = new StreamReader(new MemoryStream(ms.ToArray())); modInfo = r.ReadToEnd(); if (modInfo == null) { modInfo = "{\n\t\"displayName\": \"" + modName + "\",\n\t\"author\": \"<unknown>\"\n\t\"info\": \"\"\n}"; } else { try { JsonData j = JsonMapper.ToObject(modInfo); if (!j.Has("displayName") || !j.Has("author")) { modInfo = "{\n\t\"displayName\": \"" + modName + "\",\n\t\"author\": \"<unknown>\"\n\t\"info\": \"\"\n}"; } } catch (JsonException) // invalid JSON thrown in JsonMapper.ToObject { modInfo = "{\n\t\"displayName\": \"" + modName + "\",\n\t\"author\": \"<unknown>\"\n\t\"info\": \"\"\n}"; } } r.Close(); } ms.Dispose(); } } #endregion File.Copy(dllFile, modFile); #region write data BinBuffer bb = new BinBuffer(); // write version bb.Write(Constants.versionAssembly); // write modinfo bb.Write(modInfo); // write file name + length bb.Write(files.Count); foreach (Tuple <string, byte[]> pfile in files) { bb.Write(pfile.Item1); bb.Write(pfile.Item2.Length); } // write file data foreach (Tuple <string, byte[]> pfile in files) { bb.Write(pfile.Item2); } // write assembly bb.Write(File.ReadAllBytes(dllFile)); // reset bb.Pos = 0; // write it all to the .tapimod file File.WriteAllBytes(modFile, bb.ReadBytes(bb.GetSize())); #endregion #region generate false folders & files to foul the hash checker, and generate hashes // not checked anymore in r4 /*if (!Directory.Exists(modPath)) * Directory.CreateDirectory(modPath); * * // get info to write to modinfo.cs * JsonData jModInfo = JsonMapper.ToObject(modInfo); * * string actualModName = modName; * string codeModBaseName = "TAPI." + actualModName + ".ModBase"; * * if (jModInfo.Has("name")) * codeModBaseName = "TAPI." + (actualModName = (string)jModInfo["name"]) + ".ModBase"; * * if (jModInfo != null && jModInfo.Has("code") && jModInfo["code"].Has("modBaseName")) * codeModBaseName = (string)jModInfo["code"]["modBaseName"]; * * // get namespace (and modbase class name) * string[] nsSplit = codeModBaseName.Split('.'); * * string @namespace = nsSplit[0]; * for (int i = 1; i < nsSplit.Length - 1; i++) * @namespace += "." + nsSplit[i]; * * // kinda crucial * using (FileStream fs = new FileStream(modPath + "\\" + nsSplit[nsSplit.Length - 1] + ".cs", FileMode.Create)) * { * using (StreamWriter bw = new StreamWriter(fs)) * { * bw.Write( * "using System;\n" + * "using TAPI;\n" + * "\n" + * "namespace " + @namespace + "\n" + * "{\n" + * " public class " + nsSplit[nsSplit.Length - 1] + " : TAPI.ModBase\n" + * " {\n" + * " public " + nsSplit[nsSplit.Length - 1] + "() : base() { }\n" + * " }\n" + * "}\n" * ); * } * } * * // write modinfo * File.WriteAllText(modPath + "\\ModInfo.json", modInfo); * * // write .dll file, you'll never know if... * File.Copy(dllFile, modPath + "\\" + Path.GetFileName(dllFile), true); * * CommonToolUtilities.AddHashes(modName, modPath);*/ #endregion }