Remove member history from expeditions

Expedition uuids are now used to check if characters may re-join
This commit is contained in:
hg 2020-06-13 20:19:03 -04:00
parent da2a6205ed
commit 06d84b83de
8 changed files with 40 additions and 63 deletions

View File

@ -35,7 +35,6 @@ CREATE TABLE `expedition_members` (
`id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
`expedition_id` INT(10) UNSIGNED NOT NULL DEFAULT 0,
`character_id` INT(10) UNSIGNED NOT NULL DEFAULT 0,
`is_current_member` TINYINT(4) UNSIGNED NOT NULL DEFAULT 0,
PRIMARY KEY (`id`),
UNIQUE INDEX `expedition_id_character_id` (`expedition_id`, `character_id`),
CONSTRAINT `FK_expedition_members_expedition_details` FOREIGN KEY (`expedition_id`) REFERENCES `expedition_details` (`id`) ON DELETE CASCADE

View File

@ -205,20 +205,19 @@ void ExpeditionCache::Process()
void ExpeditionDatabase::PurgeExpiredExpeditions()
{
LogExpeditionsDetail("Purging expired expeditions");
std::string query = SQL(
DELETE expedition FROM expedition_details expedition
DELETE expedition
FROM expedition_details expedition
LEFT JOIN instance_list ON expedition.instance_id = instance_list.id
LEFT JOIN (
SELECT expedition_id, COUNT(IF(is_current_member = TRUE, 1, NULL)) member_count
SELECT expedition_id, COUNT(*) member_count
FROM expedition_members
GROUP BY expedition_id
) AS expedition_members
ON expedition_members.expedition_id = expedition.id
WHERE
expedition.instance_id IS NULL
OR expedition_members.member_count = 0
OR expedition_members.member_count IS NULL
OR (instance_list.start_time + instance_list.duration) <= UNIX_TIMESTAMP();
);
@ -227,8 +226,6 @@ void ExpeditionDatabase::PurgeExpiredExpeditions()
void ExpeditionDatabase::PurgeExpiredCharacterLockouts()
{
LogExpeditionsDetail("Purging expired lockouts");
std::string query = SQL(
DELETE FROM expedition_character_lockouts
WHERE expire_time <= NOW();
@ -239,8 +236,6 @@ void ExpeditionDatabase::PurgeExpiredCharacterLockouts()
std::vector<Expedition> ExpeditionDatabase::LoadExpeditions()
{
LogExpeditionsDetail("Loading expeditions for world cache");
std::vector<Expedition> expeditions;
std::string query = SQL(
@ -253,9 +248,7 @@ std::vector<Expedition> ExpeditionDatabase::LoadExpeditions()
expedition_members.character_id
FROM expedition_details
INNER JOIN instance_list ON expedition_details.instance_id = instance_list.id
INNER JOIN expedition_members
ON expedition_members.expedition_id = expedition_details.id
AND expedition_members.is_current_member = TRUE
INNER JOIN expedition_members ON expedition_members.expedition_id = expedition_details.id
ORDER BY expedition_details.id;
);
@ -305,9 +298,7 @@ Expedition ExpeditionDatabase::LoadExpedition(uint32_t expedition_id)
expedition_members.character_id
FROM expedition_details
INNER JOIN instance_list ON expedition_details.instance_id = instance_list.id
INNER JOIN expedition_members
ON expedition_members.expedition_id = expedition_details.id
AND expedition_members.is_current_member = TRUE
INNER JOIN expedition_members ON expedition_members.expedition_id = expedition_details.id
WHERE expedition_details.id = {};
), expedition_id);

View File

@ -427,7 +427,7 @@ void DynamicZone::RemoveAllCharacters(bool enable_removal_timers)
database.RemoveClientsFromInstance(GetInstanceID());
}
void DynamicZone::SaveInstanceMembersToDatabase(const std::unordered_set<uint32_t>& character_ids)
void DynamicZone::SaveInstanceMembersToDatabase(const std::vector<uint32_t>& character_ids)
{
LogDynamicZonesDetail("Saving [{}] instance members to database", character_ids.size());

View File

@ -25,7 +25,6 @@
#include <cstdint>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <vector>
class MySQLRequestRow;
@ -75,7 +74,7 @@ public:
uint32_t CreateInstance();
void AddCharacter(uint32_t character_id);
void SaveInstanceMembersToDatabase(const std::unordered_set<uint32_t>& character_ids);
void SaveInstanceMembersToDatabase(const std::vector<uint32_t>& character_ids);
uint64_t GetExpireTime() const { return std::chrono::system_clock::to_time_t(m_expire_time); }
uint16_t GetInstanceID() const { return static_cast<uint16_t>(m_instance_id); };

View File

@ -212,9 +212,8 @@ void Expedition::CacheExpeditions(MySQLRequestResult& results)
if (current_expedition)
{
auto member_id = strtoul(row[col::member_id], nullptr, 10);
bool is_current_member = (strtoul(row[col::is_current_member], nullptr, 10) != 0);
current_expedition->AddInternalMember(
row[col::member_name], member_id, ExpeditionMemberStatus::Offline, is_current_member
row[col::member_name], member_id, ExpeditionMemberStatus::Offline
);
expedition_character_ids.emplace_back(std::make_pair(expedition_id, member_id));
}
@ -309,14 +308,16 @@ void Expedition::SaveLockouts(ExpeditionRequest& request)
void Expedition::SaveMembers(ExpeditionRequest& request)
{
m_members = request.GetMembers();
std::vector<uint32_t> member_ids;
for (const auto& member : m_members)
{
m_member_id_history.emplace(member.char_id);
member_ids.emplace_back(member.char_id);
}
ExpeditionDatabase::InsertMembers(m_id, m_members);
ExpeditionDatabase::DeleteAllMembersPendingLockouts(m_members);
m_dynamiczone.SaveInstanceMembersToDatabase(m_member_id_history); // all are current members here
m_dynamiczone.SaveInstanceMembersToDatabase(member_ids);
}
Expedition* Expedition::FindCachedExpeditionByCharacterID(uint32_t character_id)
@ -465,22 +466,17 @@ void Expedition::RemoveLockout(const std::string& event_name)
}
void Expedition::AddInternalMember(
const std::string& char_name, uint32_t character_id, ExpeditionMemberStatus status, bool is_current_member)
const std::string& char_name, uint32_t character_id, ExpeditionMemberStatus status)
{
if (is_current_member)
auto it = std::find_if(m_members.begin(), m_members.end(),
[character_id](const ExpeditionMember& member) {
return member.char_id == character_id;
});
if (it == m_members.end())
{
auto it = std::find_if(m_members.begin(), m_members.end(),
[character_id](const ExpeditionMember& member) {
return member.char_id == character_id;
});
if (it == m_members.end())
{
m_members.emplace_back(ExpeditionMember{character_id, char_name, status});
}
m_members.emplace_back(ExpeditionMember{character_id, char_name, status});
}
m_member_id_history.emplace(character_id);
}
bool Expedition::AddMember(const std::string& add_char_name, uint32_t add_char_id)
@ -504,7 +500,7 @@ void Expedition::RemoveAllMembers(bool enable_removal_timers)
m_dynamiczone.RemoveAllCharacters(enable_removal_timers);
ExpeditionDatabase::DeleteAllMembersPendingLockouts(m_members);
ExpeditionDatabase::UpdateAllMembersRemoved(m_id);
ExpeditionDatabase::DeleteAllMembers(m_id);
SendUpdatesToZoneMembers(true);
SendWorldExpeditionUpdate(ServerOP_ExpeditionMembersRemoved);
@ -520,7 +516,7 @@ bool Expedition::RemoveMember(const std::string& remove_char_name)
return false;
}
ExpeditionDatabase::UpdateMemberRemoved(m_id, member.char_id);
ExpeditionDatabase::DeleteMember(m_id, member.char_id);
m_dynamiczone.RemoveCharacter(member.char_id);
ProcessMemberRemoved(member.name, member.char_id);
@ -549,7 +545,7 @@ void Expedition::SwapMember(Client* add_client, const std::string& remove_char_n
}
// make remove and add atomic to avoid racing with separate world messages
ExpeditionDatabase::UpdateMemberRemoved(m_id, member.char_id);
ExpeditionDatabase::DeleteMember(m_id, member.char_id);
ExpeditionDatabase::InsertMember(m_id, add_client->CharacterID());
m_dynamiczone.RemoveCharacter(member.char_id);
m_dynamiczone.AddCharacter(add_client->CharacterID());

View File

@ -27,7 +27,6 @@
#include <memory>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <vector>
class Client;
@ -138,7 +137,7 @@ private:
static void CacheExpeditions(MySQLRequestResult& results);
static void SendWorldGetOnlineMembers(const std::vector<std::pair<uint32_t, uint32_t>>& expedition_character_ids);
void AddInternalMember(const std::string& char_name, uint32_t char_id, ExpeditionMemberStatus status, bool is_current_member = true);
void AddInternalMember(const std::string& char_name, uint32_t char_id, ExpeditionMemberStatus status);
bool ChooseNewLeader();
bool ConfirmLeaderCommand(Client* requester);
bool ProcessAddConflicts(Client* leader_client, Client* add_client, bool swapping);
@ -183,8 +182,7 @@ private:
std::string m_expedition_name;
DynamicZone m_dynamiczone { DynamicZoneType::Expedition };
ExpeditionMember m_leader;
std::vector<ExpeditionMember> m_members; // current members
std::unordered_set<uint32_t> m_member_id_history; // track past members to allow invites for replay timer bypass
std::vector<ExpeditionMember> m_members;
std::unordered_map<std::string, ExpeditionLockoutTimer> m_lockouts;
};

View File

@ -65,7 +65,6 @@ std::string ExpeditionDatabase::LoadExpeditionsSelectQuery()
expedition_details.is_locked,
character_data.name leader_name,
expedition_members.character_id,
expedition_members.is_current_member,
member_data.name
FROM expedition_details
INNER JOIN character_data ON expedition_details.leader_id = character_data.id
@ -259,9 +258,7 @@ MySQLRequestResult ExpeditionDatabase::LoadMembersForCreateRequest(
AND lockout.is_pending = FALSE
AND lockout.expire_time > NOW()
AND lockout.expedition_name = '{}'
LEFT JOIN expedition_members member
ON character_data.id = member.character_id
AND member.is_current_member = TRUE
LEFT JOIN expedition_members member ON character_data.id = member.character_id
WHERE character_data.name IN ({})
ORDER BY character_data.id;
), expedition_name, in_character_names_query);
@ -420,8 +417,7 @@ uint32_t ExpeditionDatabase::GetExpeditionIDFromCharacterID(uint32_t character_i
uint32_t expedition_id = 0;
auto query = fmt::format(SQL(
SELECT expedition_id FROM expedition_members
WHERE character_id = {} AND is_current_member = TRUE;
SELECT expedition_id FROM expedition_members WHERE character_id = {};
), character_id);
auto results = database.QueryDatabase(query);
@ -641,10 +637,10 @@ void ExpeditionDatabase::InsertMember(uint32_t expedition_id, uint32_t character
auto query = fmt::format(SQL(
INSERT INTO expedition_members
(expedition_id, character_id, is_current_member)
(expedition_id, character_id)
VALUES
({}, {}, TRUE)
ON DUPLICATE KEY UPDATE is_current_member = TRUE;
({}, {})
ON DUPLICATE KEY UPDATE character_id = VALUES(character_id);
), expedition_id, character_id);
database.QueryDatabase(query);
@ -659,7 +655,7 @@ void ExpeditionDatabase::InsertMembers(
for (const auto& member : members)
{
fmt::format_to(std::back_inserter(insert_values),
"({}, {}, TRUE),",
"({}, {}),",
expedition_id, member.char_id
);
}
@ -669,7 +665,8 @@ void ExpeditionDatabase::InsertMembers(
insert_values.pop_back(); // trailing comma
auto query = fmt::format(SQL(
INSERT INTO expedition_members (expedition_id, character_id, is_current_member)
INSERT INTO expedition_members
(expedition_id, character_id)
VALUES {};
), insert_values);
@ -699,25 +696,23 @@ void ExpeditionDatabase::UpdateLockState(uint32_t expedition_id, bool is_locked)
database.QueryDatabase(query);
}
void ExpeditionDatabase::UpdateMemberRemoved(uint32_t expedition_id, uint32_t character_id)
void ExpeditionDatabase::DeleteMember(uint32_t expedition_id, uint32_t character_id)
{
LogExpeditionsDetail("Removing member [{}] from expedition [{}]", character_id, expedition_id);
auto query = fmt::format(SQL(
UPDATE expedition_members SET is_current_member = FALSE
WHERE expedition_id = {} AND character_id = {};
DELETE FROM expedition_members WHERE expedition_id = {} AND character_id = {};
), expedition_id, character_id);
database.QueryDatabase(query);
}
void ExpeditionDatabase::UpdateAllMembersRemoved(uint32_t expedition_id)
void ExpeditionDatabase::DeleteAllMembers(uint32_t expedition_id)
{
LogExpeditionsDetail("Updating all members of expedition [{}] as removed", expedition_id);
auto query = fmt::format(SQL(
UPDATE expedition_members SET is_current_member = FALSE
WHERE expedition_id = {};
DELETE FROM expedition_members WHERE expedition_id = {};
), expedition_id);
database.QueryDatabase(query);

View File

@ -47,6 +47,8 @@ namespace ExpeditionDatabase
std::vector<ExpeditionLockoutTimer> LoadCharacterLockouts(uint32_t character_id, const std::string& expedition_name);
std::unordered_map<uint32_t, std::unordered_map<std::string, ExpeditionLockoutTimer>>
LoadMultipleExpeditionLockouts(const std::vector<uint32_t>& expedition_ids);
void DeleteAllMembers(uint32_t expedition_id);
void DeleteMember(uint32_t expedition_id, uint32_t character_id);
void DeleteAllCharacterLockouts(uint32_t character_id);
void DeleteAllCharacterLockouts(uint32_t character_id, const std::string& expedition_name);
void DeleteCharacterLockout(uint32_t character_id, const std::string& expedition_name, const std::string& event_name);
@ -69,8 +71,6 @@ namespace ExpeditionDatabase
void InsertMembers(uint32_t expedition_id, const std::vector<ExpeditionMember>& members);
void UpdateLeaderID(uint32_t expedition_id, uint32_t leader_id);
void UpdateLockState(uint32_t expedition_id, bool is_locked);
void UpdateMemberRemoved(uint32_t expedition_id, uint32_t character_id);
void UpdateAllMembersRemoved(uint32_t expedition_id);
void UpdateReplayLockoutOnJoin(uint32_t expedition_id, bool add_on_join);
};
@ -89,7 +89,6 @@ namespace LoadExpeditionColumns
is_locked,
leader_name,
member_id,
is_current_member,
member_name
};
};