/// <summary> /// Handles all logic when player disconnects /// </summary> /// <param name="netId"></param> public static void DisconnectPlayer(ShortGuid netId) { bool removed = false; lock (Players) { if (Players.ContainsKey(netId)) { removed = true; var player = Players[netId]; //player.ClearAllInvites(); LobbyServer.LeaveLobby(player); if (player.IsInGame && player.PlayerState == PlayerState.IN_GAME) { var gamePlayer = player.Game.GetPlayer(player); GameServer.EndGame(gamePlayer.Opponent, gamePlayer, GameResult.PLAYER_DISCONNECTED); } try { Players[netId].Connection.CloseConnection(false); } catch { } Players.Remove(netId); } } if (removed) { LobbyServer.BroadcastPlayerCount(); } }
public static void Bind() { Net.Init(); NetworkComms.AppendGlobalConnectionEstablishHandler((connection) => { // todo: Automatically disconnect after 60 seconds without a handshake }); NetworkComms.AppendGlobalConnectionCloseHandler((connection) => { DisconnectPlayer(connection.GetID()); }); Net.On <C2S_Handshake>((header, connection, obj) => { var response = new S2C_HandshakeResponse(obj.Version == VERSION, IsNicknameValid(obj.Nickname), "OK", null); if (IsValidPlayer(connection.GetID())) { //handshake for second time.. let's disconnect DisconnectPlayer(connection.GetID()); } if (!response.OK) { response.Message = $"Error:\n Version: {response.VersionOK}\n Nickname: {response.NicknameOK}"; if (!response.NicknameOK) { response.Message += "\n Nickname length must be within 3-16 characters and MUST be unique."; } } else { // OK! var player = new RemotePlayer() { Connection = connection, Nickname = obj.Nickname, PlayerState = PlayerState.HANDSHAKE_OK }; response.LocalPlayer = player.GetDisplay(); AddPlayer(player); } connection.Send(response); }); Net.On <C2S_JoinLobby>((header, connection, obj) => { RemotePlayer player; if (IsValidPlayer(connection.GetID(), out player)) { LobbyServer.EnterLobby(player); } }); Net.On <C2S_SendPlayerInvite>((header, connection, obj) => { RemotePlayer source, destination; if (IsValidPlayer(connection.GetID(), out source, PlayerState.IN_LOBBY) && IsValidPlayer(obj.Destination, out destination, PlayerState.IN_LOBBY)) { source.SendInvite(destination); } }); Net.On <C2S_RevokeSentPlayerInvite>((header, connection, obj) => { RemotePlayer source, destination; if (IsValidPlayer(connection.GetID(), out source, PlayerState.IN_LOBBY) && IsValidPlayer(obj.Destination, out destination, PlayerState.IN_LOBBY)) { source.RevokeSentInvite(destination); } }); Net.On <C2S_AcceptIncomingPlayerInvite>((header, connection, obj) => { RemotePlayer source, destination; if (IsValidPlayer(obj.Source, out source, PlayerState.IN_LOBBY) && IsValidPlayer(connection.GetID(), out destination, PlayerState.IN_LOBBY)) { if (source.HasSentInviteTo(destination)) { //We have a pair :) LobbyServer.LeaveLobby(source); LobbyServer.LeaveLobby(destination); GameServer.InitNewGame(source, destination); } } }); Net.On <C2S_GameReady>((header, connection, obj) => { RemotePlayer player; if (IsValidPlayer(connection.GetID(), out player, PlayerState.IN_GAME)) { var p = player.Game.GetPlayer(player); player.Game.OnPlayerReady(p); } }); Net.On <C2S_FireAt>((header, connection, obj) => { RemotePlayer player; if (IsValidPlayer(connection.GetID(), out player, PlayerState.IN_GAME)) { var p = player.Game.GetPlayer(player); p.FireAtEnemy(obj.X, obj.Y); } }); }