void WardenMac::HandleHashResult(ByteBuffer &buff) { // test int keyIn[4]; keyData mod_seed = { { { { 0x4D, 0x80, 0x8D, 0x2C, 0x77, 0xD9, 0x05, 0xC4, 0x1A, 0x63, 0x80, 0xEC, 0x08, 0x58, 0x6A, 0xFE } } } }; for (int i = 0; i < 4; ++i) { keyIn[i] = mod_seed.ints.ints[i]; } int keyOut[4]; int keyIn1, keyIn2; keyOut[0] = keyIn[0]; keyIn[0] ^= 0xDEADBEEFu; keyIn1 = keyIn[1]; keyIn[1] -= 0x35014542u; keyIn2 = keyIn[2]; keyIn[2] += 0x5313F22u; keyIn[3] *= 0x1337F00Du; keyOut[1] = keyIn1 - 0x6A028A84; keyOut[2] = keyIn2 + 0xA627E44; keyOut[3] = 0x1337F00D * keyIn[3]; // end test buff.rpos(buff.wpos()); SHA1Hash sha1; sha1.UpdateData((uint8*)keyIn, 16); sha1.Finalize(); //const uint8 validHash[20] = { 0x56, 0x8C, 0x05, 0x4C, 0x78, 0x1A, 0x97, 0x2A, 0x60, 0x37, 0xA2, 0x29, 0x0C, 0x22, 0xB5, 0x25, 0x71, 0xA0, 0x6F, 0x4E }; // Verify key if (memcmp(buff.contents() + 1, sha1.GetDigest(), 20) != 0) { TC_LOG_WARN("warden", "%s failed hash reply. Action: %s", _session->GetPlayerInfo().c_str(), Penalty().c_str()); return; } TC_LOG_DEBUG("warden", "Request hash reply: succeed"); // client 7F96EEFDA5B63D20A4DF8E00CBF48304 //const uint8 client_key[16] = { 0x7F, 0x96, 0xEE, 0xFD, 0xA5, 0xB6, 0x3D, 0x20, 0xA4, 0xDF, 0x8E, 0x00, 0xCB, 0xF4, 0x83, 0x04 }; // server C2B7ADEDFCCCA9C2BFB3F85602BA809B //const uint8 server_key[16] = { 0xC2, 0xB7, 0xAD, 0xED, 0xFC, 0xCC, 0xA9, 0xC2, 0xBF, 0xB3, 0xF8, 0x56, 0x02, 0xBA, 0x80, 0x9B }; // change keys here memcpy(_inputKey, keyIn, 16); memcpy(_outputKey, keyOut, 16); _inputCrypto.Init(_inputKey); _outputCrypto.Init(_outputKey); _initialized = true; _previousTimestamp = getMSTime(); }
void WorldSession::HandleQuestgiverQuestAutoLaunch(WorldPacket& /*recvPacket*/) { TC_LOG_DEBUG("network", "WORLD: Received CMSG_QUESTGIVER_QUEST_AUTOLAUNCH"); }
void PlayerMenu::SendQuestGiverQuestDetails(Quest const* quest, ObjectGuid npcGUID, bool activateAccept) const { std::string questLogTitle = quest->GetLogTitle(); std::string questLogDescription = quest->GetLogDescription(); std::string questDescription = quest->GetQuestDescription(); std::string portraitGiverText = quest->GetPortraitGiverText(); std::string portraitGiverName = quest->GetPortraitGiverName(); std::string portraitTurnInText = quest->GetPortraitTurnInText(); std::string portraitTurnInName = quest->GetPortraitTurnInName(); LocaleConstant localeConstant = _session->GetSessionDbLocaleIndex(); if (localeConstant >= LOCALE_enUS) { if (QuestTemplateLocale const* questTemplateLocale = sObjectMgr->GetQuestLocale(quest->GetQuestId())) { ObjectMgr::GetLocaleString(questTemplateLocale->LogTitle, localeConstant, questLogTitle); ObjectMgr::GetLocaleString(questTemplateLocale->LogDescription, localeConstant, questLogDescription); ObjectMgr::GetLocaleString(questTemplateLocale->QuestDescription, localeConstant, questDescription); ObjectMgr::GetLocaleString(questTemplateLocale->PortraitGiverText, localeConstant, portraitGiverText); ObjectMgr::GetLocaleString(questTemplateLocale->PortraitGiverName, localeConstant, portraitGiverName); ObjectMgr::GetLocaleString(questTemplateLocale->PortraitTurnInText, localeConstant, portraitTurnInText); ObjectMgr::GetLocaleString(questTemplateLocale->PortraitTurnInName, localeConstant, portraitTurnInName); } } if (sWorld->getBoolConfig(CONFIG_UI_QUESTLEVELS_IN_DIALOGS)) AddQuestLevelToTitle(questLogTitle, quest->GetQuestLevel()); WorldPackets::Quest::QuestGiverQuestDetails packet; packet.QuestGiverGUID = npcGUID; packet.InformUnit = _session->GetPlayer()->GetDivider(); packet.QuestID = quest->GetQuestId(); packet.QuestTitle = questLogTitle; packet.LogDescription = questLogDescription; packet.DescriptionText = questDescription; packet.PortraitGiverText = portraitGiverText; packet.PortraitGiverName = portraitGiverName; packet.PortraitTurnInText = portraitTurnInText; packet.PortraitTurnInName = portraitTurnInName; packet.PortraitGiver = quest->GetQuestGiverPortrait(); packet.PortraitTurnIn = quest->GetQuestTurnInPortrait(); packet.DisplayPopup = activateAccept; packet.QuestFlags[0] = quest->GetFlags(); packet.QuestFlags[1] = quest->GetFlagsEx(); packet.SuggestedPartyMembers = quest->GetSuggestedPlayers(); if (quest->GetSrcSpell()) packet.LearnSpells.push_back(quest->GetSrcSpell()); quest->BuildQuestRewards(packet.Rewards, _session->GetPlayer()); packet.DescEmotes.resize(QUEST_EMOTE_COUNT); for (uint32 i = 0; i < QUEST_EMOTE_COUNT; ++i) { packet.DescEmotes[i].Type = quest->DetailsEmote[i]; packet.DescEmotes[i].Delay = quest->DetailsEmoteDelay[i]; } QuestObjectives const& objs = quest->GetObjectives(); packet.Objectives.resize(objs.size()); for (uint32 i = 0; i < objs.size(); ++i) { packet.Objectives[i].ID = objs[i].ID; packet.Objectives[i].ObjectID = objs[i].ObjectID; packet.Objectives[i].Amount = objs[i].Amount; packet.Objectives[i].Type = objs[i].Type; } _session->SendPacket(packet.Write()); TC_LOG_DEBUG("network", "WORLD: Sent SMSG_QUESTGIVER_QUEST_DETAILS NPC=%s, questid=%u", npcGUID.ToString().c_str(), quest->GetQuestId()); }
void WorldSession::HandleMoveSplineDoneOpcode(WorldPacket& recvData) { recvData.read_skip<uint32>(); // unk MovementInfo movementInfo; // used only for proper packet read _player->ValidateMovementInfo(&movementInfo); // in taxi flight packet received in 2 case: // 1) end taxi path in far (multi-node) flight // 2) switch from one map to other in case multim-map taxi path // we need process only (1) uint32 curDest = GetPlayer()->m_taxi.GetTaxiDestination(); if (!curDest) return; TaxiNodesEntry const* curDestNode = sTaxiNodesStore.LookupEntry(curDest); // far teleport case if (curDestNode && curDestNode->MapID != GetPlayer()->GetMapId()) { if (GetPlayer()->GetMotionMaster()->GetCurrentMovementGeneratorType() == FLIGHT_MOTION_TYPE) { // short preparations to continue flight FlightPathMovementGenerator* flight = (FlightPathMovementGenerator*)(GetPlayer()->GetMotionMaster()->top()); flight->SetCurrentNodeAfterTeleport(); TaxiPathNodeEntry const& node = flight->GetPath()[flight->GetCurrentNode()]; flight->SkipCurrentNode(); GetPlayer()->TeleportTo(curDestNode->MapID, node.Loc.X, node.Loc.Y, node.Loc.Z, GetPlayer()->GetOrientation()); } return; } uint32 destinationnode = GetPlayer()->m_taxi.NextTaxiDestination(); if (destinationnode > 0) // if more destinations to go { // current source node for next destination uint32 sourcenode = GetPlayer()->m_taxi.GetTaxiSource(); // Add to taximask middle hubs in taxicheat mode (to prevent having player with disabled taxicheat and not having back flight path) if (GetPlayer()->isTaxiCheater()) { if (GetPlayer()->m_taxi.SetTaximaskNode(sourcenode)) { WorldPacket data(SMSG_NEW_TAXI_PATH, 0); _player->GetSession()->SendPacket(&data); } } TC_LOG_DEBUG("network", "WORLD: Taxi has to go from %u to %u", sourcenode, destinationnode); uint32 mountDisplayId = sObjectMgr->GetTaxiMountDisplayId(sourcenode, GetPlayer()->GetTeam()); uint32 path, cost; sObjectMgr->GetTaxiPath(sourcenode, destinationnode, path, cost); if (path && mountDisplayId) SendDoFlight(mountDisplayId, path, 1); // skip start fly node else GetPlayer()->m_taxi.ClearTaxiDestinations(); // clear problematic path and next return; } else GetPlayer()->m_taxi.ClearTaxiDestinations(); // not destinations, clear source node GetPlayer()->CleanupAfterTaxiFlight(); GetPlayer()->SetFallInformation(0, GetPlayer()->GetPositionZ()); if (GetPlayer()->pvpInfo.IsHostile) GetPlayer()->CastSpell(GetPlayer(), 2479, true); }
void WorldSession::HandleQuestgiverChooseRewardOpcode(WorldPacket& recvData) { uint32 questId, reward; ObjectGuid guid; recvData >> guid >> questId >> reward; if (reward >= QUEST_REWARD_CHOICES_COUNT) { TC_LOG_ERROR("network", "Error in CMSG_QUESTGIVER_CHOOSE_REWARD: player %s (guid %d) tried to get invalid reward (%u) (possible packet-hacking detected)", _player->GetName().c_str(), _player->GetGUID().GetCounter(), reward); return; } TC_LOG_DEBUG("network", "WORLD: Received CMSG_QUESTGIVER_CHOOSE_REWARD npc = %s, quest = %u, reward = %u", guid.ToString().c_str(), questId, reward); Object* object = ObjectAccessor::GetObjectByTypeMask(*_player, guid, TYPEMASK_UNIT | TYPEMASK_GAMEOBJECT); if (!object || !object->hasInvolvedQuest(questId)) return; // some kind of WPE protection if (!_player->CanInteractWithQuestGiver(object)) return; if (Quest const* quest = sObjectMgr->GetQuestTemplate(questId)) { if ((!_player->CanSeeStartQuest(quest) && _player->GetQuestStatus(questId) == QUEST_STATUS_NONE) || (_player->GetQuestStatus(questId) != QUEST_STATUS_COMPLETE && !quest->IsAutoComplete())) { TC_LOG_ERROR("network", "Error in QUEST_STATUS_COMPLETE: player %s (guid %u) tried to complete quest %u, but is not allowed to do so (possible packet-hacking or high latency)", _player->GetName().c_str(), _player->GetGUID().GetCounter(), questId); return; } if (_player->CanRewardQuest(quest, reward, true)) { _player->RewardQuest(quest, reward, object); switch (object->GetTypeId()) { case TYPEID_UNIT: { Creature* questgiver = object->ToCreature(); if (!sScriptMgr->OnQuestReward(_player, questgiver, quest, reward)) { // Send next quest if (Quest const* nextQuest = _player->GetNextQuest(guid, quest)) { // Only send the quest to the player if the conditions are met if (_player->CanTakeQuest(nextQuest, false)) { if (nextQuest->IsAutoAccept() && _player->CanAddQuest(nextQuest, true)) _player->AddQuestAndCheckCompletion(nextQuest, object); _player->PlayerTalkClass->SendQuestGiverQuestDetails(nextQuest, guid, true); } } questgiver->AI()->sQuestReward(_player, quest, reward); } break; } case TYPEID_GAMEOBJECT: { GameObject* questGiver = object->ToGameObject(); if (!sScriptMgr->OnQuestReward(_player, questGiver, quest, reward)) { // Send next quest if (Quest const* nextQuest = _player->GetNextQuest(guid, quest)) { // Only send the quest to the player if the conditions are met if (_player->CanTakeQuest(nextQuest, false)) { if (nextQuest->IsAutoAccept() && _player->CanAddQuest(nextQuest, true)) _player->AddQuestAndCheckCompletion(nextQuest, object); _player->PlayerTalkClass->SendQuestGiverQuestDetails(nextQuest, guid, true); } } questGiver->AI()->QuestReward(_player, quest, reward); } break; } default: break; } } else _player->PlayerTalkClass->SendQuestGiverOfferReward(quest, guid, true); } }
int RASocket::subnegotiate() { char buf[1024]; ACE_Data_Block db(sizeof (buf), ACE_Message_Block::MB_DATA, buf, 0, 0, ACE_Message_Block::DONT_DELETE, 0); ACE_Message_Block message_block(&db, ACE_Message_Block::DONT_DELETE, 0); const size_t recv_size = message_block.space(); // Wait a maximum of 1000ms for negotiation packet - not all telnet clients may send it ACE_Time_Value waitTime = ACE_Time_Value(1); const ssize_t n = peer().recv(message_block.wr_ptr(), recv_size, &waitTime); if (n <= 0) return int(n); if (n >= 1024) { TC_LOG_DEBUG("commands.ra", "RASocket::subnegotiate: allocated buffer 1024 bytes was too small for negotiation packet, size: %u", uint32(n)); return -1; } buf[n] = '\0'; #ifdef _DEBUG for (uint8 i = 0; i < n; ) { uint8 iac = buf[i]; if (iac == 0xFF) // "Interpret as Command" (IAC) { uint8 command = buf[++i]; std::stringstream ss; switch (command) { case 0xFB: // WILL ss << "WILL "; break; case 0xFC: // WON'T ss << "WON'T "; break; case 0xFD: // DO ss << "DO "; break; case 0xFE: // DON'T ss << "DON'T "; break; default: return -1; // not allowed } uint8 param = buf[++i]; ss << uint32(param); TC_LOG_DEBUG("commands.ra", ss.str().c_str()); } ++i; } #endif //! Just send back end of subnegotiation packet uint8 const reply[2] = {0xFF, 0xF0}; #ifdef MSG_NOSIGNAL return int(peer().send(reply, 2, MSG_NOSIGNAL)); #else return int(peer().send(reply, 2)); #endif // MSG_NOSIGNAL }
void WorldSession::SendTrainerList(uint64 guid, const std::string& strTitle) { TC_LOG_DEBUG("network", "WORLD: SendTrainerList"); Creature* unit = GetPlayer()->GetNPCIfCanInteractWith(guid, UNIT_NPC_FLAG_TRAINER); if (!unit) { TC_LOG_DEBUG("network", "WORLD: SendTrainerList - Unit (GUID: %u) not found or you can not interact with him.", uint32(GUID_LOPART(guid))); return; } // remove fake death if (GetPlayer()->HasUnitState(UNIT_STATE_DIED)) GetPlayer()->RemoveAurasByType(SPELL_AURA_FEIGN_DEATH); CreatureTemplate const* ci = unit->GetCreatureTemplate(); if (!ci) { TC_LOG_DEBUG("network", "WORLD: SendTrainerList - (GUID: %u) NO CREATUREINFO!", GUID_LOPART(guid)); return; } TrainerSpellData const* trainer_spells = unit->GetTrainerSpells(); if (!trainer_spells) { TC_LOG_DEBUG("network", "WORLD: SendTrainerList - Training spells not found for creature (GUID: %u Entry: %u)", GUID_LOPART(guid), unit->GetEntry()); return; } WorldPacket data(SMSG_TRAINER_LIST, 8+4+4+trainer_spells->spellList.size()*38 + strTitle.size()+1); data << guid; data << uint32(trainer_spells->trainerType); size_t count_pos = data.wpos(); data << uint32(trainer_spells->spellList.size()); // reputation discount float fDiscountMod = _player->GetReputationPriceDiscount(unit); bool can_learn_primary_prof = GetPlayer()->GetFreePrimaryProfessionPoints() > 0; uint32 count = 0; for (TrainerSpellMap::const_iterator itr = trainer_spells->spellList.begin(); itr != trainer_spells->spellList.end(); ++itr) { TrainerSpell const* tSpell = &itr->second; bool valid = true; bool primary_prof_first_rank = false; for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) { if (!tSpell->learnedSpell[i]) continue; if (!_player->IsSpellFitByClassAndRace(tSpell->learnedSpell[i])) { valid = false; break; } SpellInfo const* learnedSpellInfo = sSpellMgr->GetSpellInfo(tSpell->learnedSpell[i]); if (learnedSpellInfo && learnedSpellInfo->IsPrimaryProfessionFirstRank()) primary_prof_first_rank = true; } if (!valid) continue; TrainerSpellState state = _player->GetTrainerSpellState(tSpell); data << uint32(tSpell->spell); // learned spell (or cast-spell in profession case) data << uint8(state == TRAINER_SPELL_GREEN_DISABLED ? TRAINER_SPELL_GREEN : state); data << uint32(floor(tSpell->spellCost * fDiscountMod)); data << uint32(primary_prof_first_rank && can_learn_primary_prof ? 1 : 0); // primary prof. learn confirmation dialog data << uint32(primary_prof_first_rank ? 1 : 0); // must be equal prev. field to have learn button in enabled state data << uint8(tSpell->reqLevel); data << uint32(tSpell->reqSkill); data << uint32(tSpell->reqSkillValue); //prev + req or req + 0 uint8 maxReq = 0; for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) { if (!tSpell->learnedSpell[i]) continue; if (uint32 prevSpellId = sSpellMgr->GetPrevSpellInChain(tSpell->learnedSpell[i])) { data << uint32(prevSpellId); ++maxReq; } if (maxReq == 3) break; SpellsRequiringSpellMapBounds spellsRequired = sSpellMgr->GetSpellsRequiredForSpellBounds(tSpell->learnedSpell[i]); for (SpellsRequiringSpellMap::const_iterator itr2 = spellsRequired.first; itr2 != spellsRequired.second && maxReq < 3; ++itr2) { data << uint32(itr2->second); ++maxReq; } if (maxReq == 3) break; } while (maxReq < 3) { data << uint32(0); ++maxReq; } ++count; } data << strTitle; data.put<uint32>(count_pos, count); SendPacket(&data); }
// Reconnect Challenge command handler bool AuthSocket::_HandleReconnectChallenge() { TC_LOG_DEBUG(LOG_FILTER_AUTHSERVER, "Entering _HandleReconnectChallenge"); if (socket().recv_len() < sizeof(sAuthLogonChallenge_C)) return false; // Read the first 4 bytes (header) to get the length of the remaining of the packet std::vector<uint8> buf; buf.resize(4); socket().recv((char *)&buf[0], 4); #if TRINITY_ENDIAN == TRINITY_BIGENDIAN EndianConvert(*((uint16*)(buf[0]))); #endif uint16 remaining = ((sAuthLogonChallenge_C *)&buf[0])->size; TC_LOG_DEBUG(LOG_FILTER_AUTHSERVER, "[ReconnectChallenge] got header, body is %#04x bytes", remaining); if ((remaining < sizeof(sAuthLogonChallenge_C) - buf.size()) || (socket().recv_len() < remaining)) return false; // No big fear of memory outage (size is int16, i.e. < 65536) buf.resize(remaining + buf.size() + 1); buf[buf.size() - 1] = 0; sAuthLogonChallenge_C *ch = (sAuthLogonChallenge_C*)&buf[0]; // Read the remaining of the packet socket().recv((char *)&buf[4], remaining); TC_LOG_DEBUG(LOG_FILTER_AUTHSERVER, "[ReconnectChallenge] got full packet, %#04x bytes", ch->size); TC_LOG_DEBUG(LOG_FILTER_AUTHSERVER, "[ReconnectChallenge] name(%d): '%s'", ch->I_len, ch->I); _login = (const char*)ch->I; PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_SESSIONKEY); stmt->setString(0, _login); PreparedQueryResult result = LoginDatabase.Query(stmt); // Stop if the account is not found if (!result) { TC_LOG_ERROR(LOG_FILTER_AUTHSERVER, "'%s:%d' [ERROR] user %s tried to login and we cannot find his session key in the database.", socket().getRemoteAddress().c_str(), socket().getRemotePort(), _login.c_str()); socket().shutdown(); return false; } // Reinitialize build, expansion and the account securitylevel _build = ch->build; _expversion = uint8(AuthHelper::IsPostBCAcceptedClientBuild(_build) ? POST_BC_EXP_FLAG : (AuthHelper::IsPreBCAcceptedClientBuild(_build) ? PRE_BC_EXP_FLAG : NO_VALID_EXP_FLAG)); _os = (const char*)ch->os; if (_os.size() > 4) return false; // Restore string order as its byte order is reversed std::reverse(_os.begin(), _os.end()); Field* fields = result->Fetch(); uint8 secLevel = fields[2].GetUInt8(); _accountSecurityLevel = secLevel <= SEC_ADMINISTRATOR ? AccountTypes(secLevel) : SEC_ADMINISTRATOR; K.SetHexStr ((*result)[0].GetCString()); // Sending response ByteBuffer pkt; pkt << uint8(AUTH_RECONNECT_CHALLENGE); pkt << uint8(0x00); _reconnectProof.SetRand(16 * 8); pkt.append(_reconnectProof.AsByteArray(16), 16); // 16 bytes random pkt << uint64(0x00) << uint64(0x00); // 16 bytes zeros socket().send((char const*)pkt.contents(), pkt.size()); return true; }
// Realm List command handler bool AuthSocket::_HandleRealmList() { TC_LOG_DEBUG(LOG_FILTER_AUTHSERVER, "Entering _HandleRealmList"); if (socket().recv_len() < 5) return false; socket().recv_skip(5); // Get the user id (else close the connection) // No SQL injection (prepared statement) PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_ACCOUNT_ID_BY_NAME); stmt->setString(0, _login); PreparedQueryResult result = LoginDatabase.Query(stmt); if (!result) { TC_LOG_ERROR(LOG_FILTER_AUTHSERVER, "'%s:%d' [ERROR] user %s tried to login but we cannot find him in the database.", socket().getRemoteAddress().c_str(), socket().getRemotePort(), _login.c_str()); socket().shutdown(); return false; } Field* fields = result->Fetch(); uint32 id = fields[0].GetUInt32(); // Update realm list if need sRealmList->UpdateIfNeed(); // Circle through realms in the RealmList and construct the return packet (including # of user characters in each realm) ByteBuffer pkt; size_t RealmListSize = 0; for (RealmList::RealmMap::const_iterator i = sRealmList->begin(); i != sRealmList->end(); ++i) { // don't work with realms which not compatible with the client bool okBuild = ((_expversion & POST_BC_EXP_FLAG) && i->second.gamebuild == _build) || ((_expversion & PRE_BC_EXP_FLAG) && !AuthHelper::IsPreBCAcceptedClientBuild(i->second.gamebuild)); // No SQL injection. id of realm is controlled by the database. uint32 flag = i->second.flag; RealmBuildInfo const* buildInfo = AuthHelper::GetBuildInfo(i->second.gamebuild); if (!okBuild) { if (!buildInfo) continue; flag |= REALM_FLAG_OFFLINE | REALM_FLAG_SPECIFYBUILD; // tell the client what build the realm is for } if (!buildInfo) flag &= ~REALM_FLAG_SPECIFYBUILD; std::string name = i->first; if (_expversion & PRE_BC_EXP_FLAG && flag & REALM_FLAG_SPECIFYBUILD) { std::ostringstream ss; ss << name << " (" << buildInfo->MajorVersion << '.' << buildInfo->MinorVersion << '.' << buildInfo->BugfixVersion << ')'; name = ss.str(); } uint8 lock = (i->second.allowedSecurityLevel > _accountSecurityLevel) ? 1 : 0; uint8 AmountOfCharacters = 0; stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_NUM_CHARS_ON_REALM); stmt->setUInt32(0, i->second.m_ID); stmt->setUInt32(1, id); result = LoginDatabase.Query(stmt); if (result) AmountOfCharacters = (*result)[0].GetUInt8(); pkt << i->second.icon; // realm type if (_expversion & POST_BC_EXP_FLAG) // only 2.x and 3.x clients pkt << lock; // if 1, then realm locked pkt << uint8(flag); // RealmFlags pkt << name; pkt << i->second.RealmAddress; pkt << i->second.populationLevel; pkt << AmountOfCharacters; pkt << i->second.timezone; // realm category if (_expversion & POST_BC_EXP_FLAG) // 2.x and 3.x clients pkt << uint8(0x2C); // unk, may be realm number/id? else pkt << uint8(0x0); // 1.12.1 and 1.12.2 clients if (_expversion & POST_BC_EXP_FLAG && flag & REALM_FLAG_SPECIFYBUILD) { pkt << uint8(buildInfo->MajorVersion); pkt << uint8(buildInfo->MinorVersion); pkt << uint8(buildInfo->BugfixVersion); pkt << uint16(buildInfo->Build); } ++RealmListSize; } if (_expversion & POST_BC_EXP_FLAG) // 2.x and 3.x clients { pkt << uint8(0x10); pkt << uint8(0x00); } else // 1.12.1 and 1.12.2 clients { pkt << uint8(0x00); pkt << uint8(0x02); } // make a ByteBuffer which stores the RealmList's size ByteBuffer RealmListSizeBuffer; RealmListSizeBuffer << uint32(0); if (_expversion & POST_BC_EXP_FLAG) // only 2.x and 3.x clients RealmListSizeBuffer << uint16(RealmListSize); else RealmListSizeBuffer << uint32(RealmListSize); ByteBuffer hdr; hdr << uint8(REALM_LIST); hdr << uint16(pkt.size() + RealmListSizeBuffer.size()); hdr.append(RealmListSizeBuffer); // append RealmList's size buffer hdr.append(pkt); // append realms in the realmlist socket().send((char const*)hdr.contents(), hdr.size()); return true; }
// Logon Challenge command handler bool AuthSocket::_HandleLogonChallenge() { TC_LOG_DEBUG(LOG_FILTER_AUTHSERVER, "Entering _HandleLogonChallenge"); if (socket().recv_len() < sizeof(sAuthLogonChallenge_C)) return false; // Read the first 4 bytes (header) to get the length of the remaining of the packet std::vector<uint8> buf; buf.resize(4); socket().recv((char *)&buf[0], 4); #if TRINITY_ENDIAN == TRINITY_BIGENDIAN EndianConvert(*((uint16*)(buf[0]))); #endif uint16 remaining = ((sAuthLogonChallenge_C *)&buf[0])->size; TC_LOG_DEBUG(LOG_FILTER_AUTHSERVER, "[AuthChallenge] got header, body is %#04x bytes", remaining); if ((remaining < sizeof(sAuthLogonChallenge_C) - buf.size()) || (socket().recv_len() < remaining)) return false; //No big fear of memory outage (size is int16, i.e. < 65536) buf.resize(remaining + buf.size() + 1); buf[buf.size() - 1] = 0; sAuthLogonChallenge_C *ch = (sAuthLogonChallenge_C*)&buf[0]; // Read the remaining of the packet socket().recv((char *)&buf[4], remaining); TC_LOG_DEBUG(LOG_FILTER_AUTHSERVER, "[AuthChallenge] got full packet, %#04x bytes", ch->size); TC_LOG_DEBUG(LOG_FILTER_AUTHSERVER, "[AuthChallenge] name(%d): '%s'", ch->I_len, ch->I); // BigEndian code, nop in little endian case // size already converted #if TRINITY_ENDIAN == TRINITY_BIGENDIAN EndianConvert(*((uint32*)(&ch->gamename[0]))); EndianConvert(ch->build); EndianConvert(*((uint32*)(&ch->platform[0]))); EndianConvert(*((uint32*)(&ch->os[0]))); EndianConvert(*((uint32*)(&ch->country[0]))); EndianConvert(ch->timezone_bias); EndianConvert(ch->ip); #endif ByteBuffer pkt; _login = (const char*)ch->I; _build = ch->build; _expversion = uint8(AuthHelper::IsPostBCAcceptedClientBuild(_build) ? POST_BC_EXP_FLAG : (AuthHelper::IsPreBCAcceptedClientBuild(_build) ? PRE_BC_EXP_FLAG : NO_VALID_EXP_FLAG)); _os = (const char*)ch->os; if (_os.size() > 4) return false; // Restore string order as its byte order is reversed std::reverse(_os.begin(), _os.end()); pkt << uint8(AUTH_LOGON_CHALLENGE); pkt << uint8(0x00); // Verify that this IP is not in the ip_banned table LoginDatabase.Execute(LoginDatabase.GetPreparedStatement(LOGIN_DEL_EXPIRED_IP_BANS)); std::string const& ip_address = socket().getRemoteAddress(); PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_IP_BANNED); stmt->setString(0, ip_address); PreparedQueryResult result = LoginDatabase.Query(stmt); if (result) { pkt << uint8(WOW_FAIL_BANNED); TC_LOG_DEBUG(LOG_FILTER_AUTHSERVER, "'%s:%d' [AuthChallenge] Banned ip tries to login!", socket().getRemoteAddress().c_str(), socket().getRemotePort()); } else { // Get the account details from the account table // No SQL injection (prepared statement) stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_LOGONCHALLENGE); stmt->setString(0, _login); PreparedQueryResult res2 = LoginDatabase.Query(stmt); if (res2) { Field* fields = res2->Fetch(); // If the IP is 'locked', check that the player comes indeed from the correct IP address bool locked = false; if (fields[2].GetUInt8() == 1) // if ip is locked { TC_LOG_DEBUG(LOG_FILTER_AUTHSERVER, "[AuthChallenge] Account '%s' is locked to IP - '%s'", _login.c_str(), fields[3].GetCString()); TC_LOG_DEBUG(LOG_FILTER_AUTHSERVER, "[AuthChallenge] Player address is '%s'", ip_address.c_str()); if (strcmp(fields[4].GetCString(), ip_address.c_str())) { TC_LOG_DEBUG(LOG_FILTER_AUTHSERVER, "[AuthChallenge] Account IP differs"); pkt << (uint8) WOW_FAIL_SUSPENDED; locked = true; } else TC_LOG_DEBUG(LOG_FILTER_AUTHSERVER, "[AuthChallenge] Account IP matches"); } //else //{ // TC_LOG_DEBUG(LOG_FILTER_AUTHSERVER, "[AuthChallenge] Account '%s' is not locked to ip", _login.c_str()); // std::string accountCountry = fields[3].GetString(); // if (accountCountry.empty() || accountCountry == "00") // TC_LOG_DEBUG(LOG_FILTER_AUTHSERVER, "[AuthChallenge] Account '%s' is not locked to country", _login.c_str()); // else if (!accountCountry.empty()) // { // uint32 ip = inet_addr(ip_address.c_str()); // EndianConvertReverse(ip); // stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_LOGON_COUNTRY); // stmt->setUInt32(0, ip); // if (PreparedQueryResult sessionCountryQuery = LoginDatabase.Query(stmt)) // { // std::string loginCountry = (*sessionCountryQuery)[0].GetString(); // TC_LOG_DEBUG(LOG_FILTER_AUTHSERVER, "[AuthChallenge] Account '%s' is locked to country: '%s' Player country is '%s'", _login.c_str(), accountCountry.c_str(), loginCountry.c_str()); // if (loginCountry != accountCountry) // { // TC_LOG_DEBUG(LOG_FILTER_AUTHSERVER, "[AuthChallenge] Account country differs."); // pkt << uint8(WOW_FAIL_UNLOCKABLE_LOCK); // locked = true; // } // else // TC_LOG_DEBUG(LOG_FILTER_AUTHSERVER, "[AuthChallenge] Account country matches"); // } // else // TC_LOG_DEBUG(LOG_FILTER_AUTHSERVER, "[AuthChallenge] IP2NATION Table empty"); // } //} if (!locked) { //set expired bans to inactive LoginDatabase.Execute(LoginDatabase.GetPreparedStatement(LOGIN_UPD_EXPIRED_ACCOUNT_BANS)); // If the account is banned, reject the logon attempt stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_ACCOUNT_BANNED); stmt->setUInt32(0, fields[1].GetUInt32()); PreparedQueryResult banresult = LoginDatabase.Query(stmt); if (banresult) { if ((*banresult)[0].GetUInt32() == (*banresult)[1].GetUInt32()) { pkt << uint8(WOW_FAIL_BANNED); TC_LOG_DEBUG(LOG_FILTER_AUTHSERVER, "'%s:%d' [AuthChallenge] Banned account %s tried to login!", socket().getRemoteAddress().c_str(), socket().getRemotePort(), _login.c_str ()); } else { pkt << uint8(WOW_FAIL_SUSPENDED); TC_LOG_DEBUG(LOG_FILTER_AUTHSERVER, "'%s:%d' [AuthChallenge] Temporarily banned account %s tried to login!", socket().getRemoteAddress().c_str(), socket().getRemotePort(), _login.c_str ()); } } else { // Get the password from the account table, upper it, and make the SRP6 calculation std::string rI = fields[0].GetString(); // Don't calculate (v, s) if there are already some in the database std::string databaseV = fields[6].GetString(); std::string databaseS = fields[7].GetString(); TC_LOG_DEBUG(LOG_FILTER_NETWORKIO, "database authentication values: v='%s' s='%s'", databaseV.c_str(), databaseS.c_str()); // multiply with 2 since bytes are stored as hexstring if (databaseV.size() != s_BYTE_SIZE * 2 || databaseS.size() != s_BYTE_SIZE * 2) _SetVSFields(rI); else { s.SetHexStr(databaseS.c_str()); v.SetHexStr(databaseV.c_str()); } b.SetRand(19 * 8); BigNumber gmod = g.ModExp(b, N); B = ((v * 3) + gmod) % N; ASSERT(gmod.GetNumBytes() <= 32); BigNumber unk3; unk3.SetRand(16 * 8); // Fill the response packet with the result if (AuthHelper::IsAcceptedClientBuild(_build)) pkt << uint8(WOW_SUCCESS); else pkt << uint8(WOW_FAIL_VERSION_INVALID); // B may be calculated < 32B so we force minimal length to 32B pkt.append(B.AsByteArray(32), 32); // 32 bytes pkt << uint8(1); pkt.append(g.AsByteArray(), 1); pkt << uint8(32); pkt.append(N.AsByteArray(32), 32); pkt.append(s.AsByteArray(), s.GetNumBytes()); // 32 bytes pkt.append(unk3.AsByteArray(16), 16); uint8 securityFlags = 0; pkt << uint8(securityFlags); // security flags (0x0...0x04) if (securityFlags & 0x01) // PIN input { pkt << uint32(0); pkt << uint64(0) << uint64(0); // 16 bytes hash? } if (securityFlags & 0x02) // Matrix input { pkt << uint8(0); pkt << uint8(0); pkt << uint8(0); pkt << uint8(0); pkt << uint64(0); } if (securityFlags & 0x04) // Security token input pkt << uint8(1); uint8 secLevel = fields[5].GetUInt8(); _accountSecurityLevel = secLevel <= SEC_ADMINISTRATOR ? AccountTypes(secLevel) : SEC_ADMINISTRATOR; _localizationName.resize(4); for (int i = 0; i < 4; ++i) _localizationName[i] = ch->country[4-i-1]; TC_LOG_DEBUG(LOG_FILTER_AUTHSERVER, "'%s:%d' [AuthChallenge] account %s is using '%c%c%c%c' locale (%u)", socket().getRemoteAddress().c_str(), socket().getRemotePort(), _login.c_str (), ch->country[3], ch->country[2], ch->country[1], ch->country[0], GetLocaleByName(_localizationName) ); } } } else //no account pkt << uint8(WOW_FAIL_UNKNOWN_ACCOUNT); } socket().send((char const*)pkt.contents(), pkt.size()); return true; }
// Logon Proof command handler bool AuthSocket::_HandleLogonProof() { TC_LOG_DEBUG(LOG_FILTER_AUTHSERVER, "Entering _HandleLogonProof"); // Read the packet sAuthLogonProof_C lp; if (!socket().recv((char *)&lp, sizeof(sAuthLogonProof_C))) return false; // If the client has no valid version if (_expversion == NO_VALID_EXP_FLAG) { // Check if we have the appropriate patch on the disk TC_LOG_DEBUG(LOG_FILTER_NETWORKIO, "Client with invalid version, patching is not implemented"); socket().shutdown(); return true; } // Continue the SRP6 calculation based on data received from the client BigNumber A; A.SetBinary(lp.A, 32); // SRP safeguard: abort if A == 0 if (A.isZero()) { socket().shutdown(); return true; } SHA1Hash sha; sha.UpdateBigNumbers(&A, &B, NULL); sha.Finalize(); BigNumber u; u.SetBinary(sha.GetDigest(), 20); BigNumber S = (A * (v.ModExp(u, N))).ModExp(b, N); uint8 t[32]; uint8 t1[16]; uint8 vK[40]; memcpy(t, S.AsByteArray(32), 32); for (int i = 0; i < 16; ++i) t1[i] = t[i * 2]; sha.Initialize(); sha.UpdateData(t1, 16); sha.Finalize(); for (int i = 0; i < 20; ++i) vK[i * 2] = sha.GetDigest()[i]; for (int i = 0; i < 16; ++i) t1[i] = t[i * 2 + 1]; sha.Initialize(); sha.UpdateData(t1, 16); sha.Finalize(); for (int i = 0; i < 20; ++i) vK[i * 2 + 1] = sha.GetDigest()[i]; K.SetBinary(vK, 40); uint8 hash[20]; sha.Initialize(); sha.UpdateBigNumbers(&N, NULL); sha.Finalize(); memcpy(hash, sha.GetDigest(), 20); sha.Initialize(); sha.UpdateBigNumbers(&g, NULL); sha.Finalize(); for (int i = 0; i < 20; ++i) hash[i] ^= sha.GetDigest()[i]; BigNumber t3; t3.SetBinary(hash, 20); sha.Initialize(); sha.UpdateData(_login); sha.Finalize(); uint8 t4[SHA_DIGEST_LENGTH]; memcpy(t4, sha.GetDigest(), SHA_DIGEST_LENGTH); sha.Initialize(); sha.UpdateBigNumbers(&t3, NULL); sha.UpdateData(t4, SHA_DIGEST_LENGTH); sha.UpdateBigNumbers(&s, &A, &B, &K, NULL); sha.Finalize(); BigNumber M; M.SetBinary(sha.GetDigest(), 20); // Check if SRP6 results match (password is correct), else send an error if (!memcmp(M.AsByteArray(), lp.M1, 20)) { TC_LOG_DEBUG(LOG_FILTER_AUTHSERVER, "'%s:%d' User '%s' successfully authenticated", socket().getRemoteAddress().c_str(), socket().getRemotePort(), _login.c_str()); // Update the sessionkey, last_ip, last login time and reset number of failed logins in the account table for this account // No SQL injection (escaped user name) and IP address as received by socket const char *K_hex = K.AsHexStr(); PreparedStatement *stmt = LoginDatabase.GetPreparedStatement(LOGIN_UPD_LOGONPROOF); stmt->setString(0, K_hex); stmt->setString(1, socket().getRemoteAddress().c_str()); stmt->setUInt32(2, GetLocaleByName(_localizationName)); stmt->setString(3, _os); stmt->setString(4, _login); LoginDatabase.Execute(stmt); OPENSSL_free((void*)K_hex); // Finish SRP6 and send the final result to the client sha.Initialize(); sha.UpdateBigNumbers(&A, &M, &K, NULL); sha.Finalize(); if (_expversion & POST_BC_EXP_FLAG) // 2.x and 3.x clients { sAuthLogonProof_S proof; memcpy(proof.M2, sha.GetDigest(), 20); proof.cmd = AUTH_LOGON_PROOF; proof.error = 0; proof.unk1 = 0x00800000; // Accountflags. 0x01 = GM, 0x08 = Trial, 0x00800000 = Pro pass (arena tournament) proof.unk2 = 0x00; // SurveyId proof.unk3 = 0x00; socket().send((char *)&proof, sizeof(proof)); } else { sAuthLogonProof_S_Old proof; memcpy(proof.M2, sha.GetDigest(), 20); proof.cmd = AUTH_LOGON_PROOF; proof.error = 0; proof.unk2 = 0x00; socket().send((char *)&proof, sizeof(proof)); } _authed = true; } else { char data[4] = { AUTH_LOGON_PROOF, WOW_FAIL_UNKNOWN_ACCOUNT, 3, 0 }; socket().send(data, sizeof(data)); TC_LOG_DEBUG(LOG_FILTER_AUTHSERVER, "'%s:%d' [AuthChallenge] account %s tried to login with invalid password!", socket().getRemoteAddress().c_str(), socket().getRemotePort(), _login.c_str ()); uint32 MaxWrongPassCount = sConfigMgr->GetIntDefault("WrongPass.MaxCount", 0); if (MaxWrongPassCount > 0) { //Increment number of failed logins by one and if it reaches the limit temporarily ban that account or IP PreparedStatement *stmt = LoginDatabase.GetPreparedStatement(LOGIN_UPD_FAILEDLOGINS); stmt->setString(0, _login); LoginDatabase.Execute(stmt); stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_FAILEDLOGINS); stmt->setString(0, _login); if (PreparedQueryResult loginfail = LoginDatabase.Query(stmt)) { uint32 failed_logins = (*loginfail)[1].GetUInt32(); if (failed_logins >= MaxWrongPassCount) { uint32 WrongPassBanTime = sConfigMgr->GetIntDefault("WrongPass.BanTime", 600); bool WrongPassBanType = sConfigMgr->GetBoolDefault("WrongPass.BanType", false); if (WrongPassBanType) { uint32 acc_id = (*loginfail)[0].GetUInt32(); stmt = LoginDatabase.GetPreparedStatement(LOGIN_INS_ACCOUNT_AUTO_BANNED); stmt->setUInt32(0, acc_id); stmt->setUInt32(1, WrongPassBanTime); LoginDatabase.Execute(stmt); TC_LOG_DEBUG(LOG_FILTER_AUTHSERVER, "'%s:%d' [AuthChallenge] account %s got banned for '%u' seconds because it failed to authenticate '%u' times", socket().getRemoteAddress().c_str(), socket().getRemotePort(), _login.c_str(), WrongPassBanTime, failed_logins); } else { stmt = LoginDatabase.GetPreparedStatement(LOGIN_INS_IP_AUTO_BANNED); stmt->setString(0, socket().getRemoteAddress()); stmt->setUInt32(1, WrongPassBanTime); LoginDatabase.Execute(stmt); TC_LOG_DEBUG(LOG_FILTER_AUTHSERVER, "'%s:%d' [AuthChallenge] IP %s got banned for '%u' seconds because account %s failed to authenticate '%u' times", socket().getRemoteAddress().c_str(), socket().getRemotePort(), socket().getRemoteAddress().c_str(), WrongPassBanTime, _login.c_str(), failed_logins); } } } } } return true; }
void AuthSocket::OnClose(void) { TC_LOG_DEBUG(LOG_FILTER_AUTHSERVER, "AuthSocket::OnClose"); }
// Accept the connection void AuthSocket::OnAccept(void) { TC_LOG_DEBUG(LOG_FILTER_AUTHSERVER, "'%s:%d' Accepting connection", socket().getRemoteAddress().c_str(), socket().getRemotePort()); }
void WardenMac::InitializeModule() { TC_LOG_DEBUG("warden", "Initialize module"); }
/// @todo get rid of this many variables passed in function. void npc_escortAI::Start(bool isActiveAttacker /* = true*/, bool run /* = false */, uint64 playerGUID /* = 0 */, Quest const* quest /* = NULL */, bool instantRespawn /* = false */, bool canLoopPath /* = false */, bool resetWaypoints /* = true */) { if (me->GetVictim()) { TC_LOG_ERROR("misc", "TSCR ERROR: EscortAI (script: %s, creature entry: %u) attempts to Start while in combat", me->GetScriptName().c_str(), me->GetEntry()); return; } if (HasEscortState(STATE_ESCORT_ESCORTING)) { TC_LOG_ERROR("scripts", "EscortAI (script: %s, creature entry: %u) attempts to Start while already escorting", me->GetScriptName().c_str(), me->GetEntry()); return; } if (!ScriptWP && resetWaypoints) // sd2 never adds wp in script, but tc does { if (!WaypointList.empty()) WaypointList.clear(); FillPointMovementListForCreature(); } if (WaypointList.empty()) { TC_LOG_ERROR("scripts", "EscortAI (script: %s, creature entry: %u) starts with 0 waypoints (possible missing entry in script_waypoint. Quest: %u).", me->GetScriptName().c_str(), me->GetEntry(), quest ? quest->GetQuestId() : 0); return; } //set variables m_bIsActiveAttacker = isActiveAttacker; m_bIsRunning = run; m_uiPlayerGUID = playerGUID; m_pQuestForEscort = quest; m_bCanInstantRespawn = instantRespawn; m_bCanReturnToStart = canLoopPath; if (m_bCanReturnToStart && m_bCanInstantRespawn) TC_LOG_DEBUG("scripts", "EscortAI is set to return home after waypoint end and instant respawn at waypoint end. Creature will never despawn."); if (me->GetMotionMaster()->GetCurrentMovementGeneratorType() == WAYPOINT_MOTION_TYPE) { me->GetMotionMaster()->MovementExpired(); me->GetMotionMaster()->MoveIdle(); TC_LOG_DEBUG("scripts", "EscortAI start with WAYPOINT_MOTION_TYPE, changed to MoveIdle."); } //disable npcflags me->SetUInt32Value(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_NONE); if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_NPC)) { HasImmuneToNPCFlags = true; me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_NPC); } TC_LOG_DEBUG("scripts", "EscortAI started with " UI64FMTD " waypoints. ActiveAttacker = %d, Run = %d, PlayerGUID = " UI64FMTD "", uint64(WaypointList.size()), m_bIsActiveAttacker, m_bIsRunning, m_uiPlayerGUID); CurrentWP = WaypointList.begin(); //Set initial speed if (m_bIsRunning) me->SetWalk(false); else me->SetWalk(true); AddEscortState(STATE_ESCORT_ESCORTING); }
void AccountMgr::LoadRBAC() { ClearRBAC(); TC_LOG_DEBUG("rbac", "AccountMgr::LoadRBAC"); uint32 oldMSTime = getMSTime(); uint32 count1 = 0; uint32 count2 = 0; uint32 count3 = 0; TC_LOG_DEBUG("rbac", "AccountMgr::LoadRBAC: Loading permissions"); QueryResult result = LoginDatabase.Query("SELECT id, name FROM rbac_permissions"); if (!result) { TC_LOG_INFO("server.loading", ">> Loaded 0 account permission definitions. DB table `rbac_permissions` is empty."); return; } do { Field* field = result->Fetch(); uint32 id = field[0].GetUInt32(); _permissions[id] = new rbac::RBACPermission(id, field[1].GetString()); ++count1; } while (result->NextRow()); TC_LOG_DEBUG("rbac", "AccountMgr::LoadRBAC: Loading linked permissions"); result = LoginDatabase.Query("SELECT id, linkedId FROM rbac_linked_permissions ORDER BY id ASC"); if (!result) { TC_LOG_INFO("server.loading", ">> Loaded 0 linked permissions. DB table `rbac_linked_permissions` is empty."); return; } uint32 permissionId = 0; rbac::RBACPermission* permission = NULL; do { Field* field = result->Fetch(); uint32 newId = field[0].GetUInt32(); if (permissionId != newId) { permissionId = newId; permission = _permissions[newId]; } uint32 linkedPermissionId = field[1].GetUInt32(); if (linkedPermissionId == permissionId) { TC_LOG_ERROR("sql.sql", "RBAC Permission %u has itself as linked permission. Ignored", permissionId); continue; } permission->AddLinkedPermission(linkedPermissionId); ++count2; } while (result->NextRow()); TC_LOG_DEBUG("rbac", "AccountMgr::LoadRBAC: Loading default permissions"); result = LoginDatabase.PQuery("SELECT secId, permissionId FROM rbac_default_permissions WHERE (realmId = %u OR realmId = -1) ORDER BY secId ASC", realm.Id.Realm); if (!result) { TC_LOG_INFO("server.loading", ">> Loaded 0 default permission definitions. DB table `rbac_default_permissions` is empty."); return; } uint8 secId = 255; rbac::RBACPermissionContainer* permissions = NULL; do { Field* field = result->Fetch(); uint32 newId = field[0].GetUInt32(); if (secId != newId || permissions == NULL) { secId = newId; permissions = &_defaultPermissions[secId]; } permissions->insert(field[1].GetUInt32()); ++count3; } while (result->NextRow()); TC_LOG_INFO("server.loading", ">> Loaded %u permission definitions, %u linked permissions and %u default permissions in %u ms", count1, count2, count3, GetMSTimeDiffToNow(oldMSTime)); }
bool ArenaTeam::AddMember(uint64 playerGuid) { std::string playerName; uint8 playerClass; // Check if arena team is full (Can't have more than type * 2 players) if (GetMembersSize() >= GetType() * 2) return false; if (Type == ARENA_TEAM_5v5 && GetMembersSize() >= 1) // Im 1on1 Team kann auch nur 1 Spieler sein. return false; // Get player name and class either from db or ObjectMgr Player* player = ObjectAccessor::FindPlayer(playerGuid); if (player) { playerClass = player->getClass(); playerName = player->GetName(); } else { // 0 1 // SELECT name, class FROM characters WHERE guid = ? PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHARACTER_NAME_CLASS); stmt->setUInt32(0, GUID_LOPART(playerGuid)); PreparedQueryResult result = CharacterDatabase.Query(stmt); if (!result) return false; playerName = (*result)[0].GetString(); playerClass = (*result)[1].GetUInt8(); } // Check if player is already in a similar arena team if ((player && player->GetArenaTeamId(GetSlot())) || Player::GetArenaTeamIdFromDB(playerGuid, GetType()) != 0) { TC_LOG_DEBUG(LOG_FILTER_ARENAS, "Arena: Player %s (guid: %u) already has an arena team of type %u", playerName.c_str(), GUID_LOPART(playerGuid), GetType()); return false; } // Set player's personal rating uint32 personalRating = 0; if (sWorld->getIntConfig(CONFIG_ARENA_START_PERSONAL_RATING) > 0) personalRating = sWorld->getIntConfig(CONFIG_ARENA_START_PERSONAL_RATING); else if (GetRating() >= 1000) personalRating = 1000; if (Type == ARENA_TEAM_5v5) // Im 1on1 kein Rating (0) personalRating = 0; // Try to get player's match maker rating from db and fall back to config setting if not found PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_MATCH_MAKER_RATING); stmt->setUInt32(0, GUID_LOPART(playerGuid)); stmt->setUInt8(1, GetSlot()); PreparedQueryResult result = CharacterDatabase.Query(stmt); uint32 matchMakerRating; if (result) matchMakerRating = (*result)[0].GetUInt16(); else matchMakerRating = sWorld->getIntConfig(CONFIG_ARENA_START_MATCHMAKER_RATING); if (Type == ARENA_TEAM_5v5) // Im 1on1 kein Rating (0) matchMakerRating = 0; // Remove all player signatures from other petitions // This will prevent player from joining too many arena teams and corrupt arena team data integrity Player::RemovePetitionsAndSigns(playerGuid, GetType()); // Feed data to the struct ArenaTeamMember newMember; newMember.Name = playerName; newMember.Guid = playerGuid; newMember.Class = playerClass; newMember.SeasonGames = 0; newMember.WeekGames = 0; newMember.SeasonWins = 0; newMember.WeekWins = 0; newMember.PersonalRating = personalRating; newMember.MatchMakerRating = matchMakerRating; Members.push_back(newMember); // Save player's arena team membership to db stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_ARENA_TEAM_MEMBER); stmt->setUInt32(0, TeamId); stmt->setUInt32(1, GUID_LOPART(playerGuid)); CharacterDatabase.Execute(stmt); // Inform player if online if (player) { player->SetInArenaTeam(TeamId, GetSlot(), GetType()); player->SetArenaTeamIdInvited(0); // Hide promote/remove buttons if (CaptainGuid != playerGuid) player->SetArenaTeamInfoField(GetSlot(), ARENA_TEAM_MEMBER, 1); } TC_LOG_INFO(LOG_FILTER_ARENAS, "Player: %s [GUID: %u] joined arena team type: %u [Id: %u, Name: %s].", playerName.c_str(), GUID_LOPART(playerGuid), GetType(), GetId(), GetName().c_str()); return true; }
void WorldSession::HandleMoveTeleportAck(WorldPacket& recvPacket) { TC_LOG_DEBUG("network", "MSG_MOVE_TELEPORT_ACK"); ObjectGuid guid; uint32 flags, time; recvPacket >> flags >> time; guid[5] = recvPacket.ReadBit(); guid[0] = recvPacket.ReadBit(); guid[1] = recvPacket.ReadBit(); guid[6] = recvPacket.ReadBit(); guid[3] = recvPacket.ReadBit(); guid[7] = recvPacket.ReadBit(); guid[2] = recvPacket.ReadBit(); guid[4] = recvPacket.ReadBit(); recvPacket.ReadByteSeq(guid[4]); recvPacket.ReadByteSeq(guid[2]); recvPacket.ReadByteSeq(guid[7]); recvPacket.ReadByteSeq(guid[6]); recvPacket.ReadByteSeq(guid[5]); recvPacket.ReadByteSeq(guid[1]); recvPacket.ReadByteSeq(guid[3]); recvPacket.ReadByteSeq(guid[0]); TC_LOG_DEBUG("network", "Guid " UI64FMTD, uint64(guid)); TC_LOG_DEBUG("network", "Flags %u, time %u", flags, time/IN_MILLISECONDS); Player* plMover = _player->m_mover->ToPlayer(); if (!plMover || !plMover->IsBeingTeleportedNear()) return; if (guid != plMover->GetGUID()) return; plMover->SetSemaphoreTeleportNear(false); uint32 old_zone = plMover->GetZoneId(); WorldLocation const& dest = plMover->GetTeleportDest(); plMover->UpdatePosition(dest, true); uint32 newzone, newarea; plMover->GetZoneAndAreaId(newzone, newarea); plMover->UpdateZone(newzone, newarea); // new zone if (old_zone != newzone) { // honorless target if (plMover->pvpInfo.IsHostile) plMover->CastSpell(plMover, 2479, true); // in friendly area else if (plMover->IsPvP() && !plMover->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_IN_PVP)) plMover->UpdatePvP(false, false); } // resummon pet GetPlayer()->ResummonPetTemporaryUnSummonedIfAny(); //lets process all delayed operations on successful teleport GetPlayer()->ProcessDelayedOperations(); }
/// Launch the auth server extern int main(int argc, char **argv) { // Command line parsing to get the configuration file name char const* cfg_file = _TRINITY_REALM_CONFIG; int c = 1; while (c < argc) { if (strcmp(argv[c], "-c") == 0) { if (++c >= argc) { printf("Runtime-Error: -c option requires an input argument\n"); usage(argv[0]); return 1; } else cfg_file = argv[c]; } ++c; } if (!ConfigMgr::Load(cfg_file)) { printf("Invalid or missing configuration file : %s\n", cfg_file); printf("Verify that the file exists and has \'[authserver]\' written in the top of the file!\n"); return 1; } TC_LOG_INFO(LOG_FILTER_AUTHSERVER, "%s (authserver)", _FULLVERSION); TC_LOG_INFO(LOG_FILTER_AUTHSERVER, " "); TC_LOG_INFO(LOG_FILTER_AUTHSERVER, " A World of Warcraft: Woltk Core Emulator "); TC_LOG_INFO(LOG_FILTER_AUTHSERVER, " _/_/ _/ _/_/_/_/ "); TC_LOG_INFO(LOG_FILTER_AUTHSERVER, " _/ _/ _/_/_/_/ _/ "); TC_LOG_INFO(LOG_FILTER_AUTHSERVER, " _/ _/ _/ _/ _/_/_/ "); TC_LOG_INFO(LOG_FILTER_AUTHSERVER, " _/ _/ _/ _/ _/ "); TC_LOG_INFO(LOG_FILTER_AUTHSERVER, " _/_/ _/ _/ _/_/_/_/ "); TC_LOG_INFO(LOG_FILTER_AUTHSERVER, " Autentificador de Cuentas AUTH "); TC_LOG_INFO(LOG_FILTER_AUTHSERVER, " https://github.com/ApocalypseCore/ "); TC_LOG_INFO(LOG_FILTER_AUTHSERVER, " One Community developers Costa Rica(c) 2013 "); TC_LOG_INFO(LOG_FILTER_AUTHSERVER, " Desarrollado por ApocalypseEmu "); TC_LOG_INFO(LOG_FILTER_AUTHSERVER, " One "); TC_LOG_INFO(LOG_FILTER_AUTHSERVER, "Presione <Ctrl-C> para detenerlo.\n"); TC_LOG_INFO(LOG_FILTER_AUTHSERVER, " El archivo de configuration usado es %s.", cfg_file); TC_LOG_WARN(LOG_FILTER_AUTHSERVER, "%s (Library: %s)", OPENSSL_VERSION_TEXT, SSLeay_version(SSLEAY_VERSION)); #if defined (ACE_HAS_EVENT_POLL) || defined (ACE_HAS_DEV_POLL) ACE_Reactor::instance(new ACE_Reactor(new ACE_Dev_Poll_Reactor(ACE::max_handles(), 1), 1), true); #else ACE_Reactor::instance(new ACE_Reactor(new ACE_TP_Reactor(), true), true); #endif TC_LOG_DEBUG(LOG_FILTER_AUTHSERVER, "Max allowed open files is %d", ACE::max_handles()); // authserver PID file creation std::string pidfile = ConfigMgr::GetStringDefault("PidFile", ""); if (!pidfile.empty()) { uint32 pid = CreatePIDFile(pidfile); if (!pid) { TC_LOG_ERROR(LOG_FILTER_AUTHSERVER, "Cannot create PID file %s.\n", pidfile.c_str()); return 1; } TC_LOG_INFO(LOG_FILTER_AUTHSERVER, "Daemon PID: %u\n", pid); } // Initialize the database connection if (!StartDB()) return 1; // Get the list of realms for the server sRealmList->Initialize(ConfigMgr::GetIntDefault("RealmsStateUpdateDelay", 20)); if (sRealmList->size() == 0) { TC_LOG_ERROR(LOG_FILTER_AUTHSERVER, "No valid realms specified."); return 1; } // Launch the listening network socket RealmAcceptor acceptor; int32 rmport = ConfigMgr::GetIntDefault("RealmServerPort", 3724); if (rmport < 0 || rmport > 0xFFFF) { TC_LOG_ERROR(LOG_FILTER_AUTHSERVER, "Specified port out of allowed range (1-65535)"); return 1; } std::string bind_ip = ConfigMgr::GetStringDefault("BindIP", "0.0.0.0"); ACE_INET_Addr bind_addr(uint16(rmport), bind_ip.c_str()); if (acceptor.open(bind_addr, ACE_Reactor::instance(), ACE_NONBLOCK) == -1) { TC_LOG_ERROR(LOG_FILTER_AUTHSERVER, "Auth server can not bind to %s:%d", bind_ip.c_str(), rmport); return 1; } // Initialise the signal handlers AuthServerSignalHandler SignalINT, SignalTERM; // Register authservers's signal handlers ACE_Sig_Handler Handler; Handler.register_handler(SIGINT, &SignalINT); Handler.register_handler(SIGTERM, &SignalTERM); ///- Handle affinity for multiple processors and process priority on Windows #ifdef _WIN32 { HANDLE hProcess = GetCurrentProcess(); uint32 Aff = ConfigMgr::GetIntDefault("UseProcessors", 0); if (Aff > 0) { ULONG_PTR appAff; ULONG_PTR sysAff; if (GetProcessAffinityMask(hProcess, &appAff, &sysAff)) { ULONG_PTR curAff = Aff & appAff; // remove non accessible processors if (!curAff) TC_LOG_ERROR(LOG_FILTER_AUTHSERVER, "Processors marked in UseProcessors bitmask (hex) %x not accessible for authserver. Accessible processors bitmask (hex): %x", Aff, appAff); else if (SetProcessAffinityMask(hProcess, curAff)) TC_LOG_INFO(LOG_FILTER_AUTHSERVER, "Using processors (bitmask, hex): %x", curAff); else TC_LOG_ERROR(LOG_FILTER_AUTHSERVER, "Can't set used processors (hex): %x", curAff); } } bool Prio = ConfigMgr::GetBoolDefault("ProcessPriority", false); if (Prio) { if (SetPriorityClass(hProcess, HIGH_PRIORITY_CLASS)) TC_LOG_INFO(LOG_FILTER_AUTHSERVER, "The auth server process priority class has been set to HIGH"); else TC_LOG_ERROR(LOG_FILTER_AUTHSERVER, "Can't set auth server process priority class."); } } #endif // maximum counter for next ping uint32 numLoops = (ConfigMgr::GetIntDefault("MaxPingTime", 30) * (MINUTE * 1000000 / 100000)); uint32 loopCounter = 0; // Wait for termination signal while (!stopEvent) { // dont move this outside the loop, the reactor will modify it ACE_Time_Value interval(0, 100000); if (ACE_Reactor::instance()->run_reactor_event_loop(interval) == -1) break; if ((++loopCounter) == numLoops) { loopCounter = 0; TC_LOG_INFO(LOG_FILTER_AUTHSERVER, "Ping MySQL to keep connection alive"); LoginDatabase.KeepAlive(); } } // Close the Database Pool and library StopDB(); TC_LOG_INFO(LOG_FILTER_AUTHSERVER, "Halting process..."); return 0; }
void WorldSession::HandleMoveWorldportAckOpcode(WorldPacket & /*recvData*/) { TC_LOG_DEBUG("network", "WORLD: got MSG_MOVE_WORLDPORT_ACK."); HandleMoveWorldportAckOpcode(); }
void WorldSession::HandleStableRevivePet(WorldPacket &/* recvData */) { TC_LOG_DEBUG("network", "HandleStableRevivePet: Not implemented"); }
void WorldSession::HandleForceSpeedChangeAck(WorldPacket &recvData) { uint32 opcode = recvData.GetOpcode(); /* extract packet */ MovementInfo movementInfo; static MovementStatusElements const speedElement = MSEExtraFloat; Movement::ExtraMovementStatusElement extras(&speedElement); GetPlayer()->ReadMovementInfo(recvData, &movementInfo, &extras); // now can skip not our packet if (_player->GetGUID() != movementInfo.guid) { recvData.rfinish(); // prevent warnings spam return; } float newspeed = extras.Data.floatData; /*----------------*/ // client ACK send one packet for mounted/run case and need skip all except last from its // in other cases anti-cheat check can be fail in false case UnitMoveType move_type; static char const* const move_type_name[MAX_MOVE_TYPE] = { "Walk", "Run", "RunBack", "Swim", "SwimBack", "TurnRate", "Flight", "FlightBack", "PitchRate" }; switch (opcode) { case CMSG_MOVE_FORCE_WALK_SPEED_CHANGE_ACK: move_type = MOVE_WALK; break; case CMSG_MOVE_FORCE_RUN_SPEED_CHANGE_ACK: move_type = MOVE_RUN; break; case CMSG_MOVE_FORCE_RUN_BACK_SPEED_CHANGE_ACK: move_type = MOVE_RUN_BACK; break; case CMSG_MOVE_FORCE_SWIM_SPEED_CHANGE_ACK: move_type = MOVE_SWIM; break; case CMSG_MOVE_FORCE_SWIM_BACK_SPEED_CHANGE_ACK: move_type = MOVE_SWIM_BACK; break; case CMSG_MOVE_FORCE_TURN_RATE_CHANGE_ACK: move_type = MOVE_TURN_RATE; break; case CMSG_MOVE_FORCE_FLIGHT_SPEED_CHANGE_ACK: move_type = MOVE_FLIGHT; break; case CMSG_MOVE_FORCE_FLIGHT_BACK_SPEED_CHANGE_ACK: move_type = MOVE_FLIGHT_BACK; break; case CMSG_MOVE_FORCE_PITCH_RATE_CHANGE_ACK: move_type = MOVE_PITCH_RATE; break; default: TC_LOG_ERROR("network", "WorldSession::HandleForceSpeedChangeAck: Unknown move type opcode: %u", opcode); return; } // skip all forced speed changes except last and unexpected // in run/mounted case used one ACK and it must be skipped. m_forced_speed_changes[MOVE_RUN] store both. if (_player->m_forced_speed_changes[move_type] > 0) { --_player->m_forced_speed_changes[move_type]; if (_player->m_forced_speed_changes[move_type] > 0) return; } if (!_player->GetTransport() && fabs(_player->GetSpeed(move_type) - newspeed) > 0.01f) { if (_player->GetSpeed(move_type) > newspeed) // must be greater - just correct { TC_LOG_ERROR("network", "%sSpeedChange player %s is NOT correct (must be %f instead %f), force set to correct value", move_type_name[move_type], _player->GetName().c_str(), _player->GetSpeed(move_type), newspeed); _player->SetSpeed(move_type, _player->GetSpeedRate(move_type), true); } else // must be lesser - cheating { TC_LOG_DEBUG("misc", "Player %s from account id %u kicked for incorrect speed (must be %f instead %f)", _player->GetName().c_str(), _player->GetSession()->GetAccountId(), _player->GetSpeed(move_type), newspeed); _player->GetSession()->KickPlayer(); } } }
void WorldSession::HandleQuestgiverAcceptQuestOpcode(WorldPacket& recvData) { ObjectGuid guid; uint32 questId; uint32 startCheat; recvData >> guid >> questId >> startCheat; TC_LOG_DEBUG("network", "WORLD: Received CMSG_QUESTGIVER_ACCEPT_QUEST %s, quest = %u, startCheat = %u", guid.ToString().c_str(), questId, startCheat); Object* object; if (!guid.IsPlayer()) object = ObjectAccessor::GetObjectByTypeMask(*_player, guid, TYPEMASK_UNIT | TYPEMASK_GAMEOBJECT | TYPEMASK_ITEM); else object = ObjectAccessor::FindPlayer(guid); #define CLOSE_GOSSIP_CLEAR_DIVIDER() \ do { \ _player->PlayerTalkClass->SendCloseGossip(); \ _player->SetDivider(ObjectGuid::Empty); \ } while (0) // no or incorrect quest giver if (!object) { CLOSE_GOSSIP_CLEAR_DIVIDER(); return; } if (Player* playerQuestObject = object->ToPlayer()) { if ((_player->GetDivider() && _player->GetDivider() != guid) || !playerQuestObject->CanShareQuest(questId)) { CLOSE_GOSSIP_CLEAR_DIVIDER(); return; } if (!_player->IsInSameRaidWith(playerQuestObject)) { CLOSE_GOSSIP_CLEAR_DIVIDER(); return; } } else { if (!object->hasQuest(questId)) { CLOSE_GOSSIP_CLEAR_DIVIDER(); return; } } // some kind of WPE protection if (!_player->CanInteractWithQuestGiver(object)) { CLOSE_GOSSIP_CLEAR_DIVIDER(); return; } if (Quest const* quest = sObjectMgr->GetQuestTemplate(questId)) { // prevent cheating if (!GetPlayer()->CanTakeQuest(quest, true)) { CLOSE_GOSSIP_CLEAR_DIVIDER(); return; } if (!_player->GetDivider().IsEmpty()) { Player* player = ObjectAccessor::FindPlayer(_player->GetDivider()); if (player) { player->SendPushToPartyResponse(_player, QUEST_PARTY_MSG_ACCEPT_QUEST); _player->SetDivider(ObjectGuid::Empty); } } if (_player->CanAddQuest(quest, true)) { _player->AddQuestAndCheckCompletion(quest, object); if (quest->HasFlag(QUEST_FLAGS_PARTY_ACCEPT)) { if (Group* group = _player->GetGroup()) { for (GroupReference* itr = group->GetFirstMember(); itr != NULL; itr = itr->next()) { Player* player = itr->GetSource(); if (!player || player == _player) // not self continue; if (player->CanTakeQuest(quest, true)) { player->SetDivider(_player->GetGUID()); // need confirmation that any gossip window will close player->PlayerTalkClass->SendCloseGossip(); _player->SendQuestConfirmAccept(quest, player); } } } } _player->PlayerTalkClass->SendCloseGossip(); if (quest->GetSrcSpell() > 0) _player->CastSpell(_player, quest->GetSrcSpell(), true); return; } } CLOSE_GOSSIP_CLEAR_DIVIDER(); #undef CLOSE_GOSSIP_CLEAR_DIVIDER }
void WorldSession::HandleNpcTextQueryOpcode(WorldPacket& recvData) { uint32 textID; uint64 guid; recvData >> textID; TC_LOG_DEBUG(LOG_FILTER_NETWORKIO, "WORLD: CMSG_NPC_TEXT_QUERY ID '%u'", textID); recvData >> guid; GossipText const* pGossip = sObjectMgr->GetGossipText(textID); WorldPacket data(SMSG_NPC_TEXT_UPDATE, 100); // guess size data << textID; if (!pGossip) { for (uint32 i = 0; i < MAX_GOSSIP_TEXT_OPTIONS; ++i) { data << float(0); data << "Greetings $N"; data << "Greetings $N"; data << uint32(0); data << uint32(0); data << uint32(0); data << uint32(0); data << uint32(0); data << uint32(0); data << uint32(0); } } else { std::string Text_0[MAX_LOCALES], Text_1[MAX_LOCALES]; for (int i = 0; i < MAX_GOSSIP_TEXT_OPTIONS; ++i) { Text_0[i]=pGossip->Options[i].Text_0; Text_1[i]=pGossip->Options[i].Text_1; } int loc_idx = GetSessionDbLocaleIndex(); if (loc_idx >= 0) { if (NpcTextLocale const* nl = sObjectMgr->GetNpcTextLocale(textID)) { for (int i = 0; i < MAX_LOCALES; ++i) { ObjectMgr::GetLocaleString(nl->Text_0[i], loc_idx, Text_0[i]); ObjectMgr::GetLocaleString(nl->Text_1[i], loc_idx, Text_1[i]); } } } for (int i = 0; i < MAX_GOSSIP_TEXT_OPTIONS; ++i) { data << pGossip->Options[i].Probability; if (Text_0[i].empty()) data << Text_1[i]; else data << Text_0[i]; if (Text_1[i].empty()) data << Text_0[i]; else data << Text_1[i]; data << pGossip->Options[i].Language; for (int j = 0; j < MAX_GOSSIP_TEXT_EMOTES; ++j) { data << pGossip->Options[i].Emotes[j]._Delay; data << pGossip->Options[i].Emotes[j]._Emote; } } } SendPacket(&data); TC_LOG_DEBUG(LOG_FILTER_NETWORKIO, "WORLD: Sent SMSG_NPC_TEXT_UPDATE"); }
void WorldSession::HandleQuestgiverCancel(WorldPacket& /*recvData*/) { TC_LOG_DEBUG("network", "WORLD: Received CMSG_QUESTGIVER_CANCEL"); _player->PlayerTalkClass->SendCloseGossip(); }
/// Only _static_ data is sent in this packet !!! void WorldSession::HandleCreatureQueryOpcode(WorldPacket& recvData) { uint32 entry; recvData >> entry; uint64 guid; recvData >> guid; CreatureTemplate const* ci = sObjectMgr->GetCreatureTemplate(entry); if (ci) { std::string Name, SubName; Name = ci->Name; SubName = ci->SubName; int loc_idx = GetSessionDbLocaleIndex(); if (loc_idx >= 0) { if (CreatureLocale const* cl = sObjectMgr->GetCreatureLocale(entry)) { ObjectMgr::GetLocaleString(cl->Name, loc_idx, Name); ObjectMgr::GetLocaleString(cl->SubName, loc_idx, SubName); } } TC_LOG_DEBUG(LOG_FILTER_NETWORKIO, "WORLD: CMSG_CREATURE_QUERY '%s' - Entry: %u.", ci->Name.c_str(), entry); // guess size WorldPacket data(SMSG_CREATURE_QUERY_RESPONSE, 100); data << uint32(entry); // creature entry data << Name; data << uint8(0) << uint8(0) << uint8(0); // name2, name3, name4, always empty data << SubName; data << ci->IconName; // "Directions" for guard, string for Icons 2.3.0 data << uint32(ci->type_flags); // flags data << uint32(ci->type); // CreatureType.dbc data << uint32(ci->family); // CreatureFamily.dbc data << uint32(ci->rank); // Creature Rank (elite, boss, etc) data << uint32(ci->KillCredit[0]); // new in 3.1, kill credit data << uint32(ci->KillCredit[1]); // new in 3.1, kill credit data << uint32(ci->Modelid1); // Modelid1 data << uint32(ci->Modelid2); // Modelid2 data << uint32(ci->Modelid3); // Modelid3 data << uint32(ci->Modelid4); // Modelid4 data << float(ci->ModHealth); // dmg/hp modifier data << float(ci->ModMana); // dmg/mana modifier data << uint8(ci->RacialLeader); for (uint32 i = 0; i < MAX_CREATURE_QUEST_ITEMS; ++i) data << uint32(ci->questItems[i]); // itemId[6], quest drop data << uint32(ci->movementId); // CreatureMovementInfo.dbc SendPacket(&data); TC_LOG_DEBUG(LOG_FILTER_NETWORKIO, "WORLD: Sent SMSG_CREATURE_QUERY_RESPONSE"); } else { TC_LOG_DEBUG(LOG_FILTER_NETWORKIO, "WORLD: CMSG_CREATURE_QUERY - NO CREATURE INFO! (GUID: %u, ENTRY: %u)", GUID_LOPART(guid), entry); WorldPacket data(SMSG_CREATURE_QUERY_RESPONSE, 4); data << uint32(entry | 0x80000000); SendPacket(&data); TC_LOG_DEBUG(LOG_FILTER_NETWORKIO, "WORLD: Sent SMSG_CREATURE_QUERY_RESPONSE"); } }
void WorldSession::HandlePushQuestToParty(WorldPacket& recvPacket) { uint32 questId; recvPacket >> questId; if (!_player->CanShareQuest(questId)) return; TC_LOG_DEBUG("network", "WORLD: Received CMSG_PUSHQUESTTOPARTY questId = %u", questId); Quest const* quest = sObjectMgr->GetQuestTemplate(questId); if (!quest) return; Player * const sender = GetPlayer(); Group* group = sender->GetGroup(); if (!group) return; for (GroupReference* itr = group->GetFirstMember(); itr != NULL; itr = itr->next()) { Player* receiver = itr->GetSource(); if (!receiver || receiver == sender) continue; if (!receiver->SatisfyQuestStatus(quest, false)) { sender->SendPushToPartyResponse(receiver, QUEST_PARTY_MSG_HAVE_QUEST); continue; } if (receiver->GetQuestStatus(questId) == QUEST_STATUS_COMPLETE) { sender->SendPushToPartyResponse(receiver, QUEST_PARTY_MSG_FINISH_QUEST); continue; } if (!receiver->CanTakeQuest(quest, false)) { sender->SendPushToPartyResponse(receiver, QUEST_PARTY_MSG_CANT_TAKE_QUEST); continue; } if (!receiver->SatisfyQuestLog(false)) { sender->SendPushToPartyResponse(receiver, QUEST_PARTY_MSG_LOG_FULL); continue; } if (receiver->GetDivider()) { sender->SendPushToPartyResponse(receiver, QUEST_PARTY_MSG_BUSY); continue; } sender->SendPushToPartyResponse(receiver, QUEST_PARTY_MSG_SHARING_QUEST); if (quest->IsAutoAccept() && receiver->CanAddQuest(quest, true) && receiver->CanTakeQuest(quest, true)) receiver->AddQuestAndCheckCompletion(quest, sender); if ((quest->IsAutoComplete() && quest->IsRepeatable() && !quest->IsDailyOrWeekly()) || quest->HasFlag(QUEST_FLAGS_AUTOCOMPLETE)) receiver->PlayerTalkClass->SendQuestGiverRequestItems(quest, sender->GetGUID(), receiver->CanCompleteRepeatableQuest(quest), true); else { receiver->SetDivider(sender->GetGUID()); receiver->PlayerTalkClass->SendQuestGiverQuestDetails(quest, sender->GetGUID(), true); } } }
void npc_escortAI::UpdateAI(uint32 diff) { //Waypoint Updating if (HasEscortState(STATE_ESCORT_ESCORTING) && !me->GetVictim() && m_uiWPWaitTimer && !HasEscortState(STATE_ESCORT_RETURNING)) { if (m_uiWPWaitTimer <= diff) { //End of the line if (CurrentWP == WaypointList.end()) { if (DespawnAtEnd) { TC_LOG_DEBUG("scripts", "EscortAI reached end of waypoints"); if (m_bCanReturnToStart) { float fRetX, fRetY, fRetZ; me->GetRespawnPosition(fRetX, fRetY, fRetZ); me->GetMotionMaster()->MovePoint(POINT_HOME, fRetX, fRetY, fRetZ); m_uiWPWaitTimer = 0; TC_LOG_DEBUG("scripts", "EscortAI are returning home to spawn location: %u, %f, %f, %f", POINT_HOME, fRetX, fRetY, fRetZ); return; } if (m_bCanInstantRespawn) { me->setDeathState(JUST_DIED); me->Respawn(); } else me->DespawnOrUnsummon(); return; } else { TC_LOG_DEBUG("scripts", "EscortAI reached end of waypoints with Despawn off"); return; } } if (!HasEscortState(STATE_ESCORT_PAUSED)) { me->GetMotionMaster()->MovePoint(CurrentWP->id, CurrentWP->x, CurrentWP->y, CurrentWP->z); TC_LOG_DEBUG("scripts", "EscortAI start waypoint %u (%f, %f, %f).", CurrentWP->id, CurrentWP->x, CurrentWP->y, CurrentWP->z); WaypointStart(CurrentWP->id); m_uiWPWaitTimer = 0; } } else m_uiWPWaitTimer -= diff; } //Check if player or any member of his group is within range if (HasEscortState(STATE_ESCORT_ESCORTING) && m_uiPlayerGUID && !me->GetVictim() && !HasEscortState(STATE_ESCORT_RETURNING)) { if (m_uiPlayerCheckTimer <= diff) { if (DespawnAtFar && !IsPlayerOrGroupInRange()) { TC_LOG_DEBUG("scripts", "EscortAI failed because player/group was to far away or not found"); if (m_bCanInstantRespawn) { me->setDeathState(JUST_DIED); me->Respawn(); } else me->DespawnOrUnsummon(); return; } m_uiPlayerCheckTimer = 1000; } else m_uiPlayerCheckTimer -= diff; } UpdateEscortAI(diff); }
void PlayerMenu::SendQuestQueryResponse(Quest const* quest) const { LocaleConstant localeConstant = _session->GetSessionDbLocaleIndex(); std::string questLogTitle = quest->GetLogTitle(); std::string questLogDescription = quest->GetLogDescription(); std::string questDescription = quest->GetQuestDescription(); std::string areaDescription = quest->GetAreaDescription(); std::string questCompletionLog = quest->GetQuestCompletionLog(); std::string portraitGiverText = quest->GetPortraitGiverText(); std::string portraitGiverName = quest->GetPortraitGiverName(); std::string portraitTurnInText = quest->GetPortraitTurnInText(); std::string portraitTurnInName = quest->GetPortraitTurnInName(); if (localeConstant >= LOCALE_enUS) { if (QuestTemplateLocale const* questTemplateLocale = sObjectMgr->GetQuestLocale(quest->GetQuestId())) { ObjectMgr::GetLocaleString(questTemplateLocale->LogTitle, localeConstant, questLogTitle); ObjectMgr::GetLocaleString(questTemplateLocale->LogDescription, localeConstant, questLogDescription); ObjectMgr::GetLocaleString(questTemplateLocale->QuestDescription, localeConstant, questDescription); ObjectMgr::GetLocaleString(questTemplateLocale->AreaDescription, localeConstant, areaDescription); ObjectMgr::GetLocaleString(questTemplateLocale->QuestCompletionLog, localeConstant, questCompletionLog); ObjectMgr::GetLocaleString(questTemplateLocale->PortraitGiverText, localeConstant, portraitGiverText); ObjectMgr::GetLocaleString(questTemplateLocale->PortraitGiverName, localeConstant, portraitGiverName); ObjectMgr::GetLocaleString(questTemplateLocale->PortraitTurnInText, localeConstant, portraitTurnInText); ObjectMgr::GetLocaleString(questTemplateLocale->PortraitTurnInName, localeConstant, portraitTurnInName); } } WorldPackets::Quest::QueryQuestInfoResponse packet; packet.Allow = true; packet.QuestID = quest->GetQuestId(); packet.Info.QuestID = quest->GetQuestId(); packet.Info.QuestType = quest->GetQuestType(); packet.Info.QuestLevel = quest->GetQuestLevel(); packet.Info.QuestPackageID = quest->GetQuestPackageID(); packet.Info.QuestMinLevel = quest->GetMinLevel(); packet.Info.QuestSortID = quest->GetZoneOrSort(); packet.Info.QuestInfoID = quest->GetQuestInfoID(); packet.Info.SuggestedGroupNum = quest->GetSuggestedPlayers(); packet.Info.RewardNextQuest = quest->GetNextQuestInChain(); packet.Info.RewardXPDifficulty = quest->GetXPDifficulty(); packet.Info.RewardXPMultiplier = quest->GetXPMultiplier(); if (!quest->HasFlag(QUEST_FLAGS_HIDDEN_REWARDS)) packet.Info.RewardMoney = quest->RewardMoney < 0 ? quest->RewardMoney : _session->GetPlayer()->GetQuestMoneyReward(quest); packet.Info.RewardMoneyDifficulty = quest->GetRewMoneyDifficulty(); packet.Info.RewardMoneyMultiplier = quest->GetMoneyMultiplier(); packet.Info.RewardBonusMoney = quest->GetRewMoneyMaxLevel(); for (uint8 i = 0; i < QUEST_REWARD_DISPLAY_SPELL_COUNT; ++i) packet.Info.RewardDisplaySpell[i] = quest->RewardDisplaySpell[i]; packet.Info.RewardSpell = quest->GetRewSpell(); packet.Info.RewardHonor = quest->GetRewHonor(); packet.Info.RewardKillHonor = quest->GetRewKillHonor(); packet.Info.RewardArtifactXPDifficulty = quest->GetArtifactXPDifficulty(); packet.Info.RewardArtifactXPMultiplier = quest->GetArtifactXPMultiplier(); packet.Info.RewardArtifactCategoryID = quest->GetArtifactCategoryId(); packet.Info.StartItem = quest->GetSrcItemId(); packet.Info.Flags = quest->GetFlags(); packet.Info.FlagsEx = quest->GetFlagsEx(); packet.Info.RewardTitle = quest->GetRewTitle(); packet.Info.RewardArenaPoints = quest->GetRewArenaPoints(); packet.Info.RewardSkillLineID = quest->GetRewardSkillId(); packet.Info.RewardNumSkillUps = quest->GetRewardSkillPoints(); packet.Info.RewardFactionFlags = quest->GetRewardReputationMask(); packet.Info.PortraitGiver = quest->GetQuestGiverPortrait(); packet.Info.PortraitTurnIn = quest->GetQuestTurnInPortrait(); for (uint8 i = 0; i < QUEST_ITEM_DROP_COUNT; ++i) { packet.Info.ItemDrop[i] = quest->ItemDrop[i]; packet.Info.ItemDropQuantity[i] = quest->ItemDropQuantity[i]; } if (!quest->HasFlag(QUEST_FLAGS_HIDDEN_REWARDS)) { for (uint8 i = 0; i < QUEST_REWARD_ITEM_COUNT; ++i) { packet.Info.RewardItems[i] = quest->RewardItemId[i]; packet.Info.RewardAmount[i] = quest->RewardItemCount[i]; } for (uint8 i = 0; i < QUEST_REWARD_CHOICES_COUNT; ++i) { packet.Info.UnfilteredChoiceItems[i].ItemID = quest->RewardChoiceItemId[i]; packet.Info.UnfilteredChoiceItems[i].Quantity = quest->RewardChoiceItemCount[i]; } } for (uint8 i = 0; i < QUEST_REWARD_REPUTATIONS_COUNT; ++i) { packet.Info.RewardFactionID[i] = quest->RewardFactionId[i]; packet.Info.RewardFactionValue[i] = quest->RewardFactionValue[i]; packet.Info.RewardFactionOverride[i] = quest->RewardFactionOverride[i]; packet.Info.RewardFactionCapIn[i] = quest->RewardFactionCapIn[i]; } packet.Info.POIContinent = quest->GetPOIContinent(); packet.Info.POIx = quest->GetPOIx(); packet.Info.POIy = quest->GetPOIy(); packet.Info.POIPriority = quest->GetPOIPriority(); if (sWorld->getBoolConfig(CONFIG_UI_QUESTLEVELS_IN_DIALOGS)) AddQuestLevelToTitle(questLogTitle, quest->GetQuestLevel()); packet.Info.LogTitle = questLogTitle; packet.Info.LogDescription = questLogDescription; packet.Info.QuestDescription = questDescription; packet.Info.AreaDescription = areaDescription; packet.Info.QuestCompletionLog = questCompletionLog; packet.Info.AllowableRaces = quest->GetAllowableRaces(); packet.Info.QuestRewardID = quest->GetRewardId(); for (QuestObjective const& questObjective : quest->GetObjectives()) { packet.Info.Objectives.push_back(questObjective); if (localeConstant >= LOCALE_enUS) { if (QuestObjectivesLocale const* questObjectivesLocale = sObjectMgr->GetQuestObjectivesLocale(questObjective.ID)) ObjectMgr::GetLocaleString(questObjectivesLocale->Description, localeConstant, packet.Info.Objectives.back().Description); } } for (uint32 i = 0; i < QUEST_REWARD_CURRENCY_COUNT; ++i) { packet.Info.RewardCurrencyID[i] = quest->RewardCurrencyId[i]; packet.Info.RewardCurrencyQty[i] = quest->RewardCurrencyCount[i]; } packet.Info.PortraitGiverText = portraitGiverText; packet.Info.PortraitGiverName = portraitGiverName; packet.Info.PortraitTurnInText = portraitTurnInText; packet.Info.PortraitTurnInName = portraitTurnInName; packet.Info.AcceptedSoundKitID = quest->GetSoundAccept(); packet.Info.CompleteSoundKitID = quest->GetSoundTurnIn(); packet.Info.AreaGroupID = quest->GetAreaGroupID(); packet.Info.TimeAllowed = quest->GetLimitTime(); _session->SendPacket(packet.Write()); TC_LOG_DEBUG("network", "WORLD: Sent SMSG_QUEST_QUERY_RESPONSE questid=%u", quest->GetQuestId()); }
void WorldSession::HandlePetCastSpellOpcode(WorldPacket& recvPacket) { TC_LOG_DEBUG("network", "WORLD: CMSG_PET_CAST_SPELL"); ObjectGuid casterGUID; ObjectGuid unkGUID1; ObjectGuid transportDstGUID; ObjectGuid transportSrcGUID; ObjectGuid targetGUID; ObjectGuid unkGUID2; bool hasDestPos; bool hasSrcPos; bool hasSpeed; bool hasSpell; bool hasGlyphIndex; bool hasTargetFlags; bool hasElevation; bool hasString; bool hasCastCount; bool hasUnk5bits; uint32 archeologyCounter = 0; WorldLocation dstLoc, srcLoc; float speed = 0.0f; float elevation = 0.0f; uint32 targetFlags = 0; uint32 spellID = 0; uint32 stringLenght = 0; uint8 castCount = 0; recvPacket.ReadBitSeq<3, 5>(casterGUID); hasDestPos = recvPacket.ReadBit(); recvPacket.ReadBit(); // unk bit hasSpeed = !recvPacket.ReadBit(); hasSrcPos = recvPacket.ReadBit(); hasSpell = !recvPacket.ReadBit(); recvPacket.ReadBitSeq<0>(casterGUID); hasGlyphIndex = !recvPacket.ReadBit(); recvPacket.ReadBitSeq<7>(casterGUID); hasTargetFlags = !recvPacket.ReadBit(); hasElevation = !recvPacket.ReadBit(); recvPacket.ReadBit(); // has movement info hasString = !recvPacket.ReadBit(); recvPacket.ReadBit(); // !inverse bit, unk hasCastCount = !recvPacket.ReadBit(); recvPacket.ReadBitSeq<2, 4>(casterGUID); archeologyCounter = recvPacket.ReadBits(2); recvPacket.ReadBitSeq<1>(casterGUID); hasUnk5bits = !recvPacket.ReadBit(); for (uint32 i = 0; i < archeologyCounter; i++) recvPacket.ReadBits(2); // archeology type recvPacket.ReadBitSeq<6>(casterGUID); if (hasDestPos) recvPacket.ReadBitSeq<2, 7, 4, 0, 1, 6, 5, 3>(transportDstGUID); // movement block (disabled by patch client-side) if (hasSrcPos) recvPacket.ReadBitSeq<6, 2, 3, 1, 5, 4, 0, 7>(transportSrcGUID); if (hasUnk5bits) recvPacket.ReadBits(5); // unk 5 bits // Target GUID recvPacket.ReadBitSeq<3, 5, 6, 2, 4, 1, 7, 0>(targetGUID); // unkGUID1 recvPacket.ReadBitSeq<3, 1, 5, 2, 4, 7, 0, 6>(unkGUID1); if (hasTargetFlags) targetFlags = recvPacket.ReadBits(20); if (hasString) stringLenght = recvPacket.ReadBits(7); recvPacket.ReadByteSeq<0, 4, 5, 1, 2, 3, 7>(casterGUID); for (uint32 i = 0; i < archeologyCounter; i++) { recvPacket.read_skip<uint32>(); // entry recvPacket.read_skip<uint32>(); // counter } recvPacket.ReadByteSeq<6>(casterGUID); recvPacket.ReadByteSeq<1, 5, 4, 2, 7, 3, 0>(unkGUID1); if (hasSrcPos) { recvPacket.ReadByteSeq<4>(transportSrcGUID); srcLoc.m_positionY = recvPacket.read<float>(); recvPacket.ReadByteSeq<2, 6>(transportSrcGUID); srcLoc.m_positionZ = recvPacket.read<float>(); srcLoc.m_positionX = recvPacket.read<float>(); recvPacket.ReadByteSeq<1, 3, 5, 7, 0>(transportSrcGUID); } // Target GUID recvPacket.ReadByteSeq<7, 4, 2, 6, 3, 0, 5, 1>(targetGUID); if (hasDestPos) { dstLoc.m_positionX = recvPacket.read<float>(); recvPacket.ReadByteSeq<5, 7, 2, 0, 1, 3, 6>(transportDstGUID); dstLoc.m_positionZ = recvPacket.read<float>(); dstLoc.m_positionY = recvPacket.read<float>(); recvPacket.ReadByteSeq<4>(transportDstGUID); } if (hasGlyphIndex) recvPacket.read_skip<uint32>(); // glyph index if (hasElevation) elevation = recvPacket.read<float>(); if (hasSpell) spellID = recvPacket.read<uint32>(); if (hasCastCount) castCount = recvPacket.read<uint8>(); if (hasString) recvPacket.ReadString(stringLenght); if (hasSpeed) speed = recvPacket.read<float>(); TC_LOG_DEBUG("network", "WORLD: CMSG_PET_CAST_SPELL, castCount: %u, spellId %u, targetFlags %u", castCount, spellID, targetFlags); // This opcode is also sent from charmed and possessed units (players and creatures) if (!_player->GetGuardianPet() && !_player->GetCharm()) return; Unit* caster = ObjectAccessor::GetUnit(*_player, casterGUID); if (!caster || (caster != _player->GetGuardianPet() && caster != _player->GetCharm())) { TC_LOG_ERROR("network", "HandlePetCastSpellOpcode: Pet %u isn't pet of player %s .", uint32(GUID_LOPART(casterGUID)), GetPlayer()->GetName().c_str()); return; } SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellID); if (!spellInfo) { TC_LOG_ERROR("network", "WORLD: unknown PET spell id %i", spellID); return; } if (spellInfo->StartRecoveryCategory > 0) // Check if spell is affected by GCD if (caster->GetTypeId() == TYPEID_UNIT && caster->GetCharmInfo() && caster->GetCharmInfo()->GetGlobalCooldownMgr().HasGlobalCooldown(caster, spellInfo)) { caster->SendPetCastFail(spellID, SPELL_FAILED_NOT_READY); return; } // do not cast not learned spells if (!caster->HasSpell(spellID) || spellInfo->IsPassive()) return; SpellCastTargets targets; targets.Initialize(targetFlags, targetGUID, unkGUID1, transportDstGUID, dstLoc, transportSrcGUID, srcLoc); targets.SetElevation(elevation); targets.SetSpeed(speed); targets.Update(caster); // Interrupt auto-cast if other spell is forced by player if (caster->IsNonMeleeSpellCasted(false, true, true, false, true)) caster->InterruptNonMeleeSpells(false, 0, false); caster->ClearUnitState(UNIT_STATE_FOLLOW); Spell* spell = new Spell(caster, spellInfo, TRIGGERED_NONE, 0, false, true); spell->m_cast_count = castCount; // probably pending spell cast spell->m_targets = targets; // TODO: need to check victim? SpellCastResult result; if (caster->m_movedPlayer) result = spell->CheckPetCast(caster->m_movedPlayer->GetSelectedUnit()); else result = spell->CheckPetCast(NULL); if (result == SPELL_CAST_OK) { if (caster->GetTypeId() == TYPEID_UNIT) { Creature* pet = caster->ToCreature(); pet->AddCreatureSpellCooldown(spellID); if (pet->isPet()) { Pet* p = (Pet*)pet; // 10% chance to play special pet attack talk, else growl // actually this only seems to happen on special spells, fire shield for imp, torment for voidwalker, but it's stupid to check every spell if (p->getPetType() == SUMMON_PET && (urand(0, 100) < 10)) pet->SendPetTalk((uint32)PET_TALK_SPECIAL_SPELL); else pet->SendPetAIReaction(spellID); } } spell->prepare(&(spell->m_targets)); } else { caster->SendPetCastFail(spellID, result); if (caster->GetTypeId() == TYPEID_PLAYER) { if (!caster->ToPlayer()->HasSpellCooldown(spellID)) GetPlayer()->SendClearCooldown(spellID, caster); } else { if (!caster->ToCreature()->HasSpellCooldown(spellID)) GetPlayer()->SendClearCooldown(spellID, caster); } spell->finish(false); delete spell; } }