Exemple #1
0
//=================================================================================================
bool QuestManager::Read(BitStream& stream)
{
	const int QUEST_MIN_SIZE = sizeof(int) + sizeof(byte) * 3;
	word quest_count;
	if(!stream.Read(quest_count)
		|| !EnsureSize(stream, QUEST_MIN_SIZE * quest_count))
	{
		Error("Read world: Broken packet for quests.");
		return false;
	}
	quests.resize(quest_count);

	int index = 0;
	for(Quest*& quest : quests)
	{
		quest = new PlaceholderQuest;
		quest->quest_index = index;
		if(!stream.Read(quest->refid) ||
			!stream.ReadCasted<byte>(quest->state) ||
			!ReadString1(stream, quest->name) ||
			!ReadStringArray<byte, word>(stream, quest->msgs))
		{
			Error("Read world: Broken packet for quest %d.", index);
			return false;
		}
		++index;
	}

	return true;
}
int main()
{
	FullyConnectedMesh2 fcm2;
	ConnectionGraph2 cg2;
	rakPeer=RakNet::RakPeerInterface::GetInstance();
	rakPeer->AttachPlugin(&fcm2);
	rakPeer->AttachPlugin(&cg2);
	fcm2.SetAutoparticipateConnections(true);
	RakNet::SocketDescriptor sd;
	sd.socketFamily=AF_INET; // Only IPV4 supports broadcast on 255.255.255.255
	sd.port=60000;
	while (IRNS2_Berkley::IsPortInUse(sd.port, sd.hostAddress, sd.socketFamily, SOCK_DGRAM)==true)
		sd.port++;
	StartupResult sr = rakPeer->Startup(8,&sd,1);
	RakAssert(sr==RAKNET_STARTED);
	rakPeer->SetMaximumIncomingConnections(8);
	rakPeer->SetTimeoutTime(1000,RakNet::UNASSIGNED_SYSTEM_ADDRESS);
	printf("Our guid is %s\n", rakPeer->GetGuidFromSystemAddress(RakNet::UNASSIGNED_SYSTEM_ADDRESS).ToString());
	printf("Started on %s\n", rakPeer->GetMyBoundAddress().ToString(true));
	BitStream contextBs;
	contextBs.Write(RakString("Our guid is %s\n", rakPeer->GetGuidFromSystemAddress(RakNet::UNASSIGNED_SYSTEM_ADDRESS).ToString()));
	fcm2.SetMyContext(&contextBs);

//	PacketLogger packetLogger;
//	rakPeer->AttachPlugin(&packetLogger);
//	packetLogger.SetLogDirectMessages(false);

	bool quit=false;
	RakNet::Packet *packet;
	char ch;
	while (!quit)
	{
		for (packet = rakPeer->Receive(); packet; rakPeer->DeallocatePacket(packet), packet = rakPeer->Receive())
		{
			switch (packet->data[0])
			{
			case ID_DISCONNECTION_NOTIFICATION:
				// Connection lost normally
				printf("ID_DISCONNECTION_NOTIFICATION\n");
				break;


			case ID_NEW_INCOMING_CONNECTION:
				// Somebody connected.  We have their IP now
				printf("ID_NEW_INCOMING_CONNECTION from %s. guid=%s.\n", packet->systemAddress.ToString(true), packet->guid.ToString());
				break;

			case ID_CONNECTION_REQUEST_ACCEPTED:
				// Somebody connected.  We have their IP now
				printf("ID_CONNECTION_REQUEST_ACCEPTED from %s. guid=%s.\n", packet->systemAddress.ToString(true), packet->guid.ToString());
				break;


			case ID_CONNECTION_LOST:
				// Couldn't deliver a reliable packet - i.e. the other system was abnormally
				// terminated
				printf("ID_CONNECTION_LOST\n");
				break;

			case ID_ADVERTISE_SYSTEM:
				if (packet->guid!=rakPeer->GetMyGUID())
					rakPeer->Connect(packet->systemAddress.ToString(false), packet->systemAddress.GetPort(),0,0);
				break;

			case ID_FCM2_NEW_HOST:
				{
				if (packet->guid==rakPeer->GetMyGUID())
					printf("Got new host (ourselves)");
				else
					printf("Got new host %s, GUID=%s", packet->systemAddress.ToString(true), packet->guid.ToString());
					RakNet::BitStream bs(packet->data,packet->length,false);
					bs.IgnoreBytes(1);
					RakNetGUID oldHost;
					bs.Read(oldHost);
					// If oldHost is different then the current host, then we lost connection to the host
					if (oldHost!=UNASSIGNED_RAKNET_GUID)
						printf(". Oldhost Guid=%s\n", oldHost.ToString());
					else
						printf(". (First reported host)\n");
				}
				break;

// 			case ID_REMOTE_NEW_INCOMING_CONNECTION:
// 				{
// 					uint32_t count;
// 					RakNet::BitStream bsIn(packet->data, packet->length,false);
// 					bsIn.IgnoreBytes(1);
// 					bsIn.Read(count);
// 					SystemAddress sa;
// 					RakNetGUID guid;
// 					printf("ID_REMOTE_NEW_INCOMING_CONNECTION from %s\n", packet->systemAddress.ToString(true));
// 					for (uint32_t i=0; i < count; i++)
// 					{
// 						bsIn.Read(sa);
// 						bsIn.Read(guid);
// 
// 						printf("%s ", sa.ToString(true));
// 					}
// 					printf("\n");
// 				}
			}
		}

		if (kbhit())
		{
			ch=getch();
			if (ch==' ')
			{

				DataStructures::List<RakNetGUID> participantList;
				fcm2.GetParticipantList(participantList);
				printf("%i participants\n", participantList.Size());
				for (int i=0; i < participantList.Size(); i++)
				{
					BitStream userContext;
					fcm2.GetParticipantContext(participantList[i], &userContext);
					RakString str;
					userContext.Read(str);
					printf("%i. %s: %s", i+1, participantList[i].ToString(), str.C_String());
				}
			}
			if (ch=='q' || ch=='Q')
			{
				printf("Quitting.\n");
				quit=true;
			}
		}

		RakSleep(30);
		for (int i=0; i < 32; i++)
		{
			if (rakPeer->GetInternalID(RakNet::UNASSIGNED_SYSTEM_ADDRESS,0).GetPort()!=60000+i)
				rakPeer->AdvertiseSystem("255.255.255.255", 60000+i, 0,0,0);
		}
	}

	RakNet::RakPeerInterface::DestroyInstance(rakPeer);
	return 0;
}
Exemple #3
0
void Necklace::GetData(BitStream& bsIn)
{
	bsIn.Read(mStrBonus);
	bsIn.Read(mDefBonus);
	bsIn.Read(mDexBonus);
	bsIn.Read(mDefBonus);
	bsIn.Read(mDexBonus);
	bsIn.Read(mIntBonus);
	bsIn.Read(mAtkBonus);
	bsIn.Read(mCritBonus);
	bsIn.Read(mHealthBonus);
	bsIn.Read(mManaBonus);
	bsIn.Read(mDefence);
	bsIn.Read(mLevelReq);
	bsIn.Read(mStrReq);
	bsIn.Read(mDefReq);
	bsIn.Read(mDexReq);
	bsIn.Read(mIntReq);
	bsIn.Read(mAtkReq);
}
int main(void)
{
	printf("Demonstrates networking elements for a P2P game on the PC, self-released,\nwith player hosted game servers\n");
	printf("Difficulty: Advanced\n\n");

	// ---------------------------------------------------------------------------------------------------------------------
	// Allocate plugins. See declaration in this file for description of each
	// ---------------------------------------------------------------------------------------------------------------------
	rakPeer=RakNet::RakPeerInterface::GetInstance();
	teamManager=TeamManager::GetInstance();
	fullyConnectedMesh2=FullyConnectedMesh2::GetInstance();
	networkIDManager = NetworkIDManager::GetInstance();
	cloudClient = CloudClient::GetInstance();
	natPunchthroughClient = NatPunchthroughClient::GetInstance();
#ifdef NAT_TYPE_DETECTION_SERVER
	natTypeDetectionClient = NatTypeDetectionClient::GetInstance();
#endif
	rpc4 = RPC4::GetInstance();
	readyEvent = ReadyEvent::GetInstance();
	replicaManager3=new SampleRM3;

	// ---------------------------------------------------------------------------------------------------------------------
	// Attach plugins
	// ---------------------------------------------------------------------------------------------------------------------
	rakPeer->AttachPlugin(fullyConnectedMesh2);
	rakPeer->AttachPlugin(teamManager);
	rakPeer->AttachPlugin(cloudClient);
	rakPeer->AttachPlugin(natPunchthroughClient);
#ifdef NAT_TYPE_DETECTION_SERVER
	rakPeer->AttachPlugin(natTypeDetectionClient);
#endif
	rakPeer->AttachPlugin(rpc4);
	rakPeer->AttachPlugin(readyEvent);
	rakPeer->AttachPlugin(replicaManager3);

	// ---------------------------------------------------------------------------------------------------------------------
	// Setup plugins: Disable automatically adding new connections. Allocate initial objects and register for replication
	// ---------------------------------------------------------------------------------------------------------------------
	// Allocate a world instance to be used for team operations
	teamManager->AddWorld(0);
	// Do not automatically count new connections
	teamManager->SetAutoManageConnections(false);
	
	// New connections do not count until after login.
	fullyConnectedMesh2->SetAutoparticipateConnections(false);	
		
	// Tell ReplicaManager3 which networkIDManager to use for object lookup, used for automatic serialization
	replicaManager3->SetNetworkIDManager(networkIDManager);
	// Do not automatically count new connections, but do drop lost connections automatically
	replicaManager3->SetAutoManageConnections(false,true);
	
	// Reference static game objects that always exist
	game = new Game;
	game->SetNetworkIDManager(networkIDManager);
	game->SetNetworkID(0);
	replicaManager3->Reference(game);

	// Setup my own user
	User *user = new User;
	user->SetNetworkIDManager(networkIDManager);
	user->userName = rakPeer->GetMyGUID().ToString();
	// Inform TeamManager of my user's team member info
	teamManager->GetWorldAtIndex(0)->ReferenceTeamMember(&user->tmTeamMember,user->GetNetworkID());

	// ---------------------------------------------------------------------------------------------------------------------
	// Startup RakNet on first available port
	// ---------------------------------------------------------------------------------------------------------------------
	RakNet::SocketDescriptor sd;
	sd.socketFamily=AF_INET; // Only IPV4 supports broadcast on 255.255.255.255
	sd.port=0;
	StartupResult sr = rakPeer->Startup(8,&sd,1);
	RakAssert(sr==RAKNET_STARTED);
	rakPeer->SetMaximumIncomingConnections(8);
	rakPeer->SetTimeoutTime(30000,RakNet::UNASSIGNED_SYSTEM_ADDRESS);
	printf("Our guid is %s\n", rakPeer->GetGuidFromSystemAddress(RakNet::UNASSIGNED_SYSTEM_ADDRESS).ToString());
	printf("Started on %s\n", rakPeer->GetMyBoundAddress().ToString(true));
	
	// Connect to master server
	game->EnterPhase(Game::CONNECTING_TO_SERVER);

	// ---------------------------------------------------------------------------------------------------------------------
	// Read packets loop
	// ---------------------------------------------------------------------------------------------------------------------
	char ch;
	Packet *packet;
	while (game->phase!=Game::EXIT_SAMPLE)
	{
		for (packet = rakPeer->Receive(); packet; rakPeer->DeallocatePacket(packet), packet = rakPeer->Receive())
		{
			switch (packet->data[0])
			{
			case ID_NEW_INCOMING_CONNECTION:
				{
					printf("ID_NEW_INCOMING_CONNECTION from %s. guid=%s.\n", packet->systemAddress.ToString(true), packet->guid.ToString());
				}
				break;
			case ID_CONNECTION_REQUEST_ACCEPTED:
				{
					printf("ID_CONNECTION_REQUEST_ACCEPTED from %s,guid=%s\n", packet->systemAddress.ToString(true), packet->guid.ToString());

					if (game->phase==Game::CONNECTING_TO_SERVER)
					{
						game->masterServerAddress=packet->systemAddress;
						game->masterServerGuid=packet->guid;

						// ---------------------------------------------------------------------------------------------------------------------
						// PC self-hosted servers only: Use master server to determine NAT type. Attempt to open router if needed.
						// ---------------------------------------------------------------------------------------------------------------------
						if (NAT_TYPE_DETECTION_SERVER)
						{
							game->EnterPhase(Game::DETERMINE_NAT_TYPE);
						}
						else
						{
							OpenUPNP();
							game->EnterPhase(Game::SEARCH_FOR_GAMES);
						}
					}
					else if (game->phase==Game::CONNECTING_TO_GAME_HOST)
					{
						printf("Asking host to join session...\n");

						// So time in single player does not count towards which system has been running multiplayer the longest
						fullyConnectedMesh2->ResetHostCalculation();

						// Custom message to ask to join the game
						// We first connect to the game host, and the game host is responsible for calling StartVerifiedJoin() for us to join the session
						BitStream bsOut;
						bsOut.Write((MessageID)ID_USER_PACKET_ENUM);
						rakPeer->Send(&bsOut,HIGH_PRIORITY,RELIABLE_ORDERED,0,packet->guid,false);
					}
				}
				break;
			case ID_CONNECTION_LOST:
			case ID_DISCONNECTION_NOTIFICATION:
				if (game->phase==Game::DETERMINE_NAT_TYPE)
				{
					printf("Lost connection during NAT type detection. Reason %s. Retrying...\n", PacketLogger::BaseIDTOString(packet->data[0]));
					game->EnterPhase(Game::CONNECTING_TO_SERVER);
				}
				else if (game->phase==Game::NAT_PUNCH_TO_GAME_HOST)
				{
					printf("Lost connection during NAT punch to game host. Reason %s.\n", PacketLogger::BaseIDTOString(packet->data[0]));
					game->EnterPhase(Game::SEARCH_FOR_GAMES);
				}
				else
				{
					if (packet->guid==game->masterServerGuid)
					{
						printf("Server connection lost. Reason %s.\nGame session is no longer searchable.\n", PacketLogger::BaseIDTOString(packet->data[0]));
					}
					else
					{
						printf("Peer connection lost. Reason %s.\n", PacketLogger::BaseIDTOString(packet->data[0]));
					}
				}
				break;

			case ID_ALREADY_CONNECTED:
				printf("ID_ALREADY_CONNECTED with guid %"PRINTF_64_BIT_MODIFIER"u\n", packet->guid);
				break;

			case ID_INVALID_PASSWORD:
			case ID_NO_FREE_INCOMING_CONNECTIONS:
			case ID_CONNECTION_ATTEMPT_FAILED:
			case ID_CONNECTION_BANNED:
			case ID_IP_RECENTLY_CONNECTED:
			case ID_INCOMPATIBLE_PROTOCOL_VERSION:
				// Note: Failing to connect to another system does not automatically mean we cannot join a session, since that system may be disconnecting from the host simultaneously
				// FullyConnectedMesh2::StartVerifiedJoin() internally handles success or failure and notifies the client through ID_FCM2_VERIFIED_JOIN_FAILED if needed.
				printf("Failed to connect to %s. Reason %s\n", packet->systemAddress.ToString(true), PacketLogger::BaseIDTOString(packet->data[0]));

				if (game->phase==Game::CONNECTING_TO_SERVER)
					game->EnterPhase(Game::EXIT_SAMPLE);
				break;
				
			case ID_FCM2_NEW_HOST:
				{
					RakNet::BitStream bs(packet->data,packet->length,false);
					bs.IgnoreBytes(1);
					RakNetGUID oldHost;
					bs.Read(oldHost);

					if (packet->guid==rakPeer->GetMyGUID())
					{
						if (oldHost!=UNASSIGNED_RAKNET_GUID)
						{
							PostRoomToCloud();
							printf("ID_FCM2_NEW_HOST: Taking over as host from the old host.\nNew options:\n");
						}
						else
						{
							// Room not hosted if we become host the first time since this was done in CreateRoom() already
							printf("ID_FCM2_NEW_HOST: We have become host for the first time. New options:\n");
						}

						printf("(L)ock and unlock game\n");
					}
					else
					{
						if (oldHost!=UNASSIGNED_RAKNET_GUID)
							printf("ID_FCM2_NEW_HOST: A new system %s has become host, GUID=%s\n", packet->systemAddress.ToString(true), packet->guid.ToString());
						else
							printf("ID_FCM2_NEW_HOST: System %s is host, GUID=%s\n", packet->systemAddress.ToString(true), packet->guid.ToString());
					}

					if (oldHost==UNASSIGNED_RAKNET_GUID)
					{
						// First time calculated host. Add existing connections to ReplicaManager3
						DataStructures::List<RakNetGUID> participantList;
						fullyConnectedMesh2->GetParticipantList(participantList);
						for (unsigned int i=0; i < participantList.Size(); i++)
							RegisterGameParticipant(participantList[i]);

						// Reference previously created replicated objects, which cannot be serialized until host is known the first time
						if (packet->guid==rakPeer->GetMyGUID())
						{
							// As host, reference the teams we created
							for (unsigned int i=0; i < game->teams.Size(); i++)
								replicaManager3->Reference(game->teams[i]);
						}

						// Reference the user we created (host or not)
						for (unsigned int i=0; i < game->users.Size(); i++)
							replicaManager3->Reference(game->users[i]);
					}
				}
				break;
			case ID_TEAM_BALANCER_TEAM_ASSIGNED:
				{
					printf("ID_TEAM_BALANCER_TEAM_ASSIGNED for ");
					TM_World *world;
					TM_TeamMember *teamMember;
					teamManager->DecodeTeamAssigned(packet, &world, &teamMember);
					printf("worldId=%i teamMember=%s", world->GetWorldId(), ((User*)teamMember->GetOwner())->userName.C_String());
					if (teamMember->GetCurrentTeam()==0)
						printf(" not on team\n");
					else
						printf(" on team %s\n", ((Team*)(teamMember->GetCurrentTeam()->GetOwner()))->teamName.C_String());
				}
				break;
			case ID_TEAM_BALANCER_REQUESTED_TEAM_FULL:
				{
					printf("ID_TEAM_BALANCER_REQUESTED_TEAM_FULL\n");
				}
				break;
			case ID_TEAM_BALANCER_REQUESTED_TEAM_LOCKED:
				{
					printf("ID_TEAM_BALANCER_REQUESTED_TEAM_LOCKED\n");
				}
				break;
			case ID_TEAM_BALANCER_TEAM_REQUESTED_CANCELLED:
				{
					printf("ID_TEAM_BALANCER_TEAM_REQUESTED_CANCELLED\n");
				}
				break;
			case ID_NAT_TARGET_NOT_CONNECTED:
			case ID_NAT_TARGET_UNRESPONSIVE:
			case ID_NAT_CONNECTION_TO_TARGET_LOST:
			case ID_NAT_PUNCHTHROUGH_FAILED:
				{
					// As with connection failed, this does not automatically mean we cannot join the session
					// We only fail on ID_FCM2_VERIFIED_JOIN_FAILED
					printf("NAT punch to %s failed. Reason %s\n", packet->guid.ToString(), PacketLogger::BaseIDTOString(packet->data[0]));

					if (game->phase==Game::NAT_PUNCH_TO_GAME_HOST)
						game->EnterPhase(Game::SEARCH_FOR_GAMES);
				}

			case ID_NAT_ALREADY_IN_PROGRESS:
				// Can ignore this
				break;

			case ID_NAT_PUNCHTHROUGH_SUCCEEDED:
				{
					if (game->phase==Game::NAT_PUNCH_TO_GAME_HOST || game->phase==Game::VERIFIED_JOIN)
					{
						// Connect to the session host
						ConnectionAttemptResult car = rakPeer->Connect(packet->systemAddress.ToString(false), packet->systemAddress.GetPort(), 0, 0);
						if (car!=RakNet::CONNECTION_ATTEMPT_STARTED)
						{
							printf("Failed connect call to %s. Code=%i\n", packet->systemAddress.ToString(false), car);
							game->EnterPhase(Game::SEARCH_FOR_GAMES);
						}
						else
						{
							if (game->phase==Game::NAT_PUNCH_TO_GAME_HOST)
							{
								printf("NAT punch completed. Connecting to %s (game host)...\n", packet->systemAddress.ToString(true));
								game->EnterPhase(Game::CONNECTING_TO_GAME_HOST);
							}
							else
							{
								printf("NAT punch completed. Connecting to %s (game client)...\n", packet->systemAddress.ToString(true));
							}
						}
					}
				}
				break;


			case ID_CLOUD_GET_RESPONSE:
				{
					cloudClient->DeallocateWithDefaultAllocator(&cloudQueryResult);
					cloudClient->OnGetReponse(&cloudQueryResult, packet);
					unsigned int rowIndex;

					for (rowIndex=0; rowIndex < cloudQueryResult.rowsReturned.Size(); rowIndex++)
					{
						RakNet::CloudQueryRow *row = cloudQueryResult.rowsReturned[rowIndex];
						printf("%i. ", rowIndex);
						PrintRow(row);
					}

					printf("(J)oin room\n");
					printf("(C)reate room\n");
					printf("(S)earch rooms\n");
				}
				break;
			
			case ID_NAT_TYPE_DETECTION_RESULT:
				{
					game->myNatType = (RakNet::NATTypeDetectionResult) packet->data[1];
					printf("NAT Type is %s (%s)\n", NATTypeDetectionResultToString(game->myNatType), NATTypeDetectionResultToStringFriendly(game->myNatType));

					if (game->myNatType!=RakNet::NAT_TYPE_NONE)
					{
						OpenUPNP();
					}

					if (game->myNatType==RakNet::NAT_TYPE_PORT_RESTRICTED || game->myNatType==RakNet::NAT_TYPE_SYMMETRIC)
					{
						printf("Note: Your router must support UPNP or have the user manually forward ports.\n");
						printf("Otherwise NATPunchthrough may not always succeed.\n");
					}

					game->EnterPhase(Game::SEARCH_FOR_GAMES);
				}
				break;
				
			case ID_READY_EVENT_ALL_SET:
				printf("Got ID_READY_EVENT_ALL_SET from %s\n", packet->systemAddress.ToString(true));
				printf("All users ready.\n");
				if (fullyConnectedMesh2->IsConnectedHost())
					printf("New options:\n(B)egin gameplay\n");
				break;

			case ID_READY_EVENT_SET:
				printf("Got ID_READY_EVENT_SET from %s\n", packet->systemAddress.ToString(true));
				break;

			case ID_READY_EVENT_UNSET:
				printf("Got ID_READY_EVENT_UNSET from %s\n", packet->systemAddress.ToString(true));
				break;

			// ID_USER_PACKET_ENUM is used by this sample as a custom message to ask to join a game
			case ID_USER_PACKET_ENUM:
				if (game->phase > Game::SEARCH_FOR_GAMES)
				{
					printf("Got request from client to join session.\nExecuting StartVerifiedJoin()\n");
					fullyConnectedMesh2->StartVerifiedJoin(packet->guid);
				}
				else
				{
					BitStream bsOut;
					bsOut.Write((MessageID)(ID_USER_PACKET_ENUM+1));
					rakPeer->Send(&bsOut,HIGH_PRIORITY,RELIABLE_ORDERED,0,packet->guid,false);
				}
				break;
			// ID_USER_PACKET_ENUM+1 is used by this sample as a custom message to reject a join game request
			// Requests may also be later rejected through FullyConnectedMesh2::RespondOnVerifiedJoinCapable() to send ID_FCM2_VERIFIED_JOIN_REJECTED
			case (ID_USER_PACKET_ENUM+1):
				printf("Join request denied\n");
				game->EnterPhase(Game::SEARCH_FOR_GAMES);
				break;
			case ID_FCM2_VERIFIED_JOIN_START:
				{
					game->EnterPhase(Game::VERIFIED_JOIN);

					// This message means the session host sent us a list of systems in the session
					// Once we connect to, or fail to connect to, each of these systems we will get ID_FCM2_VERIFIED_JOIN_FAILED, ID_FCM2_VERIFIED_JOIN_ACCEPTED, or ID_FCM2_VERIFIED_JOIN_REJECTED
					printf("Host sent us system list. Doing NAT punch to each system...\n");
					DataStructures::List<SystemAddress> addresses;
					DataStructures::List<RakNetGUID> guids;
					fullyConnectedMesh2->GetVerifiedJoinRequiredProcessingList(packet->guid, addresses, guids);
					for (unsigned int i=0; i < guids.Size(); i++)
						natPunchthroughClient->OpenNAT(guids[i], game->masterServerAddress);
				}
				break;

			case ID_FCM2_VERIFIED_JOIN_CAPABLE:
				printf("Client is capable of joining FullyConnectedMesh2.\n");
				if (game->lockGame)
				{
					RakNet::BitStream bsOut;
					bsOut.Write("Game is locked");
					fullyConnectedMesh2->RespondOnVerifiedJoinCapable(packet, false, &bsOut);
				}
				else
					fullyConnectedMesh2->RespondOnVerifiedJoinCapable(packet, true, 0);
				break;

			case ID_FCM2_VERIFIED_JOIN_ACCEPTED:
				{
					DataStructures::List<RakNetGUID> systemsAccepted;
					bool thisSystemAccepted;
					fullyConnectedMesh2->GetVerifiedJoinAcceptedAdditionalData(packet, &thisSystemAccepted, systemsAccepted, 0);
					if (thisSystemAccepted)
						printf("Game join request accepted\n");
					else
						printf("System %s joined the mesh\n", systemsAccepted[0].ToString());

					// Add the new participant to the game if we already know who the host is. Otherwise do this
					// once ID_FCM2_NEW_HOST arrives
					if (fullyConnectedMesh2->GetConnectedHost()!=UNASSIGNED_RAKNET_GUID)
					{
						// FullyConnectedMesh2 already called AddParticipant() for each accepted system
						// Still need to add those systems to the other plugins though
						for (unsigned int i=0; i < systemsAccepted.Size(); i++)
							RegisterGameParticipant(systemsAccepted[i]);

						if (thisSystemAccepted)
							game->EnterPhase(Game::IN_LOBBY_WITH_HOST);
					}
					else
					{
						if (thisSystemAccepted)
							game->EnterPhase(Game::IN_LOBBY_WAITING_FOR_HOST);
					}

					printf("(E)xit room\n");
				}
				break;

			case ID_FCM2_VERIFIED_JOIN_REJECTED:
				{
					BitStream additionalData;
					fullyConnectedMesh2->GetVerifiedJoinRejectedAdditionalData(packet, &additionalData);
					RakString reason;
					additionalData.Read(reason);
					printf("Join rejected. Reason=%s\n", reason.C_String());
					rakPeer->CloseConnection(packet->guid, true);
					game->EnterPhase(Game::SEARCH_FOR_GAMES);
					break;
				}

			case ID_REPLICA_MANAGER_DOWNLOAD_COMPLETE:
				{
					if (replicaManager3->GetAllConnectionDownloadsCompleted()==true)
					{
						printf("Completed all remote downloads\n");

						if (game->gameInLobby)
							game->EnterPhase(Game::IN_LOBBY_WITH_HOST);
						else
							game->EnterPhase(Game::IN_GAME);
					}

					break;
				}
			}
		}

		if (kbhit())
		{
			ch=getch();

			if (game->phase==Game::SEARCH_FOR_GAMES)
			{
				if (ch=='c' || ch=='C')
				{
					CreateRoom();
				}
				if (ch=='s' || ch=='S')
				{
					game->SearchForGames();
				}
				else if (ch=='j' || ch=='J')
				{
					// Join room
					if (cloudQueryResult.rowsReturned.Size()==0)
					{
						printf("No rooms to join.\n");
					}
					else
					{
						int index;
						if (cloudQueryResult.rowsReturned.Size()>1)
						{
							printf("Enter index of room to join.\n");
							char indexstr[64];
							Gets(indexstr,64);
							index = atoi(indexstr);
						}
						else
						{
							index = 0;
						}

						if (index < 0 || (unsigned int) index >= cloudQueryResult.rowsReturned.Size())
						{
							printf("Index out of range.\n");
						}
						else
						{
							CloudQueryRow *row = cloudQueryResult.rowsReturned[index];
							// Connect to the session host using NATPunchthrough
							natPunchthroughClient->OpenNAT(row->clientGUID, game->masterServerAddress);
							game->EnterPhase(Game::NAT_PUNCH_TO_GAME_HOST);
						}
					}
				}
			}
			else
			{
				if (game->phase==Game::IN_GAME)
				{
					if (ch=='c' || ch=='C')
					{
						DataStructures::List<RakNetGUID> participantList;
						fullyConnectedMesh2->GetParticipantList(participantList);

						if (participantList.Size()>0)
						{
							printf("Enter in-game chat message: ");
							char str[256];
							Gets(str, 256);
							RakString rs;
							// Don't use RakString constructor to assign str, or will process % escape characters
							rs=str;
							BitStream bsOut;
							bsOut.Write(rs);
							for (unsigned int i=0; i < participantList.Size(); i++)
								rpc4->Signal("InGameChat", &bsOut, HIGH_PRIORITY, RELIABLE_ORDERED, 0, participantList[i], false, false);
						}
					}
				}

				if (ch=='1')
				{
					user->tmTeamMember.RequestTeamSwitch(&game->teams[0]->tmTeam, 0);
				}
				else if (ch=='2')
				{
					user->tmTeamMember.RequestTeamSwitch(&game->teams[1]->tmTeam, 0);
				}
				else if (ch=='r' || ch=='R')
				{
					if (readyEvent->SetEvent(0, true))
						printf("We are ready to start.\n");
				}
				else if (ch=='u' || ch=='U')
				{
					if (readyEvent->SetEvent(0, false))
						printf("We are no longer ready to start.\n");
				}
				else if (ch=='l' || ch=='L')
				{
					if (fullyConnectedMesh2->IsConnectedHost())
					{
						if (game->lockGame)
						{
							printf("Game is no longer locked\n");
							game->lockGame=false;
						}
						else
						{
							printf("Game is now locked\n");
							game->lockGame=true;
						}
					}
				}
				else if (ch=='b' || ch=='B')
				{
					if (fullyConnectedMesh2->IsConnectedHost())
					{
						if (game->gameInLobby)
						{
							readyEvent->ForceCompletion(0);
							game->gameInLobby=false;
							game->EnterPhase(Game::IN_GAME);
						}
						else
						{
							readyEvent->DeleteEvent(0);
							printf("Game ended, and now in lobby\n");
							game->gameInLobby=true;
							game->EnterPhase(Game::IN_LOBBY_WITH_HOST);
						}
					}
				}
				else if (ch=='e' || ch=='E')
				{
					// Disconnect from FullyConnectedMesh2 participants
					DataStructures::List<RakNetGUID> participantList;
					fullyConnectedMesh2->GetParticipantList(participantList);
					for (unsigned int i=0; i < participantList.Size(); i++)
						rakPeer->CloseConnection(participantList[i], true);

					// User instances are deleted automatically from ReplicaManager3.
					// However, teams are not deleted since the Team class can migrate between systems. So delete Team instances manually
					while (game->teams.Size())
						delete game->teams[game->teams.Size()-1];

					// If we were the host, no longer list this session
					// The new host will call PostRoomToCloud to reupload under a new IP address on ID_FCM2_NEW_HOST
					ReleaseRoomFromCloud();

					// Clear out state data from plugins
					fullyConnectedMesh2->Clear();
					readyEvent->DeleteEvent(0);
					replicaManager3->Clear(false);
					replicaManager3->Reference(game);

					game->Reset();
					game->EnterPhase(Game::SEARCH_FOR_GAMES);
				}
				else if (ch=='q' || ch=='Q')
				{
					printf("Quitting.\n");
					// Disconnecting from the master server automatically releases from cloud
					game->EnterPhase(Game::EXIT_SAMPLE);
				}
			}
		}

		RakSleep(30);
	}

	rakPeer->Shutdown(100);

	while (game->teams.Size())
		delete game->teams[game->teams.Size()-1];
	while (game->users.Size())
		delete game->users[game->users.Size()-1];
	delete game;

	cloudClient->DeallocateWithDefaultAllocator(&cloudQueryResult);
	RakPeerInterface::DestroyInstance(rakPeer);
	TeamManager::DestroyInstance(teamManager);
	FullyConnectedMesh2::DestroyInstance(fullyConnectedMesh2);
	cloudClient->DeallocateWithDefaultAllocator(&cloudQueryResult);
	CloudClient::DestroyInstance(cloudClient);
	NatPunchthroughClient::DestroyInstance(natPunchthroughClient);
	NatTypeDetectionClient::DestroyInstance(natTypeDetectionClient);
	RPC4::DestroyInstance(rpc4);
	ReadyEvent::DestroyInstance(readyEvent);
	delete replicaManager3;
	NetworkIDManager::DestroyInstance(networkIDManager);

	return 1;
}
int ReliableOrderedConvertedTest::RunTest(DataStructures::List<RakString> params,bool isVerbose,bool noPauses)
{

	RakPeerInterface *sender, *receiver;
	unsigned int packetNumberSender[32],packetNumberReceiver[32], receivedPacketNumberReceiver, receivedTimeReceiver;
	char str[256];
	char ip[32];
	TimeMS sendInterval, nextSend, currentTime, quitTime;
	unsigned short remotePort, localPort;
	unsigned char streamNumberSender,streamNumberReceiver;
	BitStream bitStream;
	Packet *packet;
	bool doSend=false;

	for (int i=0; i < 32; i++)
	{
		packetNumberSender[i]=0;
		packetNumberReceiver[i]=0;

	}

	/*
	if (argc==2)
	{
	fp = fopen(argv[1],"wt");
	SetMalloc_Ex(LoggedMalloc);
	SetRealloc_Ex(LoggedRealloc);
	SetFree_Ex(LoggedFree);
	}
	else
	*/
	fp=0;
	destroyList.Clear(false,_FILE_AND_LINE_);

	sender =RakPeerInterface::GetInstance();
	destroyList.Push(	sender ,_FILE_AND_LINE_);
	//sender->ApplyNetworkSimulator(.02, 100, 50);

	/*
	if (str[0]==0)
	sendInterval=30;
	else
	sendInterval=atoi(str);*///possible future params

	sendInterval=30;

	/*
	printf("Enter remote IP: ");
	Gets(ip, sizeof(ip));
	if (ip[0]==0)*/
	strcpy(ip, "127.0.0.1");

	/*
	printf("Enter remote port: ");
	Gets(str, sizeof(str));
	if (str[0]==0)*/
	strcpy(str, "60000");
	remotePort=atoi(str);
	/*
	printf("Enter local port: ");
	Gets(str, sizeof(str));
	if (str[0]==0)*/
	strcpy(str, "0");
	localPort=atoi(str);

	if (isVerbose)
		printf("Connecting...\n");

	sender->Startup(1, &SocketDescriptor(localPort,0), 1);
	sender->Connect(ip, remotePort, 0, 0);

	receiver =RakPeerInterface::GetInstance();
	destroyList.Push(	receiver ,_FILE_AND_LINE_);

	/*
	printf("Enter local port: ");
	Gets(str, sizeof(str));
	if (str[0]==0)*/
	strcpy(str, "60000");
	localPort=atoi(str);

	if (isVerbose)
		printf("Waiting for connections...\n");

	receiver->Startup(32, &SocketDescriptor(localPort,0), 1);
	receiver->SetMaximumIncomingConnections(32);

	//	if (sender)
	//		sender->ApplyNetworkSimulator(128000, 50, 100);
	//	if (receiver)
	//		receiver->ApplyNetworkSimulator(128000, 50, 100);

	/*printf("How long to run this test for, in seconds?\n");
	Gets(str, sizeof(str));
	if (str[0]==0)*/
	strcpy(str, "12");

	currentTime = GetTimeMS();
	quitTime = atoi(str) * 1000 + currentTime;

	nextSend=currentTime;

	while (currentTime < quitTime)
		//while (1)
	{

		packet = sender->Receive();
		while (packet)
		{
			// PARSE TYPES
			switch(packet->data[0])
			{
			case ID_CONNECTION_REQUEST_ACCEPTED:
				if (isVerbose)
					printf("ID_CONNECTION_REQUEST_ACCEPTED\n");
				doSend=true;
				nextSend=currentTime;
				break;
			case ID_NO_FREE_INCOMING_CONNECTIONS:
				if (isVerbose)
					printf("ID_NO_FREE_INCOMING_CONNECTIONS\n");
				break;
			case ID_DISCONNECTION_NOTIFICATION:
				if (isVerbose)
					printf("ID_DISCONNECTION_NOTIFICATION\n");
				break;
			case ID_CONNECTION_LOST:
				if (isVerbose)
					printf("ID_CONNECTION_LOST\n");
				break;
			case ID_CONNECTION_ATTEMPT_FAILED:
				if (isVerbose)
					printf("Connection attempt failed\n");
				break;
			}

			sender->DeallocatePacket(packet);
			packet = sender->Receive();
		}

		while (doSend && currentTime > nextSend)
		{
			streamNumberSender=0;
			//	streamNumber = randomMT() % 32;
			// Do the send
			bitStream.Reset();
			bitStream.Write((unsigned char) (ID_USER_PACKET_ENUM+1));
			bitStream.Write(packetNumberSender[streamNumberSender]++);
			bitStream.Write(streamNumberSender);
			bitStream.Write(currentTime);
			char *pad;
			int padLength = (randomMT() % 5000) + 1;
			pad = new char [padLength];
			bitStream.Write(pad, padLength);
			delete [] pad;
			// Send on a random priority with a random stream
			// if (sender->Send(&bitStream, HIGH_PRIORITY, (PacketReliability) (RELIABLE + (randomMT() %2)) ,streamNumber, UNASSIGNED_SYSTEM_ADDRESS, true)==false)
			if (sender->Send(&bitStream, HIGH_PRIORITY, RELIABLE_ORDERED ,streamNumberSender, UNASSIGNED_SYSTEM_ADDRESS, true)==false)
				packetNumberSender[streamNumberSender]--; // Didn't finish connecting yet?

			RakNetStatistics *rssSender;
			rssSender=sender->GetStatistics(sender->GetSystemAddressFromIndex(0));
			if (isVerbose)
				printf("Snd: %i.\n", packetNumberSender[streamNumberSender]);

			nextSend+=sendInterval;

			// Test halting
			//	if (rand()%20==0)
			//		nextSend+=1000;
		}

		packet = receiver->Receive();
		while (packet)
		{
			switch(packet->data[0])
			{
			case ID_NEW_INCOMING_CONNECTION:
				if (isVerbose)
					printf("ID_NEW_INCOMING_CONNECTION\n");
				break;
			case ID_DISCONNECTION_NOTIFICATION:
				if (isVerbose)
					printf("ID_DISCONNECTION_NOTIFICATION\n");
				break;
			case ID_CONNECTION_LOST:
				if (isVerbose)
					printf("ID_CONNECTION_LOST\n");
				break;
			case ID_USER_PACKET_ENUM+1:
				bitStream.Reset();
				bitStream.Write((char*)packet->data, packet->length);
				bitStream.IgnoreBits(8); // Ignore ID_USER_PACKET_ENUM+1
				bitStream.Read(receivedPacketNumberReceiver);
				bitStream.Read(streamNumberReceiver);
				bitStream.Read(receivedTimeReceiver);

				if (receivedPacketNumberReceiver!=packetNumberReceiver[streamNumberReceiver])
				{

					//WARNING: If you modify the below code make sure the whole string remains in bounds, sprintf will NOT do it for you. 
					//The error string is 512 in length

					//Note: Removed buffer checking because chance is insignificant, left code if wanted in future. Needs limits.h ISO C standard.

					/*
					int maxIntWorkingCopy= INT_MAX;

					int maxIntCharLen =0; 

					while (maxIntWorkingCopy>0)
					{maxIntCharLen++;
					maxIntWorkingCopy/=10;
					}

					if (strlen(lastError)>maxIntCharLen* 3 +27)//512 should be a good len for now
					{*/

					sprintf(lastError,"Expecting %i got %i (channel %i).",packetNumberReceiver[streamNumberReceiver], receivedPacketNumberReceiver, streamNumberReceiver);

					/*
					}
					else
					{
					sprintf(lastError,"Did not get what was expected. More details can be given if the error string buffer size is increased.");

					}*/

					if (isVerbose)
					{

						RakNetStatistics *rssSender,*rssReceiver;
						char message[2048];

						rssSender=sender->GetStatistics(sender->GetSystemAddressFromIndex(0));

						rssReceiver=receiver->GetStatistics(receiver->GetSystemAddressFromIndex(0));
						StatisticsToString(rssSender, message, 2);
						printf("Server stats %s\n", message);
						StatisticsToString(rssReceiver, message, 2);
						printf("Client stats%s", message);

						DebugTools::ShowError(lastError,!noPauses && isVerbose,__LINE__,__FILE__);
					}

					return 1;
				}
				else
					if (isVerbose)
					{
						printf("Got %i.Channel %i.Len %i.", packetNumberReceiver[streamNumberReceiver], streamNumberReceiver, packet->length);

						printf("Sent=%u Received=%u Diff=%i.\n", receivedTimeReceiver, currentTime, (int)currentTime - (int) receivedTimeReceiver);
					}

					packetNumberReceiver[streamNumberReceiver]++;
					break;
			}

			receiver->DeallocatePacket(packet);
			packet = receiver->Receive();
		}

		RakSleep(0);

		currentTime=GetTimeMS();
	}

	if (isVerbose)
	{

		RakNetStatistics *rssSender,*rssReceiver;
		char message[2048];

		rssSender=sender->GetStatistics(sender->GetSystemAddressFromIndex(0));

		rssReceiver=receiver->GetStatistics(receiver->GetSystemAddressFromIndex(0));
		StatisticsToString(rssSender, message, 2);
		printf("Server stats %s\n", message);
		StatisticsToString(rssReceiver, message, 2);
		printf("Client stats%s", message);
	}

	if (fp)
		fclose(fp);

	return 0;
}
Exemple #6
0
/*
What is being done here is having 8 peers all connect to eachother and be
connected. Then it check if they all connect. If so send data in ordered reliable mode for 100
loops.

Possible ideas for changes:
Possibly use rakpeerinterfaces GetSystemList() for number of 
connected peers instead of manually tracking. Would be slower though,
shouldn't be significant at this number but the recieve speed it part of the test.

Success conditions:
Peers connect and receive all packets in order.
No disconnections allowed in this version of the test.

Failure conditions:

If cannot connect to all peers for 20 seconds.
All packets are not recieved.
All packets are not in order.
Disconnection.
*/
int EightPeerTest::RunTest(DataStructures::List<RakString> params,bool isVerbose,bool noPauses)
{
	const int peerNum= 8;
	RakPeerInterface *peerList[peerNum];//A list of 8 peers
	int connectionAmount[peerNum];//Counter for me to keep track of connection requests and accepts
	int recievedFromList[peerNum][peerNum];//Counter for me to keep track of packets received
	int lastNumberReceivedFromList[peerNum][peerNum];//Counter for me to keep track of last recieved sequence number
	const int numPackets=100;
	Packet *packet;
	BitStream bitStream;
	destroyList.Clear(false,_FILE_AND_LINE_);

	//Initializations of the arrays
	for (int i=0;i<peerNum;i++)
	{
		peerList[i]=RakPeerInterface::GetInstance();
		destroyList.Push(peerList[i],_FILE_AND_LINE_);
		connectionAmount[i]=0;

		for (int j=0;j<peerNum;j++)
		{
			recievedFromList[i][j]=0;
			lastNumberReceivedFromList[i][j]=0;
		}

		peerList[i]->Startup(peerNum*2, &SocketDescriptor(60000+i,0), 1);
		peerList[i]->SetMaximumIncomingConnections(peerNum);

	}

	//Connect all the peers together
	for (int i=0;i<peerNum;i++)
	{
		for (int j=i+1;j<peerNum;j++)//Start at i+1 so don't connect two of the same together.
		{
			if (peerList[i]->Connect("127.0.0.1", 60000+j, 0,0)!=CONNECTION_ATTEMPT_STARTED)
			{
				if (isVerbose)
				{
					DebugTools::ShowError("Problem while calling connect. \n",!noPauses && isVerbose,__LINE__,__FILE__);

				}
				return 1;//This fails the test, don't bother going on.
			}
		}

	}

	TimeMS entryTime=GetTimeMS();//Loop entry time
	TimeMS finishTimer=GetTimeMS();
	bool initialConnectOver=false;//Our initial connect all has been done.

	for (int k=0;k<numPackets||GetTimeMS()-finishTimer<5000;)//Quit after we send 100 messages while connected, if not all connected and not failure, otherwise fail after 20 seconds and exit
	{
		bool allConnected=true;//Start true, only one failed case makes it all fail
		for (int i=0;i<peerNum;i++)//Make sure all peers are connected to eachother
		{
			if (connectionAmount[i]<peerNum-1)
			{
				allConnected=false;
			}
		}

		if (GetTimeMS()-entryTime>20000 &&!initialConnectOver &&!allConnected)//failed for 20 seconds
		{

			if (isVerbose)
				DebugTools::ShowError("Failed to connect to all peers after 20 seconds",!noPauses && isVerbose,__LINE__,__FILE__);
			return 2;
			break;
		}

		if (allConnected)
		{
			if(!initialConnectOver)
				initialConnectOver=true;
			if (k<numPackets)
			{
			for (int i=0;i<peerNum;i++)//Have all peers send a message to all peers
			{

				bitStream.Reset();

				bitStream.Write((unsigned char) (ID_USER_PACKET_ENUM+1));

				bitStream.Write(k);
				bitStream.Write(i);

				peerList[i]->Send(&bitStream, HIGH_PRIORITY, RELIABLE_ORDERED ,0, UNASSIGNED_SYSTEM_ADDRESS, true);

			}
			}
			k++;
		}

		if (k>=numPackets-3)//This is our last 3 packets, give it time to send packet and arrive on interface, 2 seconds is more than enough 
		{
			RakSleep(300);
			if (k==numPackets)
			{
				finishTimer=GetTimeMS();
			}
		}

		for (int i=0;i<peerNum;i++)//Receive for all peers
		{
			if (allConnected)//If all connected try to make the data more visually appealing by bunching it in one receive
			{
				int waittime=0;
				do
				{
					packet=peerList[i]->Receive();
					waittime++;

					if (!packet)
					{
						RakSleep(1);

					}

					if (waittime>1000)//Check for packet every millisec and if one second has passed move on, don't block execution
					{
						break;
					}
				}
				while(!packet);//For testing purposes wait for packet a little while, go if not recieved
			}
			else//Otherwise just keep recieving quickly until connected
			{
				packet=peerList[i]->Receive();
			}
			if (isVerbose)
				printf("For peer %i with %i connected peers.\n",i,connectionAmount[i]);
			while(packet)
			{
				switch (packet->data[0])
				{
				case ID_REMOTE_DISCONNECTION_NOTIFICATION:
					if (isVerbose)
					{
						printf("Another client has disconnected.\n");
						DebugTools::ShowError("Test failed.\n",!noPauses && isVerbose,__LINE__,__FILE__);
					}
					return 3;
					break;
				case ID_REMOTE_CONNECTION_LOST:
					if (isVerbose)
					{
						printf("Another client has lost the connection.\n");
						DebugTools::ShowError("Test failed.\n",!noPauses && isVerbose,__LINE__,__FILE__);           
					}
					return 3;
					break;
				case ID_REMOTE_NEW_INCOMING_CONNECTION:
					if (isVerbose)              
						printf("Another client has connected.\n");
					break;
				case ID_CONNECTION_REQUEST_ACCEPTED:
					if (isVerbose)              
						printf("Our connection request has been accepted.\n");
					connectionAmount[i]++;

					break;
				case ID_CONNECTION_ATTEMPT_FAILED:

					if (isVerbose)
						DebugTools::ShowError("A connection has failed.\n Test failed.\n",!noPauses && isVerbose,__LINE__,__FILE__);
					return 2;
					break;

				case ID_NEW_INCOMING_CONNECTION:
					if (isVerbose)              
						printf("A connection is incoming.\n");
					connectionAmount[i]++;//For this test assume connection. Test will fail if connection fails.
					break;
				case ID_NO_FREE_INCOMING_CONNECTIONS://Should not happend
					if (isVerbose)    
					{
						printf("The server is full. This shouldn't happen in this test ever.\n");

						DebugTools::ShowError("Test failed.\n",!noPauses && isVerbose,__LINE__,__FILE__);
					}
					return 2;
					break;

				case ID_ALREADY_CONNECTED:
					if (isVerbose)              
						printf("Already connected\n");//Shouldn't happen

					break;

				case ID_DISCONNECTION_NOTIFICATION:
					if (isVerbose)
					{
						printf("We have been disconnected.\n");

						DebugTools::ShowError("Test failed.\n",!noPauses && isVerbose,__LINE__,__FILE__);
					}
					return 3;
					break;
				case ID_CONNECTION_LOST:
					allConnected=false;
					connectionAmount[i]--;
					if (isVerbose)
					{
						printf("Connection lost.\n");

						DebugTools::ShowError("Test failed.\n",!noPauses && isVerbose,__LINE__,__FILE__);
					}

					return 3;

					break;
				default:

					if (packet->data[0]==ID_USER_PACKET_ENUM+1)
					{
						int thePeerNum;
						int sequenceNum;
						bitStream.Reset();
						bitStream.Write((char*)packet->data, packet->length);
						bitStream.IgnoreBits(8);
						bitStream.Read(sequenceNum);
						bitStream.Read(thePeerNum);
						if (isVerbose)
							printf("Message %i from %i\n",sequenceNum,thePeerNum );

						if (thePeerNum>=0&&thePeerNum<peerNum)
						{
							if (lastNumberReceivedFromList[i][thePeerNum]==sequenceNum)
							{
								lastNumberReceivedFromList[i][thePeerNum]++;
							}
							else
							{
								if (isVerbose)
								{
									printf("Packets out of order");
									DebugTools::ShowError("Test failed.\n",!noPauses && isVerbose,__LINE__,__FILE__);

								}
								return 4;
							}
							recievedFromList[i][thePeerNum]++;}
					}
					break;
				}
				peerList[i]->DeallocatePacket(packet);
				// Stay in the loop as long as there are more packets.
				packet = peerList[i]->Receive();
			}
		}
		RakSleep(0);//If needed for testing
	}

	for (int i=0;i<peerNum;i++)
	{

		for (int j=0;j<peerNum;j++)
		{
			if (i!=j)
			{
				if (isVerbose)
					printf("%i recieved %i packets from %i\n",i,recievedFromList[i][j],j);
				if  (recievedFromList[i][j]!=numPackets)
				{
					if (isVerbose)
					{
						printf("Not all packets recieved. it was in reliable ordered mode so that means test failed or wait time needs increasing\n");

						DebugTools::ShowError("Test failed.\n",!noPauses && isVerbose,__LINE__,__FILE__);
					}
					return 5;

				}

			}
		}
	}

	printf("All packets recieved in order,pass\n");
	return 0;

}
void BasicNetworkingApp::ReadObjectDataFromServer(BitStream& bsIn)
{
	//Create a temp object that we will pull all the object data into
	GameObject tempGameObject;

	//Read in the object data
	bsIn.Read(tempGameObject.syncType);
	if (tempGameObject.syncType == INTERPOLATION)
	{
		bsIn.Read(tempGameObject.xVelocity);
		bsIn.Read(tempGameObject.zVelocity);
		tempGameObject.xPos = 0.0f;
		tempGameObject.zPos = 0.0f;
	}
	else
	{
		bsIn.Read(tempGameObject.xPos);
		bsIn.Read(tempGameObject.zPos);
		tempGameObject.xVelocity = 0.0f;
		tempGameObject.zVelocity = 0.0f;
	}
	bsIn.Read(tempGameObject.redColour);
	bsIn.Read(tempGameObject.greenColour);
	bsIn.Read(tempGameObject.blueColour);
	bsIn.Read(tempGameObject.ownerClientID);

	//Check to see whether or not this object is already stored in our local object list
	bool found = false;
	for (unsigned int i = 0; i < m_gameObjects.size(); i++)
	{
		if (m_gameObjects[i].ownerClientID == tempGameObject.ownerClientID)
		{
			found = true;

			//Update the game object
			GameObject& obj = m_gameObjects[i];
			obj.redColour = tempGameObject.redColour;
			obj.greenColour = tempGameObject.greenColour;
			obj.blueColour = tempGameObject.blueColour;
			obj.syncType = tempGameObject.syncType;

			switch (obj.syncType)
			{
			case POSITION_ONLY:
				obj.xPos = tempGameObject.xPos;
				obj.zPos = tempGameObject.zPos;
				break;
			case INTERPOLATION:
				m_tempVel.x = tempGameObject.xVelocity;
				m_tempVel.z = tempGameObject.zVelocity;
			case LERP:
				m_tempPos.x = tempGameObject.xPos;
				m_tempPos.z = tempGameObject.zPos;
				break;
			}
		}
	}

	//If we didn't find it, then it is a new object - add it to our object list
	if (!found)
	{
		m_gameObjects.push_back(tempGameObject);
		if (tempGameObject.ownerClientID == m_clientId)
			m_clientObjectIndex = m_gameObjects.size() - 1;
	}
}