Instance * ClusterMgr::CreateInstance(uint32 MapId, WServer * server) { Instance * pInstance = new Instance; pInstance->InstanceId = ++m_maxInstanceId; pInstance->MapId = MapId; pInstance->Server = server; Instances.insert( make_pair( pInstance->InstanceId, pInstance ) ); if(IS_MAIN_MAP(MapId)) SingleInstanceMaps[MapId] = pInstance; /* tell the actual server to create the instance */ WorldPacket data(ISMSG_CREATE_INSTANCE, 8); data << MapId << pInstance->InstanceId; server->SendPacket(&data); server->AddInstance(pInstance); Log.Debug("ClusterMgr", "Allocating instance %u on map %u to server %u", pInstance->InstanceId, pInstance->MapId, server->GetID()); return pInstance; }
void Session::HandlePlayerLogin(WorldPacket & pck) { WorldPacket data(SMSG_CHARACTER_LOGIN_FAILED, 30); LocationVector LoginCoord; Instance * dest; ASSERT(!m_currentPlayer); uint64 guid; pck >> guid; if(sClientMgr.GetRPlayer((uint32)guid) != NULL) { data << uint8(CHAR_LOGIN_DUPLICATE_CHARACTER); SendPacket(&data); return; } m_currentPlayer = sClientMgr.CreateRPlayer((uint32)guid); RPlayerInfo * p = m_currentPlayer; sClientMgr.AddSessionRPInfo(this, p); /* Load player data */ QueryResult * result = CharacterDatabase.Query("SELECT acct, name, level, guild_data.guildid, positionX, positionY, zoneId, mapId, race, class, gender, instance_id, entrypointmap, entrypointx, entrypointy, entrypointz, entrypointo, difficulty FROM characters LEFT JOIN guild_data ON characters.guid = guild_data.playerid WHERE guid = %u", guid); if(result) { Field * f = result->Fetch(); p->AccountId = f[0].GetUInt32(); p->Name = f[1].GetString(); p->Level = f[2].GetUInt32(); p->GuildId = f[3].GetUInt32(); p->PositionX = f[4].GetFloat(); p->PositionY = f[5].GetFloat(); p->ZoneId = f[6].GetUInt32(); p->MapId = f[7].GetUInt32(); p->Race = f[8].GetUInt8(); p->Class = f[9].GetUInt8(); p->Gender = f[10].GetUInt8(); p->Latency = m_latency; p->GMPermissions = m_GMPermissions; p->Account_Flags = m_accountFlags; p->InstanceId = f[11].GetUInt32(); p->RecoveryMapId = f[12].GetUInt32(); p->RecoveryPosition.ChangeCoords(f[13].GetFloat(), f[14].GetFloat(), f[15].GetFloat(), f[16].GetFloat()); p->iInstanceType = f[17].GetUInt32(); p->ClientBuild = m_ClientBuild; p->session = this; uint8 team = 0; // work out the side static uint8 teams[12] = { 0, 0, 1, 0, 0, 1, 1, 0, 1, 0, 1, 0 }; team = teams[p->Race]; p->Team = team; delete result; } else { data << uint8(CHAR_LOGIN_NO_CHARACTER); SendPacket(&data); sClientMgr.DestroyRPlayerInfo((uint32)guid); m_currentPlayer = NULL; return; } //now we're here, insert rplayerinfo into string hash map sClientMgr.AddStringPlayerInfo(p); if(IS_MAIN_MAP(m_currentPlayer->MapId)) { /* we're on a continent, try to find the world server we're going to */ dest = sClusterMgr.GetInstanceByMapId(m_currentPlayer->MapId); } else { /* we're in an instanced map, try to find the world server we're going to */ dest = sClusterMgr.GetInstanceByInstanceId(m_currentPlayer->InstanceId); if(dest && dest->MapId != m_currentPlayer->MapId) { /* our instance has been deleted or no longer valid, world server probably crashed */ MapInfo * info = WorldMapInfoStorage.LookupEntry(dest->MapId); if(info) { Log.Error("HandlePlayerLogin", "Instance has been deleted or no longer valid, attempting repop on map %u", info->repopmapid); m_currentPlayer->MapId = info->repopmapid; LoginCoord.x = info->repopx; LoginCoord.y = info->repopy; LoginCoord.z = info->repopz; LoginCoord.o = 0.0f; /* obtain instance */ dest = sClusterMgr.GetInstanceByMapId(m_currentPlayer->MapId); if(dest) { data.SetOpcode(SMSG_NEW_WORLD); data << m_currentPlayer->MapId << LoginCoord << float(0); SendPacket(&data); data.clear(); } else { dest = NULL; Log.Error("HandlePlayerLogin", "Repop failed, could not find instance, for map %u", m_currentPlayer->MapId); } } else { dest = NULL; Log.Error("HandlePlayerLogin", "Repop failed, no map info, for map %u", m_currentPlayer->MapId); } } if(!dest) { Log.Error("HandlePlayerLogin", "Could not find instance, attempting recovery"); /* our instance has been deleted or no longer valid */ m_currentPlayer->MapId = m_currentPlayer->RecoveryMapId; LoginCoord = m_currentPlayer->RecoveryPosition; /* obtain instance */ dest = sClusterMgr.GetInstanceByMapId(m_currentPlayer->MapId); if(dest) { data.SetOpcode(SMSG_NEW_WORLD); data << m_currentPlayer->MapId << m_currentPlayer->RecoveryPosition << float(0); SendPacket(&data); data.clear(); } } } if(dest == NULL || dest->Server == NULL) // Shouldn't happen { Log.Error("CharacterHandler", "World server is down!"); /* world server is down */ data << uint8(CHAR_LOGIN_NO_WORLD); SendPacket(&data); sClientMgr.DestroyRPlayerInfo((uint32)guid); m_currentPlayer = NULL; return; } /* log the player into that WS */ data.SetOpcode(ISMSG_PLAYER_LOGIN); /* append info */ data << uint32(guid) << uint32(dest->MapId) << uint32(dest->InstanceId); /* append the account information */ data << uint32(m_accountId) << uint32(m_accountFlags) << uint32(m_sessionId) << m_GMPermissions << m_accountName << m_ClientBuild; dest->Server->SendPacket(&data); m_nextServer = dest->Server; }
void WServer::HandleTeleportRequest(WorldPacket & pck) { WorldPacket data(ISMSG_TELEPORT_RESULT, 100); RPlayerInfo * pi; Session * s; Instance * dest; uint32 mapid, sessionid, instanceid; /* this packet is only used upon changing main maps! */ pck >> sessionid >> mapid >> instanceid; DEBUG_LOG("TeleportRequest", "session %u, mapid %u, instanceid %u", sessionid, mapid, instanceid); s = sClientMgr.GetSession(sessionid); if(s) { pi = s->GetPlayer(); ASSERT(pi); if(IS_MAIN_MAP(mapid) || instanceid == 0) { /* we're on a continent, try to find the world server we're going to */ dest = sClusterMgr.GetInstanceByMapId(mapid); } else { /* we're in an instanced map, try to find the world server we're going to */ dest = sClusterMgr.GetInstanceByInstanceId(instanceid); } //try and find a prototype instance, and its server if (dest == NULL) { DEBUG_LOG("TeleportRequest", "Could not find instance, will use prototype..."); dest = sClusterMgr.GetPrototypeInstanceByMapId(mapid); } /* server up? */ if(!dest) { DEBUG_LOG("TeleportRequest", "INSTANCE_ABORT_NOT_FOUND"); data.Initialize(SMSG_TRANSFER_ABORTED); data << uint32(0x02); // INSTANCE_ABORT_NOT_FOUND s->SendPacket(&data); } else { /* server found! */ LocationVector vec; pck >> vec >> vec.o; pi->MapId = mapid; pi->InstanceId = dest->InstanceId; pi->PositionX = vec.x; pi->PositionY = vec.y; if(dest->Server == s->GetServer()) { DEBUG_LOG("TeleportRequest", "intra-server teleport"); /* we're not changing servers, the new instance is on the same server */ data << sessionid << uint8(1) << mapid << instanceid << vec << vec.o; SendPacket(&data); } else { DEBUG_LOG("TeleportRequest", "inter-server teleport"); /* notify the old server to pack the player info together to send to the new server, and delete the player */ data << sessionid << uint8(0) << mapid << instanceid << vec << vec.o; //cache this to next server and switch servers when were ready :P s->SetNextServer(dest->Server); SendPacket(&data); } data.Initialize(ISMSG_PLAYER_INFO); pi->Pack(data); sClusterMgr.DistributePacketToAll(&data, this); data.Initialize(SMSG_NEW_WORLD); data << mapid << vec << vec.o; s->SendPacket(&data); } } }
Instance * ClusterMgr::GetInstanceByMapId(uint32 MapId) { ASSERT(IS_MAIN_MAP(MapId)); return SingleInstanceMaps[MapId]; }
WServer * ClusterMgr::GetServerByMapId(uint32 MapId) { ASSERT(IS_MAIN_MAP(MapId)); return SingleInstanceMaps[MapId]->Server; }