Beispiel #1
0
        public async Task <IActionResult> FireCannon([FromBody] P2PFireCannonDto dto)
        {
            if (string.IsNullOrWhiteSpace(dto.ConnectionId))
            {
                return(BadRequest());
            }

            if (string.IsNullOrWhiteSpace(dto.Code))
            {
                return(BadRequest());
            }

            PeerToPeerSessionState session = await _p2pSvc.FindActiveSessionAsync(dto.Code, dto.ConnectionId);

            if (session == null)
            {
                return(BadRequest());
            }

            var connectionId = dto.ConnectionId == session.HostConnectionId ? session.FriendConnectionId : session.HostConnectionId;

            FireCannonDto srDto = new FireCannonDto
            {
                GameId = session.GameId,
                CellId = dto.CellId
            };

            await _gameHubContext.Clients.Client(connectionId).SendAsync("MakeFireFromServer", srDto);

            return(Ok(new { }));
        }
Beispiel #2
0
        public async Task <IActionResult> RestartGame([FromBody] P2PGameKeyDto dto)
        {
            if (string.IsNullOrWhiteSpace(dto.Code))
            {
                return(BadRequest());
            }

            if (string.IsNullOrWhiteSpace(dto.ConnectionId))
            {
                return(BadRequest());
            }

            PeerToPeerSessionState session = await _p2pSvc.FindActiveSessionAsync(dto.Code, dto.ConnectionId);

            if (session == null)
            {
                return(BadRequest());
            }

            //only host can restart game for now
            if (dto.ConnectionId != session.HostConnectionId)
            {
                return(BadRequest());
            }

            session = await _p2pSvc.RestartGameAsync(session);

            await _gameHubContext.Clients.Client(session.FriendConnectionId).SendAsync("RestartGame");

            return(Ok(new { }));
        }
        public async Task RestartGame_Ok()
        {
            var p2pSvc  = new Mock <IPeerToPeerGameService>();
            var session = new PeerToPeerSessionState()
            {
                Code = "12345", HostConnectionId = "c1",
            };

            p2pSvc.Setup(x => x.FindActiveSessionAsync(It.IsAny <string>(), It.IsAny <string>()))
            .ReturnsAsync(session);

            p2pSvc.Setup(x => x.RestartGameAsync(It.IsAny <PeerToPeerSessionState>()))
            .ReturnsAsync(session);

            var controller = new PeerToPeerGameController(p2pSvc.Object, _mapper, _signalRHub.Object, _logger.Object);

            var output = await controller.RestartGame(new P2PGameKeyDto { Code = "12345", ConnectionId = "c1" });

            p2pSvc.Verify(p => p.FindActiveSessionAsync(It.IsAny <string>(), It.IsAny <string>()), Times.Once);
            p2pSvc.Verify(p => p.RestartGameAsync(It.IsAny <PeerToPeerSessionState>()), Times.Once);

            _signalRHub.VerifyGet(p => p.Clients, Times.Once);

            Assert.AreEqual(output.GetType(), typeof(OkObjectResult));
        }
        public async Task <PeerToPeerSessionState> UpdateP2PSessionAsync(PeerToPeerSessionState p2pSession)
        {
            //TODO: Implement
            await Task.FromResult(0);

            throw new NotImplementedException();
        }
        public virtual async Task <PeerToPeerSessionState> StartNewGameAsync(PeerToPeerSessionState session)
        {
            PeerToPeerGameState game = PeerToPeerGameState.CreateNew();

            session.GameId = game.GameId;

            game = await _storage.AddP2PGameAsync(game);

            return(await _storage.UpdateP2PSessionAsync(session));
        }
        public async Task StartNewSessionAsync_Ok()
        {
            PeerToPeerGameService svc = new PeerToPeerGameService(_storage.Object);

            _storage.Setup(p => p.AddP2PSessionAsync(It.IsAny <PeerToPeerSessionState>())).ReturnsAsync(new PeerToPeerSessionState());

            PeerToPeerSessionState res = await svc.StartNewSessionAsync("connectionId");

            _storage.Verify(p => p.AddP2PSessionAsync(It.IsAny <PeerToPeerSessionState>()), Times.Once);

            Assert.IsNotNull(res);
        }
        public async Task <PeerToPeerSessionState> StartNewSessionAsync(string hostConnectionId)
        {
            //fallback afer 1000 tries if game is super popular :)
            string code = await GenerateCode() ?? hostConnectionId;

            PeerToPeerSessionState session = new PeerToPeerSessionState()
            {
                HostConnectionId = hostConnectionId,
                Code             = code
            };

            return(await _storage.AddP2PSessionAsync(session));
        }
Beispiel #8
0
        public async Task <IActionResult> StartSession([FromBody] string connectionId)
        {
            if (string.IsNullOrWhiteSpace(connectionId))
            {
                return(BadRequest());
            }

            PeerToPeerSessionState g = await _p2pSvc.StartNewSessionAsync(connectionId);

            return(Ok(new P2PStartSessionDto {
                Code = g.Code
            }));
        }
        public async Task RestartGameAsync()
        {
            PeerToPeerGameService  svc     = new PeerToPeerGameService(_storage.Object);
            PeerToPeerSessionState session = new PeerToPeerSessionState();

            _storage.Setup(p => p.UpdateP2PSessionAsync(It.IsAny <PeerToPeerSessionState>())).ReturnsAsync(session);

            PeerToPeerSessionState res = await svc.RestartGameAsync(session);

            _storage.Verify(p => p.UpdateP2PSessionAsync(It.IsAny <PeerToPeerSessionState>()), Times.Once);

            Assert.IsNotNull(res);
        }
        public async Task AddPeerToSession_SessionNotFound()
        {
            PeerToPeerGameService svc = new PeerToPeerGameService(_storage.Object);

            _storage.Setup(p => p.FindP2PSessionAsync(It.IsAny <string>())).ReturnsAsync((PeerToPeerSessionState)null);

            PeerToPeerSessionState res = await svc.AddPeerToSession("code", "FriendConnectionId", new List <ShipInfo>());

            _storage.Verify(p => p.FindP2PSessionAsync(It.IsAny <string>()), Times.Once);
            _storage.Verify(p => p.UpdateP2PSessionAsync(It.IsAny <PeerToPeerSessionState>()), Times.Never);

            Assert.IsNull(res);
        }
        public async Task AddPeerToSession_GameAlreadyJoinedByAll()
        {
            PeerToPeerGameService svc = new PeerToPeerGameService(_storage.Object);
            var session = new PeerToPeerSessionState()
            {
                Code               = "code",
                HostConnectionId   = "HostConnectionId",
                FriendConnectionId = "FriendConnectionId",
                GameStartedCount   = 2,
            };

            _storage.Setup(p => p.FindP2PSessionAsync(It.IsAny <string>())).ReturnsAsync(session);

            PeerToPeerSessionState res = await svc.AddPeerToSession("code", "FriendConnectionId", new List <ShipInfo>());
        }
        public async Task <PeerToPeerSessionState> FindActiveSessionAsync(string code, string connectionId)
        {
            PeerToPeerSessionState session = await _storage.FindP2PSessionAsync(code);

            if (session == null)
            {
                return(null);
            }

            if (session.HostConnectionId == connectionId || session.FriendConnectionId == connectionId)
            {
                return(session);
            }

            return(null);
        }
        public async Task <PeerToPeerSessionState> AddPeerToSession(string code, string connectionId, IEnumerable <ShipInfo> ships)
        {
            PeerToPeerSessionState s = await _storage.FindP2PSessionAsync(code);

            if (s == null)
            {
                return(null);
            }

            //game already started by both peers
            if (s.GameStartedCount == 2)
            {
                throw new InvalidOperationException("Game already has 2 participants");
            }

            if (s.HostConnectionId == connectionId && s.HostStartedGame)
            {
                throw new InvalidOperationException("Host already started game");
            }

            if (s.FriendConnectionId == connectionId && s.FriendStartedGame)
            {
                throw new InvalidOperationException("Friend already started game");
            }

            if (s.HostConnectionId == connectionId || s.FriendConnectionId == connectionId)
            {
                if (s.HostConnectionId == connectionId)
                {
                    s.HostStartedGame = true;
                    s.HostShips       = new List <ShipInfo>(ships);
                }
                else if (s.FriendConnectionId == connectionId)
                {
                    s.FriendStartedGame = true;
                    s.FriendShips       = new List <ShipInfo>(ships);
                }

                s.GameStartedCount++;

                s = await _storage.UpdateP2PSessionAsync(s);

                return(s);
            }

            return(null);
        }
        public async Task JoinSessionAsync_FriendAlreadyConnected()
        {
            PeerToPeerGameService svc = new PeerToPeerGameService(_storage.Object);

            _storage.Setup(p => p.FindP2PSessionAsync(It.IsAny <string>())).ReturnsAsync(new PeerToPeerSessionState()
            {
                FriendConnectionId = "connectionId"
            });
            _storage.Setup(p => p.UpdateP2PSessionAsync(It.IsAny <PeerToPeerSessionState>())).ReturnsAsync(new PeerToPeerSessionState());

            PeerToPeerSessionState res = await svc.JoinSessionAsync("code", "connectionId");

            _storage.Verify(p => p.FindP2PSessionAsync(It.IsAny <string>()), Times.Once);
            _storage.Verify(p => p.UpdateP2PSessionAsync(It.IsAny <PeerToPeerSessionState>()), Times.Never);

            Assert.IsNull(res);
        }
Beispiel #15
0
        public async Task <IActionResult> FireCannonProcessResult([FromBody] P2PFireCannonCallbackDto dto)
        {
            if (string.IsNullOrWhiteSpace(dto.ConnectionId))
            {
                return(BadRequest());
            }

            if (string.IsNullOrWhiteSpace(dto.Code))
            {
                return(BadRequest());
            }

            PeerToPeerSessionState session = await _p2pSvc.FindActiveSessionAsync(dto.Code, dto.ConnectionId);

            if (session == null)
            {
                return(BadRequest());
            }

            List <ShipInfo> ships = dto.ConnectionId == session.HostConnectionId ? session.FriendShips : session.HostShips;

            FireCannonResultDto respDto = new FireCannonResultDto
            {
                CellId               = dto.CellId,
                ShipDestroyed        = dto.ShipDestroyed,
                IsAwaitingServerTurn = !dto.Result,
                IsGameOver           = dto.IsGameOver,
                Result               = dto.Result,
            };

            var connectionId = dto.ConnectionId == session.HostConnectionId ? session.FriendConnectionId : session.HostConnectionId;

            await _gameHubContext.Clients.Client(connectionId).SendAsync("MakeFireProcessResult", respDto);

            if (dto.IsGameOver)
            {
                await _p2pSvc.StopGameAsync(session);

                GameOverDto shipsDto = new GameOverDto {
                    Ships = ships.Select(s => s.Cells).ToList()
                };
                return(Ok(shipsDto));
            }

            return(Ok(new { }));
        }
        public virtual async Task <PeerToPeerSessionState> StopGameAsync(PeerToPeerSessionState session)
        {
            PeerToPeerGameState game = await FindActiveP2PGameAsync(session.GameId);

            if (game == null)
            {
                return(null);
            }

            game.DateEnd = DateTime.Now;
            await _storage.UpdateP2PGameAsync(game);

            session.PreviousGames.Add(session.GameId);
            session.GameId = null;

            return(await _storage.UpdateP2PSessionAsync(session));
        }
        /// <summary>
        /// Cleanup old objects from memory storage
        /// </summary>
        /// <returns></returns>
        public Task Cleanup()
        {
            DateTime now = DateTime.Now;

            if (_games.Count > 500)
            {
                foreach (string key in _games.Keys)
                {
                    GameState g  = _games[key];
                    TimeSpan  ts = now - g.LastUpdated;
                    if (ts.TotalHours >= HoursToLive)
                    {
                        _games.TryRemove(key, out _);
                    }
                }
            }

            if (_p2pGames.Count > 500)
            {
                foreach (string key in _p2pGames.Keys)
                {
                    PeerToPeerGameState g  = _p2pGames[key];
                    TimeSpan            ts = now - g.LastUpdated;
                    if (ts.TotalHours >= HoursToLive)
                    {
                        _p2pGames.TryRemove(key, out _);
                    }
                }
            }

            if (_p2pSessions.Count > 500)
            {
                foreach (string key in _p2pSessions.Keys)
                {
                    PeerToPeerSessionState g = _p2pSessions[key];
                    TimeSpan ts = now - g.LastUpdated;
                    if (ts.TotalHours >= HoursToLive)
                    {
                        _p2pSessions.TryRemove(key, out _);
                    }
                }
            }

            return(Task.FromResult(0));
        }
        public async Task StopGameAsync()
        {
            PeerToPeerGameService  svc     = new PeerToPeerGameService(_storage.Object);
            PeerToPeerGameState    game    = PeerToPeerGameState.CreateNew();
            PeerToPeerSessionState session = new PeerToPeerSessionState();

            _storage.Setup(p => p.FindActiveP2PGameAsync(It.IsAny <string>())).ReturnsAsync(game);
            _storage.Setup(p => p.UpdateP2PGameAsync(It.IsAny <PeerToPeerGameState>())).ReturnsAsync(game);
            _storage.Setup(p => p.UpdateP2PSessionAsync(It.IsAny <PeerToPeerSessionState>())).ReturnsAsync(session);

            PeerToPeerSessionState res = await svc.StopGameAsync(session);

            _storage.Verify(p => p.FindActiveP2PGameAsync(It.IsAny <string>()), Times.Once);
            _storage.Verify(p => p.UpdateP2PGameAsync(It.IsAny <PeerToPeerGameState>()), Times.Once);
            _storage.Verify(p => p.UpdateP2PSessionAsync(It.IsAny <PeerToPeerSessionState>()), Times.Once);

            Assert.IsNotNull(res);
        }
        public async Task <PeerToPeerSessionState> JoinSessionAsync(string code, string connectionId)
        {
            PeerToPeerSessionState session = await _storage.FindP2PSessionAsync(code);

            if (session == null)
            {
                return(null);
            }

            //if friend already joined.
            if (!string.IsNullOrWhiteSpace(session.FriendConnectionId))
            {
                return(null);
            }

            session.FriendConnectionId = connectionId;

            return(await _storage.UpdateP2PSessionAsync(session));
        }
        public async Task AddPeerToSession_WrongConnectionId()
        {
            PeerToPeerGameService svc = new PeerToPeerGameService(_storage.Object);
            var session = new PeerToPeerSessionState()
            {
                Code               = "code",
                HostConnectionId   = "HostConnectionId",
                FriendConnectionId = "FriendConnectionId",
            };

            _storage.Setup(p => p.FindP2PSessionAsync(It.IsAny <string>())).ReturnsAsync(session);

            PeerToPeerSessionState res = await svc.AddPeerToSession("code", "WrongConnectionId", new List <ShipInfo>());

            _storage.Verify(p => p.FindP2PSessionAsync(It.IsAny <string>()), Times.Once);
            _storage.Verify(p => p.UpdateP2PSessionAsync(It.IsAny <PeerToPeerSessionState>()), Times.Never);

            Assert.IsNull(res);
        }
        public async Task CleanupTest()
        {
            InMemoryStaticStorage s = new InMemoryStaticStorage
            {
                HoursToLive = 0
            };


            //clean results of older runs
            await s.Cleanup();

            for (int i = 0; i < 1000; i++)
            {
                var game = PeerToPeerGameState.CreateNew();
                await s.AddP2PGameAsync(game);
            }

            for (int i = 0; i < 1000; i++)
            {
                var session = new PeerToPeerSessionState()
                {
                    Code = i.ToString(),
                };
                await s.AddP2PSessionAsync(session);
            }

            for (int i = 0; i < 1000; i++)
            {
                var game = new GameState
                {
                    GameId = Guid.NewGuid().ToString()
                };
                await s.AddGameAsync(game);
            }

            await s.Cleanup();

            Assert.AreEqual(0, s.PeerToPeerGamesCount);
            Assert.AreEqual(0, s.PeerToPeerSessionsCount);
            Assert.AreEqual(0, s.GamesCount);
        }
        private async Task <string> GenerateCode()
        {
            Random rnd = new Random();
            int    i   = 0;

            while (i < 1000)
            {
                int    num  = rnd.Next(0, 9999);
                string code = num.ToString().PadLeft(4, '0');

                //if session not found - code OK. Otherwise generate new code
                PeerToPeerSessionState s = await _storage.FindP2PSessionAsync(code);

                if (s == null)
                {
                    return(code);
                }
                ++i;
            }
            return(null);
        }
Beispiel #23
0
        public async Task <IActionResult> JoinSession([FromBody] P2PGameKeyDto dto)
        {
            if (string.IsNullOrWhiteSpace(dto.ConnectionId))
            {
                return(BadRequest());
            }

            PeerToPeerSessionState g = await _p2pSvc.JoinSessionAsync(dto.Code, dto.ConnectionId);

            if (g == null)
            {
                return(BadRequest());
            }

            if (dto.ConnectionId == g.HostConnectionId)
            {
                return(BadRequest());
            }

            await _gameHubContext.Clients.Client(g.HostConnectionId).SendAsync("FriendConnected");

            return(Ok(new { }));
        }
        public async Task AddPeerToSession_HostAdded()
        {
            PeerToPeerGameService svc = new PeerToPeerGameService(_storage.Object);
            var session = new PeerToPeerSessionState()
            {
                Code               = "code",
                HostConnectionId   = "HostConnectionId",
                FriendConnectionId = "FriendConnectionId"
            };

            _storage.Setup(p => p.FindP2PSessionAsync(It.IsAny <string>())).ReturnsAsync(session);
            _storage.Setup(p => p.UpdateP2PSessionAsync(It.IsAny <PeerToPeerSessionState>())).ReturnsAsync(session);

            PeerToPeerSessionState res = await svc.AddPeerToSession("code", "HostConnectionId", new List <ShipInfo>());

            _storage.Verify(p => p.FindP2PSessionAsync(It.IsAny <string>()), Times.Once);
            _storage.Verify(p => p.UpdateP2PSessionAsync(It.IsAny <PeerToPeerSessionState>()), Times.Once);

            Assert.IsNotNull(res);
            Assert.IsTrue(session.HostStartedGame);
            Assert.AreEqual(1, session.GameStartedCount);
            Assert.IsNotNull(session.HostShips);
        }
        public Task <PeerToPeerSessionState> FindP2PSessionAsync(string code)
        {
            PeerToPeerSessionState p2pSession = _p2pSessions.FirstOrDefault(u => u.Key == code).Value;

            return(Task.FromResult(p2pSession));
        }
 public Task <PeerToPeerSessionState> UpdateP2PSessionAsync(PeerToPeerSessionState p2pSession)
 {
     p2pSession.LastUpdated = DateTime.Now;
     p2pSession             = _p2pSessions.AddOrUpdate(p2pSession.Code, p2pSession, (key, val) => p2pSession);
     return(Task.FromResult(p2pSession));
 }
Beispiel #27
0
        public async Task <IActionResult> StartNewGame([FromBody] P2PNewGametDto dto)
        {
            if (string.IsNullOrWhiteSpace(dto.ConnectionId))
            {
                return(BadRequest());
            }

            if (string.IsNullOrWhiteSpace(dto.Code))
            {
                return(BadRequest());
            }

            if (dto.Ships == null || dto.Ships.Length != 10)
            {
                return(BadRequest());
            }

            PeerToPeerSessionState session = null;

            try
            {
                session = await _p2pSvc.AddPeerToSession(dto.Code, dto.ConnectionId, _mapper.Map <IEnumerable <ShipInfo> >(dto.Ships));
            }
            catch (Exception e)
            {
                _logger.LogError(e, e.Message);
            }

            if (session == null)
            {
                return(BadRequest());
            }

            if (session.HostConnectionId == session.FriendConnectionId)
            {
                return(BadRequest());
            }

            if (session.GameStartedCount == 2)
            {
                //TODO: Implement add board to Game and track battle history
                session = await _p2pSvc.StartNewGameAsync(session);

                var connectionId = dto.ConnectionId == session.HostConnectionId ? session.FriendConnectionId : session.HostConnectionId;
                await _gameHubContext.Clients.Client(connectionId).SendAsync("GameStartedYourMove", new P2PNewGameResultDto {
                    GameId = session.GameId, YourMove = true
                });

                await _gameHubContext.Clients.Client(dto.ConnectionId).SendAsync("GameStartedFriendsMove", new P2PNewGameResultDto {
                    GameId = session.GameId, YourMove = false
                });
            }
            else
            {
                var connectionId = dto.ConnectionId == session.HostConnectionId ? session.FriendConnectionId : session.HostConnectionId;
                await _gameHubContext.Clients.Client(connectionId).SendAsync("FriendStartedGame");

                await _gameHubContext.Clients.Client(dto.ConnectionId).SendAsync("YouStartedGame");
            }

            return(Ok(new { }));
        }
 public Task <PeerToPeerSessionState> AddP2PSessionAsync(PeerToPeerSessionState p2pSession)
 {
     p2pSession.LastUpdated = DateTime.Now;
     p2pSession             = _p2pSessions.GetOrAdd(p2pSession.Code, p2pSession);
     return(Task.FromResult(p2pSession));
 }
        public async Task <PeerToPeerSessionState> RestartGameAsync(PeerToPeerSessionState session)
        {
            session.Reset();

            return(await _storage.UpdateP2PSessionAsync(session));
        }