private static void ExceptionHandler(object sender, UnhandledExceptionEventArgs e) { if (e.ExceptionObject is Exception ex) { Logger.Error(null, ex.ToString()); if (Debugger.IsAttached) { throw ex; } } unchecked { Environment.Exit((int)0xDEADBEEF); } }
public void AddTask(Action action) { if (Program.Flags?.DisableAsyncSave == true) { action(); } else { m_pendingTasks.Add(Task.Run(() => { try { action(); } catch (Exception e) { Logger.Error("Combo", $"Async exception: {e}"); } })); } }
public static void ConvertSoundFile(Stream stream, Stream outputStream) { try { using (Sound.WwiseRIFFVorbis vorbis = new Sound.WwiseRIFFVorbis(stream, Path.GetFullPath(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Third Party", "packed_codebooks_aoTuV_603.bin")))) { Stream vorbisStream = new MemoryStream(); vorbis.ConvertToOgg(vorbisStream); vorbisStream.Position = 0; using (Stream revorbStream = RevorbStd.Revorb.Jiggle(vorbisStream)) { revorbStream.Position = 0; revorbStream.CopyTo(outputStream); } } } catch (Exception e) { Logger.Error("Combo", $"Error converting sound: {e}"); } }
private static void ConvertAnimation(Stream animStream, string path, bool convertAnims, FindLogic.Combo.AnimationAsset animationInfo, bool scaleAnims) { var parsedAnimation = default(teAnimation); var priority = 100; try { parsedAnimation = new teAnimation(animStream, true); priority = parsedAnimation.Header.Priority; } catch (Exception) { Logger.Error("Combo", $"Unable to parse animation {animationInfo.GetName()}"); } string animationDirectory = Path.Combine(path, "Animations", priority.ToString()); if (convertAnims && parsedAnimation != null) { SEAnim seAnim = new SEAnim(parsedAnimation, scaleAnims); string animOutput = Path.Combine(animationDirectory, animationInfo.GetNameIndex() + "." + seAnim.Extension); CreateDirectoryFromFile(animOutput); using (Stream fileStream = new FileStream(animOutput, FileMode.Create)) { seAnim.Write(fileStream); } } else { animStream.Position = 0; string rawAnimOutput = Path.Combine(animationDirectory, $"{animationInfo.GetNameIndex()}.{teResourceGUID.Type(animationInfo.m_GUID):X3}"); CreateDirectoryFromFile(rawAnimOutput); using (Stream fileStream = new FileStream(rawAnimOutput, FileMode.Create)) { animStream.CopyTo(fileStream); } } }
private static void Main() { InitTankSettings(); HookConsole(); var tools = GetTools(); #if DEBUG FlagParser.CheckCollisions(typeof(ToolFlags), (flag, duplicate) => { Logger.Error("Flag", $"The flag \"{flag}\" from {duplicate} is a duplicate!"); }); #endif FlagParser.LoadArgs(); Logger.Info("Core", $"{Assembly.GetExecutingAssembly().GetName().Name} v{Util.GetVersion(typeof(Program).Assembly)}"); Logger.Info("Core", $"CommandLine: [{string.Join(", ", FlagParser.AppArgs.Select(x => $"\"{x}\""))}]"); Flags = FlagParser.Parse <ToolFlags>(full => PrintHelp(full, tools)); if (Flags == null) { return; } Logger.Info("Core", $"CommandLineFile: {FlagParser.ArgFilePath}"); if (Flags.SaveArgs) { FlagParser.AppArgs = FlagParser.AppArgs.Where(x => !x.StartsWith("--arg")) .ToArray(); FlagParser.SaveArgs(Flags.OverwatchDirectory); } else if (Flags.ResetArgs || Flags.DeleteArgs) { FlagParser.ResetArgs(); if (Flags.DeleteArgs) { FlagParser.DeleteArgs(); } Logger.Info("Core", $"CommandLineNew: [{string.Join(", ", FlagParser.AppArgs.Select(x => $"\"{x}\""))}]"); Flags = FlagParser.Parse <ToolFlags>(full => PrintHelp(full, tools)); if (Flags == null) { return; } } if (string.IsNullOrWhiteSpace(Flags.OverwatchDirectory) || string.IsNullOrWhiteSpace(Flags.Mode) || Flags.Help) { PrintHelp(false, tools); return; } ITool targetTool = null; ICLIFlags targetToolFlags = null; ToolAttribute targetToolAttributes = null; #region Tool Activation foreach (var type in tools) { var attribute = type.GetCustomAttribute <ToolAttribute>(); if (!string.Equals(attribute.Keyword, Flags.Mode, StringComparison.InvariantCultureIgnoreCase)) { continue; } targetTool = Activator.CreateInstance(type) as ITool; targetToolAttributes = attribute; if (attribute.CustomFlags != null) { var flags = attribute.CustomFlags; if (typeof(ICLIFlags).IsAssignableFrom(flags)) { targetToolFlags = typeof(FlagParser).GetMethod(nameof(FlagParser.Parse), new Type[] { }) ?.MakeGenericMethod(flags) .Invoke(null, null) as ICLIFlags; } } break; } if (targetToolFlags == null) { return; } #endregion if (targetTool == null) { FlagParser.Help <ToolFlags>(false, new Dictionary <string, string>()); PrintHelp(false, tools); return; } if (!targetToolAttributes.UtilNoArchiveNeeded) { InitStorage(); //foreach (KeyValuePair<ushort, HashSet<ulong>> type in TrackedFiles.OrderBy(x => x.Key)) { // //Console.Out.WriteLine($"Found type: {type.Key:X4} ({type.Value.Count} files)"); // Console.Out.WriteLine($"Found type: {type.Key:X4}"); //} InitKeys(); InitMisc(); } var stopwatch = new Stopwatch(); Logger.Info("Core", "Tooling..."); stopwatch.Start(); targetTool.Parse(targetToolFlags); stopwatch.Stop(); Logger.Success("Core", $"Execution finished in {stopwatch.Elapsed} seconds"); ShutdownMisc(); }
public static void InitStorage(bool online = true) { if (Flags.Language != null) { Logger.Info("CASC", $"Set language to {Flags.Language}"); } if (Flags.SpeechLanguage != null) { Logger.Info("CASC", $"Set speech language to {Flags.SpeechLanguage}"); } var args = new ClientCreateArgs { SpeechLanguage = Flags.SpeechLanguage, TextLanguage = Flags.Language, HandlerArgs = new ClientCreateArgs_Tank { CacheAPM = Flags.UseCache }, Online = online }; LoadHelper.PreLoad(); Client = new ClientHandler(Flags.OverwatchDirectory, args); LoadHelper.PostLoad(Client); if (args.TextLanguage != "enUS") { Logger.Warn("Core", "Reminder! When extracting data in other languages, the names of the heroes/skins/etc must be in the language you have chosen."); } if (Client.AgentProduct.ProductCode != "pro") { Logger.Warn("Core", $"The branch \"{Client.AgentProduct.ProductCode}\" is not supported!. This might result in failure to load. Proceed with caution."); } if (!Client.AgentProduct.Settings.Languages.Select(x => x.Language) .Contains(args.TextLanguage)) { Logger.Warn("Core", "Battle.Net Agent reports that language {0} is not installed.", args.TextLanguage); } else if (!Client.AgentProduct.Settings.Languages.Select(x => x.Language) .Contains(args.SpeechLanguage)) { Logger.Warn("Core", "Battle.Net Agent reports that language {0} is not installed.", args.SpeechLanguage); } TankHandler = Client.ProductHandler as ProductHandler_Tank; if (TankHandler == null) { Logger.Error("Core", $"Not a valid Overwatch installation (detected product: {Client.Product})"); return; } BuildVersion = uint.Parse(Client.InstallationInfo.Values["Version"] .Split('.') .Last()); if (BuildVersion < 39028) { Logger.Error("Core", "DataTool doesn't support Overwatch versions below 1.14. Please use OverTool."); } else if (BuildVersion < 56957) { Logger.Error("Core", "This version of DataTool doesn't support versions of Overwatch below 1.35. Please downgrade DataTool."); } InitTrackedFiles(); }
private static async Task SaveTextureTask(ICLIFlags flags, string path, SaveContext info, ulong textureGUID, string name = null) { bool convertTextures = true; string convertType = "tif"; string multiSurfaceConvertType = "tif"; bool createMultiSurfaceSheet = false; bool lossless = false; int maxMips = 1; if (flags is ExtractFlags extractFlags) { if (extractFlags.SkipTextures) { return; } createMultiSurfaceSheet = extractFlags.SheetMultiSurface; convertTextures = !extractFlags.RawTextures && !extractFlags.Raw; convertType = extractFlags.ConvertTexturesType.ToLowerInvariant(); lossless = extractFlags.ConvertTexturesLossless; multiSurfaceConvertType = convertType; if (extractFlags.ForceDDSMultiSurface) { multiSurfaceConvertType = "dds"; } if (convertType == "dds" && extractFlags.SaveMips) { maxMips = 0xF; } } if (!path.EndsWith(Path.DirectorySeparatorChar.ToString())) { path += Path.DirectorySeparatorChar; } FindLogic.Combo.TextureAsset textureInfo = info.m_info.m_textures[textureGUID]; string filePath = Path.Combine(path, name ?? $"{textureInfo.GetNameIndex()}"); if (teResourceGUID.Type(textureGUID) != 0x4) { filePath += $".{teResourceGUID.Type(textureGUID):X3}"; } if (Program.Flags != null && Program.Flags.Deduplicate) { if (ScratchDBInstance.HasRecord(textureGUID)) { return; } ScratchDBInstance[textureGUID] = new ScratchDB.ScratchPath($"{filePath}.{convertType}", true); } CreateDirectoryFromFile(path); await s_texurePrepareSemaphore.WaitAsync(); try { if (!convertTextures) { teTexture texture; using (Stream textureStream = OpenFile(textureGUID)) { texture = new teTexture(textureStream, true); textureStream.Position = 0; WriteFile(textureStream, $"{filePath}.004"); } if (!texture.PayloadRequired) { return; } for (int i = 0; i < texture.Payloads.Length; ++i) { using (Stream texturePayloadStream = OpenFile(texture.GetPayloadGUID(textureGUID, i))) WriteFile(texturePayloadStream, $"{filePath}_{i}.04D"); } } else { teTexture texture; using (Stream textureStream = OpenFile(textureGUID)) { if (textureStream == null) { return; } texture = new teTexture(textureStream); } //if (texture.Header.Flags.HasFlag(teTexture.Flags.CUBEMAP)) return; // for diffing when they add/regen loads of cubemaps if (texture.PayloadRequired) { for (int i = 0; i < texture.Payloads.Length; ++i) { using (var payloadStream = OpenFile(texture.GetPayloadGUID(textureGUID, i))) texture.LoadPayload(payloadStream, i); if (maxMips == 1) { break; } } } uint?width = null; uint?height = null; uint?surfaces = null; if (texture.Header.IsCubemap || texture.Header.IsArray || texture.HasMultipleSurfaces) { if (createMultiSurfaceSheet) { Logger.Debug("Combo", $"Saving {Path.GetFileName(filePath)} as a sheet because it has more than one surface"); height = (uint)(texture.Header.Height * texture.Header.Surfaces); surfaces = 1; texture.Header.Flags = 0; } else if (convertType != "tif" && convertType != "dds") { Logger.Debug("Combo", $"Saving {Path.GetFileName(filePath)} as {multiSurfaceConvertType} because it has more than one surface"); convertType = multiSurfaceConvertType; } } WICCodecs?imageFormat = null; switch (convertType) { case "tif": imageFormat = WICCodecs.TIFF; break; case "png": imageFormat = WICCodecs.PNG; break; case "jpg": imageFormat = WICCodecs.JPEG; break; } // if (convertType == "tga") imageFormat = Im.... oh // so there is no TGA image format. // sucks to be them if (convertType == "dds") { using (Stream convertedStream = texture.SaveToDDS(maxMips == 1 ? 1 : texture.Header.MipCount, width, height, surfaces)) { WriteFile(convertedStream, $"{filePath}.dds"); } return; } Process pProcess; using (Stream convertedStream = texture.SaveToDDS(maxMips == 1 ? 1 : texture.Header.MipCount, width, height, surfaces)) { var data = DDSConverter.ConvertDDS(convertedStream, DXGI_FORMAT.R8G8B8A8_UNORM, imageFormat.Value, 0); if (data != null) { WriteFile(data, $"{filePath}.{convertType}"); } else { convertedStream.Position = 0; WriteFile(convertedStream, $"{filePath}.dds"); Logger.Error("Combo", $"Unable to save {Path.GetFileName(filePath)} as {convertType} because DirectXTex failed."); } } } } finally { s_texurePrepareSemaphore.Release(); } }