/// <summary> /// Removes a match from the list of games that a particular server is tracking - GamesPerServerMap /// </summary> /// <param name="serverName">the server to remove this game from</param> /// <param name="id">the id of the game to remove</param> /// <param name="lockData">if the match data should be thread-synchronized. set yes, if you know this method is called first in the stack (i.e. when you're calling it as a response to an inbound packet). Using the wrong will value will decrease performance as unnecessary thread Monitors will be set</param> public void RemoveGameFromServerTracking(Guid id, bool lockData) { if (lockData) { Monitor.Enter(MatchDataLock); } try { DB.Instance.Lobby_UntrackGameForServer(id); GameServerGame sg = null; if (Games.TryGetValue(id, out sg)) { if (Games.Remove(id)) { Log1.Logger("Server").Info("Removed game [" + id.ToString() + "] from server. Now tracking [" + Games.Count.ToString() + " games] on this server."); } m_TotalProjectedPlayerCount -= sg.MaxObservers + sg.MaxPlayers; Log1.Logger("Server").Debug("Padded connection count for server is now [" + m_TotalProjectedPlayerCount + "]."); } } catch { } finally { if (lockData) { Monitor.Exit(MatchDataLock); } } }
protected virtual GameServerGame OnCreateNewGameServerGame(Game game) { GameServerGame g = new GameServerGame(game); game.Decorator = g; return(g); }
/// <summary> /// Override HandlePacket because we dont want to incur multiple Hashtable looks for game packets /// </summary> /// <param name="p"></param> protected override void HandlePacket(Packet p) { if (p.PacketTypeID == (int)LobbyPacketType.GameMessage) { try { GameServerGame g = ServerUser.CurrentCharacter.GetCurrentGame(); if (g == null) { // drop the packet return; } g.AddGamePacketForProcessing(this, p as PacketGameMessage); } catch { // something went wrong. drop packet. return; } } else { base.HandlePacket(p); } }
public void OnPlayerLeaveGame(INetworkConnection sender, Packet gmsg) { PacketGenericMessage msg = gmsg as PacketGenericMessage; GameServerGame g = ServerUser.CurrentCharacter.GetCurrentGame(); if (g != null) { g.RemovePlayer(ServerUser.CurrentCharacter, "left the game.", true); g.RemoveObserver(ServerUser.CurrentCharacter); } }
/// <summary> /// Adds a match to the GamesPerServerMap list of games that a particular server is tracking /// </summary> /// <param name="serverName">the name of the server to register this game under</param> /// <param name="game">the game to register</param> /// <param name="lockData">if the match data should be thread-synchronized. set yes, if you know this method is called first in the stack (i.e. when you're calling it as a response to an inbound packet). Using the wrong will value will decrease performance as unnecessary thread Monitors will be set</param> public bool CreateNewGame(GameServerGame game, bool lockData) { if (lockData) { Monitor.Enter(MatchDataLock); } try { if (GameCreationRequest != null) { if (!GameCreationRequest(game)) { return(false); } } if (Games.ContainsKey(game.GameID)) { // hm. we already know about that game. probably not great. #if DEBUG throw new ArgumentException("Tried AddGameToServerTracking for a game that we alrady knew about."); #endif return(false); } Games.Add(game.GameID, game); m_TotalProjectedPlayerCount += (game.MaxPlayers + game.MaxObservers); Log1.Logger("Server").Debug("Padded connection count for server is now [" + m_TotalProjectedPlayerCount + "]."); Log1.Logger("Server").Info("After adding this one, we are tracking [" + Games.Count.ToString() + " games] on this server now."); if (GameCreated != null) { GameCreated(game); } } catch { return(false); } finally { if (lockData) { Monitor.Exit(MatchDataLock); } } return(true); }
public void OnRequestStartGame(INetworkConnection sender, Packet gmsg) { PacketGenericMessage msg = gmsg as PacketGenericMessage; msg.ReplyPacket = CreateStandardReply(msg, ReplyType.Failure, ""); try { GameServerGame game = ServerUser.CurrentCharacter.GetCurrentGame(); if (!game.IsPlayerPartOfGame(ServerUser.CurrentCharacter.ID)) { KillConnection("Tried to send game packets to game that we're not part of any more."); return;; } if (!game.GameStartStrategy.CanGameBeStartedManually) { game.SendGameInfoMessageToPlayer(ServerUser.CurrentCharacter, "Game will be started automatically when ready."); return; } if (!game.GameStartStrategy.DoesGameMeetStartConditions) { game.SendGameInfoMessageToPlayer(ServerUser.CurrentCharacter, "Game can't be started yet."); return; } if (game.Owner != ServerUser.CurrentCharacter.ID) { // send a nag message game.BroadcastGameInfoMessage(ServerUser.CurrentCharacter.CharacterName + " is requesting that we begin. Leader, please start game if ready.", true); return; } string tmsg = ""; if (!OnPlayerRequestStartGame(msg, ref tmsg) || !game.StartGame(ref tmsg, true)) { msg.ReplyPacket.ReplyMessage = tmsg; return; } // if it succeeded, no need to send the reply packet as everyone will have received a game started message from game.StartGame() msg.NeedsReply = false; } catch (Exception e) { msg.ReplyPacket.ReplyMessage = "Unknown error occured OnRequestStartGame."; Log.LogMsg("[" + ServerUser.AccountName + "] failed to start game. " + e.Message); } }
protected override void OnSocketKilled(string msg) { if (ServerUser != null && ServerUser.CurrentCharacter != null) { GameServerGame gsg = ServerUser.CurrentCharacter.GetCurrentGame(); if (gsg != null) { gsg.RemovePlayer(ServerUser.CurrentCharacter, "Disconnected.", true); gsg.RemoveObserver(ServerUser.CurrentCharacter); } CharacterCache.UncacheCharacter(ServerUser.CurrentCharacter.ID); } base.OnSocketKilled(msg); DB.Instance.Server_Register(MyServer.ServerUserID, MyServer.ServerAddress, MyServer.ListenOnPort, DateTime.UtcNow, "content", ConnectionManager.PaddedConnectionCount, MyServer.MaxConnections); }
public void SendMatchChangeNotificationToPlayers(MatchNotificationType kind, GameServerGame theGame, ServerCharacterInfo targetPlayer) { string text = ""; switch (kind) { case MatchNotificationType.PlayerRemoved: text = "Goodbye, " + targetPlayer.CharacterName; break; case MatchNotificationType.PlayerAdded: text = "Welcome, " + targetPlayer.CharacterName; break; case MatchNotificationType.MatchEnded: text = "Game '" + theGame.Name + "' ended."; break; } theGame.SendMatchChangeNotificationToPlayers(kind, targetPlayer, text, false); }
/// <summary> /// Gets the game, if this server knows about, regardless if it's local or not /// </summary> /// <param name="game">the id of the game we want to fetch</param> /// <param name="sg">the game, if we found it</param> /// <returns>true if we know about the game, false otherwise</returns> public bool GetGame(Guid game, out GameServerGame sg) { return(Games.TryGetValue(game, out sg)); }
protected override bool OnPlayerLoginResolved(PacketLoginRequest login, bool result, ref string msg) { ///............. if (!base.OnPlayerLoginResolved(login, result, ref msg)) { return(result); } if (ServerUser.CurrentCharacter == null) { msg = "Can't join or create games without an active character."; return(false); } Guid gameId = Guid.Empty; GameServerGame sg = null; PacketMatchNotification note = (PacketMatchNotification)CreatePacket((int)LobbyPacketType.MatchNotification, 0, false, false); // Requesting to join as observer? bool observeOnly = login.Parms.GetBoolProperty("Observe").GetValueOrDefault(false); if (login.Parms.GetBoolProperty("IsNewGame").GetValueOrDefault(false)) { Log1.Logger("Server").Debug("Player [" + ServerUser.AccountName + "] logging in with NEW GAME request."); note.Kind = MatchNotificationType.MatchCreated; note.NeedsReply = false; note.ReplyCode = ReplyType.Failure; // new game. create it. Game g = new Game(); g.Name = login.Parms.GetStringProperty((int)PropertyID.Name); g.MaxPlayers = login.Parms.GetIntProperty((int)PropertyID.MaxPlayers).GetValueOrDefault(1); g.MaxObservers = login.Parms.GetIntProperty((int)PropertyID.MaxObservers).GetValueOrDefault(0); g.Owner = ServerUser.CurrentCharacter.ID; // Create the actual game object, specific to the game type we are serving. sg = OnCreateNewGameServerGame(g); //sg = null; if (sg != null) { // Track the new game object on this server if (!GameManager.Instance.CreateNewGame(sg, true)) { msg = "Failed to create game on server. Internal server error."; note.ReplyMessage = msg; Send(note); TransferToLobbyOrDisconnect(); return(true); } // Report the new game in the database if (!DB.Instance.Lobby_TrackGameForServer(MyServer.ServerUserID, sg, DateTime.UtcNow, ServerUser)) { msg = "Failed to register the game in the database. Internal server error."; note.ReplyMessage = msg; Send(note); TransferToLobbyOrDisconnect(); return(true); } // Update player counts for this server, based on the expected player count for the new game. if (DB.Instance.Server_Register(MyServer.ServerUserID, MyServer.ServerAddress, MyServer.ListenOnPort, DateTime.UtcNow, "content", ConnectionManager.PaddedConnectionCount, MyServer.MaxConnections)) { note.ReplyCode = ReplyType.OK; } else { DB.Instance.Lobby_UntrackGameForServer(sg.GameID); note.ReplyMessage = "Failed to register game with master game listing. Internal server error."; Send(note); TransferToLobbyOrDisconnect(); return(true); } } else { msg = "Unable to create game at this time."; Log1.Logger("Server").Debug("Failed to create NEW GAME for player [" + ServerUser.AccountName + "]."); login.ReplyPacket.Parms.SetProperty("CreateReply", msg); note.ReplyMessage = msg; Send(note); TransferToLobbyOrDisconnect(); return(true); } } else // it's a join - get game reference from existing games table { Log1.Logger("Server").Debug("Player [" + ServerUser.AccountName + "] logging in with request to JOIN EXISTING game. [Observe = " + observeOnly.ToString() + "]"); note = (PacketMatchNotification)CreatePacket((int)LobbyPacketType.MatchNotification, 0, false, false); if (observeOnly) { note.Kind = MatchNotificationType.ObserverAdded; } else { note.Kind = MatchNotificationType.PlayerAdded; } note.TargetPlayer = ServerUser.CurrentCharacter.CharacterInfo; note.ReplyCode = ReplyType.Failure; Guid targetGame = login.Parms.GetGuidProperty((int)PropertyID.GameId); if (targetGame == Guid.Empty) { msg = "Failed to join game. No target game specified."; Log1.Logger("Server").Debug("Player [" + ServerUser.AccountName + "] failed to JOIN EXISTING game. No target game specified in join request."); note.ReplyMessage = msg; Send(note); TransferToLobbyOrDisconnect(); return(true); } if (!GameManager.Instance.GetGame(targetGame, out sg)) { Log1.Logger("Server").Debug("Player [" + ServerUser.AccountName + "] failed to JOIN EXISTING game. Target game specified does not currently exist."); msg = "Failed to join game. Target game [" + targetGame.ToString() + "] does not currently exist on [" + MyServer.ServerUserID + "]."; note.ReplyMessage = msg; Send(note); TransferToLobbyOrDisconnect(); return(true); } } if (sg == null) { Log1.Logger("Server").Debug("Player [" + ServerUser.AccountName + "] failed to locate game. Internal Server Error."); msg = "Unable to locate game. Internal Server Error."; // should never happen note.ReplyMessage = msg; Send(note); TransferToLobbyOrDisconnect(); return(true); } // join game as player or observer if (!observeOnly && sg.AddPlayer(ServerUser.CurrentCharacter, ref msg)) { login.ReplyPacket.Parms.SetProperty("TargetGame", (ISerializableWispObject)sg.Game); RegisterPacketHandler((int)PacketType.PacketGenericMessage, (int)GenericLobbyMessageType.RequestStartGame, OnRequestStartGame); } else if (observeOnly && sg.AddObserver(ServerUser.CurrentCharacter, ref msg)) { login.ReplyPacket.Parms.SetProperty("TargetGame", (ISerializableWispObject)sg.Game); } else { msg = "Unable to join game."; note.ReplyMessage = msg; Send(note); TransferToLobbyOrDisconnect(); return(true); } RegisterPacketHandler((int)PacketType.PacketGenericMessage, (int)GenericLobbyMessageType.LeaveGame, OnPlayerLeaveGame); return(result); }
/// <summary> /// Sets a reference to the game that the character is currently attached to /// </summary> /// <param name="toon"></param> /// <param name="curGame"></param> public static void SetCurrentGame(this ServerCharacterInfo toon, GameServerGame curGame) { toon.Properties.SetProperty("CurrentGame", curGame); toon.Properties.SetLocalFlag("CurrentGame", true); }
/// <summary> /// Returns a reference to the game that the character is attached to /// </summary> /// <param name="toon"></param> /// <returns></returns> public static GameServerGame GetCurrentGame(this ServerCharacterInfo toon) { GameServerGame g = toon.Properties.GetComponentProperty("CurrentGame") as GameServerGame; return(g); }