コード例 #1
0
// Scenario 1: Player is idle and gets suspended -- no other players in game
static void doScenario1(GamePair &gamePair)
{
   ClientGame *clientGame = gamePair.getClient(0);
   ServerGame *serverGame = gamePair.server;

   // Idle for a while -- ship should become spawn delayed.  GameConnection::SPAWN_DELAY_TIME is measured in ms.
   gamePair.idle(10, GameConnection::SPAWN_DELAY_TIME / 10);

   ASSERT_TRUE(serverGame->getClientInfo(0)->isPlayerInactive());    // No input from player, should be flagged as inactive
   // Note that spawn delay does not get set until the delayed ship tries to spawn, even if player is marked as inactive

   // Kill the ship again -- should be delayed when it tries to respawn because client has been inactive
   fillVector.clear();
   serverGame->getLevel()->findObjects(PlayerShipTypeNumber, fillVector);
   EXPECT_EQ(1, fillVector.size());    // Should only be one ship

   Ship *ship = static_cast<Ship *>(fillVector[0]);      // Server's copy of the ship

   killShip(ship);

   gamePair.idle(10, GameType::RespawnDelay / 10 + 5);
   // Since server has received no input from client for GameConnection::SPAWN_DELAY_TIME ms, and ship has attempted to respawn, should be spawn-delayed
   ASSERT_TRUE(serverGame->getClientInfo(0)->isSpawnDelayed());
   ASSERT_TRUE(clientGame->isSpawnDelayed());      // Status should have propagated to client by now

   // At this point, client and server are both aware that the spawn is delayed due to player inactivity

   gamePair.idle(10, 10);              // Idle 10x
   // If spawn were not delayed, ship would have respawned.  Check for it on the server.
   // (Dead ship may linger on client while exploding, so we won't check there.)
   fillVector.clear();
   serverGame->getLevel()->findObjects(PlayerShipTypeNumber, fillVector);
   ASSERT_EQ(0, fillVector.size());                   // Ship is spawn delayed and won't spawn... hence no ships
   ASSERT_EQ(0, serverGame->getClientInfo(0)->getReturnToGameTime());      // No returnToGamePenalty in this scenario
   ASSERT_EQ(0, clientGame->getReturnToGameDelay());
   ASSERT_FALSE(static_cast<FullClientInfo *>(serverGame->getClientInfo(0))->hasReturnToGamePenalty());   // No penalty in the works

   // Undelay spawn
   clientGame->undelaySpawn();         // This is what gets run when player presses a key
   gamePair.idle(10, 5);               // Idle 5x; give things time to propagate

   ASSERT_FALSE(serverGame->getClientInfo(0)->isSpawnDelayed());     // Player should no longer be spawn delayed
   ASSERT_FALSE(clientGame->inReturnToGameCountdown());
   fillVector.clear();
   serverGame->getLevel()->findObjects(PlayerShipTypeNumber, fillVector);
   ASSERT_EQ(1, fillVector.size());    // Ship should have spawned and be available on client and server
   fillVector.clear();
   clientGame->getLevel()->findObjects(PlayerShipTypeNumber, fillVector);
   ASSERT_EQ(1, fillVector.size());    // Ship should have spawned and be available on client and server
}
コード例 #2
0
TEST(ObjectScopeTest, TestItemPropagation)
{
   for(S32 i = 0; i < testInfos.size(); i++)
   {
      // Create a GamePair using our text item code, with 2 clients; one will be red, the other blue.
      // The test will confirm which players get the red text item, the blue line, and the zone object.
      string levelCode = getLevelCodeForItemPropagationTests(testInfos[i].itemToTest);

      GamePair gamePair(levelCode, 2);

      // First, ensure we have two players, one red, one blue
      ServerGame *serverGame = gamePair.server;

      ASSERT_EQ(2, serverGame->getPlayerCount());
      ASSERT_EQ(Colors::blue.toHexString(), serverGame->getTeamColor(0).toHexString());
      ASSERT_EQ(Colors::red.toHexString(), serverGame->getTeamColor(1).toHexString());

      // Do the following rigamarole to break dependency on assumption client0 is blue and client1 is red
      ClientGame *client0 = gamePair.getClient(0);
      ClientGame *client1 = gamePair.getClient(1);

      ClientGame *blue = (serverGame->getTeamColor(client0->getLocalRemoteClientInfo()->getTeamIndex()).toHexString() ==
         Colors::blue.toHexString()) ? client0 : client1;

      ClientGame *red = (serverGame->getTeamColor(client0->getLocalRemoteClientInfo()->getTeamIndex()).toHexString() ==
         Colors::red.toHexString()) ? client0 : client1;

      ASSERT_EQ(Colors::blue.toHexString(), serverGame->getTeamColor(blue->getLocalRemoteClientInfo()->getTeamIndex()).toHexString());
      ASSERT_EQ(Colors::red.toHexString(), serverGame->getTeamColor(red->getLocalRemoteClientInfo()->getTeamIndex()).toHexString());

      ASSERT_FALSE(serverGame->getClientInfos()->get(0)->getConnection()->mInCommanderMap);
      ASSERT_FALSE(serverGame->getClientInfos()->get(1)->getConnection()->mInCommanderMap);

      // Now that we know which client is which, we can check to see which objects are available where
      {
         SCOPED_TRACE("Not in CommandersMap // " + testInfos[i].itemToTest);
         testScope(serverGame, blue, red, testInfos[i], testInfos[i].startingCondition);
      }

      // Turn on cmdrs map... should not affect results
      red->setUsingCommandersMap(true);
      blue->setUsingCommandersMap(true);

      gamePair.idle(10, 5);     // Let things settle

      ASSERT_TRUE(serverGame->getClientInfos()->get(0)->getConnection()->mInCommanderMap);
      ASSERT_TRUE(serverGame->getClientInfos()->get(1)->getConnection()->mInCommanderMap);
      {
         SCOPED_TRACE("In CommandersMap // " + testInfos[i].itemToTest);
         testScope(serverGame, blue, red, testInfos[i], testInfos[i].startingCondition);
      }

      Vector<DatabaseObject *> fillVector;

      // Change the textitem from red to blue
      serverGame->getLevel()->findObjects(testInfos[i].objectTypeNumber, fillVector);
      ASSERT_EQ(1, fillVector.size());
      BfObject *obj = static_cast<BfObject *>(fillVector[0]);
      obj->setTeam(0);     // Blue team

      gamePair.idle(10, 5);     // Let things settle
      {
         SCOPED_TRACE("Item Moved To Blue // " + testInfos[i].itemToTest);
         testScope(serverGame, blue, red, testInfos[i], testInfos[i].itemMovedToBlue);
      }
      obj->setTeam(1);          // Back to red

      gamePair.idle(10, 5);     // Let things settle
      {
         SCOPED_TRACE("Item Moved To Red // " + testInfos[i].itemToTest);
         testScope(serverGame, blue, red, testInfos[i], testInfos[i].itemMovedToRed);
      }

      // Now change the player's team from blue to red
      blue->changeOwnTeam(1);
      EXPECT_EQ(0, blue->getLocalRemoteClientInfo()->getTeamIndex()) << "Expect this client to be on team 0 (change hasn't propagated yet)";
      gamePair.idle(10, 5);     // Let things settle
      EXPECT_EQ(1, blue->getLocalRemoteClientInfo()->getTeamIndex()) << "Expect this client to be on team 1 (change should have propagated)";

      EXPECT_EQ(1, serverGame->getClientInfos()->get(0)->getTeamIndex());
      EXPECT_EQ(1, serverGame->getClientInfos()->get(1)->getTeamIndex());
      {
         SCOPED_TRACE("Blue Player Moved To Red, Items On Red // " + testInfos[i].itemToTest);
         testScope(serverGame, blue, red, testInfos[i], testInfos[i].playersMovedToRed);
      }

      // And put both players on blue
      blue->changeOwnTeam(0);
      red->changeOwnTeam(0);

      EXPECT_EQ(1, blue->getLocalRemoteClientInfo()->getTeamIndex()) << "Expect this client to be on team 1 (change hasn't propagated yet)";
      EXPECT_EQ(1, red->getLocalRemoteClientInfo()->getTeamIndex()) << "Expect this client to be on team 1 (change hasn't propagated yet)";
      gamePair.idle(10, 5);     // Let things settle
      EXPECT_EQ(0, blue->getLocalRemoteClientInfo()->getTeamIndex()) << "Expect this client to be on team 0 (change should have propagated)";
      EXPECT_EQ(0, blue->getLocalRemoteClientInfo()->getTeamIndex()) << "Expect this client to be on team 0 (change should have propagated)";

      EXPECT_EQ(0, serverGame->getClientInfos()->get(0)->getTeamIndex());
      EXPECT_EQ(0, serverGame->getClientInfos()->get(1)->getTeamIndex());
      {
         SCOPED_TRACE("Both Players Moved To Blue, Items On Red // " + testInfos[i].itemToTest);
         testScope(serverGame, blue, red, testInfos[i], testInfos[i].playersMovedToBlue);
      }

      // Make items neutral and see if they propagate properly
      fillVector.clear();
      serverGame->getLevel()->findObjects(testInfos[i].objectTypeNumber, fillVector);
      ASSERT_EQ(1, fillVector.size());
      for(S32 j = 0; j < fillVector.size(); j++)
         static_cast<BfObject *>(fillVector[j])->setTeam(TEAM_NEUTRAL);
      gamePair.idle(10, 5);     // Let things settle
      {
         SCOPED_TRACE("Items On Neutral // " + testInfos[i].itemToTest);
         testScope(serverGame, blue, red, testInfos[i], testInfos[i].itemMovedToNeutral);
      }

      for(S32 j = 0; j < fillVector.size(); j++)
         static_cast<BfObject *>(fillVector[j])->setTeam(TEAM_HOSTILE);
      gamePair.idle(10, 5);     // Let things settle
      {
         SCOPED_TRACE("Items On Hostile // " + testInfos[i].itemToTest);
         testScope(serverGame, blue, red, testInfos[i], testInfos[i].itemsMovedToHostile);
      }
   }
}
コード例 #3
0
// Scenario 2: Player enters idle command, other players, so server does not suspend itself.  Since
// player used idle command, a 5 second penalty will be levied against them.
static void doScenario2(GamePair &gamePair)
{
   ServerGame *serverGame = gamePair.server;

   string player1Name = "TestPlayer0";
   ASSERT_EQ(1, gamePair.getClientCount());                          // Should have had a client here when we arrived
   ASSERT_EQ(player1Name, gamePair.getClient(0)->getPlayerName());   // With this name

   string player2Name = "TestUser2";
   gamePair.addClientAndSetTeam(player2Name.c_str(), 0);

   ClientGame *client1 = gamePair.getClient(0);
   ClientGame *client2 = gamePair.getClient(1);

   // Make sure the names are what we think they are... can't move on unless they are
   ASSERT_EQ(player1Name, client1->getPlayerName());
   ASSERT_EQ(player2Name, client2->getPlayerName());

   // Should now be 2 ships in the game -- one belonging to client1 and another belonging to client2
   gamePair.idle(10, 5);               // Idle 5x; give things time to propagate
   fillVector.clear();
   serverGame->getLevel()->findObjects(PlayerShipTypeNumber, fillVector);
   ASSERT_EQ(2, fillVector.size());                  
   fillVector.clear();
   client1->getLevel()->findObjects(PlayerShipTypeNumber, fillVector);
   ASSERT_EQ(2, fillVector.size());
   fillVector.clear();
   client2->getLevel()->findObjects(PlayerShipTypeNumber, fillVector);
   ASSERT_EQ(2, fillVector.size());

   Vector<string> words;
   ChatCommands::idleHandler(client1, words);         // Make client 1 go /idle
   gamePair.idle(Ship::KillDeleteDelay / 15, 30);     // Give things time to propagate, timers to time out, etc.

   ASSERT_TRUE(serverGame->getClientInfo(0)->isSpawnDelayed());
   ASSERT_TRUE(client1->isSpawnDelayed());            // Status should have propagated to client by now
   fillVector.clear();
   serverGame->getLevel()->findObjects(PlayerShipTypeNumber, fillVector);
   ASSERT_EQ(1, fillVector.size());                   // Ship should have been killed off -- only 2nd player ship should be left
   fillVector.clear();
   client1->getLevel()->findObjects(PlayerShipTypeNumber, fillVector);
   ASSERT_EQ(0, fillVector.size());                   // Suspended players don't see remote objects
   fillVector.clear();
   client2->getLevel()->findObjects(PlayerShipTypeNumber, fillVector);
   //ASSERT_EQ(1, fillVector.size());                   // Player 2 should see self

   ASSERT_TRUE(client2->findClientInfo(client1->getPlayerName())->isSpawnDelayed());    // Check that other player knows our status

   // ReturnToGame penalty has been set, but won't start to count down until ship attempts to spawn
   ASSERT_FALSE(client1->inReturnToGameCountdown());
   ASSERT_TRUE(static_cast<FullClientInfo *>(serverGame->getClientInfo(0))->hasReturnToGamePenalty()); // Penalty has been primed
   ASSERT_EQ(0, serverGame->getClientInfo(0)->getReturnToGameTime());

   // Player presses a key to rejoin the game; there should be a SPAWN_UNDELAY_TIMER_DELAY ms penalty incurred for using /idle
   ASSERT_FALSE(serverGame->isSuspended()) << "Game is suspended -- subsequent tests will fail";
   client1->undelaySpawn();                                                // Simulate effects of key press
   gamePair.idle(10, 10);                                                  // Idle; give things time to propagate
   ASSERT_TRUE(serverGame->getClientInfo(0)->getReturnToGameTime() > 0);   // Timers should be set and counting down
   ASSERT_TRUE(client1->inReturnToGameCountdown());

   // Check to ensure ship didn't spawn -- spawn should be delayed until penalty period has expired
   fillVector.clear();
   serverGame->getLevel()->findObjects(PlayerShipTypeNumber, fillVector);
   ASSERT_EQ(1, fillVector.size());   // (one ship for client2) 

   // Client 1 won't see spawning ship while he is suspended
   fillVector.clear();
   client1->getLevel()->findObjects(PlayerShipTypeNumber, fillVector);
   ASSERT_EQ(0, fillVector.size());

   // Client 2 should see that client 1 has been delayed
   ASSERT_TRUE(client2->findClientInfo(player1Name.c_str())->isSpawnDelayed());

   // After some time has passed -- no longer in returnToGameCountdown period, ship should have appeared on server and client
   gamePair.idle(ClientInfo::SPAWN_UNDELAY_TIMER_DELAY / 100, 105);  // More time than SPAWN_UNDELAY_TIMER_DELAY
   ASSERT_FALSE(client1->inReturnToGameCountdown());
   fillVector.clear();
   serverGame->getLevel()->findObjects(PlayerShipTypeNumber, fillVector);
   ASSERT_EQ(2, fillVector.size());    
   fillVector.clear();
   client1->getLevel()->findObjects(PlayerShipTypeNumber, fillVector);
   ASSERT_EQ(2, fillVector.size());

   gamePair.removeClient(1);
}
コード例 #4
0
// The spawnDelay mechansim is complex and interacts with other weird things like levelUp messages and server suspension
TEST(SpawnDelayTest, SpawnDelayTests)
{
   GamePair gamePair;     // An empty level should work fine here
   ClientGame *clientGame = gamePair.getClient(0);
   ServerGame *serverGame = gamePair.server;

   ASSERT_TRUE(serverGame->getGameType()) << "Expect a GameType by now!";

   // Idle for a while, let things settle
   gamePair.idle(10, 5);

   ASSERT_TRUE(clientGame->getGameType()) << "Expect a GameType by now!";

   Vector<DatabaseObject *> fillVector;

   // Ship should have spawned by now... check for it on the client and server
   fillVector.clear();
   serverGame->getLevel()->findObjects(PlayerShipTypeNumber, fillVector);
   ASSERT_EQ(1, fillVector.size());    // Ship should have spawned by now

   Ship *ship = static_cast<Ship *>(fillVector[0]);      // Server's copy of the ship

   fillVector.clear();
   clientGame->getLevel()->findObjects(PlayerShipTypeNumber, fillVector);
   ASSERT_EQ(1, fillVector.size());    // And it should be on the client, too

   ASSERT_FALSE(clientGame->isSpawnDelayed());     // Should not be spawn-delayed at this point

   killShip(ship);

   gamePair.idle(10, 5);      // 5 cycles

   // Ship should have spawned by now... check for it on the client and server
   fillVector.clear();
   serverGame->getLevel()->findObjects(PlayerShipTypeNumber, fillVector);
   ASSERT_EQ(1, fillVector.size());    //  Ship should have respawned and be available on the server...
   fillVector.clear();
   clientGame->getLevel()->findObjects(PlayerShipTypeNumber, fillVector);
   ASSERT_EQ(1, fillVector.size());    // ...and also on the client

   // Scenario 1: Player is idle and gets spawn delayed -- no other players in game
   // TODO: Also need a scenario where palyer goes idle and gets spawn delayed, but game does not get suspended due to other players
   doScenario1(gamePair);

   // Scenario 2: Player enters idle command, other players, so server does not suspend itself.  Since
   // player used idle command, a 5 second penalty will be levied against them.
   doScenario2(gamePair);

   // Scenarios 3 & 4 -- Player enters /idle command, no other players, so server suspends itself partially (3) or fully (4)
   // See https://code.google.com/p/googletest/wiki/AdvancedGuide#Using_Assertions_in_Sub-routines for details on this technique
   {
      SCOPED_TRACE("Scenario 3, letGameSlipIntoFullSuspendMode is false");
      doScenario34(gamePair, false);
   }
   {
      SCOPED_TRACE("Scenario 4, letGameSlipIntoFullSuspendMode is true");
      doScenario34(gamePair, true);
   }

   // Scenario 5 -- Player enters idle when in punishment delay period for pervious /idle command
   doScenario5(gamePair);  // Not complete

   // Scenario 6 -- Player is shown a new levelup screen
   doScenario6(gamePair);  // Not complete

   // Scenario 7 -- Player is shown a levelup screen they have already seen
   doScenario7(gamePair);  // Not complete

   // Scenario 8 -- Player is shown (new) levelup screen while they are idle due to inaction

   // Scenario 9 -- Player is shown (new) levelup screen while they are idle due to idle command

   // Scenario 10 -- Player is shown (new) levelup screen while they are in penalty phase of idle command

   // Scenario 11 -- Player is changing their loadout when the level changes.  This triggers a delayed spawn.
   doScenario11(gamePair);
}
コード例 #5
0
// Scenario 3, 4 -- Player enters /idle command, no other players, so server suspends itself
// In this case, no returnToGame penalty should be levied
// In this scenario 3, player un-idles during the suspend game timer countdown (there is a 2 second delay after all players are idle)
// In scenario 4, player enters full suspend mode before unidling
static void doScenario34(GamePair &gamePair, bool letGameSlipIntoFullSuspendMode)
{
   ClientGame *clientGame = gamePair.getClient(0);
   ServerGame *serverGame = gamePair.server;

   // Make sure we start off in a "normal" state
   ASSERT_FALSE(serverGame->isOrIsAboutToBeSuspended());
   ASSERT_FALSE(clientGame->isSpawnDelayed());         

   gamePair.idle(Ship::KillDeleteDelay / 15, 20);     // Idle; give things time to propagate
   fillVector.clear();
   serverGame->getLevel()->findObjects(PlayerShipTypeNumber, fillVector);
   ASSERT_EQ(1, fillVector.size());                   // Now that player 2 has left, should only be one ship
   fillVector.clear();
   clientGame->getLevel()->findObjects(PlayerShipTypeNumber, fillVector);
   ASSERT_EQ(1, fillVector.size());

   Vector<string> words;
   ChatCommands::idleHandler(clientGame, words);
   gamePair.idle(10, 10);     // Idle; give things time to propagate, timers to time out, etc.
   ASSERT_TRUE(serverGame->getClientInfo(0)->isSpawnDelayed());
   ASSERT_TRUE(serverGame->isOrIsAboutToBeSuspended());
   EXPECT_FALSE(serverGame->isSuspended());
   ASSERT_TRUE(clientGame->isSpawnDelayed());         // Status should have propagated to client by now
   EXPECT_FALSE(clientGame->isSuspended());

   fillVector.clear();
   serverGame->getLevel()->findObjects(PlayerShipTypeNumber, fillVector);
   ASSERT_EQ(0, fillVector.size());                   // No ships remaining in game -- don't check client as it may have exploding ship there
   fillVector.clear();

   // ReturnToGame penalty has been set, but won't start to count down until ship attempts to spawn
   ASSERT_FALSE(clientGame->inReturnToGameCountdown());
   ASSERT_TRUE(static_cast<FullClientInfo *>(serverGame->getClientInfo(0))->hasReturnToGamePenalty()); // Penalty has been primed
   ASSERT_EQ(0, serverGame->getClientInfo(0)->getReturnToGameTime());

   if(letGameSlipIntoFullSuspendMode)
		gamePair.idle(ServerGame::PreSuspendSettlingPeriod / 20, 25);

   // Player presses a key to rejoin the game; since game was suspended, player can resume without penalty
   ASSERT_TRUE(serverGame->isOrIsAboutToBeSuspended()) << "Game should be suspended";

   if(letGameSlipIntoFullSuspendMode)
   {
      // In here, game is suspended

      EXPECT_TRUE(serverGame->isSuspended());
      EXPECT_TRUE(clientGame->isSuspended());

      // Check if server clocks are still counting down... should be stopped
      S32 snow = serverGame->getGameType()->getRemainingGameTimeInMs();
      S32 cnow = clientGame->getGameType()->getRemainingGameTimeInMs();
      gamePair.idle(10, 10);
      S32 slater = serverGame->getGameType()->getRemainingGameTimeInMs();
      S32 clater = clientGame->getGameType()->getRemainingGameTimeInMs();
      EXPECT_EQ(snow, slater) << "Looks like server clock is still running (should be stopped)!";
      EXPECT_EQ(cnow, clater) << "Looks like client clock is still running (should be stopped)!";
   }
   else
   {
      // In here, game is not (yet) suspended, but is in the 2 second cooldown period that comes after 
      // all players have left or are idle, but before full suspension

      EXPECT_FALSE(serverGame->isSuspended());
      EXPECT_FALSE(clientGame->isSuspended());

      // Check if clocks are still counting down... should be still running
      S32 snow = serverGame->getGameType()->getRemainingGameTimeInMs();
      S32 cnow = clientGame->getGameType()->getRemainingGameTimeInMs();
      gamePair.idle(10, 10);
      S32 slater = serverGame->getGameType()->getRemainingGameTimeInMs();
      S32 clater = clientGame->getGameType()->getRemainingGameTimeInMs();
      EXPECT_NE(snow, slater) << "Looks like server clock is stopped (should be running)!";
      EXPECT_NE(cnow, clater) << "Looks like client clock is stopped (should be running)!";
   }

   clientGame->undelaySpawn();                                          // Simulate effects of key press
   gamePair.idle(10, 5);                                                // Idle; give things time to propagate
   ASSERT_FALSE(serverGame->isOrIsAboutToBeSuspended());

   ASSERT_EQ(0, serverGame->getClientInfo(0)->getReturnToGameTime());   // No returnToGame penalty
   ASSERT_FALSE(clientGame->inReturnToGameCountdown());

   gamePair.idle(Ship::KillDeleteDelay / 15, 20);     // Idle; give dead ships time to be cleaned up

   // Check to ensure ship spawned
   fillVector.clear();
   serverGame->getLevel()->findObjects(PlayerShipTypeNumber, fillVector);
   ASSERT_EQ(1, fillVector.size());   
   fillVector.clear();
   clientGame->getLevel()->findObjects(PlayerShipTypeNumber, fillVector);
   ASSERT_EQ(1, fillVector.size());

   ASSERT_FALSE(serverGame->isOrIsAboutToBeSuspended());
   ASSERT_FALSE(clientGame->isSpawnDelayed());         
}