private void LoadMP3(string path, byte[] bytes) { string wavCacheFilename = this.Name + "_" + path.Replace('/', '_') + "_" + Version + ".wav"; WAVCacheIO.DeleteIfOlder(File.path, wavCacheFilename); try { if (path.StartsWith("Sounds/Music/")) { if (ModLoader.musicStreamMode != 1) { //no cache musics[path] = new MusicData(bytes, true); return; } if (!WAVCacheIO.WAVCacheAvailable(wavCacheFilename)) { WAVCacheIO.CacheMP3(wavCacheFilename, new MemoryStream(bytes)); } musics[path] = new MusicData(Path.Combine(WAVCacheIO.ModCachePath, wavCacheFilename)); return; } sounds[path] = WAVCacheIO.WAVCacheAvailable(wavCacheFilename) ? SoundEffect.FromStream(WAVCacheIO.GetWavStream(wavCacheFilename)) : WAVCacheIO.CacheMP3(wavCacheFilename, new MemoryStream(bytes)); } catch (Exception e) { throw new ResourceLoadException(Language.GetTextValue("tModLoader.LoadErrorMP3SoundFailedToLoad", path) + (Main.engine == null ? "\n" + Language.GetTextValue("tModLoader.LoadErrorSoundFailedToLoadAudioDeviceHint") : ""), e); } }
private static bool Build(BuildingMod mod, IBuildStatus status) { byte[] winDLL = null; byte[] monoDLL = null; byte[] winPDB = null; if (mod.properties.noCompile) { winDLL = monoDLL = ReadIfExists(Path.Combine(mod.path, "All.dll")); winPDB = ReadIfExists(Path.Combine(mod.path, "All.pdb")); if (winDLL == null) { winDLL = ReadIfExists(Path.Combine(mod.path, "Windows.dll")); monoDLL = ReadIfExists(Path.Combine(mod.path, "Mono.dll")); winPDB = ReadIfExists(Path.Combine(mod.path, "Windows.pdb")); } if (winDLL == null || monoDLL == null) { ErrorLogger.LogDllBuildError(mod.path); return(false); } } else { var refMods = FindReferencedMods(mod.properties); if (refMods == null) { return(false); } if (Program.LaunchParameters.ContainsKey("-eac")) { if (!windows) { ErrorLogger.LogBuildError("Edit and continue is only supported on windows"); return(false); } try { status.SetStatus("Loading pre-compiled Windows.dll with edit and continue support"); var winPath = Program.LaunchParameters["-eac"]; var pdbPath = Path.ChangeExtension(winPath, "pdb"); winDLL = File.ReadAllBytes(winPath); winPDB = File.ReadAllBytes(pdbPath); mod.properties.editAndContinue = true; } catch (Exception e) { ErrorLogger.LogBuildError("Failed to load pre-compiled edit and continue dll " + e); return(false); } } else { status.SetStatus(Language.GetTextValue("tModLoader.MSCompilingWindows", mod)); status.SetProgress(0, 2); CompileMod(mod, refMods, true, ref winDLL, ref winPDB); } if (winDLL == null) { return(false); } status.SetStatus(Language.GetTextValue("tModLoader.MSCompilingMono", mod)); status.SetProgress(1, 2); CompileMod(mod, refMods, false, ref monoDLL, ref winPDB); //the pdb reference won't actually be written to if (monoDLL == null) { return(false); } } if (!VerifyName(mod.Name, winDLL) || !VerifyName(mod.Name, monoDLL)) { return(false); } status.SetStatus(Language.GetTextValue("tModLoader.MSBuilding") + mod + "..."); status.SetProgress(0, 1); mod.modFile.AddFile("Info", mod.properties.ToBytes()); if (Equal(winDLL, monoDLL)) { mod.modFile.AddFile("All.dll", winDLL); if (winPDB != null) { mod.modFile.AddFile("All.pdb", winPDB); } } else { mod.modFile.AddFile("Windows.dll", winDLL); mod.modFile.AddFile("Mono.dll", monoDLL); if (winPDB != null) { mod.modFile.AddFile("Windows.pdb", winPDB); } } foreach (var resource in Directory.GetFiles(mod.path, "*", SearchOption.AllDirectories)) { var relPath = resource.Substring(mod.path.Length + 1); if (mod.properties.ignoreFile(relPath) || relPath == "build.txt" || relPath == ".gitattributes" || relPath == ".gitignore" || relPath.StartsWith(".git" + Path.DirectorySeparatorChar) || relPath.StartsWith(".vs" + Path.DirectorySeparatorChar) || relPath.StartsWith("bin" + Path.DirectorySeparatorChar) || relPath.StartsWith("obj" + Path.DirectorySeparatorChar) || !mod.properties.includeSource && sourceExtensions.Contains(Path.GetExtension(resource)) || Path.GetFileName(resource) == "Thumbs.db") { continue; } mod.modFile.AddFile(relPath, File.ReadAllBytes(resource)); } WAVCacheIO.ClearCache(mod.Name); mod.modFile.Save(); EnableMod(mod.modFile); ActivateExceptionReporting(); ModLoader.isModder = true; return(true); }
private bool Build(BuildingMod mod) { status.SetMod(mod.Name); status.SetStatus(Language.GetTextValue("tModLoader.Building", mod.Name)); byte[] winDLL = null; byte[] monoDLL = null; byte[] winPDB = null; if (mod.properties.noCompile) { winDLL = monoDLL = ReadIfExists(Path.Combine(mod.path, "All.dll")); winPDB = ReadIfExists(Path.Combine(mod.path, "All.pdb")); if (winDLL == null) { winDLL = ReadIfExists(Path.Combine(mod.path, "Windows.dll")); monoDLL = ReadIfExists(Path.Combine(mod.path, "Mono.dll")); winPDB = ReadIfExists(Path.Combine(mod.path, "Windows.pdb")); } if (winDLL == null || monoDLL == null) { var missing = new List <string> { "All.dll" }; if (winDLL == null) { missing.Add("Windows.dll"); } if (monoDLL == null) { missing.Add("Mono.dll"); } status.LogError(Language.GetTextValue("tModLoader.BuildErrorMissingDllFiles", string.Join(", ", missing))); return(false); } } else { List <LocalMod> refMods; try { refMods = FindReferencedMods(mod.properties); } catch (Exception e) { status.LogError(e.Message, e.InnerException); return(false); } if (Program.LaunchParameters.ContainsKey("-eac")) { if (!windows) { status.LogError(Language.GetTextValue("tModLoader.BuildErrorEACWindowsOnly")); return(false); } var winPath = Program.LaunchParameters["-eac"]; try { status.SetStatus(Language.GetTextValue("tModLoader.LoadingEAC")); var pdbPath = Path.ChangeExtension(winPath, "pdb"); winDLL = File.ReadAllBytes(winPath); winPDB = File.ReadAllBytes(pdbPath); mod.properties.editAndContinue = true; } catch (Exception e) { status.LogError(Language.GetTextValue("tModLoader.BuildErrorEACLoadFailed", winPath + "/.pdb"), e); return(false); } } else { status.SetStatus(Language.GetTextValue("tModLoader.CompilingWindows", mod)); status.SetProgress(0, 2); CompileMod(mod, refMods, true, ref winDLL, ref winPDB); } if (winDLL == null) { return(false); } status.SetStatus(Language.GetTextValue("tModLoader.CompilingMono", mod)); status.SetProgress(1, 2); CompileMod(mod, refMods, false, ref monoDLL, ref winPDB); //the pdb reference won't actually be written to if (monoDLL == null) { return(false); } } if (!VerifyName(mod.Name, winDLL) || !VerifyName(mod.Name, monoDLL)) { return(false); } status.SetStatus(Language.GetTextValue("tModLoader.Packaging", mod)); status.SetProgress(0, 1); mod.modFile.AddFile("Info", mod.properties.ToBytes()); if (Equal(winDLL, monoDLL)) { mod.modFile.AddFile("All.dll", winDLL); if (winPDB != null) { mod.modFile.AddFile("All.pdb", winPDB); } } else { mod.modFile.AddFile("Windows.dll", winDLL); mod.modFile.AddFile("Mono.dll", monoDLL); if (winPDB != null) { mod.modFile.AddFile("Windows.pdb", winPDB); } } foreach (var resource in Directory.GetFiles(mod.path, "*", SearchOption.AllDirectories)) { var relPath = resource.Substring(mod.path.Length + 1); if (mod.properties.ignoreFile(relPath) || relPath == "build.txt" || relPath == ".gitattributes" || relPath == ".gitignore" || relPath.StartsWith(".git" + Path.DirectorySeparatorChar) || relPath.StartsWith(".vs" + Path.DirectorySeparatorChar) || relPath.StartsWith(".idea" + Path.DirectorySeparatorChar) || relPath.StartsWith("bin" + Path.DirectorySeparatorChar) || relPath.StartsWith("obj" + Path.DirectorySeparatorChar) || !mod.properties.includeSource && sourceExtensions.Contains(Path.GetExtension(resource)) || Path.GetFileName(resource) == "Thumbs.db") { continue; } AddResource(mod.modFile, relPath, resource); } WAVCacheIO.ClearCache(mod.Name); GetMod(mod.Name)?.File?.Close(); // if the mod is currently loaded, the file-handle needs to be released mod.modFile.Save(); mod.modFile.Close(); EnableMod(mod.Name); return(true); }
private static void LoadMod(TmodFile modFile, BuildProperties properties) { AddAssemblyResolver(); string fileName = Path.GetFileNameWithoutExtension(modFile.Name); Interface.loadMods.SetProgressReading(fileName, 0, 2); Assembly modCode; string rootDirectory; if (modFile.HasFile("All")) { modCode = Assembly.Load(modFile.GetFile("All")); } else { modCode = Assembly.Load(modFile.GetFile(windows ? "Windows" : "Other")); } Interface.loadMods.SetProgressReading(fileName, 1, 2); using (MemoryStream memoryStream = new MemoryStream(modFile.GetFile("Resources"))) { using (BinaryReader reader = new BinaryReader(memoryStream)) { rootDirectory = reader.ReadString(); for (string path = reader.ReadString(); path != "end"; path = reader.ReadString()) { byte[] data = reader.ReadBytes(reader.ReadInt32()); files[path] = data; if (Main.dedServ) { continue; } string extension = Path.GetExtension(path); switch (extension) { case ".png": string texturePath = Path.ChangeExtension(path, null); using (MemoryStream buffer = new MemoryStream(data)) { textures[texturePath] = Texture2D.FromStream(Main.instance.GraphicsDevice, buffer); } break; case ".wav": string soundPath = Path.ChangeExtension(path, null); using (MemoryStream buffer = new MemoryStream(data)) { sounds[soundPath] = SoundEffect.FromStream(buffer); } break; case ".mp3": string mp3Path = Path.ChangeExtension(path, null); string wavCacheFilename = mp3Path.Replace('/', '_') + "_" + properties.version + ".wav"; if (WAVCacheIO.WAVCacheAvailable(wavCacheFilename)) { sounds[mp3Path] = SoundEffect.FromStream(WAVCacheIO.GetWavStream(wavCacheFilename)); break; } ushort wFormatTag = 1; ushort nChannels; uint nSamplesPerSec; uint nAvgBytesPerSec; ushort nBlockAlign; ushort wBitsPerSample = 16; const int headerSize = 44; MemoryStream output = new MemoryStream(headerSize + data.Length); using (MemoryStream yourMp3FileStream = new MemoryStream(data)) { using (MP3Sharp.MP3Stream input = new MP3Sharp.MP3Stream(yourMp3FileStream)) { using (BinaryWriter writer = new BinaryWriter(output, Encoding.UTF8)) { output.Position = headerSize; input.CopyTo(output); UInt32 wavDataLength = (UInt32)output.Length - headerSize; output.Position = 0; nChannels = (ushort)input.ChannelCount; nSamplesPerSec = (uint)input.Frequency; nBlockAlign = (ushort)(nChannels * (wBitsPerSample / 8)); nAvgBytesPerSec = (uint)(nSamplesPerSec * nChannels * (wBitsPerSample / 8)); //write the header writer.Write("RIFF".ToCharArray()); //4 writer.Write((UInt32)(wavDataLength + 36)); // 4 writer.Write("WAVE".ToCharArray()); //4 writer.Write("fmt ".ToCharArray()); //4 writer.Write(16); //4 writer.Write(wFormatTag); // writer.Write((ushort)nChannels); writer.Write(nSamplesPerSec); writer.Write(nAvgBytesPerSec); writer.Write(nBlockAlign); writer.Write(wBitsPerSample); writer.Write("data".ToCharArray()); writer.Write((UInt32)(wavDataLength)); output.Position = 0; WAVCacheIO.SaveWavStream(output, wavCacheFilename); sounds[mp3Path] = SoundEffect.FromStream(output); } } } break; } } } } Type[] classes = modCode.GetTypes(); foreach (Type type in classes) { if (type.IsSubclassOf(typeof(Mod))) { Mod mod = (Mod)Activator.CreateInstance(type); mod.file = modFile.Name; mod.buildVersion = properties.modBuildVersion; mod.code = modCode; mod.Init(); if (mod.Name == "Terraria") { throw new DuplicateNameException("Mods cannot be named Terraria"); } if (mods.ContainsKey(mod.Name)) { throw new DuplicateNameException("Two mods share the internal name " + mod.Name); } if (rootDirectory != mod.Name) { throw new MissingResourceException("Mod name " + mod.Name + " does not match source directory name " + rootDirectory); } mods[mod.Name] = mod; loadOrder.Push(mod.Name); } } }
internal static bool do_BuildMod(object threadContext) { Interface.buildMod.SetReading(); BuildProperties properties = BuildProperties.ReadBuildFile(modToBuild); if (!CreateModReferenceDlls(properties)) { if (!buildAll) { Main.menuMode = Interface.errorMessageID; } return(false); } LoadReferences(); byte[] windowsData; byte[] otherData; if (properties.noCompile) { string modDir = modToBuild + Path.DirectorySeparatorChar; if (File.Exists(modDir + "All.dll")) { windowsData = File.ReadAllBytes(modDir + "All.dll"); otherData = File.ReadAllBytes(modDir + "All.dll"); } else if (File.Exists(modDir + "Windows.dll") && File.Exists(modDir + "Other.dll")) { windowsData = File.ReadAllBytes(modDir + "Windows.dll"); otherData = File.ReadAllBytes(modDir + "Other.dll"); } else { ErrorLogger.LogDllBuildError(modToBuild); if (!buildAll) { Main.menuMode = Interface.errorMessageID; } return(false); } } else { Interface.buildMod.SetCompiling(0); windowsData = CompileMod(modToBuild, properties, true); Interface.buildMod.SetCompiling(1); otherData = CompileMod(modToBuild, properties, false); if (windowsData == null || otherData == null) { if (!buildAll) { Main.menuMode = Interface.errorMessageID; } return(false); } } Interface.buildMod.SetBuildText(); string file = ModPath + Path.DirectorySeparatorChar + Path.GetFileName(modToBuild) + ".tmod"; byte[] propertiesData = properties.ToBytes(); TmodFile modFile = new TmodFile(file); using (MemoryStream memoryStream = new MemoryStream()) { using (BinaryWriter writer = new BinaryWriter(memoryStream)) { writer.Write(version); writer.Write(propertiesData.Length); writer.Write(propertiesData); writer.Flush(); modFile.AddFile("Info", memoryStream.ToArray()); } } using (MemoryStream memoryStream = new MemoryStream()) { using (BinaryWriter writer = new BinaryWriter(memoryStream)) { writer.Write(Path.GetFileName(modToBuild)); string[] resources = Directory.GetFiles(modToBuild, "*", SearchOption.AllDirectories); foreach (string resource in resources) { if (properties.ignoreFile(resource.Replace(modToBuild + Path.DirectorySeparatorChar, null))) { continue; } if (Path.GetExtension(resource) == ".cs" && !properties.includeSource) { continue; } if (Path.GetFileName(resource) == "Thumbs.db") { continue; } if (resource.Substring(modToBuild.Length + 1) == "build.txt") { continue; } string resourcePath = resource.Replace(ModSourcePath + Path.DirectorySeparatorChar, null); resourcePath = resourcePath.Replace(Path.DirectorySeparatorChar, '/'); byte[] buffer = File.ReadAllBytes(resource); writer.Write(resourcePath); writer.Write(buffer.Length); writer.Write(buffer); } writer.Write("end"); writer.Flush(); modFile.AddFile("Resources", memoryStream.ToArray()); } } bool same = windowsData.Length == otherData.Length; if (same) { for (int k = 0; k < windowsData.Length; k++) { if (windowsData[k] != otherData[k]) { same = false; break; } } } if (same) { modFile.AddFile("All", windowsData); } else { modFile.AddFile("Windows", windowsData); modFile.AddFile("Other", otherData); } modFile.Save(); WAVCacheIO.ClearCache(modFile.Name); EnableMod(file); if (!buildAll) { Main.menuMode = reloadAfterBuild ? Interface.reloadModsID : 0; } return(true); }