diff options
author | xinef1 <w.szyszko2@gmail.com> | 2017-04-27 07:02:33 +0200 |
---|---|---|
committer | Shauren <shauren.trinity@gmail.com> | 2020-05-01 19:32:11 +0200 |
commit | 48a40fae0a713c3d96e4796da78f7186260ebbd3 (patch) | |
tree | 6e4fad6cf80c9b86d10f10f7750579cfe1c90890 /src/server/game/Handlers/PetitionsHandler.cpp | |
parent | c3811b26bc39e4e98da5d8542575400a0287cb9c (diff) |
Core/Misc: implemented petition manager (#19010)
- Implemented manager for petitions to perform all petition related tasks and synchronize data with database.
- This kills ugly synchronous querys on packet handlers
(cherry picked from commit a4aa95a5a39d75b9e38fe03aac57ceb7d9bba90f)
Diffstat (limited to 'src/server/game/Handlers/PetitionsHandler.cpp')
-rw-r--r-- | src/server/game/Handlers/PetitionsHandler.cpp | 301 |
1 files changed, 86 insertions, 215 deletions
diff --git a/src/server/game/Handlers/PetitionsHandler.cpp b/src/server/game/Handlers/PetitionsHandler.cpp index a5984a3b052..b510aec0d1f 100644 --- a/src/server/game/Handlers/PetitionsHandler.cpp +++ b/src/server/game/Handlers/PetitionsHandler.cpp @@ -26,6 +26,7 @@ #include "ObjectAccessor.h" #include "ObjectMgr.h" #include "Opcodes.h" +#include "PetitionMgr.h" #include "PetitionPackets.h" #include "Player.h" #include "World.h" @@ -103,82 +104,52 @@ void WorldSession::HandlePetitionBuy(WorldPackets::Petition::PetitionBuy& packet // a petition is invalid, if both the owner and the type matches // we checked above, if this player is in an arenateam, so this must be // datacorruption - CharacterDatabasePreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_PETITION_BY_OWNER); - stmt->setUInt64(0, _player->GetGUID().GetCounter()); - PreparedQueryResult result = CharacterDatabase.Query(stmt); - - std::ostringstream ssInvalidPetitionGUIDs; - - if (result) + if (Petition const* petition = sPetitionMgr->GetPetitionByOwner(_player->GetGUID())) { - do - { - Field* fields = result->Fetch(); - ssInvalidPetitionGUIDs << '\'' << fields[0].GetUInt64() << "', "; - } while (result->NextRow()); + // clear from petition store + sPetitionMgr->RemovePetition(petition->petitionGuid); + TC_LOG_DEBUG("network", "Invalid petition GUID: %u", petition->petitionGuid.GetCounter()); } - // delete petitions with the same guid as this one - ssInvalidPetitionGUIDs << '\'' << charter->GetGUID().GetCounter() << '\''; - - TC_LOG_DEBUG("network", "Invalid petition GUIDs: %s", ssInvalidPetitionGUIDs.str().c_str()); - CharacterDatabase.EscapeString(packet.Title); - CharacterDatabaseTransaction trans = CharacterDatabase.BeginTransaction(); - trans->PAppend("DELETE FROM petition WHERE petitionguid IN (%s)", ssInvalidPetitionGUIDs.str().c_str()); - trans->PAppend("DELETE FROM petition_sign WHERE petitionguid IN (%s)", ssInvalidPetitionGUIDs.str().c_str()); - - stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_PETITION); - stmt->setUInt64(0, _player->GetGUID().GetCounter()); - stmt->setUInt64(1, charter->GetGUID().GetCounter()); - stmt->setString(2, packet.Title); - trans->Append(stmt); - - CharacterDatabase.CommitTransaction(trans); + // fill petition store + sPetitionMgr->AddPetition(charter->GetGUID(), _player->GetGUID(), packet.Title, false); } void WorldSession::HandlePetitionShowSignatures(WorldPackets::Petition::PetitionShowSignatures& packet) { - uint8 signs = 0; + Petition const* petition = sPetitionMgr->GetPetition(packet.Item); + if (!petition) + { + TC_LOG_DEBUG("entities.player.items", "Petition %s is not found for player %u %s", packet.Item.ToString().c_str(), GetPlayer()->GetGUID().GetCounter(), GetPlayer()->GetName().c_str()); + return; + } // if has guild => error, return; if (_player->GetGuildId()) return; - CharacterDatabasePreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_PETITION_SIGNATURE); - - stmt->setUInt64(0, packet.Item.GetCounter()); - - PreparedQueryResult result = CharacterDatabase.Query(stmt); - - // result == NULL also correct in case no sign yet - if (result) - signs = uint8(result->GetRowCount()); - TC_LOG_DEBUG("network", "CMSG_PETITION_SHOW_SIGNATURES %s", packet.Item.ToString().c_str()); + SendPetitionSigns(petition, _player); +} + +void WorldSession::SendPetitionSigns(Petition const* petition, Player* sendTo) +{ WorldPackets::Petition::ServerPetitionShowSignatures signaturesPacket; - signaturesPacket.Item = packet.Item; - signaturesPacket.Owner = _player->GetGUID(); - signaturesPacket.OwnerAccountID = ObjectGuid::Create<HighGuid::WowAccount>(sCharacterCache->GetCharacterAccountIdByGuid(_player->GetGUID())); - signaturesPacket.PetitionID = int32(packet.Item.GetCounter()); // @todo verify that... + signaturesPacket.Item = petition->petitionGuid; + signaturesPacket.Owner = petition->ownerGuid; + signaturesPacket.OwnerAccountID = ObjectGuid::Create<HighGuid::WowAccount>(sCharacterCache->GetCharacterAccountIdByGuid(petition->ownerGuid)); + signaturesPacket.PetitionID = petition->petitionGuid.GetCounter(); - signaturesPacket.Signatures.reserve(signs); - for (uint8 i = 1; i <= signs; ++i) + for (Signature const& signature : petition->signatures) { - Field* fields2 = result->Fetch(); - ObjectGuid signerGUID = ObjectGuid::Create<HighGuid::Player>(fields2[0].GetUInt64()); - - WorldPackets::Petition::ServerPetitionShowSignatures::PetitionSignature signature; - signature.Signer = signerGUID; - signature.Choice = 0; - signaturesPacket.Signatures.push_back(signature); - - // Checking the return value just to be double safe - if (!result->NextRow()) - break; + WorldPackets::Petition::ServerPetitionShowSignatures::PetitionSignature signaturePkt; + signaturePkt.Signer = signature.second; + signaturePkt.Choice = 0; + signaturesPacket.Signatures.push_back(signaturePkt); } - SendPacket(signaturesPacket.Write()); + sendTo->SendDirectMessage(signaturesPacket.Write()); } void WorldSession::HandleQueryPetition(WorldPackets::Petition::QueryPetition& packet) @@ -188,46 +159,30 @@ void WorldSession::HandleQueryPetition(WorldPackets::Petition::QueryPetition& pa SendPetitionQueryOpcode(packet.ItemGUID); } -void WorldSession::SendPetitionQueryOpcode(ObjectGuid petitionGUID) +void WorldSession::SendPetitionQueryOpcode(ObjectGuid petitionguid) { - ObjectGuid ownerGUID; - std::string title = "NO_NAME_FOR_GUID"; - WorldPackets::Petition::QueryPetitionResponse responsePacket; - responsePacket.PetitionID = uint32(petitionGUID.GetCounter()); // PetitionID (in Trinity always same as GUID_LOPART(petition guid)) - - CharacterDatabasePreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_PETITION); - - stmt->setUInt64(0, petitionGUID.GetCounter()); - - PreparedQueryResult result = CharacterDatabase.Query(stmt); - - if (result) - { - Field* fields = result->Fetch(); - ownerGUID = ObjectGuid::Create<HighGuid::Player>(fields[0].GetUInt64()); - title = fields[1].GetString(); - } - else + responsePacket.PetitionID = uint32(petitionguid.GetCounter()); // PetitionID (in Trinity always same as GUID_LOPART(petition guid)) + Petition const* petition = sPetitionMgr->GetPetition(petitionguid); + if (!petition) { responsePacket.Allow = false; SendPacket(responsePacket.Write()); - TC_LOG_DEBUG("network", "CMSG_PETITION_QUERY failed for petition (%s)", petitionGUID.ToString().c_str()); + TC_LOG_DEBUG("network", "CMSG_PETITION_QUERY failed for petition (%s)", petitionguid.ToString().c_str()); return; } - int32 reqSignatures = sWorld->getIntConfig(CONFIG_MIN_PETITION_SIGNS); + uint32 reqSignatures = sWorld->getIntConfig(CONFIG_MIN_PETITION_SIGNS); - WorldPackets::Petition::PetitionInfo petitionInfo; - petitionInfo.PetitionID = int32(petitionGUID.GetCounter()); - petitionInfo.Petitioner = ownerGUID; + WorldPackets::Petition::PetitionInfo& petitionInfo = responsePacket.Info; + petitionInfo.PetitionID = int32(petitionguid.GetCounter()); + petitionInfo.Petitioner = petition->ownerGuid; petitionInfo.MinSignatures = reqSignatures; petitionInfo.MaxSignatures = reqSignatures; - petitionInfo.Title = title; + petitionInfo.Title = petition->petitionName; responsePacket.Allow = true; - responsePacket.Info = petitionInfo; SendPacket(responsePacket.Write()); } @@ -238,6 +193,13 @@ void WorldSession::HandlePetitionRenameGuild(WorldPackets::Petition::PetitionRen if (!item) return; + Petition* petition = sPetitionMgr->GetPetition(packet.PetitionGuid); + if (!petition) + { + TC_LOG_DEBUG("network", "CMSG_PETITION_QUERY failed for petition %s", packet.PetitionGuid.ToString().c_str()); + return; + } + if (sGuildMgr->GetGuildByName(packet.NewGuildName)) { Guild::SendCommandResult(this, GUILD_COMMAND_CREATE_GUILD, ERR_GUILD_NAME_EXISTS_S, packet.NewGuildName); @@ -250,12 +212,8 @@ void WorldSession::HandlePetitionRenameGuild(WorldPackets::Petition::PetitionRen return; } - CharacterDatabasePreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_PETITION_NAME); - - stmt->setString(0, packet.NewGuildName); - stmt->setUInt64(1, packet.PetitionGuid.GetCounter()); - - CharacterDatabase.Execute(stmt); + // update petition storage + petition->UpdateName(packet.NewGuildName); WorldPackets::Petition::PetitionRenameGuildResponse renameResponse; renameResponse.PetitionGuid = packet.PetitionGuid; @@ -267,22 +225,15 @@ void WorldSession::HandlePetitionRenameGuild(WorldPackets::Petition::PetitionRen void WorldSession::HandleSignPetition(WorldPackets::Petition::SignPetition& packet) { - CharacterDatabasePreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_PETITION_SIGNATURES); - - stmt->setUInt64(0, packet.PetitionGUID.GetCounter()); - stmt->setUInt64(1, packet.PetitionGUID.GetCounter()); - - PreparedQueryResult result = CharacterDatabase.Query(stmt); - - if (!result) + Petition* petition = sPetitionMgr->GetPetition(packet.PetitionGUID); + if (!petition) { TC_LOG_ERROR("network", "Petition %s is not found for %s %s", packet.PetitionGUID.ToString().c_str(), GetPlayer()->GetGUID().ToString().c_str(), GetPlayer()->GetName().c_str()); return; } - Field* fields = result->Fetch(); - ObjectGuid ownerGuid = ObjectGuid::Create<HighGuid::Player>(fields[0].GetUInt64()); - uint64 signs = fields[1].GetUInt64(); + ObjectGuid ownerGuid = petition->ownerGuid; + uint64 signs = petition->signatures.size(); if (ownerGuid == _player->GetGUID()) return; @@ -306,47 +257,39 @@ void WorldSession::HandleSignPetition(WorldPackets::Petition::SignPetition& pack return; } - //if (++signs > type) // client signs maximum - // return; + if (++signs > 10) // client signs maximum + return; // Client doesn't allow to sign petition two times by one character, but not check sign by another character from same account // not allow sign another player from already sign player account - stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_PETITION_SIG_BY_ACCOUNT); - - stmt->setUInt32(0, GetAccountId()); - stmt->setUInt64(1, packet.PetitionGUID.GetCounter()); - - result = CharacterDatabase.Query(stmt); - WorldPackets::Petition::PetitionSignResults signResult; signResult.Player = _player->GetGUID(); signResult.Item = packet.PetitionGUID; - if (result) + bool isSigned = petition->IsPetitionSignedByAccount(GetAccountId()); + if (isSigned) { signResult.Error = int32(PETITION_SIGN_ALREADY_SIGNED); // close at signer side SendPacket(signResult.Write()); + + // update for owner if online + if (Player* owner = ObjectAccessor::FindConnectedPlayer(ownerGuid)) + owner->GetSession()->SendPacket(signResult.GetRawPacket()); return; } - stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_PETITION_SIGNATURE); - - stmt->setUInt64(0, ownerGuid.GetCounter()); - stmt->setUInt64(1, packet.PetitionGUID.GetCounter()); - stmt->setUInt64(2, _player->GetGUID().GetCounter()); - stmt->setUInt32(3, GetAccountId()); - - CharacterDatabase.Execute(stmt); + // fill petition store + petition->AddSignature(packet.PetitionGUID, GetAccountId(), _player->GetGUID(), false); TC_LOG_DEBUG("network", "PETITION SIGN: %s by player: %s (%s Account: %u)", packet.PetitionGUID.ToString().c_str(), _player->GetName().c_str(), _player->GetGUID().ToString().c_str(), GetAccountId()); signResult.Error = int32(PETITION_SIGN_OK); - // close at signer side SendPacket(signResult.Write()); + // update signs count on charter if (Item* item = _player->GetItemByGuid(packet.PetitionGUID)) { item->SetPetitionNumSignatures(signs); @@ -355,33 +298,27 @@ void WorldSession::HandleSignPetition(WorldPackets::Petition::SignPetition& pack // update for owner if online if (Player* owner = ObjectAccessor::FindConnectedPlayer(ownerGuid)) - owner->GetSession()->SendPacket(signResult.Write()); + owner->GetSession()->SendPacket(signResult.GetRawPacket()); } void WorldSession::HandleDeclinePetition(WorldPackets::Petition::DeclinePetition& packet) { TC_LOG_DEBUG("network", "Petition %s declined by %s", packet.PetitionGUID.ToString().c_str(), _player->GetGUID().ToString().c_str()); - CharacterDatabasePreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_PETITION_OWNER_BY_GUID); - stmt->setUInt64(0, packet.PetitionGUID.GetCounter()); - PreparedQueryResult result = CharacterDatabase.Query(stmt); - - if (!result) + // Disabled because packet isn't handled by the client in any way + /* + Petition const* petition = sPetitionMgr->GetPetition(packet.PetitionGUID); + if (!petition) return; - Field* fields = result->Fetch(); - ObjectGuid ownerguid = ObjectGuid::Create<HighGuid::Player>(fields[0].GetUInt64()); - - Player* owner = ObjectAccessor::FindConnectedPlayer(ownerguid); - if (owner) // petition owner online + // petition owner online + if (Player* owner = ObjectAccessor::FindConnectedPlayer(petition->ownerGuid)) { - // Disabled because packet isn't handled by the client in any way - /* WorldPackets::Petition::PetitionDeclined packet; packet.Decliner = _player->GetGUID(); owner->GetSession()->SendPacket(packet.Write()); - */ } + */ } void WorldSession::HandleOfferPetition(WorldPackets::Petition::OfferPetition& packet) @@ -390,6 +327,10 @@ void WorldSession::HandleOfferPetition(WorldPackets::Petition::OfferPetition& pa if (!player) return; + Petition const* petition = sPetitionMgr->GetPetition(packet.ItemGUID); + if (!petition) + return; + TC_LOG_DEBUG("network", "OFFER PETITION: %s, to %s", packet.ItemGUID.ToString().c_str(), packet.TargetPlayer.ToString().c_str()); if (!sWorld->getBoolConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_GUILD) && GetPlayer()->GetTeam() != player->GetTeam()) @@ -410,38 +351,7 @@ void WorldSession::HandleOfferPetition(WorldPackets::Petition::OfferPetition& pa return; } - CharacterDatabasePreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_PETITION_SIGNATURE); - stmt->setUInt64(0, packet.ItemGUID.GetCounter()); - PreparedQueryResult result = CharacterDatabase.Query(stmt); - - uint8 signs = 0; - // result == NULL also correct charter without signs - if (result) - signs = uint8(result->GetRowCount()); - - WorldPackets::Petition::ServerPetitionShowSignatures signaturesPacket; - signaturesPacket.Item = packet.ItemGUID; - signaturesPacket.Owner = _player->GetGUID(); - signaturesPacket.OwnerAccountID = ObjectGuid::Create<HighGuid::WowAccount>(player->GetSession()->GetAccountId()); - signaturesPacket.PetitionID = int32(packet.ItemGUID.GetCounter()); // @todo verify that... - - signaturesPacket.Signatures.reserve(signs); - for (uint8 i = 0; i < signs; ++i) - { - Field* fields2 = result->Fetch(); - ObjectGuid signerGUID = ObjectGuid::Create<HighGuid::Player>(fields2[0].GetUInt64()); - - WorldPackets::Petition::ServerPetitionShowSignatures::PetitionSignature signature; - signature.Signer = signerGUID; - signature.Choice = 0; - signaturesPacket.Signatures.push_back(signature); - - // Checking the return value just to be double safe - if (!result->NextRow()) - break; - } - - player->GetSession()->SendPacket(signaturesPacket.Write()); + SendPetitionSigns(petition, player); } void WorldSession::HandleTurnInPetition(WorldPackets::Petition::TurnInPetition& packet) @@ -453,28 +363,17 @@ void WorldSession::HandleTurnInPetition(WorldPackets::Petition::TurnInPetition& TC_LOG_DEBUG("network", "Petition %s turned in by %s", packet.Item.ToString().c_str(), _player->GetGUID().ToString().c_str()); - // Get petition data from db - ObjectGuid ownerguid; - std::string name; - - CharacterDatabasePreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_PETITION); - stmt->setUInt64(0, packet.Item.GetCounter()); - PreparedQueryResult result = CharacterDatabase.Query(stmt); - - if (result) - { - Field* fields = result->Fetch(); - ownerguid = ObjectGuid::Create<HighGuid::Player>(fields[0].GetUInt64()); - name = fields[1].GetString(); - } - else + Petition const* petition = sPetitionMgr->GetPetition(packet.Item); + if (!petition) { TC_LOG_ERROR("entities.player.cheat", "Player %s (%s) tried to turn in petition (%s) that is not present in the database", _player->GetName().c_str(), _player->GetGUID().ToString().c_str(), packet.Item.ToString().c_str()); return; } + std::string const name = petition->petitionName; // we need a copy, Guild::AddMember invalidates petition + // Only the petition owner can turn in the petition - if (_player->GetGUID() != ownerguid) + if (_player->GetGUID() != petition->ownerGuid) return; // Check if player is already in a guild @@ -482,7 +381,7 @@ void WorldSession::HandleTurnInPetition(WorldPackets::Petition::TurnInPetition& { WorldPackets::Petition::TurnInPetitionResult resultPacket; resultPacket.Result = int32(PETITION_TURN_ALREADY_IN_GUILD); - _player->GetSession()->SendPacket(resultPacket.Write()); + SendPacket(resultPacket.Write()); return; } @@ -493,22 +392,11 @@ void WorldSession::HandleTurnInPetition(WorldPackets::Petition::TurnInPetition& return; } - // Get petition signatures from db - uint8 signatures; - - stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_PETITION_SIGNATURE); - stmt->setUInt64(0, packet.Item.GetCounter()); - result = CharacterDatabase.Query(stmt); - - if (result) - signatures = uint8(result->GetRowCount()); - else - signatures = 0; - + SignaturesVector const signatures = petition->signatures; // we need a copy, Guild::AddMember invalidates petition uint32 requiredSignatures = sWorld->getIntConfig(CONFIG_MIN_PETITION_SIGNS); // Notify player if signatures are missing - if (signatures < requiredSignatures) + if (signatures.size() < requiredSignatures) { WorldPackets::Petition::TurnInPetitionResult resultPacket; resultPacket.Result = int32(PETITION_TURN_NEED_MORE_SIGNATURES); @@ -539,30 +427,13 @@ void WorldSession::HandleTurnInPetition(WorldPackets::Petition::TurnInPetition& CharacterDatabaseTransaction trans = CharacterDatabase.BeginTransaction(); // Add members from signatures - for (uint8 i = 0; i < signatures; ++i) - { - Field* fields = result->Fetch(); - guild->AddMember(trans, ObjectGuid::Create<HighGuid::Player>(fields[0].GetUInt64())); - - // Checking the return value just to be double safe - if (!result->NextRow()) - break; - } + for (Signature const& signature : signatures) + guild->AddMember(trans, signature.second); CharacterDatabase.CommitTransaction(trans); } - CharacterDatabaseTransaction trans = CharacterDatabase.BeginTransaction(); - - stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_PETITION_BY_GUID); - stmt->setUInt64(0, packet.Item.GetCounter()); - trans->Append(stmt); - - stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_PETITION_SIGNATURE_BY_GUID); - stmt->setUInt64(0, packet.Item.GetCounter()); - trans->Append(stmt); - - CharacterDatabase.CommitTransaction(trans); + sPetitionMgr->RemovePetition(packet.Item); // created TC_LOG_DEBUG("network", "Player %s (%s) turning in petition %s", _player->GetName().c_str(), _player->GetGUID().ToString().c_str(), packet.Item.ToString().c_str()); |