void OnPlayerConnectionClosed(object sender, PlayerConnectionClosed e) { // Remove callbacks e.Player.OnConnectionClosed -= OnPlayerConnectionClosed; e.Player.OnAwayStatusChanged -= OnPlayerAwayStatusChanged; // Inform players switch (e.CloseReason) { case PlayerCloseReason.Disconnected: EchoActionToAll(e.Player.Data, PlayerAction.Disconnected); break; case PlayerCloseReason.Left: EchoActionToAll(e.Player.Data, PlayerAction.Left); break; case PlayerCloseReason.Kicked: EchoActionToAll(e.Player.Data, PlayerAction.Kicked); break; default: break; } // Remove player var data = RoomData.Players.Find(x => x.ID == e.Player.Data.ID); RoomData.Players.Remove(data); Players.Remove(e.Player); // Return color to pool RoomIdPool.ReturnValue(e.Player.Data.RoomId); if (Players.Count != 0) { // Assign a new owner if (Owner != Players[0]) { Owner = Players[0]; RoomData.Owner = Owner.Data; EchoActionToAll(Owner.Data, PlayerAction.PromotedToOwner); } if (Players.Count < Settings.Values.Server.MinPlayers) { CancelCountdown(); } SendUpdateToAll(); } else { // Remove room if no players remain if (Game != null) { Game.End(); } if (CountdownTimer != null) { CountdownTimer.Stop(); } Logger.Log(this, "Closing room {0} as it is empty", RoomData.ID); ConnectionsHandler.RemoveMessageListener(this); if (OnEmpty != null) { OnEmpty(this, this); } } }