diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/server/game/Battlegrounds/ArenaTeam.cpp | 2 | ||||
-rw-r--r-- | src/server/game/Entities/Player/Player.cpp | 77 | ||||
-rw-r--r-- | src/server/game/Entities/Player/Player.h | 2 | ||||
-rw-r--r-- | src/server/game/Guilds/Guild.h | 16 | ||||
-rw-r--r-- | src/server/game/Handlers/PetitionsHandler.cpp | 355 | ||||
-rw-r--r-- | src/server/game/Miscellaneous/SharedDefines.h | 11 | ||||
-rw-r--r-- | src/server/game/Petitions/PetitionMgr.cpp | 263 | ||||
-rw-r--r-- | src/server/game/Petitions/PetitionMgr.h | 85 | ||||
-rw-r--r-- | src/server/game/Server/WorldSession.h | 10 | ||||
-rw-r--r-- | src/server/game/World/World.cpp | 7 |
10 files changed, 464 insertions, 364 deletions
diff --git a/src/server/game/Battlegrounds/ArenaTeam.cpp b/src/server/game/Battlegrounds/ArenaTeam.cpp index 6a17012412e..1c5a2dac3eb 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()); + Player::RemovePetitionsAndSigns(playerGuid, static_cast<CharterTypes>(GetType())); // 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 20a3e578be9..96660969332 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -63,6 +63,7 @@ #include "OutdoorPvPMgr.h" #include "Pet.h" #include "PoolMgr.h" +#include "PetitionMgr.h" #include "QueryCallback.h" #include "QuestDef.h" #include "ReputationMgr.h" @@ -4272,7 +4273,7 @@ void Player::DeleteFromDB(ObjectGuid playerguid, uint32 accountId, bool updateRe RemoveFromGroup(group, playerguid); // Remove signs from petitions (also remove petitions if owner); - RemovePetitionsAndSigns(playerguid, 10); + RemovePetitionsAndSigns(playerguid, CHARTER_TYPE_ANY); switch (charDelete_method) { @@ -21053,78 +21054,10 @@ void Player::SendProficiency(ItemClass itemClass, uint32 itemSubclassMask) const GetSession()->SendPacket(&data); } -void Player::RemovePetitionsAndSigns(ObjectGuid guid, uint32 type) +void Player::RemovePetitionsAndSigns(ObjectGuid guid, CharterTypes type) { - PreparedStatement* stmt; - - if (type == 10) - stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_PETITION_SIG_BY_GUID); - else - { - stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_PETITION_SIG_BY_GUID_TYPE); - stmt->setUInt8(1, uint8(type)); - } - - stmt->setUInt32(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(HighGuid::Player, fields[0].GetUInt32()); - ObjectGuid petitionguid = ObjectGuid(HighGuid::Item, fields[1].GetUInt32()); - - // send update if charter owner in game - Player* owner = ObjectAccessor::FindConnectedPlayer(ownerguid); - if (owner) - owner->GetSession()->SendPetitionQueryOpcode(petitionguid); - } while (result->NextRow()); - - if (type == 10) - { - stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_ALL_PETITION_SIGNATURES); - - stmt->setUInt32(0, guid.GetCounter()); - - CharacterDatabase.Execute(stmt); - } - else - { - stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_PETITION_SIGNATURE); - - stmt->setUInt32(0, guid.GetCounter()); - stmt->setUInt8(1, uint8(type)); - - CharacterDatabase.Execute(stmt); - } - } - - SQLTransaction trans = CharacterDatabase.BeginTransaction(); - if (type == 10) - { - stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_PETITION_BY_OWNER); - stmt->setUInt32(0, guid.GetCounter()); - trans->Append(stmt); - - stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_PETITION_SIGNATURE_BY_OWNER); - stmt->setUInt32(0, guid.GetCounter()); - trans->Append(stmt); - } - else - { - stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_PETITION_BY_OWNER_AND_TYPE); - stmt->setUInt32(0, guid.GetCounter()); - stmt->setUInt8(1, uint8(type)); - trans->Append(stmt); - - stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_PETITION_SIGNATURE_BY_OWNER_AND_TYPE); - stmt->setUInt32(0, guid.GetCounter()); - stmt->setUInt8(1, uint8(type)); - trans->Append(stmt); - } - CharacterDatabase.CommitTransaction(trans); + sPetitionMgr->RemoveSignaturesBySignerAndType(guid, type); + sPetitionMgr->RemovePetitionsByOwnerAndType(guid, type); } void Player::LeaveAllArenaTeams(ObjectGuid guid) diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h index 9e3debae25a..6fcbfdf7e70 100644 --- a/src/server/game/Entities/Player/Player.h +++ b/src/server/game/Entities/Player/Player.h @@ -1686,7 +1686,7 @@ class TC_GAME_API Player : public Unit, public GridObject<Player> uint32 GetGuildId() const { return GetUInt32Value(PLAYER_GUILDID); } Guild* GetGuild(); int GetGuildIdInvited() const { return m_GuildIdInvited; } - static void RemovePetitionsAndSigns(ObjectGuid guid, uint32 type); + static void RemovePetitionsAndSigns(ObjectGuid guid, CharterTypes type); // Arena Team void SetInArenaTeam(uint32 ArenaTeamId, uint8 slot, uint8 type); diff --git a/src/server/game/Guilds/Guild.h b/src/server/game/Guilds/Guild.h index 87a9c951d9e..38510d8c06b 100644 --- a/src/server/game/Guilds/Guild.h +++ b/src/server/game/Guilds/Guild.h @@ -154,22 +154,6 @@ enum GuildEvents GE_BANK_TEXT_CHANGED = 19, }; -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 -}; - 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 4481ed7505d..809237b72fd 100644 --- a/src/server/game/Handlers/PetitionsHandler.cpp +++ b/src/server/game/Handlers/PetitionsHandler.cpp @@ -29,6 +29,7 @@ #include "Guild.h" #include "ArenaTeam.h" #include "CharacterCache.h" +#include "PetitionMgr.h" #define CHARTER_DISPLAY_ID 16161 @@ -88,7 +89,7 @@ void WorldSession::HandlePetitionBuyOpcode(WorldPacket& recvData) uint32 charterid = 0; uint32 cost = 0; - uint32 type = 0; + CharterTypes type = CHARTER_TYPE_NONE; if (creature->IsTabardDesigner()) { // if tabard designer, then trying to buy a guild charter. @@ -201,98 +202,57 @@ void WorldSession::HandlePetitionBuyOpcode(WorldPacket& recvData) // 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 - PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_PETITION_BY_OWNER); - stmt->setUInt32(0, _player->GetGUID().GetCounter()); - stmt->setUInt8(1, type); - PreparedQueryResult result = CharacterDatabase.Query(stmt); - - std::ostringstream ssInvalidPetitionGUIDs; - - if (result) + CharacterDatabase.EscapeString(name); + if (Petition const* petition = sPetitionMgr->GetPetitionByOwnerWithType(_player->GetGUID(), type)) { - do - { - Field* fields = result->Fetch(); - ssInvalidPetitionGUIDs << '\'' << fields[0].GetUInt32() << "', "; - } 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(name); - SQLTransaction 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->setUInt32(0, _player->GetGUID().GetCounter()); - stmt->setUInt32(1, charter->GetGUID().GetCounter()); - stmt->setString(2, name); - stmt->setUInt8(3, uint8(type)); - trans->Append(stmt); - - CharacterDatabase.CommitTransaction(trans); + // fill petition store + sPetitionMgr->AddPetition(charter->GetGUID(), _player->GetGUID(), name, type, false); } void WorldSession::HandlePetitionShowSignOpcode(WorldPacket& recvData) { TC_LOG_DEBUG("network", "Received opcode CMSG_PETITION_SHOW_SIGNATURES"); - uint8 signs = 0; - ObjectGuid petitionguid; - recvData >> petitionguid; // petition guid - - ObjectGuid::LowType petitionGuidLow = petitionguid.GetCounter(); - - PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_PETITION_TYPE); - - stmt->setUInt32(0, petitionGuidLow); - - PreparedQueryResult result = CharacterDatabase.Query(stmt); + ObjectGuid petitionGuid; + recvData >> petitionGuid; // petition guid - if (!result) + Petition const* petition = sPetitionMgr->GetPetition(petitionGuid); + if (!petition) { - TC_LOG_DEBUG("entities.player.items", "Petition %s is not found for player %u %s", petitionguid.ToString().c_str(), GetPlayer()->GetGUID().GetCounter(), GetPlayer()->GetName().c_str()); + TC_LOG_DEBUG("entities.player.items", "Petition %s is not found for player %u %s", petitionGuid.ToString().c_str(), GetPlayer()->GetGUID().GetCounter(), GetPlayer()->GetName().c_str()); return; } - Field* fields = result->Fetch(); - uint32 type = fields[0].GetUInt8(); // if guild petition and has guild => error, return; - if (type == GUILD_CHARTER_TYPE && _player->GetGuildId()) + if (petition->petitionType == GUILD_CHARTER_TYPE && _player->GetGuildId()) return; - stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_PETITION_SIGNATURE); - - stmt->setUInt32(0, petitionGuidLow); - - result = CharacterDatabase.Query(stmt); + TC_LOG_DEBUG("network", "CMSG_PETITION_SHOW_SIGNATURES petition entry: '%u'", petitionGuid.GetCounter()); - // result == NULL also correct in case no sign yet - if (result) - signs = uint8(result->GetRowCount()); - - TC_LOG_DEBUG("network", "CMSG_PETITION_SHOW_SIGNATURES petition entry: '%u'", petitionGuidLow); + SendPetitionSigns(petition, _player); +} - WorldPacket data(SMSG_PETITION_SHOW_SIGNATURES, (8+8+4+1+signs*12)); - data << uint64(petitionguid); // petition guid - data << uint64(_player->GetGUID()); // owner guid - data << uint32(petitionGuidLow); // guild guid - data << uint8(signs); // sign's count +void WorldSession::SendPetitionSigns(Petition const* petition, Player* sendTo) +{ + SignaturesVector const& signatures = petition->signatures; + WorldPacket data(SMSG_PETITION_SHOW_SIGNATURES, (8 + 8 + 4 + 1 + signatures.size() * 12)); + data << uint64(petition->petitionGuid); // petition guid + data << uint64(petition->ownerGuid); // owner guid + data << uint32(petition->petitionGuid.GetCounter()); // guild guid + data << uint8(signatures.size()); // sign's count - for (uint8 i = 1; i <= signs; ++i) + for (Signature const& signature : signatures) { - Field* fields2 = result->Fetch(); - ObjectGuid::LowType lowGuid = fields2[0].GetUInt32(); - - data << ObjectGuid(HighGuid::Player, 0, lowGuid); // Player GUID - data << uint32(0); // there 0 ... - - result->NextRow(); + data << signature.second; // Player GUID + data << uint32(0); // there 0 ... } - SendPacket(&data); + + sendTo->GetSession()->SendPacket(&data); } void WorldSession::HandlePetitionQueryOpcode(WorldPacket& recvData) @@ -310,34 +270,20 @@ void WorldSession::HandlePetitionQueryOpcode(WorldPacket& recvData) void WorldSession::SendPetitionQueryOpcode(ObjectGuid petitionguid) { - ObjectGuid ownerguid; - uint32 type; - std::string name = "NO_NAME_FOR_GUID"; - - PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_PETITION); - - stmt->setUInt32(0, petitionguid.GetCounter()); - - PreparedQueryResult result = CharacterDatabase.Query(stmt); - - if (result) - { - Field* fields = result->Fetch(); - ownerguid = ObjectGuid(HighGuid::Player, fields[0].GetUInt32()); - name = fields[1].GetString(); - type = fields[2].GetUInt8(); - } - else + Petition const* petition = sPetitionMgr->GetPetition(petitionguid); + if (!petition) { TC_LOG_DEBUG("network", "CMSG_PETITION_QUERY failed for petition (%s)", petitionguid.ToString().c_str()); return; } - WorldPacket data(SMSG_PETITION_QUERY_RESPONSE, (4+8+name.size()+1+1+4*12+2+10)); + WorldPacket data(SMSG_PETITION_QUERY_RESPONSE, (4+8+petition->petitionName.size()+1+1+4*12+2+10)); data << uint32(petitionguid.GetCounter()); // guild/team guid (in Trinity always same as GUID_LOPART(petition guid) - data << uint64(ownerguid); // charter owner guid - data << name; // name (guild/arena team) + data << uint64(petition->ownerGuid); // charter owner guid + data << petition->petitionName; // name (guild/arena team) data << uint8(0); // some string + + CharterTypes type = petition->petitionType; if (type == GUILD_CHARTER_TYPE) { uint32 needed = sWorld->getIntConfig(CONFIG_MIN_PETITION_SIGNS); @@ -375,7 +321,6 @@ void WorldSession::HandlePetitionRenameOpcode(WorldPacket& recvData) TC_LOG_DEBUG("network", "Received opcode MSG_PETITION_RENAME"); // ok ObjectGuid petitionGuid; - uint32 type; std::string newName; recvData >> petitionGuid; // guid @@ -385,23 +330,14 @@ void WorldSession::HandlePetitionRenameOpcode(WorldPacket& recvData) if (!item) return; - PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_PETITION_TYPE); - - stmt->setUInt32(0, petitionGuid.GetCounter()); - - PreparedQueryResult result = CharacterDatabase.Query(stmt); - - if (result) - { - Field* fields = result->Fetch(); - type = fields[0].GetUInt8(); - } - else + Petition* petition = sPetitionMgr->GetPetition(petitionGuid); + if (!petition) { TC_LOG_DEBUG("network", "CMSG_PETITION_QUERY failed for petition %s", petitionGuid.ToString().c_str()); return; } + CharterTypes type = petition->petitionType; if (type == GUILD_CHARTER_TYPE) { if (sGuildMgr->GetGuildByName(newName)) @@ -429,12 +365,10 @@ void WorldSession::HandlePetitionRenameOpcode(WorldPacket& recvData) } } - stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_PETITION_NAME); - - stmt->setString(0, newName); - stmt->setUInt32(1, petitionGuid.GetCounter()); + CharacterDatabase.EscapeString(newName); - CharacterDatabase.Execute(stmt); + // update petition storage + petition->UpdateName(newName); TC_LOG_DEBUG("network", "Petition %s renamed to '%s'", petitionGuid.ToString().c_str(), newName.c_str()); WorldPacket data(MSG_PETITION_RENAME, (8+newName.size()+1)); @@ -447,32 +381,24 @@ void WorldSession::HandlePetitionSignOpcode(WorldPacket& recvData) { TC_LOG_DEBUG("network", "Received opcode CMSG_PETITION_SIGN"); // ok - Field* fields; ObjectGuid petitionGuid; uint8 unk; recvData >> petitionGuid; // petition guid recvData >> unk; - PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_PETITION_SIGNATURES); - - stmt->setUInt32(0, petitionGuid.GetCounter()); - stmt->setUInt32(1, petitionGuid.GetCounter()); - - PreparedQueryResult result = CharacterDatabase.Query(stmt); - - if (!result) + Petition* petition = sPetitionMgr->GetPetition(petitionGuid); + if (!petition) { TC_LOG_ERROR("network", "Petition %s is not found for player %u %s", petitionGuid.ToString().c_str(), GetPlayer()->GetGUID().GetCounter(), GetPlayer()->GetName().c_str()); return; } - fields = result->Fetch(); - ObjectGuid ownerGuid(HighGuid::Player, fields[0].GetUInt32()); - uint64 signs = fields[1].GetUInt64(); - uint8 type = fields[2].GetUInt8(); + ObjectGuid ownerGuid = petition->ownerGuid; + CharterTypes type = petition->petitionType; + uint8 signs = petition->signatures.size(); - ObjectGuid::LowType playerGuid = _player->GetGUID().GetCounter(); - if (ownerGuid == _player->GetGUID()) + ObjectGuid playerGuid = _player->GetGUID(); + if (ownerGuid == playerGuid) return; // not let enemies sign guild charter @@ -493,7 +419,7 @@ void WorldSession::HandlePetitionSignOpcode(WorldPacket& recvData) return; } - uint8 slot = ArenaTeam::GetSlotByType(type); + uint8 slot = ArenaTeam::GetSlotByType(static_cast<uint32>(type)); if (slot >= MAX_ARENA_SLOT) return; @@ -523,19 +449,13 @@ void WorldSession::HandlePetitionSignOpcode(WorldPacket& recvData) } } - if (++signs > type) // client signs maximum + if (++signs > static_cast<uint8>(type)) // 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->setUInt32(1, petitionGuid.GetCounter()); - - result = CharacterDatabase.Query(stmt); - - if (result) + bool isSigned = petition->IsPetitionSignedByAccount(GetAccountId()); + if (isSigned) { WorldPacket data(SMSG_PETITION_SIGN_RESULTS, (8+8+4)); data << uint64(petitionGuid); @@ -551,30 +471,17 @@ void WorldSession::HandlePetitionSignOpcode(WorldPacket& recvData) return; } - stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_PETITION_SIGNATURE); + // fill petition store + petition->AddSignature(petitionGuid, GetAccountId(), playerGuid, false); - stmt->setUInt32(0, ownerGuid.GetCounter()); - stmt->setUInt32(1, petitionGuid.GetCounter()); - stmt->setUInt32(2, playerGuid); - stmt->setUInt32(3, GetAccountId()); - - CharacterDatabase.Execute(stmt); - - TC_LOG_DEBUG("network", "PETITION SIGN: %s by player: %s (GUID: %u Account: %u)", petitionGuid.ToString().c_str(), _player->GetName().c_str(), playerGuid, GetAccountId()); + TC_LOG_DEBUG("network", "PETITION SIGN: %s by player: %s (GUID: %u Account: %u)", petitionGuid.ToString().c_str(), _player->GetName().c_str(), playerGuid.GetCounter(), GetAccountId()); WorldPacket data(SMSG_PETITION_SIGN_RESULTS, (8+8+4)); data << uint64(petitionGuid); data << uint64(_player->GetGUID()); data << uint32(PETITION_SIGN_OK); - - // close at signer side SendPacket(&data); - // update signs count on charter, required testing... - //Item* item = _player->GetItemByGuid(petitionguid)); - //if (item) - // item->SetUInt32Value(ITEM_FIELD_ENCHANTMENT_1_1+1, signs); - // update for owner if online if (Player* owner = ObjectAccessor::FindConnectedPlayer(ownerGuid)) owner->GetSession()->SendPacket(&data); @@ -588,20 +495,12 @@ void WorldSession::HandlePetitionDeclineOpcode(WorldPacket& recvData) recvData >> petitionguid; // petition guid TC_LOG_DEBUG("network", "Petition %s declined by %u", petitionguid.ToString().c_str(), _player->GetGUID().GetCounter()); - PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_PETITION_OWNER_BY_GUID); - - stmt->setUInt32(0, petitionguid.GetCounter()); - - PreparedQueryResult result = CharacterDatabase.Query(stmt); - - if (!result) + Petition const* petition = sPetitionMgr->GetPetition(petitionguid); + if (!petition) return; - Field* fields = result->Fetch(); - ObjectGuid ownerguid(HighGuid::Player, 0, fields[0].GetUInt32()); - - Player* owner = ObjectAccessor::FindConnectedPlayer(ownerguid); - if (owner) // petition owner online + // petition owner online + if (Player* owner = ObjectAccessor::FindConnectedPlayer(petition->ownerGuid)) { WorldPacket data(MSG_PETITION_DECLINE, 8); data << uint64(_player->GetGUID()); @@ -613,31 +512,23 @@ void WorldSession::HandleOfferPetitionOpcode(WorldPacket& recvData) { TC_LOG_DEBUG("network", "Received opcode CMSG_OFFER_PETITION"); // ok - uint8 signs = 0; - ObjectGuid petitionguid, plguid; - uint32 type, junk; - Player* player; + ObjectGuid petitionGuid, offererGuid; + uint32 junk; recvData >> junk; // this is not petition type! - recvData >> petitionguid; // petition guid - recvData >> plguid; // player guid + recvData >> petitionGuid; // petition guid + recvData >> offererGuid; // player guid - player = ObjectAccessor::FindConnectedPlayer(plguid); + Player* player = ObjectAccessor::FindConnectedPlayer(offererGuid); if (!player) return; - PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_PETITION_TYPE); - - stmt->setUInt32(0, petitionguid.GetCounter()); - - PreparedQueryResult result = CharacterDatabase.Query(stmt); - - if (!result) + Petition const* petition = sPetitionMgr->GetPetition(petitionGuid); + if (!petition) return; - Field* fields = result->Fetch(); - type = fields[0].GetUInt8(); + CharterTypes type = petition->petitionType; - TC_LOG_DEBUG("network", "OFFER PETITION: type %u, %s, to %s", type, petitionguid.ToString().c_str(), plguid.ToString().c_str()); + TC_LOG_DEBUG("network", "OFFER PETITION: type %u, %s, to %s", static_cast<uint32>(type), petitionGuid.ToString().c_str(), offererGuid.ToString().c_str()); if (!sWorld->getBoolConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_GUILD) && GetPlayer()->GetTeam() != player->GetTeam()) { @@ -657,7 +548,7 @@ void WorldSession::HandleOfferPetitionOpcode(WorldPacket& recvData) return; } - uint8 slot = ArenaTeam::GetSlotByType(type); + uint8 slot = ArenaTeam::GetSlotByType(static_cast<uint32>(type)); if (slot >= MAX_ARENA_SLOT) return; @@ -689,33 +580,7 @@ void WorldSession::HandleOfferPetitionOpcode(WorldPacket& recvData) } } - - stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_PETITION_SIGNATURE); - - stmt->setUInt32(0, petitionguid.GetCounter()); - - result = CharacterDatabase.Query(stmt); - - // result == NULL also correct charter without signs - if (result) - signs = uint8(result->GetRowCount()); - - WorldPacket data(SMSG_PETITION_SHOW_SIGNATURES, (8+8+4+signs+signs*12)); - data << uint64(petitionguid); // petition guid - data << uint64(_player->GetGUID()); // owner guid - data << uint32(petitionguid.GetCounter()); // guild guid - data << uint8(signs); // sign's count - - for (uint8 i = 1; i <= signs; ++i) - { - Field* fields2 = result->Fetch(); - data << uint64(ObjectGuid(HighGuid::Player, fields2[0].GetUInt32())); // Player GUID - data << uint32(0); // there 0 ... - - result->NextRow(); - } - - player->GetSession()->SendPacket(&data); + SendPetitionSigns(petition, player); } void WorldSession::HandleTurnInPetitionOpcode(WorldPacket& recvData) @@ -735,30 +600,18 @@ void WorldSession::HandleTurnInPetitionOpcode(WorldPacket& recvData) TC_LOG_DEBUG("network", "Petition %s turned in by %u", petitionGuid.ToString().c_str(), _player->GetGUID().GetCounter()); - // Get petition data from db - ObjectGuid::LowType ownerguidlo; - uint32 type; - std::string name; - - PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_PETITION); - stmt->setUInt32(0, petitionGuid.GetCounter()); - PreparedQueryResult result = CharacterDatabase.Query(stmt); - - if (result) - { - Field* fields = result->Fetch(); - ownerguidlo = fields[0].GetUInt32(); - name = fields[1].GetString(); - type = fields[2].GetUInt8(); - } - else + Petition const* petition = sPetitionMgr->GetPetition(petitionGuid); + if (!petition) { TC_LOG_ERROR("entities.player.cheat", "Player %s (guid: %u) tried to turn in petition (%s) that is not present in the database", _player->GetName().c_str(), _player->GetGUID().GetCounter(), petitionGuid.ToString().c_str()); return; } + CharterTypes type = petition->petitionType; + std::string const name = petition->petitionName; // we need a copy, it will be removed on guild/arena remove + // Only the petition owner can turn in the petition - if (_player->GetGUID().GetCounter() != ownerguidlo) + if (_player->GetGUID() != petition->ownerGuid) return; // Petition type (guild/arena) specific checks @@ -783,7 +636,7 @@ void WorldSession::HandleTurnInPetitionOpcode(WorldPacket& recvData) else { // Check for valid arena bracket (2v2, 3v3, 5v5) - uint8 slot = ArenaTeam::GetSlotByType(type); + uint8 slot = ArenaTeam::GetSlotByType(static_cast<uint32>(type)); if (slot >= MAX_ARENA_SLOT) return; @@ -802,26 +655,13 @@ void WorldSession::HandleTurnInPetitionOpcode(WorldPacket& recvData) } } - // Get petition signatures from db - uint8 signatures; - - stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_PETITION_SIGNATURE); - stmt->setUInt32(0, petitionGuid.GetCounter()); - result = CharacterDatabase.Query(stmt); - - if (result) - signatures = uint8(result->GetRowCount()); - else - signatures = 0; - - uint32 requiredSignatures; + SignaturesVector const signatures = petition->signatures; // we need a copy, it will be removed on guild/arena remove + uint32 requiredSignatures = static_cast<uint32>(type) - 1; if (type == GUILD_CHARTER_TYPE) requiredSignatures = sWorld->getIntConfig(CONFIG_MIN_PETITION_SIGNS); - else - requiredSignatures = type-1; // Notify player if signatures are missing - if (signatures < requiredSignatures) + if (signatures.size() < requiredSignatures) { data.Initialize(SMSG_TURN_IN_PETITION_RESULTS, 4); data << (uint32)PETITION_TURN_NEED_MORE_SIGNATURES; @@ -854,12 +694,8 @@ void WorldSession::HandleTurnInPetitionOpcode(WorldPacket& recvData) SQLTransaction trans = CharacterDatabase.BeginTransaction(); // Add members from signatures - for (uint8 i = 0; i < signatures; ++i) - { - Field* fields = result->Fetch(); - guild->AddMember(trans, ObjectGuid(HighGuid::Player, fields[0].GetUInt32())); - result->NextRow(); - } + for (Signature const& signature : signatures) + guild->AddMember(trans, signature.second); CharacterDatabase.CommitTransaction(trans); } @@ -884,27 +720,14 @@ void WorldSession::HandleTurnInPetitionOpcode(WorldPacket& recvData) TC_LOG_DEBUG("network", "PetitonsHandler: Arena team (guid: %u) added to ObjectMgr", arenaTeam->GetId()); // Add members - for (uint8 i = 0; i < signatures; ++i) + for (Signature const& signature : signatures) { - Field* fields = result->Fetch(); - ObjectGuid memberGUID(HighGuid::Player, fields[0].GetUInt32()); - TC_LOG_DEBUG("network", "PetitionsHandler: Adding arena team (guid: %u) member %s", arenaTeam->GetId(), memberGUID.ToString().c_str()); - arenaTeam->AddMember(memberGUID); - result->NextRow(); + TC_LOG_DEBUG("network", "PetitionsHandler: Adding arena team (guid: %u) member %s", arenaTeam->GetId(), signature.second.ToString().c_str()); + arenaTeam->AddMember(signature.second); } } - SQLTransaction trans = CharacterDatabase.BeginTransaction(); - - stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_PETITION_BY_GUID); - stmt->setUInt32(0, petitionGuid.GetCounter()); - trans->Append(stmt); - - stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_PETITION_SIGNATURE_BY_GUID); - stmt->setUInt32(0, petitionGuid.GetCounter()); - trans->Append(stmt); - - CharacterDatabase.CommitTransaction(trans); + sPetitionMgr->RemovePetition(petitionGuid); // created TC_LOG_DEBUG("network", "Player %s (%s) turning in petition %s", _player->GetName().c_str(), _player->GetGUID().ToString().c_str(), petitionGuid.ToString().c_str()); diff --git a/src/server/game/Miscellaneous/SharedDefines.h b/src/server/game/Miscellaneous/SharedDefines.h index 1ca1abbb3b6..bed2acaaf78 100644 --- a/src/server/game/Miscellaneous/SharedDefines.h +++ b/src/server/game/Miscellaneous/SharedDefines.h @@ -3593,4 +3593,15 @@ enum WeaponAttackType : uint8 MAX_ATTACK }; +enum CharterTypes +{ + CHARTER_TYPE_NONE = 0, + CHARTER_TYPE_ANY = 10, + + GUILD_CHARTER_TYPE = 9, + ARENA_TEAM_CHARTER_2v2_TYPE = 2, + ARENA_TEAM_CHARTER_3v3_TYPE = 3, + ARENA_TEAM_CHARTER_5v5_TYPE = 5 +}; + #endif diff --git a/src/server/game/Petitions/PetitionMgr.cpp b/src/server/game/Petitions/PetitionMgr.cpp new file mode 100644 index 00000000000..ffa929a395e --- /dev/null +++ b/src/server/game/Petitions/PetitionMgr.cpp @@ -0,0 +1,263 @@ +/* +* Copyright (C) 2008-2017 TrinityCore <http://www.trinitycore.org/> +* +* 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, type 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].GetUInt32()), ObjectGuid::Create<HighGuid::Player>(fields[1].GetUInt32()), fields[2].GetString(), static_cast<CharterTypes>(fields[3].GetUInt8()), 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].GetUInt32())); + if (!petition) + continue; + + petition->AddSignature(petition->petitionGuid, fields[1].GetUInt32(), ObjectGuid::Create<HighGuid::Player>(fields[2].GetUInt32()), 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, CharterTypes type, bool isLoading) +{ + Petition& p = _petitionStore[petitionGuid]; + p.petitionGuid = petitionGuid; + p.ownerGuid = ownerGuid; + p.petitionName = name; + p.petitionType = type; + p.signatures.clear(); + + if (isLoading) + return; + + PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_PETITION); + stmt->setUInt32(0, ownerGuid.GetCounter()); + stmt->setUInt32(1, petitionGuid.GetCounter()); + stmt->setString(2, name); + stmt->setUInt8(3, uint8(type)); + CharacterDatabase.Execute(stmt); +} + +void PetitionMgr::RemovePetition(ObjectGuid petitionGuid) +{ + _petitionStore.erase(petitionGuid); + + // Delete From DB + SQLTransaction trans = CharacterDatabase.BeginTransaction(); + + PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_PETITION_BY_GUID); + stmt->setUInt32(0, petitionGuid.GetCounter()); + trans->Append(stmt); + + stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_PETITION_SIGNATURE_BY_GUID); + stmt->setUInt32(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::GetPetitionByOwnerWithType(ObjectGuid ownerGuid, CharterTypes type) +{ + for (auto& petitionPair : _petitionStore) + if (petitionPair.second.ownerGuid == ownerGuid && petitionPair.second.petitionType == type) + return &petitionPair.second; + + return nullptr; +} + +void PetitionMgr::RemovePetitionsByOwnerAndType(ObjectGuid ownerGuid, CharterTypes type) +{ + for (auto itr = _petitionStore.begin(); itr != _petitionStore.end();) + { + if (itr->second.ownerGuid == ownerGuid) + { + if (type == CHARTER_TYPE_ANY) + itr = _petitionStore.erase(itr); + else if (type == itr->second.petitionType) + { + itr = _petitionStore.erase(itr); + break; + } + } + else + ++itr; + } + + PreparedStatement* stmt; + SQLTransaction trans = CharacterDatabase.BeginTransaction(); + if (type == CHARTER_TYPE_ANY) + { + 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); + } + else + { + stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_PETITION_BY_OWNER_AND_TYPE); + stmt->setUInt32(0, ownerGuid.GetCounter()); + stmt->setUInt8(1, uint8(type)); + trans->Append(stmt); + + stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_PETITION_SIGNATURE_BY_OWNER_AND_TYPE); + stmt->setUInt32(0, ownerGuid.GetCounter()); + stmt->setUInt8(1, uint8(type)); + trans->Append(stmt); + } + CharacterDatabase.CommitTransaction(trans); +} + +void PetitionMgr::RemoveSignaturesBySignerAndType(ObjectGuid signerGuid, CharterTypes type) +{ + for (auto& petitionPair : _petitionStore) + { + if (petitionPair.second.petitionType == CHARTER_TYPE_ANY || petitionPair.second.petitionType == type) + petitionPair.second.RemoveSignatureBySigner(signerGuid); + } + + PreparedStatement* stmt; + if (type == CHARTER_TYPE_ANY) + { + stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_ALL_PETITION_SIGNATURES); + stmt->setUInt32(0, signerGuid.GetCounter()); + } + else + { + stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_PETITION_SIGNATURE); + stmt->setUInt32(0, signerGuid.GetCounter()); + stmt->setUInt8(1, uint8(type)); + } + 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; + + PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_PETITION_SIGNATURE); + + stmt->setUInt32(0, ownerGuid.GetCounter()); + stmt->setUInt32(1, petitionGuid.GetCounter()); + stmt->setUInt32(2, playerGuid); + stmt->setUInt32(3, accountId); + + CharacterDatabase.Execute(stmt); +} + +void Petition::UpdateName(std::string const& newName) +{ + petitionName = newName; + + PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_PETITION_NAME); + stmt->setString(0, newName); + stmt->setUInt32(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..119f24ac255 --- /dev/null +++ b/src/server/game/Petitions/PetitionMgr.h @@ -0,0 +1,85 @@ +/* +* Copyright (C) 2008-2017 TrinityCore <http://www.trinitycore.org/> +* +* 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; + CharterTypes petitionType; + 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, CharterTypes type, bool isLoading); + void RemovePetition(ObjectGuid petitionGuid); + Petition* GetPetition(ObjectGuid petitionGuid); + Petition* GetPetitionByOwnerWithType(ObjectGuid ownerGuid, CharterTypes type); + void RemovePetitionsByOwnerAndType(ObjectGuid ownerGuid, CharterTypes type); + void RemoveSignaturesBySignerAndType(ObjectGuid signerGuid, CharterTypes type); +}; + +#define sPetitionMgr PetitionMgr::instance() + +#endif diff --git a/src/server/game/Server/WorldSession.h b/src/server/game/Server/WorldSession.h index e5ae690246f..eea430ac1b5 100644 --- a/src/server/game/Server/WorldSession.h +++ b/src/server/game/Server/WorldSession.h @@ -51,6 +51,7 @@ struct AuctionEntry; struct DeclinedName; struct ItemTemplate; struct MovementInfo; +struct Petition; struct TradeStatusInfo; namespace lfg @@ -142,14 +143,6 @@ enum ChatRestrictionType ERR_YELL_RESTRICTED = 3 }; -enum CharterTypes -{ - GUILD_CHARTER_TYPE = 9, - 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, @@ -624,6 +617,7 @@ class TC_GAME_API WorldSession void HandlePetitionBuyOpcode(WorldPacket& recvData); void HandlePetitionShowSignOpcode(WorldPacket& recvData); + void SendPetitionSigns(Petition const* petition, Player* sendTo); void HandlePetitionQueryOpcode(WorldPacket& recvData); void HandlePetitionRenameOpcode(WorldPacket& recvData); void HandlePetitionSignOpcode(WorldPacket& recvData); diff --git a/src/server/game/World/World.cpp b/src/server/game/World/World.cpp index 6cd5960ab9e..470f2f7f382 100644 --- a/src/server/game/World/World.cpp +++ b/src/server/game/World/World.cpp @@ -53,6 +53,7 @@ #include "MMapFactory.h" #include "ObjectMgr.h" #include "OutdoorPvPMgr.h" +#include "PetitionMgr.h" #include "Player.h" #include "PoolMgr.h" #include "QueryCallback.h" @@ -1842,6 +1843,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(); |