private void ui_cbAllMenus_CheckedChanged(object sender, RoutedEventArgs e) { ExtGossipMenu[] arr; if ((bool)ui_cbAllMenus.IsChecked) { arr = m_menus.Select(pair => pair.Value).ToArray(); } else { arr = new ExtGossipMenu[0]; } SetProgressBarVisible(true); m_creatingMenuDataWorker.RunWorkerAsync(arr); }
void CreateSqlForMenu(ExtGossipMenu menu, StringBuilder builder) { builder.Append("-- ").AppendLine(Strings.Gossip_SqlStructure.LocalizedFormat(menu.Menu.MenuId)); foreach (var guid in menu.Objects) { var obj = m_objects.First(_ => _.Key == guid).Value; if (obj.ObjectType == WowGuidKind.Unit) { if (obj.InitialMenus.Count == 1 && obj.InitialMenus.First() == menu.Menu.MenuId) { builder.AppendFormatLine( "UPDATE creature_template SET gossip_menu_id = {0} WHERE entry = {1}; -- {2}", menu.Menu.MenuId, obj.ObjectEntry, obj.ObjectName); } else { builder.Append("-- ").AppendLine(Strings.Gossip_SqlInitialMenus .LocalizedFormat(obj.ObjectName, obj.InitialMenus.ToStringJoin(", "))); } } else { builder.Append("-- ").AppendLine(Strings.Gossip_SqlUnsupportedObject .LocalizedFormat(obj.ObjectType, obj.ObjectName)); } } CultureInfo culture = null; if (m_viewer.CurrentLog is IHasCultureInfo) { culture = ((IHasCultureInfo)m_viewer.CurrentLog).Culture; } var locale = WowLocales.enUS; if (culture != null && culture.IsWowCompatibleCulture()) { locale = culture.GetWowLocale(); } bool defaultLocale = locale == WowLocales.enUS; builder.AppendFormatLine("REPLACE INTO gossip_menu (entry, text_id) VALUES ({0}, {1});", menu.Menu.MenuId, menu.Menu.TextId); var length = menu.Menu.GossipOptions.Length; if (length > 0) { builder.AppendLine("REPLACE INTO gossip_menu_option (menu_id, id, option_icon, option_text, npc_option_npcflag, action_menu_id, action_poi_id, box_coded, box_money, box_text) VALUES"); for (int i = 0; i < length; i++) { var opt = menu.Menu.GossipOptions[i]; builder.AppendFormat( "({0}, {1}, {2}, '{3}', {4}, {5}, {6}, {7}, {8}, '{9}')", menu.Menu.MenuId, opt.OptionId, opt.Icon, (defaultLocale ? "" : "[PH] ") + opt.Text.EscapeQuotes(), 0, menu.GossipOptionMenus[i], 0, opt.IsPasswordRequired ? 1 : 0, opt.MoneyRequired, (!defaultLocale && opt.BoxText != string.Empty ? "[PH] " : "") + opt.BoxText.EscapeQuotes()); if (i + 1 == length) { builder.AppendLine(";"); } else { builder.AppendLine(","); } } if (!defaultLocale) { builder.AppendFormatLine( "REPLACE INTO locales_gossip_menu_option " + "(menu_id, id, option_text_loc{0}, box_text_loc{0}) VALUES", (int)locale); for (int i = 0; i < length; i++) { var opt = menu.Menu.GossipOptions[i]; builder.AppendFormat( "({0}, {1}, '{2}', '{3}')", menu.Menu.MenuId, opt.OptionId, opt.Text.EscapeQuotes(), opt.BoxText.EscapeQuotes()); if (i + 1 == length) { builder.AppendLine(";"); } else { builder.AppendLine(","); } } } } }
void m_parsingItemsWorker_DoWork(object sender, DoWorkEventArgs e) { var worker = (BackgroundWorker)sender; var items = (IList <ViewerItem>)e.Argument; var nitems = items.Count; int progress = 0; var protocol = m_viewer.CurrentProtocol; var objects = new SortedDictionary <WowGuid, ObjectGossip>(new WowGuidKindEntryComparer()); var menus = new SortedDictionary <uint, ExtGossipMenu>(); ExtGossipMenu currentMenu = null; WowGuid currentObject = WowGuid.Empty; Action resetCurrent = () => { currentMenu = null; currentObject = WowGuid.Empty; }; var optSelectQueue = new Queue <GossipSelectOption>(); for (int i = 0; i < nitems && !worker.CancellationPending; i++) { var item = items[i]; var packet = item.Packet; var opcodePacket = packet as IPacketWithOpcode; if (opcodePacket == null) { continue; } var opcode = (WowOpcodes)opcodePacket.Opcode; switch (opcode) { #warning Gossip Parser not implemented //case WowOpcodes.CMSG_GOSSIP_HELLO: //case WowOpcodes.CMSG_GAMEOBJ_USE: //case WowOpcodes.CMSG_LIST_INVENTORY: //case WowOpcodes.CMSG_TRAINER_LIST: //{ // using (var reader = new StreamHandler(packet.Data)) // { // optSelectQueue.Enqueue(new GossipSelectOption() // { // Object = reader.ReadGuid(), // MenuId = uint.MaxValue, // OptionId = uint.MaxValue // }); // } // break; //} //case WowOpcodes.CMSG_GOSSIP_SELECT_OPTION: //{ // if (currentMenu != null) // { // using (var reader = new StreamHandler(packet.Data)) // { // var obj = reader.ReadGuid(); // var menuId = reader.ReadUInt32(); // var optionId = reader.ReadUInt32(); // if (currentMenu.Menu.MenuId == menuId) // { // optSelectQueue.Enqueue(new GossipSelectOption() // { // Object = obj, // MenuId = menuId, // OptionId = optionId // }); // } // else // Console.WriteLine("Error: Gossip Menu: currentMenuId != selectedMenuId ({0} != {1})", // currentMenu.Menu.MenuId, menuId); // } // } // else // Console.WriteLine("Error: Gossip Parser: Unexpected CMSG_GOSSIP_SELECT_OPTION (inner)"); // break; //} //case WowOpcodes.SMSG_DESTROY_OBJECT: //{ // var guid = new WowGuid(BitConverter.ToUInt64(packet.Data, 0)); // if (currentObject == guid) // resetCurrent(); // break; //} //case WowOpcodes.SMSG_UPDATE_OBJECT: //{ // using (var reader = new StreamHandler(packet.Data)) // { // var updateData = new UpdateData(reader, true); // foreach (var guid in updateData.DestroyedObjects) // { // if (currentObject == guid) // resetCurrent(); // } // } // break; //} //case WowOpcodes.CMSG_QUESTGIVER_ACCEPT_QUEST: //{ // var guid = new WowGuid(BitConverter.ToUInt64(packet.Data, 0)); // if (optSelectQueue.Count > 0) // { // if (optSelectQueue.Peek().Object == guid) // optSelectQueue.Dequeue(); // else // Console.WriteLine("Error: Gossip Parser: Unexpected {0} (packet #{1})", opcode, i); // } // break; //} //case WowOpcodes.SMSG_TRAINER_LIST: //case WowOpcodes.SMSG_VENDOR_INVENTORY: //case WowOpcodes.SMSG_INVALID_PROMOTION_CODE: //{ // if (optSelectQueue.Count > 0) // optSelectQueue.Dequeue(); // else // Console.WriteLine("Error: Gossip Parser: Unexpected {0} (packet #{1})", opcode, i); // break; //} //case WowOpcodes.SMSG_GOSSIP_COMPLETE: //{ // while (optSelectQueue.Count > 0 && // optSelectQueue.Peek().Object == currentObject && // optSelectQueue.Peek().MenuId == currentMenu.Menu.MenuId) // optSelectQueue.Dequeue(); // resetCurrent(); // break; //} //case WowOpcodes.CMSG_LOADING_SCREEN_NOTIFY: //case WowOpcodes.SMSG_NEW_WORLD: case WowOpcodes.SMSG_LOGIN_VERIFY_WORLD: { resetCurrent(); optSelectQueue.Clear(); break; } default: { var parser = item.Parser; if (parser == null) { protocol.CreateParser(item); parser = item.Parser; } if (parser is GossipMessageParser) { var gossip = (GossipMessageParser)parser; if (!gossip.IsParsed) { gossip.Parse(); } var menu = gossip.Menu; ExtGossipMenu extMenu; if (!menus.TryGetValue(menu.MenuId, out extMenu)) { menus[menu.MenuId] = extMenu = new ExtGossipMenu() { Menu = menu, GossipOptionMenus = new uint[menu.GossipOptions.Length] }; } else { var existingMenu = extMenu.Menu; if (!existingMenu.Equals(menu)) { Console.WriteLine("Error: Gossip Parser: New menu with same id {0}", menu.MenuId); break; } } var guid = gossip.Object; extMenu.Objects.Add(guid); ObjectGossip gossipObject; if (!objects.TryGetValue(guid, out gossipObject)) { objects[guid] = gossipObject = new ObjectGossip() { ObjectType = guid.Kind, ObjectEntry = guid.Entry }; } GossipSelectOption opt = null; while (optSelectQueue.Count > 0) { var optSelect = optSelectQueue.Dequeue(); if (optSelect.Object != guid && optSelect.Object.IsGameObject) { continue; } opt = optSelect; break; } if (opt == null) { Console.WriteLine("Error: Gossip Parser: Unexpected Gossip Message"); break; } if ((opt.MenuId == uint.MaxValue) != (currentMenu == null)) { Console.WriteLine("Error: Gossip Parser: unexpected state of gossip parser, packet = {0}", i); } if (currentMenu == null) { // Just interacted with the object gossipObject.InitialMenus.Add(menu.MenuId); currentObject = guid; } else { if (guid != currentObject) { Console.WriteLine("Error: Gossip Parser: unexpected object"); break; } // Got a gossip message after an option was selected int idx = currentMenu.Menu.GossipOptions.IndexOf(_ => _.OptionId == opt.OptionId); if (idx != -1) { currentMenu.GossipOptionMenus[idx] = menu.MenuId; } else { Console.WriteLine("Error: Gossip Parser: Unable to find option {0} in menu {1}", opt.OptionId, opt.MenuId); } } if (gossipObject.Menus.IndexOf(extMenu) < 0) { gossipObject.Menus.Add(extMenu); } currentMenu = extMenu; } else if (parser is CreatureQueryResponseParser) { var query = (CreatureQueryResponseParser)parser; if (!query.IsParsed) { query.Parse(); } var id = query.Template.Entry; if (id < 0) { continue; } m_creatureTemplates[(uint)id] = query.Template; } else if (parser is GameObjectQueryResponseParser) { var query = (GameObjectQueryResponseParser)parser; if (!query.IsParsed) { query.Parse(); } var id = query.Template.Entry; if (id < 0) { continue; } m_goTemplates[(uint)id] = query.Template; } break; } } int newProgress = 100 * i / nitems; if (newProgress != progress) { worker.ReportProgress(progress = newProgress); } } if (worker.CancellationPending) { m_objects = new KeyValuePair <WowGuid, ObjectGossip> [0]; m_menus = new KeyValuePair <uint, ExtGossipMenu> [0]; return; } // Setup names. foreach (var pair in objects) { var obj = pair.Value; var s = obj.ObjectType.ToString() + " #" + obj.ObjectEntry.ToString(); if (obj.ObjectType == WowGuidKind.GameObject) { GameObjectTemplate go; if (m_goTemplates.TryGetValue(obj.ObjectEntry, out go)) { s += " - " + go.Name[0]; } } else if (obj.ObjectType == WowGuidKind.Unit) { CreatureTemplate npc; if (m_creatureTemplates.TryGetValue(obj.ObjectEntry, out npc)) { s += " - " + npc.Name[0] + (string.IsNullOrEmpty(npc.SubName) ? "" : " <" + npc.SubName + ">"); } } obj.ObjectName = s; } m_objects = objects.ToArray(); m_menus = menus.ToArray(); }