diff --git a/world/client.cpp b/world/client.cpp index 393e9959b..c29b7d698 100644 --- a/world/client.cpp +++ b/world/client.cpp @@ -104,6 +104,7 @@ Client::Client(EQStreamInterface* ieqs) char_name[0] = 0; charid = 0; zone_waiting_for_bootup = 0; + enter_world_triggered = false; StartInTutorial = false; m_ClientVersion = eqs->ClientVersion(); @@ -1192,8 +1193,16 @@ void Client::EnterWorld(bool TryBootup) { const char *zone_name = database.GetZoneName(zone_id, true); if (zone_server) { - // warn the world we're comming, so it knows not to shutdown - zone_server->IncomingClient(this); + if (false == enter_world_triggered) { + //Drop any clients we own in other zones. + zoneserver_list.DropClient(GetLSID(), zone_server); + + // warn the zone we're coming + zone_server->IncomingClient(this); + + //tell the server not to trigger this multiple times before we get a zone unavailable + enter_world_triggered = true; + } } else { if (TryBootup) { @@ -1212,9 +1221,17 @@ void Client::EnterWorld(bool TryBootup) { return; } } + zone_waiting_for_bootup = 0; - if(!cle) { + if (GetAdmin() < 80 && zoneserver_list.IsZoneLocked(zone_id)) { + Log(Logs::General, Logs::World_Server, "Enter world failed. Zone is locked."); + TellClientZoneUnavailable(); + return; + } + + if (!cle) { + TellClientZoneUnavailable(); return; } @@ -1231,12 +1248,6 @@ void Client::EnterWorld(bool TryBootup) { ); if (seen_character_select) { - if (GetAdmin() < 80 && zoneserver_list.IsZoneLocked(zone_id)) { - Log(Logs::General, Logs::World_Server, "Enter world failed. Zone is locked."); - TellClientZoneUnavailable(); - return; - } - auto pack = new ServerPacket; pack->opcode = ServerOP_AcceptWorldEntrance; pack->size = sizeof(WorldToZone_Struct); @@ -1356,6 +1367,7 @@ void Client::TellClientZoneUnavailable() { zone_id = 0; zone_waiting_for_bootup = 0; + enter_world_triggered = false; autobootup_timeout.Disable(); } diff --git a/world/client.h b/world/client.h index e7ab52fa3..4dbad85c5 100644 --- a/world/client.h +++ b/world/client.h @@ -82,6 +82,7 @@ private: bool is_player_zoning; Timer autobootup_timeout; uint32 zone_waiting_for_bootup; + bool enter_world_triggered; bool StartInTutorial; EQEmu::versions::ClientVersion m_ClientVersion; diff --git a/world/zonelist.cpp b/world/zonelist.cpp index 1d06071c4..77782ee9b 100644 --- a/world/zonelist.cpp +++ b/world/zonelist.cpp @@ -708,11 +708,16 @@ void ZSList::WorldShutDown(uint32 time, uint32 interval) } } -void ZSList::DropClient(uint32 lsid) { +void ZSList::DropClient(uint32 lsid, ZoneServer *ignore_zoneserver) { ServerPacket packet(ServerOP_DropClient, sizeof(ServerZoneDropClient_Struct)); auto drop = (ServerZoneDropClient_Struct*)packet.pBuffer; drop->lsid = lsid; - SendPacket(&packet); + + for (auto &zs : zone_server_list) { + if (zs.get() != ignore_zoneserver) { + zs->SendPacket(&packet); + } + } } void ZSList::OnTick(EQ::Timer *t) diff --git a/world/zonelist.h b/world/zonelist.h index b99a88e09..8b8525f57 100644 --- a/world/zonelist.h +++ b/world/zonelist.h @@ -57,7 +57,7 @@ public: void SOPZoneBootup(const char *adminname, uint32 ZoneServerID, const char *zonename, bool iMakeStatic = false); void UpdateUCSServerAvailable(bool ucss_available = true); void WorldShutDown(uint32 time, uint32 interval); - void DropClient(uint32 lsid); + void DropClient(uint32 lsid, ZoneServer *ignore_zoneserver); ZoneServer* FindByPort(uint16 port); ZoneServer* FindByID(uint32 ZoneID);