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 | |
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')
-rw-r--r-- | src/server/game/Battlegrounds/ArenaTeam.cpp | 2 | ||||
-rw-r--r-- | src/server/game/Entities/Player/Player.cpp | 39 | ||||
-rw-r--r-- | src/server/game/Guilds/Guild.h | 21 | ||||
-rw-r--r-- | src/server/game/Handlers/PetitionsHandler.cpp | 301 | ||||
-rw-r--r-- | src/server/game/Miscellaneous/SharedDefines.h | 11 | ||||
-rw-r--r-- | src/server/game/Petitions/PetitionMgr.cpp | 228 | ||||
-rw-r--r-- | src/server/game/Petitions/PetitionMgr.h | 84 | ||||
-rw-r--r-- | src/server/game/Server/WorldSession.h | 14 | ||||
-rw-r--r-- | src/server/game/World/World.cpp | 7 |
9 files changed, 424 insertions, 283 deletions
diff --git a/src/server/game/Battlegrounds/ArenaTeam.cpp b/src/server/game/Battlegrounds/ArenaTeam.cpp index f8640dac106..16eac760201 100644 --- a/src/server/game/Battlegrounds/ArenaTeam.cpp +++ b/src/server/game/Battlegrounds/ArenaTeam.cpp @@ -142,7 +142,7 @@ bool ArenaTeam::AddMember(ObjectGuid playerGuid) // 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()); /// @todo arena teams removed in 5.4 + //Player::RemovePetitionsAndSigns(playerGuid, static_cast<CharterTypes>(GetType())); /// @todo arena teams removed in 5.4 // Feed data to the struct ArenaTeamMember newMember; diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index 99835ca5060..c1ccb5efa2f 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -92,6 +92,7 @@ #include "Pet.h" #include "PetPackets.h" #include "PoolMgr.h" +#include "PetitionMgr.h" #include "PhasingHandler.h" #include "QueryCallback.h" #include "QueryHolder.h" @@ -22429,42 +22430,8 @@ void Player::SendProficiency(ItemClass itemClass, uint32 itemSubclassMask) const void Player::RemovePetitionsAndSigns(ObjectGuid guid) { - CharacterDatabasePreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_PETITION_SIG_BY_GUID); - stmt->setUInt64(0, guid.GetCounter()); - PreparedQueryResult result = CharacterDatabase.Query(stmt); - - if (result) - { - do // this part effectively does nothing, since the deletion / modification only takes place _after_ the PetitionQuery. Though I don't know if the result remains intact if I execute the delete query beforehand. - { // and SendPetitionQueryOpcode reads data from the DB - Field* fields = result->Fetch(); - ObjectGuid ownerguid = ObjectGuid::Create<HighGuid::Player>(fields[0].GetUInt64()); - ObjectGuid petitionguid = ObjectGuid::Create<HighGuid::Item>(fields[1].GetUInt64()); - - // send update if charter owner in game - Player* owner = ObjectAccessor::FindConnectedPlayer(ownerguid); - if (owner) - owner->GetSession()->SendPetitionQueryOpcode(petitionguid); - } while (result->NextRow()); - - stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_ALL_PETITION_SIGNATURES); - - stmt->setUInt64(0, guid.GetCounter()); - - CharacterDatabase.Execute(stmt); - } - - CharacterDatabaseTransaction trans = CharacterDatabase.BeginTransaction(); - - stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_PETITION_BY_OWNER); - stmt->setUInt64(0, guid.GetCounter()); - trans->Append(stmt); - - stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_PETITION_SIGNATURE_BY_OWNER); - stmt->setUInt64(0, guid.GetCounter()); - trans->Append(stmt); - - CharacterDatabase.CommitTransaction(trans); + sPetitionMgr->RemoveSignaturesBySigner(guid); + sPetitionMgr->RemovePetitionsByOwner(guid); } void Player::LeaveAllArenaTeams(ObjectGuid guid) diff --git a/src/server/game/Guilds/Guild.h b/src/server/game/Guilds/Guild.h index 3e36c839e11..c9112518656 100644 --- a/src/server/game/Guilds/Guild.h +++ b/src/server/game/Guilds/Guild.h @@ -161,27 +161,6 @@ enum GuildCommandError ERR_GUILD_REP_TOO_LOW = 39 }; -enum PetitionTurns -{ - PETITION_TURN_OK = 0, - PETITION_TURN_ALREADY_IN_GUILD = 2, - PETITION_TURN_NEED_MORE_SIGNATURES = 4, - PETITION_TURN_GUILD_PERMISSIONS = 11, - PETITION_TURN_GUILD_NAME_INVALID = 12 -}; - -enum PetitionSigns -{ - PETITION_SIGN_OK = 0, - PETITION_SIGN_ALREADY_SIGNED = 1, - PETITION_SIGN_ALREADY_IN_GUILD = 2, - PETITION_SIGN_CANT_SIGN_OWN = 3, - PETITION_SIGN_NOT_SERVER = 4, - PETITION_SIGN_FULL = 5, - PETITION_SIGN_ALREADY_SIGNED_OTHER = 6, - PETITION_SIGN_RESTRICTED_ACCOUNT = 7 -}; - enum GuildBankRights { GUILD_BANK_RIGHT_VIEW_TAB = 0x01, 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()); diff --git a/src/server/game/Miscellaneous/SharedDefines.h b/src/server/game/Miscellaneous/SharedDefines.h index 68ebcfa641c..cbe5c32ff39 100644 --- a/src/server/game/Miscellaneous/SharedDefines.h +++ b/src/server/game/Miscellaneous/SharedDefines.h @@ -5400,6 +5400,17 @@ enum WeaponAttackType : uint8 MAX_ATTACK }; +enum CharterTypes +{ + CHARTER_TYPE_NONE = 0, + CHARTER_TYPE_ANY = 10, + + GUILD_CHARTER_TYPE = 4, + ARENA_TEAM_CHARTER_2v2_TYPE = 2, + ARENA_TEAM_CHARTER_3v3_TYPE = 3, + ARENA_TEAM_CHARTER_5v5_TYPE = 5 +}; + enum TokenResult { TOKEN_RESULT_SUCCESS = 0, diff --git a/src/server/game/Petitions/PetitionMgr.cpp b/src/server/game/Petitions/PetitionMgr.cpp new file mode 100644 index 00000000000..370f0e024a8 --- /dev/null +++ b/src/server/game/Petitions/PetitionMgr.cpp @@ -0,0 +1,228 @@ +/* + * This file is part of the TrinityCore Project. See AUTHORS file for Copyright information + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "PetitionMgr.h" +#include "DatabaseEnv.h" +#include "ObjectMgr.h" +#include "Player.h" +#include "WorldSession.h" +#include "Timer.h" + +#include <unordered_map> + +namespace +{ + std::unordered_map<ObjectGuid, Petition> _petitionStore; +} + +PetitionMgr* PetitionMgr::instance() +{ + static PetitionMgr instance; + return &instance; +} + +void PetitionMgr::LoadPetitions() +{ + uint32 oldMSTime = getMSTime(); + _petitionStore.clear(); + + QueryResult result = CharacterDatabase.Query("SELECT petitionguid, ownerguid, name FROM petition"); + if (!result) + { + TC_LOG_INFO("server.loading", ">> Loaded 0 petitions."); + return; + } + + uint32 count = 0; + do + { + Field* fields = result->Fetch(); + AddPetition(ObjectGuid::Create<HighGuid::Item>(fields[0].GetUInt64()), ObjectGuid::Create<HighGuid::Player>(fields[1].GetUInt64()), fields[2].GetString(), true); + ++count; + } while (result->NextRow()); + + TC_LOG_INFO("server.loading", ">> Loaded %u petitions in: %u ms.", count, GetMSTimeDiffToNow(oldMSTime)); +} + +void PetitionMgr::LoadSignatures() +{ + uint32 oldMSTime = getMSTime(); + + QueryResult result = CharacterDatabase.Query("SELECT petitionguid, player_account, playerguid FROM petition_sign"); + if (!result) + { + TC_LOG_INFO("server.loading", ">> Loaded 0 Petition signs!"); + return; + } + + uint32 count = 0; + do + { + Field* fields = result->Fetch(); + + Petition* petition = GetPetition(ObjectGuid::Create<HighGuid::Item>(fields[0].GetUInt64())); + if (!petition) + continue; + + petition->AddSignature(petition->petitionGuid, fields[1].GetUInt32(), ObjectGuid::Create<HighGuid::Player>(fields[2].GetUInt64()), true); + ++count; + } while (result->NextRow()); + + TC_LOG_INFO("server.loading", ">> Loaded %u Petition signs in %u ms.", count, GetMSTimeDiffToNow(oldMSTime)); +} + +void PetitionMgr::AddPetition(ObjectGuid petitionGuid, ObjectGuid ownerGuid, std::string const& name, bool isLoading) +{ + Petition& p = _petitionStore[petitionGuid]; + p.petitionGuid = petitionGuid; + p.ownerGuid = ownerGuid; + p.petitionName = name; + p.signatures.clear(); + + if (isLoading) + return; + + CharacterDatabasePreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_PETITION); + stmt->setUInt64(0, ownerGuid.GetCounter()); + stmt->setUInt64(1, petitionGuid.GetCounter()); + stmt->setString(2, name); + CharacterDatabase.Execute(stmt); +} + +void PetitionMgr::RemovePetition(ObjectGuid petitionGuid) +{ + _petitionStore.erase(petitionGuid); + + // Delete From DB + CharacterDatabaseTransaction trans = CharacterDatabase.BeginTransaction(); + + CharacterDatabasePreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_PETITION_BY_GUID); + stmt->setUInt64(0, petitionGuid.GetCounter()); + trans->Append(stmt); + + stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_PETITION_SIGNATURE_BY_GUID); + stmt->setUInt64(0, petitionGuid.GetCounter()); + trans->Append(stmt); + + CharacterDatabase.CommitTransaction(trans); +} + +Petition* PetitionMgr::GetPetition(ObjectGuid petitionGuid) +{ + auto itr = _petitionStore.find(petitionGuid); + if (itr != _petitionStore.end()) + return &itr->second; + + return nullptr; +} + +Petition* PetitionMgr::GetPetitionByOwner(ObjectGuid ownerGuid) +{ + for (auto& petitionPair : _petitionStore) + if (petitionPair.second.ownerGuid == ownerGuid) + return &petitionPair.second; + + return nullptr; +} + +void PetitionMgr::RemovePetitionsByOwner(ObjectGuid ownerGuid) +{ + for (auto itr = _petitionStore.begin(); itr != _petitionStore.end();) + { + if (itr->second.ownerGuid == ownerGuid) + { + _petitionStore.erase(itr); + break; + } + else + ++itr; + } + + CharacterDatabasePreparedStatement* stmt; + CharacterDatabaseTransaction trans = CharacterDatabase.BeginTransaction(); + stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_PETITION_BY_OWNER); + stmt->setUInt32(0, ownerGuid.GetCounter()); + trans->Append(stmt); + + stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_PETITION_SIGNATURE_BY_OWNER); + stmt->setUInt32(0, ownerGuid.GetCounter()); + trans->Append(stmt); + CharacterDatabase.CommitTransaction(trans); +} + +void PetitionMgr::RemoveSignaturesBySigner(ObjectGuid signerGuid) +{ + for (auto& petitionPair : _petitionStore) + petitionPair.second.RemoveSignatureBySigner(signerGuid); + + CharacterDatabasePreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_ALL_PETITION_SIGNATURES); + stmt->setUInt32(0, signerGuid.GetCounter()); + CharacterDatabase.Execute(stmt); +} + +bool Petition::IsPetitionSignedByAccount(uint32 accountId) const +{ + for (Signature const& signature : signatures) + if (signature.first == accountId) + return true; + + return false; +} + +void Petition::AddSignature(ObjectGuid petitionGuid, uint32 accountId, ObjectGuid playerGuid, bool isLoading) +{ + signatures.emplace_back(accountId, playerGuid); + + if (isLoading) + return; + + CharacterDatabasePreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_PETITION_SIGNATURE); + + stmt->setUInt64(0, ownerGuid.GetCounter()); + stmt->setUInt64(1, petitionGuid.GetCounter()); + stmt->setUInt64(2, playerGuid.GetCounter()); + stmt->setUInt32(3, accountId); + + CharacterDatabase.Execute(stmt); +} + +void Petition::UpdateName(std::string const& newName) +{ + petitionName = newName; + + CharacterDatabasePreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_PETITION_NAME); + stmt->setString(0, newName); + stmt->setUInt64(1, petitionGuid.GetCounter()); + CharacterDatabase.Execute(stmt); +} + +void Petition::RemoveSignatureBySigner(ObjectGuid playerGuid) +{ + for (auto itr = signatures.begin(); itr != signatures.end(); ++itr) + { + if (itr->second == playerGuid) + { + signatures.erase(itr); + + // notify owner + if (Player* owner = ObjectAccessor::FindConnectedPlayer(ownerGuid)) + owner->GetSession()->SendPetitionQueryOpcode(petitionGuid); + + break; + } + } +} diff --git a/src/server/game/Petitions/PetitionMgr.h b/src/server/game/Petitions/PetitionMgr.h new file mode 100644 index 00000000000..d3e37c00c1a --- /dev/null +++ b/src/server/game/Petitions/PetitionMgr.h @@ -0,0 +1,84 @@ +/* + * This file is part of the TrinityCore Project. See AUTHORS file for Copyright information + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef _PETITIONMGR_H +#define _PETITIONMGR_H + +#include "Define.h" +#include "ObjectGuid.h" +#include "SharedDefines.h" + +#include <string> +#include <utility> +#include <vector> + +enum PetitionTurns +{ + PETITION_TURN_OK = 0, + PETITION_TURN_ALREADY_IN_GUILD = 2, + PETITION_TURN_NEED_MORE_SIGNATURES = 4 +}; + +enum PetitionSigns +{ + PETITION_SIGN_OK = 0, + PETITION_SIGN_ALREADY_SIGNED = 1, + PETITION_SIGN_ALREADY_IN_GUILD = 2, + PETITION_SIGN_CANT_SIGN_OWN = 3, + PETITION_SIGN_NOT_SERVER = 4 +}; + +typedef std::pair<uint32, ObjectGuid> Signature; +typedef std::vector<Signature> SignaturesVector; + +struct Petition +{ + ObjectGuid petitionGuid; + ObjectGuid ownerGuid; + std::string petitionName; + SignaturesVector signatures; + + bool IsPetitionSignedByAccount(uint32 accountId) const; + void AddSignature(ObjectGuid petitionGuid, uint32 accountId, ObjectGuid playerGuid, bool isLoading); + void UpdateName(std::string const& newName); + void RemoveSignatureBySigner(ObjectGuid playerGuid); +}; + +class TC_GAME_API PetitionMgr +{ + public: + PetitionMgr() { } + ~PetitionMgr() { } + + static PetitionMgr* instance(); + + // Load from DB + void LoadPetitions(); + void LoadSignatures(); + + // Petitions + void AddPetition(ObjectGuid petitionGuid, ObjectGuid ownerGuid, std::string const& name, bool isLoading); + void RemovePetition(ObjectGuid petitionGuid); + Petition* GetPetition(ObjectGuid petitionGuid); + Petition* GetPetitionByOwner(ObjectGuid ownerGuid); + void RemovePetitionsByOwner(ObjectGuid ownerGuid); + void RemoveSignaturesBySigner(ObjectGuid signerGuid); +}; + +#define sPetitionMgr PetitionMgr::instance() + +#endif diff --git a/src/server/game/Server/WorldSession.h b/src/server/game/Server/WorldSession.h index 9466c8682cf..a5a774611d2 100644 --- a/src/server/game/Server/WorldSession.h +++ b/src/server/game/Server/WorldSession.h @@ -52,6 +52,7 @@ struct BlackMarketTemplate; struct DeclinedName; struct ItemTemplate; struct MovementInfo; +struct Petition; struct Position; enum class AuctionCommand : int8; enum class AuctionResult : int8; @@ -840,14 +841,6 @@ enum ChatRestrictionType ERR_CHAT_RAID_RESTRICTED = 4 }; -enum CharterTypes -{ - GUILD_CHARTER_TYPE = 4, - ARENA_TEAM_CHARTER_2v2_TYPE = 2, - ARENA_TEAM_CHARTER_3v3_TYPE = 3, - ARENA_TEAM_CHARTER_5v5_TYPE = 5, -}; - enum DeclinedNameResult { DECLINED_NAMES_RESULT_SUCCESS = 0, @@ -1293,13 +1286,14 @@ class TC_GAME_API WorldSession void HandleSetEveryoneIsAssistant(WorldPackets::Party::SetEveryoneIsAssistant& packet); void HandleClearRaidMarker(WorldPackets::Party::ClearRaidMarker& packet); - void HandleDeclinePetition(WorldPackets::Petition::DeclinePetition& packet); - void HandleOfferPetition(WorldPackets::Petition::OfferPetition& packet); void HandlePetitionBuy(WorldPackets::Petition::PetitionBuy& packet); void HandlePetitionShowSignatures(WorldPackets::Petition::PetitionShowSignatures& packet); + void SendPetitionSigns(Petition const* petition, Player* sendTo); void HandleQueryPetition(WorldPackets::Petition::QueryPetition& packet); void HandlePetitionRenameGuild(WorldPackets::Petition::PetitionRenameGuild& packet); void HandleSignPetition(WorldPackets::Petition::SignPetition& packet); + void HandleDeclinePetition(WorldPackets::Petition::DeclinePetition& packet); + void HandleOfferPetition(WorldPackets::Petition::OfferPetition& packet); void HandleTurnInPetition(WorldPackets::Petition::TurnInPetition& packet); void HandleGuildQueryOpcode(WorldPackets::Guild::QueryGuildInfo& query); diff --git a/src/server/game/World/World.cpp b/src/server/game/World/World.cpp index a94e06034ba..03ca4dbf205 100644 --- a/src/server/game/World/World.cpp +++ b/src/server/game/World/World.cpp @@ -72,6 +72,7 @@ #include "ObjectAccessor.h" #include "ObjectMgr.h" #include "OutdoorPvPMgr.h" +#include "PetitionMgr.h" #include "Player.h" #include "PlayerDump.h" #include "PoolMgr.h" @@ -2074,6 +2075,12 @@ void World::SetInitialWorldSettings() TC_LOG_INFO("server.loading", "Loading Calendar data..."); sCalendarMgr->LoadFromDB(); + TC_LOG_INFO("server.loading", "Loading Petitions..."); + sPetitionMgr->LoadPetitions(); + + TC_LOG_INFO("server.loading", "Loading Signatures..."); + sPetitionMgr->LoadSignatures(); + TC_LOG_INFO("server.loading", "Loading Item loot..."); sLootItemStorage->LoadStorageFromDB(); |