| 1862 | } |
| 1863 | |
| 1864 | void CGameContext::OnClientDrop(int ClientId, const char *pReason) |
| 1865 | { |
| 1866 | LogEvent("Disconnect", ClientId); |
| 1867 | |
| 1868 | AbortVoteKickOnDisconnect(ClientId); |
| 1869 | m_pController->OnPlayerDisconnect(m_apPlayers[ClientId], pReason); |
| 1870 | delete m_apPlayers[ClientId]; |
| 1871 | m_apPlayers[ClientId] = nullptr; |
| 1872 | |
| 1873 | delete m_apSavedTeams[ClientId]; |
| 1874 | m_apSavedTeams[ClientId] = nullptr; |
| 1875 | |
| 1876 | delete m_apSavedTees[ClientId]; |
| 1877 | m_apSavedTees[ClientId] = nullptr; |
| 1878 | |
| 1879 | m_aTeamMapping[ClientId] = -1; |
| 1880 | |
| 1881 | if(g_Config.m_SvTeam == SV_TEAM_FORCED_SOLO && PracticeByDefault()) |
| 1882 | m_pController->Teams().SetPractice(GetDDRaceTeam(ClientId), true); |
| 1883 | |
| 1884 | m_VoteUpdate = true; |
| 1885 | if(m_VoteCreator == ClientId) |
| 1886 | { |
| 1887 | m_VoteCreator = -1; |
| 1888 | } |
| 1889 | |
| 1890 | // update spectator modes |
| 1891 | for(auto &pPlayer : m_apPlayers) |
| 1892 | { |
| 1893 | if(pPlayer && pPlayer->SpectatorId() == ClientId) |
| 1894 | pPlayer->SetSpectatorId(SPEC_FREEVIEW); |
| 1895 | } |
| 1896 | |
| 1897 | // update conversation targets |
| 1898 | for(auto &pPlayer : m_apPlayers) |
| 1899 | { |
| 1900 | if(pPlayer && pPlayer->m_LastWhisperTo == ClientId) |
| 1901 | pPlayer->m_LastWhisperTo = -1; |
| 1902 | } |
| 1903 | |
| 1904 | protocol7::CNetMsg_Sv_ClientDrop Msg; |
| 1905 | Msg.m_ClientId = ClientId; |
| 1906 | Msg.m_pReason = pReason; |
| 1907 | Msg.m_Silent = false; |
| 1908 | Server()->SendPackMsg(&Msg, MSGFLAG_VITAL | MSGFLAG_NORECORD, -1); |
| 1909 | |
| 1910 | Server()->ExpireServerInfo(); |
| 1911 | } |
| 1912 | |
| 1913 | void CGameContext::TeehistorianRecordAntibot(const void *pData, int DataSize) |
| 1914 | { |
no test coverage detected