diff --git a/common/servertalk.h b/common/servertalk.h index c78bdf728..a50e5832a 100644 --- a/common/servertalk.h +++ b/common/servertalk.h @@ -141,22 +141,23 @@ #define ServerOP_LFPMatches 0x0214 #define ServerOP_ClientVersionSummary 0x0215 -#define ServerOP_ExpeditionCreate 0x0400 -#define ServerOP_ExpeditionDeleted 0x0401 -#define ServerOP_ExpeditionLeaderChanged 0x0402 -#define ServerOP_ExpeditionLockout 0x0403 -#define ServerOP_ExpeditionMemberChange 0x0404 -#define ServerOP_ExpeditionMemberSwap 0x0405 -#define ServerOP_ExpeditionMemberStatus 0x0406 -#define ServerOP_ExpeditionGetOnlineMembers 0x0407 -#define ServerOP_ExpeditionDzAddPlayer 0x0408 -#define ServerOP_ExpeditionDzMakeLeader 0x0409 -#define ServerOP_ExpeditionDzCompass 0x040a -#define ServerOP_ExpeditionDzSafeReturn 0x040b -#define ServerOP_ExpeditionDzZoneIn 0x040c +#define ServerOP_ExpeditionCreate 0x0400 +#define ServerOP_ExpeditionDeleted 0x0401 +#define ServerOP_ExpeditionLeaderChanged 0x0402 +#define ServerOP_ExpeditionLockout 0x0403 +#define ServerOP_ExpeditionMemberChange 0x0404 +#define ServerOP_ExpeditionMemberSwap 0x0405 +#define ServerOP_ExpeditionMemberStatus 0x0406 +#define ServerOP_ExpeditionGetOnlineMembers 0x0407 +#define ServerOP_ExpeditionDzAddPlayer 0x0408 +#define ServerOP_ExpeditionDzMakeLeader 0x0409 +#define ServerOP_ExpeditionDzCompass 0x040a +#define ServerOP_ExpeditionDzSafeReturn 0x040b +#define ServerOP_ExpeditionDzZoneIn 0x040c +#define ServerOP_ExpeditionRemoveCharLockouts 0x040d -#define ServerOP_DzCharacterChange 0x0450 -#define ServerOP_DzRemoveAllCharacters 0x0451 +#define ServerOP_DzCharacterChange 0x0450 +#define ServerOP_DzRemoveAllCharacters 0x0451 #define ServerOP_LSInfo 0x1000 #define ServerOP_LSStatus 0x1001 @@ -2051,6 +2052,11 @@ struct ServerExpeditionLockout_Struct { char event_name[256]; }; +struct ServerExpeditionCharacterName_Struct { + char character_name[64]; + char expedition_name[128]; +}; + struct ServerDzCommand_Struct { uint32 expedition_id; uint8 is_char_online; // 0: target name is offline, 1: online diff --git a/world/zoneserver.cpp b/world/zoneserver.cpp index cd6a17e37..35a6e27f0 100644 --- a/world/zoneserver.cpp +++ b/world/zoneserver.cpp @@ -1397,6 +1397,12 @@ void ZoneServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) { Expedition::MakeLeader(pack); break; } + case ServerOP_ExpeditionRemoveCharLockouts: + { + auto buf = reinterpret_cast(pack->pBuffer); + client_list.SendPacket(buf->character_name, pack); + break; + } case ServerOP_DzCharacterChange: case ServerOP_DzRemoveAllCharacters: { diff --git a/zone/client.cpp b/zone/client.cpp index 30146d82f..ef1b639b1 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -9665,6 +9665,25 @@ void Client::RemoveExpeditionLockout( } } +void Client::RemoveAllExpeditionLockouts(std::string expedition_name) +{ + if (expedition_name.empty()) + { + ExpeditionDatabase::DeleteAllCharacterLockouts(CharacterID()); + m_expedition_lockouts.clear(); + } + else + { + ExpeditionDatabase::DeleteAllCharacterLockouts(CharacterID(), expedition_name); + m_expedition_lockouts.erase(std::remove_if(m_expedition_lockouts.begin(), m_expedition_lockouts.end(), + [&](const ExpeditionLockoutTimer& lockout) { + return lockout.GetExpeditionName() == expedition_name; + } + ), m_expedition_lockouts.end()); + } + SendExpeditionLockoutTimers(); +} + const ExpeditionLockoutTimer* Client::GetExpeditionLockout( const std::string& expedition_name, const std::string& event_name, bool include_expired) const { diff --git a/zone/client.h b/zone/client.h index 63c0a1d2b..6e4575afc 100644 --- a/zone/client.h +++ b/zone/client.h @@ -1129,6 +1129,7 @@ public: uint32 GetPendingExpeditionInviteID() const { return m_pending_expedition_invite_id; } bool HasExpeditionLockout(const std::string& expedition_name, const std::string& event_name, bool include_expired = false); bool IsInExpedition() const { return m_expedition_id != 0; } + void RemoveAllExpeditionLockouts(std::string expedition_name = {}); void RemoveExpeditionLockout(const std::string& expedition_name, const std::string& event_name, bool update_db = false); void SetPendingExpeditionInvite(uint32 id) { m_pending_expedition_invite_id = id; } void SendExpeditionLockoutTimers(); diff --git a/zone/command.cpp b/zone/command.cpp index 789528fdb..0d8386803 100755 --- a/zone/command.cpp +++ b/zone/command.cpp @@ -6912,6 +6912,17 @@ void command_dz(Client* c, const Seperator* sep) } } } + else if (strcasecmp(sep->arg[1], "lockouts") == 0) + { + if (strcasecmp(sep->arg[2], "remove") == 0 && sep->arg[3][0] != '\0') + { + c->Message(Chat::White, fmt::format( + "Removing [{}] lockouts on [{}].", sep->arg[4][0] ? sep->arg[4] : "all", sep->arg[3] + ).c_str()); + + Expedition::RemoveAllCharacterLockouts(sep->arg[3], sep->arg[4]); + } + } else { c->Message(Chat::White, "#dz usage:"); @@ -6919,6 +6930,8 @@ void command_dz(Client* c, const Seperator* sep) c->Message(Chat::White, "#dz cache reload - reload zone cache from database"); c->Message(Chat::White, "#dz destroy - destroy expedition globally (must be in cache)"); c->Message(Chat::White, "#dz list - list all dynamic zones with corresponding instance ids from database"); + c->Message(Chat::White, "#dz lockouts remove - delete all of character's expedition lockouts"); + c->Message(Chat::White, "#dz lockouts remove \"\" - delete lockouts by expedition"); } } diff --git a/zone/expedition.cpp b/zone/expedition.cpp index ade863363..630e5631c 100644 --- a/zone/expedition.cpp +++ b/zone/expedition.cpp @@ -1530,6 +1530,20 @@ void Expedition::SendWorldGetOnlineMembers() worldserver.SendPacket(pack.get()); } +void Expedition::RemoveAllCharacterLockouts(std::string character_name, std::string expedition_name) +{ + uint32_t pack_size = sizeof(ServerExpeditionCharacterName_Struct); + auto pack = std::unique_ptr(new ServerPacket(ServerOP_ExpeditionRemoveCharLockouts, pack_size)); + auto buf = reinterpret_cast(pack->pBuffer); + strn0cpy(buf->character_name, character_name.c_str(), sizeof(buf->character_name)); + buf->expedition_name[0] = '\0'; + if (!expedition_name.empty()) + { + strn0cpy(buf->expedition_name, expedition_name.c_str(), sizeof(buf->expedition_name)); + } + worldserver.SendPacket(pack.get()); +} + void Expedition::HandleWorldMessage(ServerPacket* pack) { switch (pack->opcode) @@ -1719,6 +1733,16 @@ void Expedition::HandleWorldMessage(ServerPacket* pack) } break; } + case ServerOP_ExpeditionRemoveCharLockouts: + { + auto buf = reinterpret_cast(pack->pBuffer); + Client* client = entity_list.GetClientByName(buf->character_name); + if (client) + { + client->RemoveAllExpeditionLockouts(buf->expedition_name); + } + break; + } } } diff --git a/zone/expedition.h b/zone/expedition.h index 671a4e9b9..d4901fc38 100644 --- a/zone/expedition.h +++ b/zone/expedition.h @@ -78,6 +78,7 @@ public: static Expedition* FindCachedExpeditionByCharacterName(const std::string& char_name); static Expedition* FindCachedExpeditionByID(uint32_t expedition_id); static Expedition* FindExpeditionByInstanceID(uint32_t instance_id); + static void RemoveAllCharacterLockouts(std::string character_name, std::string expedition_name = {}); static void HandleWorldMessage(ServerPacket* pack); uint32_t GetID() const { return m_id; } diff --git a/zone/expedition_database.cpp b/zone/expedition_database.cpp index 3888e1692..c3dcd3ef8 100644 --- a/zone/expedition_database.cpp +++ b/zone/expedition_database.cpp @@ -201,6 +201,37 @@ MySQLRequestResult ExpeditionDatabase::LoadValidationData( return results; } +void ExpeditionDatabase::DeleteAllCharacterLockouts(uint32_t character_id) +{ + LogExpeditionsDetail("Deleting all character [{}] lockouts", character_id); + + if (character_id != 0) + { + std::string query = fmt::format(SQL( + DELETE FROM expedition_character_lockouts + WHERE character_id = {}; + ), character_id); + + database.QueryDatabase(query); + } +} + +void ExpeditionDatabase::DeleteAllCharacterLockouts( + uint32_t character_id, const std::string& expedition_name) +{ + LogExpeditionsDetail("Deleting all character [{}] lockouts for [{}]", character_id, expedition_name); + + if (character_id != 0 && !expedition_name.empty()) + { + std::string query = fmt::format(SQL( + DELETE FROM expedition_character_lockouts + WHERE character_id = {} AND expedition_name = '{}'; + ), character_id, expedition_name); + + database.QueryDatabase(query); + } +} + void ExpeditionDatabase::DeleteCharacterLockout( uint32_t character_id, const std::string& expedition_name, const std::string& event_name) { diff --git a/zone/expedition_database.h b/zone/expedition_database.h index 38f758258..bb8804d81 100644 --- a/zone/expedition_database.h +++ b/zone/expedition_database.h @@ -45,6 +45,8 @@ namespace ExpeditionDatabase MySQLRequestResult LoadExpeditionMembers(uint32_t expedition_id); MySQLRequestResult LoadValidationData(const std::string& character_names_query, const std::string& expedition_name); void DeleteAllMembers(uint32_t expedition_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); void DeleteExpedition(uint32_t expedition_id); void DeleteLockout(uint32_t expedition_id, const std::string& event_name); diff --git a/zone/lua_client.cpp b/zone/lua_client.cpp index 24659a6ba..c1e87cafc 100644 --- a/zone/lua_client.cpp +++ b/zone/lua_client.cpp @@ -1711,6 +1711,16 @@ void Lua_Client::AddExpeditionLockout(std::string expedition_name, std::string e self->AddNewExpeditionLockout(expedition_name, event_name, seconds); } +void Lua_Client::RemoveAllExpeditionLockouts() { + Lua_Safe_Call_Void(); + self->RemoveAllExpeditionLockouts(); +} + +void Lua_Client::RemoveAllExpeditionLockouts(std::string expedition_name) { + Lua_Safe_Call_Void(); + self->RemoveAllExpeditionLockouts(expedition_name); +} + void Lua_Client::RemoveExpeditionLockout(std::string expedition_name, std::string event_name) { Lua_Safe_Call_Void(); self->RemoveExpeditionLockout(expedition_name, event_name, true); @@ -2046,6 +2056,8 @@ luabind::scope lua_register_client() { .def("GetExpeditionLockouts", (luabind::object(Lua_Client::*)(lua_State* L))&Lua_Client::GetExpeditionLockouts) .def("GetExpeditionLockouts", (luabind::object(Lua_Client::*)(lua_State* L, std::string))&Lua_Client::GetExpeditionLockouts) .def("AddExpeditionLockout", (void(Lua_Client::*)(std::string, std::string, uint32))&Lua_Client::AddExpeditionLockout) + .def("RemoveAllExpeditionLockouts", (void(Lua_Client::*)(void))&Lua_Client::RemoveAllExpeditionLockouts) + .def("RemoveAllExpeditionLockouts", (void(Lua_Client::*)(std::string))&Lua_Client::RemoveAllExpeditionLockouts) .def("RemoveExpeditionLockout", (void(Lua_Client::*)(std::string, std::string))&Lua_Client::RemoveExpeditionLockout) .def("HasExpeditionLockout", (bool(Lua_Client::*)(std::string, std::string))&Lua_Client::HasExpeditionLockout) .def("MovePCDynamicZone", (void(Lua_Client::*)(uint32))&Lua_Client::MovePCDynamicZone) diff --git a/zone/lua_client.h b/zone/lua_client.h index 47a0ae355..e339ead7a 100644 --- a/zone/lua_client.h +++ b/zone/lua_client.h @@ -346,6 +346,8 @@ public: luabind::object GetExpeditionLockouts(lua_State* L); luabind::object GetExpeditionLockouts(lua_State* L, std::string expedition_name); void AddExpeditionLockout(std::string expedition_name, std::string event_name, uint32 seconds); + void RemoveAllExpeditionLockouts(); + void RemoveAllExpeditionLockouts(std::string expedition_name); void RemoveExpeditionLockout(std::string expedition_name, std::string event_name); bool HasExpeditionLockout(std::string expedition_name, std::string event_name); void MovePCDynamicZone(uint32 zone_id); diff --git a/zone/worldserver.cpp b/zone/worldserver.cpp index afdb9933b..fa005ea6e 100644 --- a/zone/worldserver.cpp +++ b/zone/worldserver.cpp @@ -2912,6 +2912,7 @@ void WorldServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) case ServerOP_ExpeditionDzCompass: case ServerOP_ExpeditionDzSafeReturn: case ServerOP_ExpeditionDzZoneIn: + case ServerOP_ExpeditionRemoveCharLockouts: { Expedition::HandleWorldMessage(pack); break;