//This static method is called when the user wants to host a server
void Session::StartHost(void* pVoid){
	//A parameter list is given with needed variables
	ArgumentList* pArgumentList = (ArgumentList*)pVoid;
	RakPeerInterface *pServer;
	//Filling my fields from argument list.
	pServer=pArgumentList->inter;
	std::string password = pArgumentList->password;
	int port = pArgumentList->port;
	RakNet::RPC3* rpc3Inst = pArgumentList->rpc3;
	//map that keeps track of who is who
	std::map<RakNet::SystemAddress, std::string> clientCharacterMap;

	//Register the functions we want to call RPC3 upon
	RPC3_REGISTER_FUNCTION(rpc3Inst, ReceiveInformation);
	RPC3_REGISTER_FUNCTION(rpc3Inst, UpdateCharacter);
	RPC3_REGISTER_FUNCTION(rpc3Inst, UpdateCharacterVelocity);
	RPC3_REGISTER_FUNCTION(rpc3Inst, SyncClients);
	RPC3_REGISTER_FUNCTION(rpc3Inst, ReceiveID);
	RPC3_REGISTER_FUNCTION(rpc3Inst, RemoveCharacter);
	RPC3_REGISTER_FUNCTION(rpc3Inst, AddScore);
	
	//Set up the host using RakNet
	pServer->SetIncomingPassword(password.c_str(), (int)strlen(password.c_str()));
	pServer->SetTimeoutTime(5000,UNASSIGNED_SYSTEM_ADDRESS);
	SystemAddress clientID=UNASSIGNED_SYSTEM_ADDRESS;
	RakNet::SocketDescriptor socketDescriptor(port,0);
	socketDescriptor.socketFamily=AF_INET;
	bool b = pServer->Startup(10,&socketDescriptor, 1 );
	pServer->SetMaximumIncomingConnections(10);

	pServer->SetOccasionalPing(true);
	pServer->SetUnreliableTimeout(1000);

	DataStructures::List<RakNetSmartPtr<RakNetSocket> > sockets;
	pServer->GetSockets(sockets);	
	
	// Holds packets
	Packet* p;
	// Record the first client that connects to us so we can pass it to the ping function
	clientID=UNASSIGNED_SYSTEM_ADDRESS;

	pServer->AttachPlugin(rpc3Inst);

	char message[2048];

	// Loop for input
	while (threading)
	{
		for (p=pServer->Receive(); p; pServer->DeallocatePacket(p), p=pServer->Receive())
		{
			switch (p->data[0])
			{
			case ID_DISCONNECTION_NOTIFICATION:
				{
				printf("ID_DISCONNECTION_NOTIFICATION\n");
				RakString name(clientCharacterMap[p->systemAddress].c_str());
				RemoveCharacter(name);
				rpc3Inst->CallC("RemoveCharacter", name);
				break;
				}
			case ID_ALREADY_CONNECTED:
				printf("ID_ALREADY_CONNECTED\n");
				break;
			case ID_CONNECTION_ATTEMPT_FAILED:
				printf("Connection attempt failed\n");
				break;
			case ID_NO_FREE_INCOMING_CONNECTIONS:
				printf("ID_NO_FREE_INCOMING_CONNECTIONS\n");
				break;
			case ID_UNCONNECTED_PONG:
				// Found the server
				pServer->Connect(p->systemAddress.ToString(false),p->systemAddress.GetPort(),0,0,0);
				break;
			case ID_CONNECTION_REQUEST_ACCEPTED:
				// This tells the client they have connected
				printf("ID_CONNECTION_REQUEST_ACCEPTED\n");
				//Session::SendInformation(RakNet::RakString("The italians are invading utrecht!"), rpc3Inst, 0);
				//Game::getSingletonPtr()->
				break;
			case ID_NEW_INCOMING_CONNECTION:
			{
				//When there is a new incoming connection we are change the local player to the host
				printf("New incoming connection\n");
				Game::getSingletonPtr()->getLocalPlayer()->SetNetworkName("PlayerHost");
				std::stringstream ss, ss2;
				ss << "Client" << (Game::getSingletonPtr()->GetCharacters().size()+1);
				//create a new character for the client
				Game::getSingletonPtr()->CreateCharacter(ss.str());
				clientCharacterMap[p->systemAddress] = ss.str();

				RPC3::CallExplicitParameters params;
				params.systemAddress = p->systemAddress;
				params.broadcast = false;
				//Make sure the client knows who he is
				rpc3Inst->CallExplicit("ReceiveID", &params, RakString::RakString(ss.str().c_str()));
				ss2 << Game::getSingletonPtr()->GetCharacters().size();
				//Synchronize the players with all clients; make sure they have all the characters on the screen
				RPC3::CallExplicitParameters params2;
				//params2.systemAddress = p->systemAddress;
				params2.broadcast = true;
				rpc3Inst->CallExplicit("SyncClients", &params2, RakNet::RakString(ss2.str().c_str()));
				//rpc3Inst->CallC("SyncClients", RakNet::RakString(ss2.str().c_str()));
				break;
			}				
			case ID_RPC_REMOTE_ERROR:
				{
					// Recipient system returned an error
					switch (p->data[1])
					{
					case RakNet::RPC_ERROR_NETWORK_ID_MANAGER_UNAVAILABLE:
						printf("RPC_ERROR_NETWORK_ID_MANAGER_UNAVAILABLE\n");
						break;
					case RakNet::RPC_ERROR_OBJECT_DOES_NOT_EXIST:
						printf("RPC_ERROR_OBJECT_DOES_NOT_EXIST\n");
						break;
					case RakNet::RPC_ERROR_FUNCTION_INDEX_OUT_OF_RANGE:
						printf("RPC_ERROR_FUNCTION_INDEX_OUT_OF_RANGE\n");
						break;
					case RakNet::RPC_ERROR_FUNCTION_NOT_REGISTERED:
						printf("RPC_ERROR_FUNCTION_NOT_REGISTERED\n");
						break;
					case RakNet::RPC_ERROR_FUNCTION_NO_LONGER_REGISTERED:
						printf("RPC_ERROR_FUNCTION_NO_LONGER_REGISTERED\n");
						break;
					case RakNet::RPC_ERROR_CALLING_CPP_AS_C:
						printf("RPC_ERROR_CALLING_CPP_AS_C\n");
						break;
					case RakNet::RPC_ERROR_CALLING_C_AS_CPP:
						printf("RPC_ERROR_CALLING_C_AS_CPP\n");
						break;
					}
					printf("Function: %s", p->data+2);
				}
			}
		}
	}
	pServer->Shutdown(30,0);
	RakNet::RakPeerInterface::DestroyInstance(pServer);
	delete rpc3Inst;
}