mirror of
https://github.com/EQEmu/Server.git
synced 2026-05-16 22:58:34 +00:00
Let world handle expedition leader changes
This should eliminate race conditions caused by zones trying to set a leader when members in different zones quit at the same time Zone still detects when leader goes offline to trigger a change since it's easier than having world process expedition member status updates and perform expedition lookups
This commit is contained in:
+2
-7
@@ -6984,20 +6984,15 @@ void command_dz(Client* c, const Seperator* sep)
|
||||
auto expedition = Expedition::FindCachedExpeditionByID(expedition_id);
|
||||
if (expedition)
|
||||
{
|
||||
uint32_t char_id = database.GetCharacterID(sep->arg[3]);
|
||||
auto char_name = FormatName(sep->arg[3]);
|
||||
if (char_id == 0)
|
||||
{
|
||||
c->Message(Chat::Red, fmt::format("Failed to find character id for [{}]", char_name).c_str());
|
||||
}
|
||||
else if (!expedition->HasMember(char_id))
|
||||
if (!expedition->HasMember(char_name))
|
||||
{
|
||||
c->Message(Chat::Red, fmt::format("Character [{}] is not in that expedition", char_name).c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
c->Message(Chat::White, fmt::format("Setting expedition [{}] leader to [{}]", expedition_id, char_name).c_str());
|
||||
expedition->SetNewLeader(char_id, char_name);
|
||||
expedition->SendWorldMakeLeaderRequest(c->GetName(), char_name);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
||||
+19
-68
@@ -578,12 +578,6 @@ bool Expedition::RemoveMember(const std::string& remove_char_name)
|
||||
ProcessMemberRemoved(member.name, member.char_id);
|
||||
SendWorldMemberChanged(member.name, member.char_id, true);
|
||||
|
||||
// live always sends a leader update but we can send only if leader changes
|
||||
if (member.char_id == m_leader.char_id)
|
||||
{
|
||||
ChooseNewLeader();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -609,11 +603,6 @@ void Expedition::SwapMember(Client* add_client, const std::string& remove_char_n
|
||||
ProcessMemberRemoved(member.name, member.char_id);
|
||||
ProcessMemberAdded(add_client->GetName(), add_client->CharacterID());
|
||||
SendWorldMemberSwapped(member.name, member.char_id, add_client->GetName(), add_client->CharacterID());
|
||||
|
||||
if (!m_members.empty() && member.char_id == m_leader.char_id)
|
||||
{
|
||||
ChooseNewLeader();
|
||||
}
|
||||
}
|
||||
|
||||
void Expedition::SetMemberStatus(Client* client, ExpeditionMemberStatus status)
|
||||
@@ -623,11 +612,11 @@ void Expedition::SetMemberStatus(Client* client, ExpeditionMemberStatus status)
|
||||
UpdateMemberStatus(client->CharacterID(), status);
|
||||
SendWorldMemberStatus(client->CharacterID(), status);
|
||||
|
||||
// we either changed leader status here or leader was already offline and
|
||||
// a member coming online needs to trigger a leader change
|
||||
// world could detect this itself but it'd have to process member status updates
|
||||
// a member coming online will trigger a leader change if all members were offline
|
||||
if (m_leader.status == ExpeditionMemberStatus::Offline)
|
||||
{
|
||||
ChooseNewLeader();
|
||||
SendWorldExpeditionUpdate(ServerOP_ExpeditionChooseNewLeader);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -662,20 +651,6 @@ void Expedition::UpdateMemberStatus(uint32_t update_member_id, ExpeditionMemberS
|
||||
}
|
||||
}
|
||||
|
||||
bool Expedition::ChooseNewLeader()
|
||||
{
|
||||
for (const auto& member : m_members)
|
||||
{
|
||||
if (member.char_id != m_leader.char_id && member.status == ExpeditionMemberStatus::Online)
|
||||
{
|
||||
LogExpeditionsModerate("Replacing leader [{}] with [{}]", m_leader.name, member.name);
|
||||
SetNewLeader(member.char_id, member.name);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void Expedition::SendClientExpeditionInvite(
|
||||
Client* client, const std::string& inviter_name, const std::string& swap_remove_name)
|
||||
{
|
||||
@@ -1051,17 +1026,8 @@ void Expedition::DzMakeLeader(Client* requester, std::string new_leader_name)
|
||||
return;
|
||||
}
|
||||
|
||||
// database is not updated until new leader client validated
|
||||
Client* new_leader_client = entity_list.GetClientByName(new_leader_name.c_str());
|
||||
if (new_leader_client)
|
||||
{
|
||||
ProcessMakeLeader(requester, new_leader_client, new_leader_name, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
// new leader not in this zone, let world verify and pass to new leader's zone
|
||||
SendWorldMakeLeaderRequest(requester->GetName(), new_leader_name);
|
||||
}
|
||||
// leader can only be changed by world
|
||||
SendWorldMakeLeaderRequest(requester->GetName(), new_leader_name);
|
||||
}
|
||||
|
||||
void Expedition::DzRemovePlayer(Client* requester, std::string char_name)
|
||||
@@ -1164,16 +1130,18 @@ void Expedition::SetLocked(
|
||||
}
|
||||
}
|
||||
|
||||
void Expedition::SetNewLeader(uint32_t new_leader_id, const std::string& new_leader_name)
|
||||
void Expedition::ProcessLeaderChanged(uint32_t new_leader_id)
|
||||
{
|
||||
ExpeditionDatabase::UpdateLeaderID(m_id, new_leader_id);
|
||||
ProcessLeaderChanged(new_leader_id, new_leader_name);
|
||||
SendWorldLeaderChanged();
|
||||
}
|
||||
auto new_leader = GetMemberData(new_leader_id);
|
||||
if (new_leader.char_id == 0)
|
||||
{
|
||||
LogExpeditions("Processed invalid new leader id [{}] for expedition [{}]", new_leader_id, m_id);
|
||||
return;
|
||||
}
|
||||
|
||||
void Expedition::ProcessLeaderChanged(uint32_t new_leader_id, const std::string& new_leader_name)
|
||||
{
|
||||
m_leader = { new_leader_id, new_leader_name, ExpeditionMemberStatus::Online };
|
||||
LogExpeditionsModerate("Replaced [{}] leader [{}] with [{}]", m_id, m_leader.name, new_leader.name);
|
||||
|
||||
m_leader = new_leader;
|
||||
|
||||
// update each client's expedition window in this zone
|
||||
auto outapp_leader = CreateLeaderNamePacket();
|
||||
@@ -1219,7 +1187,6 @@ void Expedition::ProcessMakeLeader(
|
||||
{
|
||||
new_leader_client->MessageString(Chat::Yellow, DZMAKELEADER_YOU);
|
||||
}
|
||||
SetNewLeader(new_leader_client->CharacterID(), new_leader_client->GetName());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1592,19 +1559,6 @@ void Expedition::SendWorldAddPlayerInvite(
|
||||
worldserver.SendPacket(pack.get());
|
||||
}
|
||||
|
||||
void Expedition::SendWorldLeaderChanged()
|
||||
{
|
||||
uint32_t pack_size = sizeof(ServerExpeditionMemberChange_Struct);
|
||||
auto pack = std::unique_ptr<ServerPacket>(new ServerPacket(ServerOP_ExpeditionLeaderChanged, pack_size));
|
||||
auto buf = reinterpret_cast<ServerExpeditionMemberChange_Struct*>(pack->pBuffer);
|
||||
buf->expedition_id = GetID();
|
||||
buf->sender_zone_id = zone ? zone->GetZoneID() : 0;
|
||||
buf->sender_instance_id = zone ? zone->GetInstanceID() : 0;
|
||||
buf->char_id = m_leader.char_id;
|
||||
strn0cpy(buf->char_name, m_leader.name.c_str(), sizeof(buf->char_name));
|
||||
worldserver.SendPacket(pack.get());
|
||||
}
|
||||
|
||||
void Expedition::SendWorldLockoutDuration(
|
||||
const ExpeditionLockoutTimer& lockout, int seconds, bool members_only)
|
||||
{
|
||||
@@ -1894,14 +1848,11 @@ void Expedition::HandleWorldMessage(ServerPacket* pack)
|
||||
}
|
||||
case ServerOP_ExpeditionLeaderChanged:
|
||||
{
|
||||
auto buf = reinterpret_cast<ServerExpeditionMemberChange_Struct*>(pack->pBuffer);
|
||||
if (zone && !zone->IsZone(buf->sender_zone_id, buf->sender_instance_id))
|
||||
auto buf = reinterpret_cast<ServerExpeditionLeaderID_Struct*>(pack->pBuffer);
|
||||
auto expedition = Expedition::FindCachedExpeditionByID(buf->expedition_id);
|
||||
if (expedition)
|
||||
{
|
||||
auto expedition = Expedition::FindCachedExpeditionByID(buf->expedition_id);
|
||||
if (expedition)
|
||||
{
|
||||
expedition->ProcessLeaderChanged(buf->char_id, buf->char_name);
|
||||
}
|
||||
expedition->ProcessLeaderChanged(buf->leader_id);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
+2
-5
@@ -122,7 +122,6 @@ public:
|
||||
void RemoveAllMembers(bool enable_removal_timers = true);
|
||||
bool RemoveMember(const std::string& remove_char_name);
|
||||
void SetMemberStatus(Client* client, ExpeditionMemberStatus status);
|
||||
void SetNewLeader(uint32_t new_leader_id, const std::string& new_leader_name);
|
||||
void SwapMember(Client* add_client, const std::string& remove_char_name);
|
||||
void SetLocked(bool lock_expedition, ExpeditionLockMessage lock_msg,
|
||||
bool update_db = false, uint32_t msg_color = Chat::Yellow);
|
||||
@@ -144,6 +143,7 @@ public:
|
||||
void SetLootEventBySpawnID(uint32_t spawn_id, const std::string& event_name);
|
||||
|
||||
void SendClientExpeditionInfo(Client* client);
|
||||
void SendWorldMakeLeaderRequest(const std::string& requester_name, const std::string& new_leader_name);
|
||||
void SendWorldPendingInvite(const ExpeditionInvite& invite, const std::string& add_name);
|
||||
|
||||
void DzAddPlayer(Client* requester, const std::string& add_char_name, const std::string& swap_remove_name = {});
|
||||
@@ -174,10 +174,9 @@ private:
|
||||
void AddLockout(const ExpeditionLockoutTimer& lockout, bool members_only = false);
|
||||
void AddLockoutDurationClients(const ExpeditionLockoutTimer& lockout, int seconds, uint32_t exclude_id = 0);
|
||||
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);
|
||||
void ProcessLeaderChanged(uint32_t new_leader_id, const std::string& new_leader_name);
|
||||
void ProcessLeaderChanged(uint32_t new_leader_id);
|
||||
void ProcessLockoutDuration(const ExpeditionLockoutTimer& lockout, int seconds, bool members_only = false);
|
||||
void ProcessLockoutUpdate(const ExpeditionLockoutTimer& lockout, bool remove, bool members_only = false);
|
||||
void ProcessMakeLeader(Client* old_leader, Client* new_leader, const std::string& new_leader_name, bool is_online);
|
||||
@@ -196,12 +195,10 @@ private:
|
||||
void SendWorldExpeditionUpdate(uint16_t server_opcode);
|
||||
void SendWorldAddPlayerInvite(const std::string& inviter_name, const std::string& swap_remove_name,
|
||||
const std::string& add_name, bool pending = false);
|
||||
void SendWorldLeaderChanged();
|
||||
void SendWorldLockoutDuration(
|
||||
const ExpeditionLockoutTimer& lockout, int seconds, bool members_only = false);
|
||||
void SendWorldLockoutUpdate(
|
||||
const ExpeditionLockoutTimer& lockout, bool remove, bool members_only = false);
|
||||
void SendWorldMakeLeaderRequest(const std::string& requester_name, const std::string& new_leader_name);
|
||||
void SendWorldMemberChanged(const std::string& char_name, uint32_t char_id, bool remove);
|
||||
void SendWorldMemberStatus(uint32_t character_id, ExpeditionMemberStatus status);
|
||||
void SendWorldMemberSwapped(const std::string& remove_char_name, uint32_t remove_char_id,
|
||||
|
||||
@@ -629,17 +629,6 @@ void ExpeditionDatabase::InsertMembers(
|
||||
}
|
||||
}
|
||||
|
||||
void ExpeditionDatabase::UpdateLeaderID(uint32_t expedition_id, uint32_t leader_id)
|
||||
{
|
||||
LogExpeditionsDetail("Updating leader [{}] for expedition [{}]", leader_id, expedition_id);
|
||||
|
||||
auto query = fmt::format(SQL(
|
||||
UPDATE expeditions SET leader_id = {} WHERE id = {};
|
||||
), leader_id, expedition_id);
|
||||
|
||||
database.QueryDatabase(query);
|
||||
}
|
||||
|
||||
void ExpeditionDatabase::UpdateLockState(uint32_t expedition_id, bool is_locked)
|
||||
{
|
||||
LogExpeditionsDetail("Updating lock state [{}] for expedition [{}]", is_locked, expedition_id);
|
||||
|
||||
@@ -71,7 +71,6 @@ namespace ExpeditionDatabase
|
||||
void InsertLockouts(uint32_t expedition_id, const std::unordered_map<std::string, ExpeditionLockoutTimer>& lockouts);
|
||||
void InsertMember(uint32_t expedition_id, uint32_t character_id);
|
||||
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 UpdateReplayLockoutOnJoin(uint32_t expedition_id, bool add_on_join);
|
||||
void AddLockoutDuration(const std::vector<ExpeditionMember>& members,
|
||||
|
||||
Reference in New Issue
Block a user