void FullyConnectedMesh2::OnRespondFCMGuid(Packet *packet)
{
	RakNet::BitStream bsIn(packet->data,packet->length,false);
	bsIn.IgnoreBytes(sizeof(MessageID));
	unsigned int responseAssignedConnectionCount;
	unsigned int responseTotalConnectionCount;
	bsIn.Read(responseAssignedConnectionCount);
	bsIn.Read(responseTotalConnectionCount);
	if (ourFCMGuid==0)
	{
		AssignOurFCMGuid(responseAssignedConnectionCount);
		guidRequestRetryList.Clear(true,__FILE__,__LINE__);
		// printf("Total connection count updated from %i to %i\n", totalConnectionCount, responseTotalConnectionCount);
		totalConnectionCount=responseTotalConnectionCount;
		if (participantList.Size()!=0)
		{
			CalculateHost(&hostSystemAddress, &hostRakNetGuid, &hostFCM2Guid);
			PushNewHost(hostSystemAddress, hostRakNetGuid);
		}
	}
	SendOurFCMGuid(packet->systemAddress);
	DataStructures::DefaultIndexType idx;
	for (idx=0; idx < participantList.Size(); idx++)
		SendOurFCMGuid(participantList[idx].systemAddress);
}
void FullyConnectedMesh2::AddParticipant(SystemAddress participant)
{
	if (rakPeerInterface->IsConnected(participant,false,false)==false)
	{
#ifdef DEBUG_FCM2
		printf("AddParticipant to %s failed (not connected)\n", participant.ToString());
#endif
		return;
	}

	// Account for different system addresses between different participants
	RakNetGUID newParticipantGuid = rakPeerInterface->GetGuidFromSystemAddress(participant);
	for (unsigned int i=0; i < participantList.Size(); i++)
	{
		if (participantList[i].rakNetGuid==newParticipantGuid)
		{
			if (participantList[i].systemAddress!=participant)
			{
				participantList[i].systemAddress=participant;
				if (ourFCMGuid==0)
				{
					SendFCMGuidRequest(participant);
					return;
				}
				else
				{
					SendOurFCMGuid(participant);
					return;
				}
			}

#ifdef DEBUG_FCM2
			printf("AddParticipant to %s failed (Same Guid and System address)\n", participant.ToString());
#endif

			// else already added
			return;
		}
	}

	// Not in the list at all
	if (ourFCMGuid==0)
	{
		SendFCMGuidRequest(participant);
		guidRequestRetryList.Push(rakPeerInterface->GetGuidFromSystemAddress(participant),__FILE__,__LINE__);
	}
	else
	{
		SendOurFCMGuid(participant);
	}
}
void FullyConnectedMesh2::OnRespondConnectionCount(Packet *packet)
{
	RakNet::BitStream bsIn(packet->data,packet->length,false);
	bsIn.IgnoreBytes(sizeof(MessageID));
	unsigned int responseTotalConnectionCount;
	bsIn.Read(responseTotalConnectionCount);
	IncrementTotalConnectionCount(responseTotalConnectionCount);
	bool wasAssigned;
	if (ourFCMGuid==0)
	{
		wasAssigned=true;
		AssignOurFCMGuid();
	}
	else
		wasAssigned=false;

	// 1 is returned to give us lower priority, but the actual minimum is 2
	IncrementTotalConnectionCount(2);

	if (wasAssigned==true)
	{
		DataStructures::DefaultIndexType idx;
		for (idx=0; idx < participantList.Size(); idx++)
			SendOurFCMGuid(rakPeerInterface->GetSystemAddressFromGuid(participantList[idx].rakNetGuid));
		CalculateAndPushHost();
	}
}
void FullyConnectedMesh2::OnRequestFCMGuid(Packet *packet)
{
	RakNet::BitStream bsIn(packet->data,packet->length,false);
	bsIn.IgnoreBytes(sizeof(MessageID));
	bool hasRemoteFCMGuid;
	bsIn.Read(hasRemoteFCMGuid);
	RakNetTimeUS senderElapsedRuntime=0;
	unsigned int remoteTotalConnectionCount=0;
	FCM2Guid theirFCMGuid=0;
	if (hasRemoteFCMGuid)
	{
		bsIn.Read(remoteTotalConnectionCount);
		bsIn.Read(theirFCMGuid);
	}
	else
	{
		bsIn.Read(senderElapsedRuntime);
	}
	AddParticipantInternal(packet->guid,theirFCMGuid);
	if (ourFCMGuid==0)
	{
		if (hasRemoteFCMGuid==false)
		{
			// Nobody has a fcmGuid

			RakNetTimeUS ourElapsedRuntime = GetElapsedRuntime();
			if (ourElapsedRuntime>senderElapsedRuntime)
			{
				// We are probably host
				SendConnectionCountResponse(packet->systemAddress, 2);
			}
			else
			{
				// They are probably host
				SendConnectionCountResponse(packet->systemAddress, 1);
			}
		}
		else
		{
			// They have a fcmGuid, we do not

			IncrementTotalConnectionCount(remoteTotalConnectionCount+1);

			AssignOurFCMGuid();
			DataStructures::DefaultIndexType idx;
			for (idx=0; idx < participantList.Size(); idx++)
				SendOurFCMGuid(rakPeerInterface->GetSystemAddressFromGuid(participantList[idx].rakNetGuid));
		}
	}
	else
	{
		if (hasRemoteFCMGuid==false)
		{
			// We have a fcmGuid they do not

			SendConnectionCountResponse(packet->systemAddress, totalConnectionCount+1);

		}
		else
		{
			// We both have fcmGuids

			IncrementTotalConnectionCount(remoteTotalConnectionCount);

			SendOurFCMGuid(packet->systemAddress);
		}
	}
	CalculateAndPushHost();
}
void FullyConnectedMesh2::OnInformFCMGuid(Packet *packet)
{
	RakNet::BitStream bsIn(packet->data,packet->length,false);
	bsIn.IgnoreBytes(sizeof(MessageID));

	DataStructures::DefaultIndexType idx;
	for (idx=0; idx < participantList.Size(); idx++)
	{
		if (participantList[idx].rakNetGuid==packet->guid)
		{
//#ifdef DEBUG_FCM2
//			printf("Duplicate participant %s\n", packet->guid.ToString());
//#endif

			// Duplicate message, just ignore since they are already in the pqqqqqqarticipantList
			return;
		}
	}

	SystemAddress theirSystemAddress;
	if (rakPeerInterface->GetSystemAddressFromGuid(packet->guid)!=UNASSIGNED_SYSTEM_ADDRESS)
		theirSystemAddress=rakPeerInterface->GetSystemAddressFromGuid(packet->guid);
	else
		theirSystemAddress=packet->systemAddress;

	FCM2Guid theirFCMGuid;
	unsigned int theirTotalConnectionCount;
	bsIn.Read(theirFCMGuid);
	bsIn.Read(theirTotalConnectionCount);

#ifdef DEBUG_FCM2
	printf("Pushing participant %s\n", packet->guid.ToString());
#endif

	idx = guidRequestRetryList.GetIndexOf(packet->guid);
	if (idx!=-1)
		guidRequestRetryList.RemoveAtIndex(idx,__FILE__,__LINE__);

	participantList.Push(FCM2Participant(theirFCMGuid, packet->guid, theirSystemAddress), __FILE__,__LINE__);
	if (theirTotalConnectionCount>totalConnectionCount)
	{
	//	printf("Total connection count IS  updated from %i to %i\n", totalConnectionCount, theirTotalConnectionCount);
		totalConnectionCount=theirTotalConnectionCount;
	}
	else
	{
	//	printf("Total connection count NOT updated from %i to %i\n", totalConnectionCount, theirTotalConnectionCount);
	}

	if (ourFCMGuid!=0)
	{
		SystemAddress systemAddress;
		RakNetGUID rakNetGuid;
		FCM2Guid fcm2Guid;
		CalculateHost(&systemAddress, &rakNetGuid, &fcm2Guid);

		if (rakNetGuid!=hostRakNetGuid)
		{
			hostSystemAddress=systemAddress;
			hostRakNetGuid=rakNetGuid;
			hostFCM2Guid=fcm2Guid;
			PushNewHost(hostSystemAddress, hostRakNetGuid);
		}

		SendOurFCMGuid(packet->systemAddress);
	}
}