public override ErrorCode TryGetRandomGame(JoinRandomGameRequest joinRequest, ILobbyPeer peer, out GameState gameState, out string message) { message = null; foreach (GameState game in this.gameDict) { if (!game.IsOpen || !game.IsVisible || !game.HasBeenCreatedOnGameServer || (game.MaxPlayer > 0 && game.PlayerCount >= game.MaxPlayer)) { continue; } if (joinRequest.GameProperties != null && game.MatchGameProperties(joinRequest.GameProperties) == false) { continue; } if (game.CheckUserIdOnJoin && (game.ContainsUser(peer.UserId) || game.IsUserInExcludeList(peer.UserId) || !game.CheckSlots(peer.UserId, joinRequest.AddUsers))) { continue; } gameState = game; return(ErrorCode.Ok); } gameState = null; return(ErrorCode.NoMatchFound); }
public override ErrorCode TryGetRandomGame(JoinRandomGameRequest joinRequest, ILobbyPeer peer, out GameState gameState, out string message) { message = null; if (this.gameDict.Count == 0) { gameState = null; return(ErrorCode.NoMatchFound); } if (string.IsNullOrEmpty(joinRequest.QueryData)) { var node = this.gameDict.First; while (node != null) { gameState = node.Value; if (gameState.IsJoinable) { if (!gameState.CheckUserIdOnJoin || (!gameState.ContainsUser(peer.UserId) && !gameState.IsUserInExcludeList(peer.UserId) && gameState.CheckSlots(peer.UserId, joinRequest.AddUsers))) { return(ErrorCode.Ok); } } node = node.Next; } gameState = null; return(ErrorCode.NoMatchFound); } string id; try { id = this.gameDatabase.FindMatch(joinRequest.QueryData); } catch (System.Data.Common.DbException sqlException) { gameState = null; message = sqlException.Message; return(ErrorCode.OperationInvalid); } if (string.IsNullOrEmpty(id)) { gameState = null; return(ErrorCode.NoMatchFound); } if (!this.gameDict.TryGet(id, out gameState)) { return(ErrorCode.NoMatchFound); } return(ErrorCode.Ok); }
public OperationResponse HandleJoinRandomGame(OperationRequest operationRequest, SendParameters sendParameters) { var joinRandomGameRequest = new JoinRandomGameRequest(this.Protocol, operationRequest); OperationResponse response; if (OperationHelper.ValidateOperation(joinRandomGameRequest, log, out response) == false) { return(response); } if (string.IsNullOrEmpty(joinRandomGameRequest.LobbyName) && this.AppLobby != null) { this.AppLobby.EnqueueOperation(this, operationRequest, sendParameters); return(null); } AppLobby lobby; if (!this.Application.LobbyFactory.GetOrCreateAppLobby(joinRandomGameRequest.LobbyName, (AppLobbyType)joinRandomGameRequest.LobbyType, out lobby)) { return(new OperationResponse { OperationCode = operationRequest.OperationCode, ReturnCode = (int)ErrorCode.OperationDenied, DebugMessage = "Lobby does not exist" }); } lobby.EnqueueOperation(this, operationRequest, sendParameters); return(null); }
private bool TryGetRandomGame(LinkedListNode <GameState> startNode, JoinRandomGameRequest joinRequest, ILobbyPeer peer, out GameState gameState) { var node = startNode; do { var game = node.Value; node = node.Next ?? this.gameDict.First; if (!IsGameJoinable(joinRequest, peer, game)) { continue; } if (joinRequest.GameProperties != null && game.MatchGameProperties(joinRequest.GameProperties) == false) { continue; } if (log.IsDebugEnabled) { log.DebugFormat("Found match. Next start node gameid={0}", node.Value.Id); } this.nextJoinRandomStartNode = node; gameState = game; return(true); }while (node != startNode); gameState = null; return(false); }
public virtual OperationResponse HandleJoinRandomGame(OperationRequest operationRequest, SendParameters sendParameters) { var response = this.CheckJoinActivity(operationRequest); if (response != null) { return(response); } var joinRandomGameRequest = new JoinRandomGameRequest(this.Protocol, operationRequest); if (OperationHelper.ValidateOperation(joinRandomGameRequest, log, out response) == false) { return(response); } AppLobby lobby; response = this.TryGetLobby(joinRandomGameRequest.LobbyName, joinRandomGameRequest.LobbyType, operationRequest.OperationCode, out lobby); if (response != null) { return(response); } this.IncConcurrentJoinRequest(1); lobby.EnqueueOperation(this, operationRequest, sendParameters); return(null); }
public JoinRandomGameResponse JoinRandomGame(JoinRandomGameRequest request, short expectedResult, params string[] expectedRoomNames) { var operationRequest = new OperationRequest(); operationRequest.OperationCode = OperationCode.JoinRandomGame; operationRequest.Parameters = new Dictionary <byte, object>(); if (request.GameProperties != null) { operationRequest.Parameters[ParameterCode.GameProperties] = request.GameProperties; } if (request.QueryData != null) { operationRequest.Parameters[(byte)Operations.ParameterCode.Data] = request.QueryData; } if (request.JoinRandomType != 0) { operationRequest.Parameters[ParameterCode.MatchMakingType] = request.JoinRandomType; } if (request.LobbyName != null) { operationRequest.Parameters[(byte)Operations.ParameterCode.LobbyName] = request.LobbyName; } if (request.LobbyType != 0) { operationRequest.Parameters[(byte)Operations.ParameterCode.LobbyType] = request.LobbyType; } var response = this.SendRequestAndWaitForResponse(operationRequest, expectedResult); var joinRandomResponse = GetJoinRandomGameResponse(response); if (expectedResult != ErrorCode.Ok) { return(joinRandomResponse); } if (expectedRoomNames == null || expectedRoomNames.Length == 0) { return(joinRandomResponse); } foreach (var id in expectedRoomNames) { if (id == joinRandomResponse.GameId) { return(joinRandomResponse); } } Assert.Fail("Unexpected game on join random: gameId={0}", joinRandomResponse.GameId); return(joinRandomResponse); }
private void JoinRandom(Hashtable properties) { if (log.IsDebugEnabled) { log.Debug("MASTER: Joining random game ..."); } var operation = new JoinRandomGameRequest { GameProperties = properties }; var request = new OperationRequest((byte)Operations.OperationCode.JoinRandomGame, operation); this.masterClient.SendOperationRequest(request, new SendParameters()); }
protected virtual OperationResponse HandleJoinRandomGame(MasterClientPeer peer, OperationRequest operationRequest) { // validate the operation request var operation = new JoinRandomGameRequest(peer.Protocol, operationRequest); OperationResponse response; if (OperationHelper.ValidateOperation(operation, log, out response) == false) { return(response); } // special handling for game properties send by AS3/Flash (Amf3 protocol) clients if (peer.Protocol.ProtocolType == ProtocolType.Amf3V152 || peer.Protocol.ProtocolType == ProtocolType.Json) { Utilities.ConvertAs3WellKnownPropertyKeys(operation.GameProperties, null); } // try to find a match GameState game; string errorMessage; var result = this.GameList.TryGetRandomGame((JoinRandomType)operation.JoinRandomType, peer, operation.GameProperties, operation.QueryData, out game, out errorMessage); if (result != ErrorCode.Ok) { if (string.IsNullOrEmpty(errorMessage)) { errorMessage = "No match found"; } response = new OperationResponse { OperationCode = operationRequest.OperationCode, ReturnCode = (short)result, DebugMessage = errorMessage }; return(response); } // match found, add peer to game and notify the peer game.AddPeer(peer); if (log.IsDebugEnabled) { log.DebugFormat("Found match: connectionId={0}, userId={1}, gameId={2}", peer.ConnectionId, peer.UserId, game.Id); } this.ScheduleCheckJoinTimeOuts(); object joinResponse = this.GetJoinRandomGameResponse(peer, game); return(new OperationResponse(operationRequest.OperationCode, joinResponse)); }
protected static bool IsGameJoinable(JoinRandomGameRequest joinRequest, ILobbyPeer peer, GameState gameState) { if (!gameState.IsJoinable) { return(false); } if (!gameState.SupportsProtocol(peer.NetworkProtocol)) { return(false); } return(!gameState.CheckUserIdOnJoin || (!gameState.ContainsUser(peer.UserId) && !gameState.IsUserInExcludeList(peer.UserId) && gameState.CheckSlots(peer.UserId, joinRequest.AddUsers))); }
public JoinRandomGameResponse JoinRandomGame(Hashtable gameProperties, byte maxPlayers, Hashtable actorProperties, MatchmakingMode mode, string lobbyName, AppLobbyType lobbyType, string sqlLobbyFilter, short errorCode = ErrorCode.Ok) { var request = new JoinRandomGameRequest { GameProperties = new Hashtable(), JoinRandomType = (byte)mode, LobbyType = (byte)lobbyType, LobbyName = lobbyName, }; if (maxPlayers > 0) { request.GameProperties.Add(GamePropertyKey.MaxPlayers, maxPlayers); } return(this.JoinRandomGame(request, errorCode)); }
private ErrorCode TryGetRandomGame(string queryData, JoinRandomGameRequest joinRequest, ILobbyPeer peer, out GameState gameState, out string message) { message = null; int skipCount = 0; while (true) { string id; try { id = this.gameDatabase.FindMatch(queryData, skipCount++); } catch (DbException sqlException) { gameState = null; message = sqlException.Message; return(ErrorCode.OperationInvalid); } if (string.IsNullOrEmpty(id)) { gameState = null; return(ErrorCode.NoMatchFound); } if (!this.gameDict.TryGet(id, out gameState)) { return(ErrorCode.NoMatchFound); } if (IsGameJoinable(joinRequest, peer, gameState)) { if (log.IsDebugEnabled) { log.Debug($"Random Game '{gameState}', CheckUserOnJoin:{gameState.CheckUserIdOnJoin}, " + $"UserLists: {gameState.GetUserListsAsString()} Properties:{ValueToString.ToString(gameState.ToHashTable())}" + $"is joinable for request: {ValueToString.OperationToString(joinRequest.OperationRequest)}, Joining User:{peer.UserId}"); } return(ErrorCode.Ok); } } }
protected virtual OperationResponse HandleJoinRandomGame(MasterClientPeer peer, OperationRequest operationRequest) { // validate the operation request var operation = new JoinRandomGameRequest(peer.Protocol, operationRequest); OperationResponse response; if (OperationHelper.ValidateOperation(operation, log, out response) == false) { return(response); } // try to find a match GameState game; string errorMessage; var result = this.GameList.TryGetRandomGame(operation, peer, out game, out errorMessage); if (result != ErrorCode.Ok) { if (string.IsNullOrEmpty(errorMessage)) { errorMessage = "No match found"; } response = new OperationResponse { OperationCode = operationRequest.OperationCode, ReturnCode = (short)result, DebugMessage = errorMessage }; return(response); } // match found, add peer to game and notify the peer game.AddPeer(peer); if (log.IsDebugEnabled) { log.DebugFormat("Found match: connectionId={0}, userId={1}, gameId={2}", peer.ConnectionId, peer.UserId, game.Id); } this.ScheduleCheckJoinTimeOuts(); object joinResponse = this.GetJoinRandomGameResponse(peer, game); return(new OperationResponse(operationRequest.OperationCode, joinResponse)); }
private ErrorCode GetFirstJoinableGame(JoinRandomGameRequest joinRequest, ILobbyPeer peer, out GameState gameState) { var node = this.gameDict.First; while (node != null) { gameState = node.Value; if (IsGameJoinable(joinRequest, peer, gameState)) { log.Debug($"First Joinable Game '{gameState}', CheckUserOnJoin:{gameState.CheckUserIdOnJoin}, " + $"UserLists: {gameState.GetUserListsAsString()} Properties:{ValueToString.ToString(gameState.ToHashTable())}" + $"is joinable for request: {ValueToString.OperationToString(joinRequest.OperationRequest)}, Joining User:{peer.UserId}"); return(ErrorCode.Ok); } node = node.Next; } gameState = null; return(ErrorCode.NoMatchFound); }
private bool TryGetRandomGame(LinkedListNode <GameState> startNode, JoinRandomGameRequest joinRequest, ILobbyPeer peer, out GameState gameState) { var node = startNode; do { var game = node.Value; node = node.Next ?? this.gameDict.First; if (!game.IsOpen || !game.IsVisible || !game.HasBeenCreatedOnGameServer || (game.MaxPlayer > 0 && game.PlayerCount >= game.MaxPlayer)) { continue; } if (joinRequest.GameProperties != null && game.MatchGameProperties(joinRequest.GameProperties) == false) { continue; } if (game.CheckUserIdOnJoin && (game.ContainsUser(peer.UserId) || game.IsUserInExcludeList(peer.UserId) || !game.CheckSlots(peer.UserId, joinRequest.AddUsers))) { continue; } if (log.IsDebugEnabled) { log.DebugFormat("Found match. Next start node gameid={0}", node.Value.Id); } this.nextJoinRandomStartNode = node; gameState = game; return(true); }while (node != startNode); gameState = null; return(false); }
public OperationResponse HandleJoinRandomGame(OperationRequest operationRequest, SendParameters sendParameters) { var joinRandomGameRequest = new JoinRandomGameRequest(this.Protocol, operationRequest); OperationResponse response; if (OperationHelper.ValidateOperation(joinRandomGameRequest, log, out response) == false) { return(response); } AppLobby lobby; response = this.TryGetLobby(joinRandomGameRequest.LobbyName, joinRandomGameRequest.LobbyType, operationRequest.OperationCode, out lobby); if (response != null) { return(response); } lobby.EnqueueOperation(this, operationRequest, sendParameters); return(null); }
public override ErrorCode TryGetRandomGame(JoinRandomGameRequest joinRequest, ILobbyPeer peer, out GameState gameState, out string message) { message = null; if (this.gameDict.Count == 0) { gameState = null; return(ErrorCode.NoMatchFound); } LinkedListNode <GameState> startNode; switch ((JoinRandomType)joinRequest.JoinRandomType) { default: case JoinRandomType.FillRoom: startNode = this.gameDict.First; break; case JoinRandomType.SerialMatching: startNode = this.nextJoinRandomStartNode ?? this.gameDict.First; break; case JoinRandomType.RandomMatching: var startNodeIndex = this.rnd.Next(this.gameDict.Count); startNode = this.gameDict.GetAtIndex(startNodeIndex); break; } if (!TryGetRandomGame(startNode, joinRequest, peer, out gameState)) { return(ErrorCode.NoMatchFound); } return(ErrorCode.Ok); }
public abstract ErrorCode TryGetRandomGame(JoinRandomGameRequest joinRequest, ILobbyPeer peer, out GameState gameState, out string message);
public override ErrorCode TryGetRandomGame(JoinRandomGameRequest joinRequest, ILobbyPeer peer, out GameState gameState, out string message) { message = null; gameState = null; if (this.gameDict.Count == 0) { // gameState = null; return(ErrorCode.NoMatchFound); } if (string.IsNullOrEmpty(joinRequest.QueryData)) { return(GetFirstJoinableGame(joinRequest, peer, out gameState)); // var node = this.gameDict.First; // while (node != null) // { // gameState = node.Value; // if (IsGameJoinable(joinRequest, peer, gameState)) // { // return ErrorCode.Ok; // } // // node = node.Next; // } // //// gameState = null; // return ErrorCode.NoMatchFound; } if (!useStoredProcedures) { //remove last semicolon, otherwise we have another (empty) query after split if (joinRequest.QueryData.EndsWith(";")) { joinRequest.QueryData = joinRequest.QueryData.Remove(joinRequest.QueryData.Length - 1); } var splitQueries = joinRequest.QueryData.Split(';'); //create a setting for max numbers of queries? if (splitQueries.Length > 3) { //create entry in ErrorMessages? message = "Max queries allowed: 3"; return(ErrorCode.OperationInvalid); } foreach (var query in splitQueries) { if (string.IsNullOrEmpty(query)) { //error or ignore? continue; // message = "Query was empty"; // return ErrorCode.OperationInvalid; } var result = TryGetRandomGame(query, joinRequest, peer, out gameState, out message); if (result != ErrorCode.NoMatchFound) { //match or error return(result); } } //no match, check options // return joinRequest.JoinRandomType == (byte)JoinRandomType.JoinRandomOnSqlNoMatch // ? GetFirstJoinableGame(joinRequest, peer, out gameState) // : ErrorCode.NoMatchFound; return(ErrorCode.NoMatchFound); // return TryGetRandomGame(joinRequest.QueryData, joinRequest, peer, out gameState, out message); } //obsolete soon //TODO const //TODO decide stored procedure prefix var spPrefix = "$SP."; var spName = joinRequest.QueryData; //temp, until the prefix is removed if (joinRequest.QueryData.StartsWith(spPrefix, StringComparison.InvariantCultureIgnoreCase)) { spName = joinRequest.QueryData.Substring(spPrefix.Length).ToLower(); } if (!storedProcedures.ContainsKey(spName) || string.IsNullOrEmpty(storedProcedures[spName])) { if (log.IsDebugEnabled) { log.DebugFormat("Stored procedure '{0}' not found", spName); } message = "Stored procedure not found"; return(ErrorCode.OperationInvalid); } var queryData = storedProcedures[spName]; //TODO const //TODO decide value // var authCookiePlaceholderPrefix = "$ac."; const char placeholderStart = '['; const char placeholderEnd = ']'; //replace placeholder values from AuthCookie //just call string.Replace for all values in the AuthCookie? var masterClientPeer = (MasterClientPeer)peer; queryData = ReplacePlaceholderIgnoreCase(queryData, masterClientPeer.AuthCookie); // if (queryData.IndexOf(authCookiePlaceholderPrefix, StringComparison.InvariantCultureIgnoreCase) >= 0) if (queryData.IndexOf(placeholderStart) >= 0 || queryData.IndexOf(placeholderEnd) >= 0) { if (log.IsDebugEnabled) { log.DebugFormat("Stored procedure '{0}' contains placeholder entries not found in AuthCookie", spName); } message = "Stored procedure contains placeholder entries not found in AuthCookie"; return(ErrorCode.OperationInvalid); } //strip last semicolon in case one was added to end of stored procedure > already done when reading file // if (queryData.EndsWith(";")) // { // queryData = queryData.Substring(0, queryData.Length - 1); // } //TODO decide delimiter. using semicolon means that funnels can only be used with stored procedures (if client sends semicolon a NotAllowedSemicolonInQuereyData is returned) var queries = queryData.Split(';'); var errorCode = ErrorCode.NoMatchFound; //TODO const //TODO max number of queries var limit = 10; for (int i = 0; i < queries.Length; i++) { if (log.IsDebugEnabled) { log.DebugFormat("Searching match, index {0}, query '{1}'", i, queries[i]); } errorCode = TryGetRandomGame(queries[i], joinRequest, peer, out gameState, out message); if (errorCode != ErrorCode.NoMatchFound || i >= limit - 1) { break; } } return(errorCode); }
public JoinRandomGameResponse JoinRandomGame(JoinRandomGameRequest request, short expectedResult, params string[] expectedRoomNames) { var operationRequest = CreateOperationRequest(OperationCode.JoinRandomGame); if (request.GameProperties != null) { operationRequest.Parameters[ParameterCode.GameProperties] = request.GameProperties; } if (request.QueryData != null) { operationRequest.Parameters[ParameterCode.Data] = request.QueryData; } if (request.JoinRandomType != 0) { operationRequest.Parameters[ParameterCode.MatchMakingType] = request.JoinRandomType; } if (request.LobbyName != null) { operationRequest.Parameters[ParameterCode.LobbyName] = request.LobbyName; } if (request.LobbyType != 0) { operationRequest.Parameters[ParameterCode.LobbyType] = request.LobbyType; } if (request.AddUsers != null) { operationRequest.Parameters[ParameterCode.Add] = request.AddUsers; } var response = this.SendRequestAndWaitForResponse(operationRequest, expectedResult); this.authenticationScheme.HandleAuthenticateResponse(this, response.Parameters); var joinRandomResponse = GetJoinRandomGameResponse(response); if (expectedResult != ErrorCode.Ok) { return(joinRandomResponse); } if (expectedRoomNames == null || expectedRoomNames.Length == 0) { return(joinRandomResponse); } foreach (var id in expectedRoomNames) { if (id == joinRandomResponse.GameId) { return(joinRandomResponse); } } Assert.Fail("Unexpected game on join random: gameId={0}", joinRandomResponse.GameId); return(joinRandomResponse); }
protected virtual OperationResponse HandleJoinRandomGame(MasterClientPeer peer, OperationRequest operationRequest) { // validate the operation request var operation = new JoinRandomGameRequest(peer.Protocol, operationRequest); OperationResponse response; if (OperationHelper.ValidateOperation(operation, log, out response) == false) { return(response); } // try to find a match GameState game; string errorMessage; var result = this.GameList.TryGetRandomGame(operation, peer, out game, out errorMessage); //create game if (result == ErrorCode.NoMatchFound && operation.CreateIfNotExists) { //random GameId if not set if (string.IsNullOrEmpty(operation.GameId)) { operation.GameId = Guid.NewGuid().ToString(); operationRequest.Parameters[(byte)ParameterKey.GameId] = operation.GameId; } //replace GameProperties (used for filter) with values for game creation if (operation.Properties != null) { operationRequest.Parameters[(byte)ParameterKey.GameProperties] = operation.Properties; } //create - we try to use current HandleCreateGame implementation var createGameResponse = HandleCreateGame(peer, operationRequest); if (createGameResponse.ReturnCode != 0) { return(new OperationResponse { OperationCode = operationRequest.OperationCode, ReturnCode = createGameResponse.ReturnCode, DebugMessage = createGameResponse.DebugMessage }); } var joinRandomGameResponse = new JoinRandomGameResponse { GameId = operation.GameId, Address = (string)createGameResponse.Parameters[(byte)ParameterKey.Address], }; //NodeId is not used anywhere atm if (createGameResponse.Parameters.ContainsKey((byte)ParameterKey.NodeId)) { joinRandomGameResponse.NodeId = (byte)createGameResponse.Parameters[(byte)ParameterKey.NodeId]; } return(new OperationResponse(operationRequest.OperationCode, joinRandomGameResponse) { //TODO other ReturnCode if game was created ReturnCode = (byte)ErrorCode.Ok }); } if (result != ErrorCode.Ok) { if (string.IsNullOrEmpty(errorMessage)) { errorMessage = "No match found"; } response = new OperationResponse { OperationCode = operationRequest.OperationCode, ReturnCode = (short)result, DebugMessage = errorMessage }; return(response); } // match found, add peer to game and notify the peer game.AddPeer(peer); if (log.IsDebugEnabled) { log.DebugFormat("Found match: connectionId={0}, userId={1}, gameId={2}", peer.ConnectionId, peer.UserId, game.Id); } this.ScheduleCheckJoinTimeOuts(); var joinResponse = this.GetJoinRandomGameResponse(peer, game); return(new OperationResponse(operationRequest.OperationCode, joinResponse)); }