public static void Parse(Packet packet, bool isMultiple = false) { ParsedStatus status; packet.WriteLine(packet.GetHeader(isMultiple)); if (packet.Opcode == 0) { return; } var opcode = Opcodes.GetOpcode(packet.Opcode, packet.Direction); var key = new KeyValuePair <ClientVersionBuild, Opcode>(ClientVersion.VersionDefiningBuild, opcode); Action <Packet> handler; var hasHandler = VersionHandlers.TryGetValue(key, out handler); ClientVersionBuild tmpFallback = ClientVersion.VersionDefiningBuild; while (!hasHandler && tmpFallback != ClientVersionBuild.Zero) { // If no handler was found, try to find a handler key = new KeyValuePair <ClientVersionBuild, Opcode>(tmpFallback, opcode); hasHandler = VersionHandlers.TryGetValue(key, out handler); tmpFallback = ClientVersion.FallbackVersionDefiningBuild(tmpFallback, ClientVersion.VersionDefiningBuild); } if (!hasHandler) { // If no handler was found, try to find a handler that works for any version. key = new KeyValuePair <ClientVersionBuild, Opcode>(ClientVersionBuild.Zero, opcode); hasHandler = VersionHandlers.TryGetValue(key, out handler); } if (hasHandler && Settings.DumpFormat != DumpFormatType.HexOnly) { if (Settings.DumpFormat == DumpFormatType.SniffDataOnly) { var attrs = handler.Method.GetCustomAttributes(typeof(HasSniffDataAttribute), false); packet.AddSniffData(StoreNameType.Opcode, packet.Opcode, Opcodes.GetOpcodeName(packet.Opcode, packet.Direction)); if (attrs.Length == 0) { packet.Status = ParsedStatus.NotParsed; return; // skip parsing "useless" packets when in SniffData-only-mode } } try { handler(packet); if (packet.Position == packet.Length) { status = ParsedStatus.Success; } else { var pos = packet.Position; var len = packet.Length; packet.WriteLine("Packet not fully read! Current position: {0} Length: {1} Bytes remaining: {2}.", pos, len, len - pos); if (len < 300) // If the packet isn't "too big" and it is not full read, print its hex table { packet.AsHex(); } status = ParsedStatus.WithErrors; } } catch (Exception ex) { packet.WriteLine(ex.GetType().ToString()); packet.WriteLine(ex.Message); packet.WriteLine(ex.StackTrace); status = ParsedStatus.WithErrors; } } else { packet.AsHex(); status = opcode == Opcode.NULL_OPCODE ? ParsedStatus.NotParsed : ParsedStatus.NoStructure; } if (!isMultiple) { packet.Status = status; if (Settings.DumpFormat != DumpFormatType.SniffDataOnly) { // added before for this type var data = status == ParsedStatus.Success ? Opcodes.GetOpcodeName(packet.Opcode, packet.Direction) : status.ToString(); packet.AddSniffData(StoreNameType.Opcode, packet.Opcode, data); } } }