示例#1
0
        public async Task StartAsync_CommandThrowsInvalidOperationException_RaisesErrorOccuredEvent()
        {
            // ARRANGE

            var contextMock = new Mock <ICommandLoopContext>();

            contextMock.SetupGet(x => x.HasNextIteration).Returns(true);
            contextMock.SetupGet(x => x.CanPlayerGiveCommand).Returns(true);
            var context = contextMock.Object;

            var tcs = new TaskCompletionSource <bool>(TaskCreationOptions.RunContinuationsAsynchronously);
            var eventWasInvokedTask = tcs.Task;

            var commandMock = new Mock <ICommand>();

            commandMock.Setup(x => x.Execute()).Throws <InvalidOperationException>();
            var command = commandMock.Object;

            var commandPool = new TestCommandPool();

            commandPool.Push(command);

            var commandLoopUpdater = new CommandLoopUpdater(context, commandPool);
            ErrorOccuredEventArgs?expectedRaisedErrorArgs = null;
            var raiseCount = 0;

            commandLoopUpdater.ErrorOccured += (s, e) =>
            {
                expectedRaisedErrorArgs = e;

                // Count raises to prevent errors with multiple events.
                raiseCount++;

                tcs.SetResult(true);
            };

            // ACT
            using var monitor = commandLoopUpdater.Monitor();
#pragma warning disable CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed
            commandLoopUpdater.StartAsync(CancellationToken.None).ConfigureAwait(false);
#pragma warning restore CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed

            var expectedEventWasRaised = await eventWasInvokedTask.ConfigureAwait(false);

            // ASSERT

            expectedEventWasRaised.Should().BeTrue();
            expectedRaisedErrorArgs.Should().BeOfType <CommandErrorOccuredEventArgs>();
            raiseCount.Should().Be(1);
        }
示例#2
0
        public async Task StartAsync_CommandIsRepeatableOnce_ExecutesCommandTwice()
        {
            // ARRANGE

            var contextMock = new Mock <ICommandLoopContext>();

            contextMock.SetupGet(x => x.HasNextIteration).Returns(true);
            contextMock.SetupGet(x => x.CanPlayerGiveCommand).Returns(true);
            var context = contextMock.Object;

            var tcs = new TaskCompletionSource <bool>(TaskCreationOptions.RunContinuationsAsynchronously);
            var waitCommandExecutedTask = tcs.Task;

            var repeatIteration = 0;
            var commandMock     = new Mock <IRepeatableCommand>();

            commandMock.Setup(x => x.Execute()).Callback(() =>
            {
                if (repeatIteration >= 1)
                {
                    tcs.SetResult(true);
                }
            });
            commandMock.Setup(x => x.CanRepeat()).Callback(() => { repeatIteration++; })
            .Returns(() => repeatIteration <= 1);
            commandMock.Setup(x => x.CanExecute()).Returns(new CanExecuteCheckResult {
                IsSuccess = true
            });

            var command = commandMock.Object;

            var commandPool = new TestCommandPool();

            commandPool.Push(command);

            var commandLoopUpdater = new CommandLoopUpdater(context, commandPool);

            // ACT

#pragma warning disable CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed
            commandLoopUpdater.StartAsync(CancellationToken.None).ConfigureAwait(false);
#pragma warning restore CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed

            await waitCommandExecutedTask.ConfigureAwait(false);

            // ASSERT

            commandMock.Verify(x => x.Execute(), Times.Exactly(2));
        }
示例#3
0
        public async Task StopAsync_StopAfterStart_CommandsAreNotRequestedAfterStop()
        {
            // ARRANGE

            var contextMock = new Mock <ICommandLoopContext>();

            contextMock.SetupGet(x => x.HasNextIteration).Returns(true);
            contextMock.SetupGet(x => x.CanPlayerGiveCommand).Returns(true);
            var context = contextMock.Object;

            var command = Mock.Of <ICommand>();

            var commandPoolMock = new Mock <ICommandPool>();
            var semaphore       = new SemaphoreSlim(0, 1);

            commandPoolMock.Setup(x => x.Pop()).Returns(() =>
            {
                Task.Delay(100).Wait();
                semaphore.Release();
                return(command);
            });
            var commandPool = commandPoolMock.Object;

            var commandLoop = new CommandLoopUpdater(context, commandPool);

            // ACT
            var commandLoopTask = commandLoop.StartAsync(CancellationToken.None);
            AggregateException?commandLoopTaskException = null;

            await semaphore.WaitAsync().ConfigureAwait(false);

            await commandLoop.StopAsync().ConfigureAwait(false);

            Func <Task> act = async() =>
            {
                await commandLoopTask.ContinueWith(task => commandLoopTaskException = task.Exception,
                                                   TaskContinuationOptions.OnlyOnFaulted).ConfigureAwait(false);
            };

            // ASSERT
            commandPoolMock.Verify(x => x.Pop(), Times.AtMost(2));

            await act.Should().ThrowAsync <TaskCanceledException>().ConfigureAwait(false);

            commandLoopTaskException.Should().BeNull();
        }
示例#4
0
        public async Task StartAsync_CommandInPoolAfterStart_ExecutesCommand()
        {
            // ARRANGE

            var contextMock = new Mock <ICommandLoopContext>();

            contextMock.SetupGet(x => x.HasNextIteration).Returns(true);
            contextMock.SetupGet(x => x.CanPlayerGiveCommand).Returns(true);
            var context = contextMock.Object;

            var tcs = new TaskCompletionSource <bool>(TaskCreationOptions.RunContinuationsAsynchronously);

            var testTask = tcs.Task;

            var commandMock = new Mock <ICommand>();

            commandMock.Setup(x => x.Execute()).Callback(() => tcs.SetResult(true));
            var command = commandMock.Object;

            var commandPool = new TestCommandPool();

            var commandLoopUpdater = new CommandLoopUpdater(context, commandPool);

            // ACT

#pragma warning disable CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed
            commandLoopUpdater.StartAsync(CancellationToken.None).ConfigureAwait(false);
#pragma warning restore CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed

            commandPool.Push(command);

            // Delay to take some time to command loop updater to perform some iterations.
            await testTask.ConfigureAwait(false);

            // ASSERT

            commandMock.Verify(x => x.Execute(), Times.Once);
        }
示例#5
0
        public async Task StartAsync_CommandInPoolBeforeStart_RaisesCompleteCommandEvent()
        {
            // ARRANGE

            var contextMock = new Mock <ICommandLoopContext>();

            contextMock.SetupGet(x => x.HasNextIteration).Returns(true);
            contextMock.SetupGet(x => x.CanPlayerGiveCommand).Returns(true);
            var context = contextMock.Object;

            var tcs       = new TaskCompletionSource <bool>(TaskCreationOptions.RunContinuationsAsynchronously);
            var eventTask = tcs.Task;

            var commandMock = new Mock <ICommand>();
            var command     = commandMock.Object;

            var commandPool = new TestCommandPool();

            commandPool.Push(command);

            var commandLoopUpdater = new CommandLoopUpdater(context, commandPool);

            commandLoopUpdater.CommandProcessed += (s, e) =>
            {
                tcs.SetResult(true);
            };

            // ACT
#pragma warning disable CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed
            commandLoopUpdater.StartAsync(CancellationToken.None).ConfigureAwait(false);
#pragma warning restore CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed

            // ASSERT

            var expectedEventWasRaised = await eventTask.ConfigureAwait(false);

            expectedEventWasRaised.Should().BeTrue();
        }
        /// <inheritdoc />
        public async Task <GameScreen> StartProcessingAsync(GameState gameState)
        {
            var serviceScope            = gameState.ServiceScope;
            var player                  = serviceScope.ServiceProvider.GetRequiredService <IPlayer>();
            var commandPool             = serviceScope.ServiceProvider.GetRequiredService <ICommandPool>();
            var animationBlockerService = serviceScope.ServiceProvider.GetRequiredService <IAnimationBlockerService>();
            var humanTaskSource         = serviceScope.ServiceProvider
                                          .GetRequiredService <IActorTaskSource <ISectorTaskSourceContext> >();

            var playerState    = serviceScope.ServiceProvider.GetRequiredService <ISectorUiState>();
            var inventoryState = serviceScope.ServiceProvider.GetRequiredService <IInventoryState>();

            var globeLoopUpdateContext = new GlobeLoopContext(player);
            var globeLoop = new GlobeLoopUpdater(globeLoopUpdateContext, animationBlockerService);

            var humanTaskSourceCasted = (IHumanActorTaskSource <ISectorTaskSourceContext>)humanTaskSource;
            var commandLoopContext    = new CommandLoopContext(player, humanTaskSourceCasted, animationBlockerService);
            var commandLoop           = new CommandLoopUpdater(commandLoopContext, commandPool);

            var globe = player.Globe;

            // Play

            using var cancellationTokenSource = new CancellationTokenSource();
            var cancellationToken = cancellationTokenSource.Token;

            globeLoop.ErrorOccured += (s, e) => { Console.WriteLine(e.Exception); };
            globeLoop.Start();

            commandLoop.ErrorOccured        += (s, e) => { Console.WriteLine(e.Exception); };
            commandLoop.CommandAutoExecuted += (s, e) => { Console.WriteLine("Auto execute last command"); };
            commandLoop.CommandProcessed    += (s, e) =>
            {
                inventoryState.SelectedProp   = null;
                playerState.SelectedViewModel = null;
            };
            var commandLoopTask = commandLoop.StartAsync(cancellationToken);

#pragma warning disable CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed
            commandLoopTask.ContinueWith(task => Console.WriteLine(task.Exception),
                                         TaskContinuationOptions.OnlyOnFaulted);
            commandLoopTask.ContinueWith(task => Console.WriteLine("Game loop stopped."),
                                         TaskContinuationOptions.OnlyOnCanceled);
#pragma warning restore CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed

            do
            {
                var playerActor = (from sectorNode in globe.SectorNodes
                                   from actor in sectorNode.Sector.ActorManager.Items
                                   where actor.Person == player.MainPerson
                                   select actor).SingleOrDefault();

                playerState.ActiveActor = new ActorViewModel {
                    Actor = playerActor
                };

                PrintState(playerState.ActiveActor.Actor);
                PrintCommandDescriptions();

                Console.WriteLine($"{UiResource.InputPrompt}:");
                var inputText = Console.ReadLine();
                if (inputText.StartsWith("m", StringComparison.InvariantCultureIgnoreCase))
                {
                    var playerActorSectorNode = GetPlayerSectorNode(player, globe);

                    HandleMoveCommand(serviceScope, playerState, commandPool, playerActorSectorNode, inputText);
                }
                else if (inputText.StartsWith("look", StringComparison.InvariantCultureIgnoreCase))
                {
                    var playerActorSectorNode = GetPlayerSectorNode(player, globe);

                    HandleLookCommand(playerState, playerActorSectorNode, inputText);
                }
                else if (inputText.StartsWith("idle", StringComparison.InvariantCultureIgnoreCase))
                {
                    HandleIdleCommand(serviceScope, commandPool);
                }
                else if (inputText.StartsWith("dead", StringComparison.InvariantCultureIgnoreCase))
                {
                    HandleDeadCommand(player);
                }
                else if (inputText.StartsWith("transit", StringComparison.InvariantCultureIgnoreCase))
                {
                    HandleSectorTransitCommand(serviceScope, commandPool);
                }
                else if (inputText.StartsWith("attack", StringComparison.InvariantCultureIgnoreCase))
                {
                    var playerActorSectorNode = GetPlayerSectorNode(player, globe);

                    HandleAttackCommand(inputText, serviceScope, playerState, playerActorSectorNode, commandPool);
                }
                else if (inputText.StartsWith("exit", StringComparison.InvariantCultureIgnoreCase))
                {
                    break;
                }

                await Task.Run(() =>
                {
                    while (true)
                    {
                        if (((IHumanActorTaskSource <ISectorTaskSourceContext>)humanTaskSource).CanIntent() &&
                            !commandLoop.HasPendingCommands())
                        {
                            break;
                        }
                    }
                }).ConfigureAwait(false);

                await animationBlockerService.WaitBlockersAsync().ConfigureAwait(false);
            } while (!player.MainPerson.GetModule <ISurvivalModule>().IsDead);

            cancellationTokenSource.Cancel();
            return(GameScreen.Scores);
        }