Example #1
0
const RakNet::RakString operator+(const RakNet::RakString &lhs, const RakNet::RakString &rhs)
{
	if (lhs.IsEmpty() && rhs.IsEmpty())
		return RakString(&RakString::emptyString);
	if (lhs.IsEmpty())
	{
		rhs.sharedString->refCount++;
		return RakString(rhs.sharedString);
	}
	if (rhs.IsEmpty())
	{
		lhs.sharedString->refCount++;
		return RakString(lhs.sharedString);
	}

	size_t len1 = lhs.GetLength();
	size_t len2 = rhs.GetLength();
	size_t allocatedBytes = len1 + len2 + 1;
	allocatedBytes = RakString::GetSizeToAllocate(allocatedBytes);
	RakString::SharedString *sharedString;

	RakString::LockMutex();
	// sharedString = RakString::pool.Allocate();
	if (RakString::freeList.Size()==0)
	{
		//RakString::sharedStringFreeList=(RakString::SharedString*) rakRealloc_Ex(RakString::sharedStringFreeList,(RakString::sharedStringFreeListAllocationCount+1024)*sizeof(RakString::SharedString), __FILE__, __LINE__);
		unsigned i;
		for (i=0; i < 1024; i++)
		{
		//	RakString::freeList.Insert(RakString::sharedStringFreeList+i+RakString::sharedStringFreeListAllocationCount);
			RakString::freeList.Insert((RakString::SharedString*)rakMalloc_Ex(sizeof(RakString::SharedString), __FILE__, __LINE__), __FILE__, __LINE__);

		}
		//RakString::sharedStringFreeListAllocationCount+=1024;
	}
	sharedString = RakString::freeList[RakString::freeList.Size()-1];
	RakString::freeList.RemoveAtIndex(RakString::freeList.Size()-1);
	RakString::UnlockMutex();

	const int smallStringSize = 128-sizeof(unsigned int)-sizeof(size_t)-sizeof(char*)*2;
	sharedString->bytesUsed=allocatedBytes;
	sharedString->refCount=1;
	if (allocatedBytes <= (size_t) smallStringSize)
	{
		sharedString->c_str=sharedString->smallString;
	}
	else
	{
		sharedString->bigString=(char*)rakMalloc_Ex(sharedString->bytesUsed, __FILE__, __LINE__);
		sharedString->c_str=sharedString->bigString;
	}

	strcpy(sharedString->c_str, lhs);
	strcat(sharedString->c_str, rhs);

	return RakString(sharedString);
}
void TwoWayAuthentication::Hash(char thierNonce[TWO_WAY_AUTHENTICATION_NONCE_LENGTH], RakNet::RakString password, char out[HASHED_NONCE_AND_PW_LENGTH])
{
#if LIBCAT_SECURITY==1
	cat::Skein hash;
	if (!hash.BeginKey(HASH_BITS)) return;
	hash.Crunch(thierNonce, TWO_WAY_AUTHENTICATION_NONCE_LENGTH);
	hash.Crunch(password.C_String(), (int) password.GetLength());
	hash.End();
	hash.Generate(out, HASH_BYTES, STRENGTHENING_FACTOR);
#else
	CSHA1 sha1;
	sha1.Update((unsigned char *) thierNonce, TWO_WAY_AUTHENTICATION_NONCE_LENGTH);
	sha1.Update((unsigned char *) password.C_String(), (unsigned int) password.GetLength());
	sha1.Final();
	sha1.GetHash((unsigned char *) out);
#endif
}
Example #3
0
void RakString::SplitURI(RakNet::RakString &header, RakNet::RakString &domain, RakNet::RakString &path)
{
	header.Clear();
	domain.Clear();
	path.Clear();

	size_t strLen = strlen(sharedString->c_str);

	char c;
	unsigned int i=0;
	if (strncmp(sharedString->c_str, "http://", 7)==0)
		i+=(unsigned int) strlen("http://");
	else if (strncmp(sharedString->c_str, "https://", 8)==0)
		i+=(unsigned int) strlen("https://");
	
	if (strncmp(sharedString->c_str, "www.", 4)==0)
		i+=(unsigned int) strlen("www.");

	if (i!=0)
	{
		header.Allocate(i+1);
		strncpy(header.sharedString->c_str, sharedString->c_str, i);
		header.sharedString->c_str[i]=0;
	}


	domain.Allocate(strLen-i+1);
	char *domainOutput=domain.sharedString->c_str;
	unsigned int outputIndex=0;
	for (; i < strLen; i++)
	{
		c=sharedString->c_str[i];
		if (c=='/')
		{
			break;
		}
		else
		{
			domainOutput[outputIndex++]=sharedString->c_str[i];
		}
	}

	domainOutput[outputIndex]=0;

	path.Allocate(strLen-header.GetLength()-outputIndex+1);
	outputIndex=0;
	char *pathOutput=path.sharedString->c_str;
	for (; i < strLen; i++)
	{
		pathOutput[outputIndex++]=sharedString->c_str[i];
	}
	pathOutput[outputIndex]=0;
}
Example #4
0
void	MasterList::pulse()
{
	RakNet::RakString	post;
	RakNet::Packet*		packet;

	while (ServerCore::getInstance().isActive())
	{
		if ((utility::TimeUtility::getMsTime() - m_lastUpdateTime) < 3000)
			continue;

		if (m_tcp->Connect(ProjectGlobals::getMasterlistUrl().c_str(), 80, true) == RakNet::UNASSIGNED_SYSTEM_ADDRESS)
			continue;

		RakSleep(100);

		if (m_state == masterListState::STATE_ADD)
			m_token = utility::StringUtility::random_string(42);

		post = RakNet::RakString::FormatForPOST(std::string(ProjectGlobals::getMasterlistUrl()).append("/api/v1/server/update").c_str(),
			"application/x-www-form-urlencoded",
			RakNet::RakString("token=%s&ip=%s&port=%d&players=%d",
				m_token.c_str(),
				ServerCore::getInstance().getServerCoreConfiguration().getAddress().c_str(),
				ServerCore::getInstance().getServerCoreConfiguration().getPort(),
				ServerCore::getInstance().getPlayerManager().getPoolSize()),
			"User-Agent: Malefice/1.0");

		m_tcp->Send(post.C_String(), post.GetLength(), m_tcp->HasCompletedConnectionAttempt(), false);

		RakSleep(1000);

		packet = m_tcp->Receive();
		if (!packet)
			continue;

		if (m_state == masterListState::STATE_ADD) {
			LOG_INFO(NETWORK) << "Server successfully posted to the MasterList";
			m_state = masterListState::STATE_UPDATE;
		}

		m_lastUpdateTime = utility::TimeUtility::getMsTime();

		m_tcp->DeallocatePacket(packet);

		RakSleep(100);
	}
}
Example #5
0
/**
* _findfirst - equivalent
*/
long _findfirst(const char *name, _finddata_t *f)
{
	RakNet::RakString nameCopy = name;
        RakNet::RakString filter;

        // This is linux only, so don't bother with '\'
	const char* lastSep = strrchr(name,'/');
	if(!lastSep)
	{
            // filter pattern only is given, search current directory.
            filter = nameCopy;
            nameCopy = ".";
	} else
	{
            // strip filter pattern from directory name, leave
            // trailing '/' intact.
            filter = lastSep+1;
            unsigned sepIndex = lastSep - name;
            nameCopy.Erase(sepIndex+1, nameCopy.GetLength() - sepIndex-1);
	}

	DIR* dir = opendir(nameCopy);
        
	if(!dir) return -1;

	_findinfo_t* fi = new _findinfo_t;
	fi->filter    = filter;
	fi->dirName   = nameCopy;  // we need to remember this for stat()
	fi->openedDir = dir;
	fileInfo.Insert(fi);

        long ret = fileInfo.Size()-1;

        // Retrieve the first file. We cannot rely on the first item
        // being '.'
        if (_findnext(ret, f) == -1) return -1;
        else return ret;
}
Example #6
0
PluginReceiveResult RPC4::OnReceive(Packet *packet)
{
	if (packet->data[0]==ID_RPC_PLUGIN)
	{
		RakNet::BitStream bsIn(packet->data,packet->length,false);
		bsIn.IgnoreBytes(2);

		if (packet->data[1]==ID_RPC4_CALL)
		{
			RakNet::RakString functionName;
			bsIn.ReadCompressed(functionName);
			bool isBlocking;
			bsIn.Read(isBlocking);
			if (isBlocking==false)
			{
				DataStructures::HashIndex skhi = registeredNonblockingFunctions.GetIndexOf(functionName.C_String());
				if (skhi.IsInvalid())
				{
					RakNet::BitStream bsOut;
					bsOut.Write((unsigned char) ID_RPC_REMOTE_ERROR);
					bsOut.Write((unsigned char) RPC_ERROR_FUNCTION_NOT_REGISTERED);
					bsOut.Write(functionName.C_String(),(unsigned int) functionName.GetLength()+1);
					SendUnified(&bsOut,HIGH_PRIORITY,RELIABLE_ORDERED,0,packet->systemAddress,false);
					return RR_STOP_PROCESSING_AND_DEALLOCATE;
				}

				void ( *fp ) ( RakNet::BitStream *, Packet * );
				fp = registeredNonblockingFunctions.ItemAtIndex(skhi);
                bsIn.AlignReadToByteBoundary();
				fp(&bsIn,packet);
			}
			else
			{
				DataStructures::HashIndex skhi = registeredBlockingFunctions.GetIndexOf(functionName.C_String());
				if (skhi.IsInvalid())
				{
					RakNet::BitStream bsOut;
					bsOut.Write((unsigned char) ID_RPC_REMOTE_ERROR);
					bsOut.Write((unsigned char) RPC_ERROR_FUNCTION_NOT_REGISTERED);
					bsOut.Write(functionName.C_String(),(unsigned int) functionName.GetLength()+1);
					SendUnified(&bsOut,HIGH_PRIORITY,RELIABLE_ORDERED,0,packet->systemAddress,false);
					return RR_STOP_PROCESSING_AND_DEALLOCATE;
				}

				void ( *fp ) ( RakNet::BitStream *, RakNet::BitStream *, Packet * );
				fp = registeredBlockingFunctions.ItemAtIndex(skhi);
				RakNet::BitStream returnData;
                bsIn.AlignReadToByteBoundary();
				fp(&bsIn, &returnData, packet);

				RakNet::BitStream out;
				out.Write((MessageID) ID_RPC_PLUGIN);
				out.Write((MessageID) ID_RPC4_RETURN);
				returnData.ResetReadPointer();
                out.AlignWriteToByteBoundary();
				out.Write(returnData);
				SendUnified(&out,IMMEDIATE_PRIORITY,RELIABLE_ORDERED,0,packet->systemAddress,false);
			}
		}
		else
		{
			RakAssert(packet->data[1]==ID_RPC4_RETURN);
			blockingReturnValue.Reset();
			blockingReturnValue.Read(bsIn);
			gotBlockingReturnValue=true;
		}
		
		return RR_STOP_PROCESSING_AND_DEALLOCATE;
	}

	bool objectExists;
	unsigned int index, index2;
	index = localCallbacks.GetIndexFromKey(packet->data[0],&objectExists);
	if (objectExists)
	{
		LocalCallback *lc;
		lc = localCallbacks[index];
		for (index2=0; index2 < lc->functions.Size(); index2++)
		{
			RakNet::BitStream bsIn(packet->data, packet->length, false);

			DataStructures::HashIndex skhi = registeredNonblockingFunctions.GetIndexOf(lc->functions[index2].C_String());
			if (skhi.IsInvalid()==false)
			{
				void ( *fp ) ( RakNet::BitStream *, Packet * );
				fp = registeredNonblockingFunctions.ItemAtIndex(skhi);
                bsIn.AlignReadToByteBoundary();
				fp(&bsIn,packet);
			}		
		}
	}

	return RR_CONTINUE_PROCESSING;
}
PGresult * PostgreSQLInterface::QueryVariadic( const char * input, ... )
{
	RakNet::RakString query;
	PGresult *result;
	DataStructures::List<VariadicSQLParser::IndexAndType> indices;
	if ( input==0 || input[0]==0 )
		return 0;

	// Lookup this query in the stored query table. If it doesn't exist, prepare it.
	RakNet::RakString inputStr;
	inputStr=input;
	unsigned int preparedQueryIndex;
	for (preparedQueryIndex=0; preparedQueryIndex < preparedQueries.Size(); preparedQueryIndex++)
	{
		if (preparedQueries[preparedQueryIndex].StrICmp(inputStr)==0)
			break;
	}

	// Find out how many params there are
	// Find out the type of each param (%f, %s)
	indices.Clear(false, _FILE_AND_LINE_);
	GetTypeMappingIndices( input, indices );

	if (preparedQueryIndex==preparedQueries.Size())
	{
//		if (indices.Size()>0)
//			query += " (";
		RakNet::RakString formatCopy;
		RakNet::RakString insertion;
		formatCopy=input;
		unsigned int i;
		unsigned int indexOffset=0;
		for (i=0; i < indices.Size(); i++)
		{
//			if (i!=0)
//				query += ",";
//			query+=typeMappings[indices[i].typeMappingIndex].type;
			formatCopy.SetChar(indices[i].strIndex+indexOffset, '$');
//			if (i < 9)
//				formatCopy.SetChar(indices[i].strIndex+1, i+1+'0');
//			else
			insertion=RakNet::RakString("%i::%s", i+1, VariadicSQLParser::GetTypeMappingAtIndex(indices[i].typeMappingIndex));
			formatCopy.SetChar(indices[i].strIndex+1+indexOffset, insertion);
			indexOffset+=(unsigned int) insertion.GetLength()-1;
		}
//		if (indices.Size()>0)
//			query += ")";
//		query += " AS ";
		query += formatCopy;
	//	query += ";\n";
		formatCopy+= ";\n";
		result = PQprepare(pgConn, RakNet::RakString("PGSQL_ExecuteVariadic_%i", preparedQueries.Size()), formatCopy.C_String(), indices.Size(), NULL);
		if (IsResultSuccessful(result, false))
		{
			PQclear(result);
			preparedQueries.Insert(inputStr, _FILE_AND_LINE_);
		}
		else
		{
			printf(formatCopy.C_String());
			printf("\n");
			printf(lastError);
			RakAssert(0);
			PQclear(result);
			return 0;
		}
	}

//	char *paramData[512];
//	int paramLength[512];
//	int paramFormat[512];

	va_list argptr;
	va_start(argptr, input);
	char **paramData;
	int *paramLength;
	int *paramFormat;
	ExtractArguments(argptr, indices, &paramData, &paramLength);
	paramFormat=RakNet::OP_NEW_ARRAY<int>(indices.Size(),_FILE_AND_LINE_);
	for (unsigned int i=0; i < indices.Size(); i++)
		paramFormat[i]=PQEXECPARAM_FORMAT_BINARY;
	result = PQexecPrepared(pgConn, RakNet::RakString("PGSQL_ExecuteVariadic_%i", preparedQueryIndex), indices.Size(), paramData, paramLength, paramFormat, PQEXECPARAM_FORMAT_BINARY );
	VariadicSQLParser::FreeArguments(indices, paramData, paramLength);
	RakNet::OP_DELETE_ARRAY(paramFormat,_FILE_AND_LINE_);
	va_end(argptr);

	if (IsResultSuccessful(result, false)==false)
	{
		printf(lastError);
		PQclear(result);
		return 0;
	}
	return result;
}
Example #8
0
	void ServerHost::doTick()
	{
		// Get a packet from either the server or the client

		for (RakNet::Packet* p = m_server->Receive(); p; m_server->DeallocatePacket(p), p=m_server->Receive())
		{
			// We got a packet, get the identifier with our handy function
			unsigned char packetIdentifier = GetPacketIdentifier(p);

			// Check if this is a network message packet
			switch (packetIdentifier)
			{
			case ID_DISCONNECTION_NOTIFICATION:
				// Connection lost normally
				printf("ID_DISCONNECTION_NOTIFICATION\n");
				m_peer.initServer(m_server,p->guid,p->systemAddress);
				onDisconnect(&m_peer);
				break;
			case ID_ALREADY_CONNECTED:
				// Connection lost normally
				printf("ID_ALREADY_CONNECTED with guid %" PRINTF_64_BIT_MODIFIER "u\n", p->guid);
				break;
			case ID_INCOMPATIBLE_PROTOCOL_VERSION:
				printf("ID_INCOMPATIBLE_PROTOCOL_VERSION\n");
				break;
			case ID_CONNECTION_BANNED: // Banned from this server
				printf("We are banned from this server.\n");
				break;			
			case ID_CONNECTION_ATTEMPT_FAILED:
				printf("Connection attempt failed\n");
				break;
			case ID_NO_FREE_INCOMING_CONNECTIONS:
				// Sorry, the server is full.  I don't do anything here but
				// A real app should tell the user
				printf("ID_NO_FREE_INCOMING_CONNECTIONS\n");
				break;

			case ID_INVALID_PASSWORD:
				printf("ID_INVALID_PASSWORD\n");
				break;

			case ID_CONNECTION_LOST:
				// Couldn't deliver a reliable packet - i.e. the other system was abnormally
				// terminated
				printf("ID_CONNECTION_LOST\n");
				m_peer.initServer(m_server,p->guid,p->systemAddress);
				onDisconnect(&m_peer);
				break;

			case ID_NEW_INCOMING_CONNECTION:
				// This tells the client they have connected
				m_peer.initServer(m_server,p->guid,p->systemAddress);
				onConnect(&m_peer);
				break;
			case ID_CONNECTED_PING:
			case ID_UNCONNECTED_PING:
				printf("Ping from %s\n", p->systemAddress.ToString(true));
				break;
			case ID_USER_PACKET_ENUM:
				{
					RakNet::RakString rs;
					RakNet::BitStream bsIn(p->data,p->length,false);
					bsIn.IgnoreBytes(sizeof(RakNet::MessageID));
					bsIn.Read(rs);
					m_peer.initServer(m_server,p->guid,p->systemAddress);
					onReceive(&m_peer,rs.C_String(),rs.GetLength());
				}
				break;
			default:
				break;
			}
		}
	}
	void ServerClient::tick()
	{
        if(m_server)
		for (RakNet::Packet* p = m_server->Receive(); p; m_server->DeallocatePacket(p), p=m_server->Receive())
		{
			// We got a packet, get the identifier with our handy function
			unsigned char packetIdentifier = GetPacketIdentifierC(p);
			//std::cout << (int)packetIdentifier << std::endl;
			// Check if this is a network message packet
            
            if(m_bgMode)
            {
                m_packets.push_back(ServerPacket());
                m_packets.back().packetID = packetIdentifier;
                for(int i = 0; i < p->length; i++)
                {
                    m_packets.back().message.push_back(p->data[i]);
                }
                continue;
            }
			switch (packetIdentifier)
			{
			case ID_DISCONNECTION_NOTIFICATION:
			case ID_CONNECTION_LOST:
				// Connection lost normally
				printf("ID_DISCONNECTION_NOTIFICATION\n");
					m_connected = false;
					m_connecting = false;
					onDisconnect();
					if(m_needsToConnect)
					{
						connect();
						m_needsToConnect = false;
					}
				break;
			case ID_ALREADY_CONNECTED:
				// Connection lost normally
				printf("ID_ALREADY_CONNECTED with guid %" PRINTF_64_BIT_MODIFIER "u\n", p->guid);
				onFailedToConnect(false);
				break;
			case ID_INCOMPATIBLE_PROTOCOL_VERSION:
				printf("ID_INCOMPATIBLE_PROTOCOL_VERSION\n");
				break;
			case ID_CONNECTION_BANNED: // Banned from this server
				printf("We are banned from this server.\n");
				break;			
			case ID_CONNECTION_ATTEMPT_FAILED:
				printf("Connection attempt failed\n");
				m_connecting = false;
				m_connected = false;
				onFailedToConnect(false);
				break;
			case ID_NO_FREE_INCOMING_CONNECTIONS:
				// Sorry, the server is full.  I don't do anything here but
				// A real app should tell the user
				printf("ID_NO_FREE_INCOMING_CONNECTIONS\n");
				break;

			case ID_INVALID_PASSWORD:
				printf("ID_INVALID_PASSWORD\n");
				break;
			case ID_CONNECTION_REQUEST_ACCEPTED:
				// This tells the client they have connected
				m_connecting = false;
				m_connected = true;
				m_needsToConnect = false;
				m_client.initClient(m_server,p->guid,p->systemAddress);
				onConnect();
				break;
			case ID_CONNECTED_PING:
			case ID_UNCONNECTED_PING:
				printf("Ping from %s\n", p->systemAddress.ToString(true));
				break;
			case ID_USER_PACKET_ENUM:
				{
					RakNet::RakString rs;
					RakNet::BitStream bsIn(p->data,p->length,false);
					bsIn.IgnoreBytes(sizeof(RakNet::MessageID));
					bsIn.Read(rs);
					onReceive(rs.C_String(),rs.GetLength());
				}
				break;
			default:
				break;
			}
		}
	}
Example #10
0
 void ServerClient::execBG()
 {
     if(m_server)
         for (int i = 0; i < m_packets.size(); ++i)
         {
             // We got a packet, get the identifier with our handy function
             unsigned char packetIdentifier = m_packets[i].packetID;
             //std::cout << (int)packetIdentifier << std::endl;
             // Check if this is a network message packet
             switch (packetIdentifier)
             {
                 case ID_DISCONNECTION_NOTIFICATION:
                 case ID_CONNECTION_LOST:
                     // Connection lost normally
                     printf("ID_DISCONNECTION_NOTIFICATION\n");
                     m_connected = false;
                     m_connecting = false;
                     onDisconnect();
                     if(m_needsToConnect)
                     {
                         connect();
                         m_needsToConnect = false;
                     }
                     break;
                 case ID_ALREADY_CONNECTED:
                     // Connection lost normally
                     onFailedToConnect(false);
                     break;
                 case ID_INCOMPATIBLE_PROTOCOL_VERSION:
                     printf("ID_INCOMPATIBLE_PROTOCOL_VERSION\n");
                     break;
                 case ID_CONNECTION_BANNED: // Banned from this server
                     printf("We are banned from this server.\n");
                     break;
                 case ID_CONNECTION_ATTEMPT_FAILED:
                     printf("Connection attempt failed\n");
                     m_connecting = false;
                     m_connected = false;
                     onFailedToConnect(false);
                     break;
                 case ID_NO_FREE_INCOMING_CONNECTIONS:
                     // Sorry, the server is full.  I don't do anything here but
                     // A real app should tell the user
                     printf("ID_NO_FREE_INCOMING_CONNECTIONS\n");
                     break;
                     
                 case ID_INVALID_PASSWORD:
                     printf("ID_INVALID_PASSWORD\n");
                     break;
                 case ID_CONNECTION_REQUEST_ACCEPTED:
                     // This tells the client they have connected
                    // m_connecting = false;
                    // m_connected = true;
                     //m_needsToConnect = false;
                     //m_client.initClient(m_server,p->guid,p->systemAddress);
                    // onConnect();
                     break;
                 case ID_CONNECTED_PING:
                 case ID_UNCONNECTED_PING:
                    // printf("Ping from %s\n", p->systemAddress.ToString(true));
                     break;
                 case ID_USER_PACKET_ENUM:
                 {
                     RakNet::RakString rs;
                     RakNet::BitStream bsIn(&m_packets[i].message[0],m_packets[i].message.size(),false);
                     bsIn.IgnoreBytes(sizeof(RakNet::MessageID));
                     bsIn.Read(rs);
                     onReceive(rs.C_String(),rs.GetLength());
                 }
                     break;
                 default:
                     break;
             }
         }
     
     m_packets.clear();
     m_bgMode = false;
 }
Example #11
0
void CDemo::run()
{
	core::dimension2d<u32> resolution ( 800, 600 );

	if ( driverType == video::EDT_BURNINGSVIDEO || driverType == video::EDT_SOFTWARE )
	{
		resolution.Width = 640;
		resolution.Height = 480;
	}

	irr::SIrrlichtCreationParameters params;
	params.DriverType=driverType;
	params.WindowSize=resolution;
	params.Bits=32;
	params.Fullscreen=fullscreen;
	params.Stencilbuffer=shadows;
	params.Vsync=vsync;
	params.AntiAlias=aa;
	params.EventReceiver=this;

	device = createDeviceEx(params);
	if (!device)
		return;

	if (device->getFileSystem()->existFile("irrlicht.dat"))
		device->getFileSystem()->addFileArchive("irrlicht.dat", true, true, io::EFAT_ZIP);
	else
		device->getFileSystem()->addFileArchive(IRRLICHT_MEDIA_PATH "irrlicht.dat", true, true, io::EFAT_ZIP);
	if (device->getFileSystem()->existFile("map-20kdm2.pk3"))
		device->getFileSystem()->addFileArchive("map-20kdm2.pk3", true, true, io::EFAT_ZIP);
	else
		device->getFileSystem()->addFileArchive(IRRLICHT_MEDIA_PATH "map-20kdm2.pk3", true, true, io::EFAT_ZIP);

	video::IVideoDriver* driver = device->getVideoDriver();
	scene::ISceneManager* smgr = device->getSceneManager();
	gui::IGUIEnvironment* guienv = device->getGUIEnvironment();

	device->setWindowCaption(L"Irrlicht Engine Demo");

	// set ambient light
	smgr->setAmbientLight ( video::SColorf ( 0x00c0c0c0 ) );


//	wchar_t tmp[255];

	// RakNet startup
	char dest[1024];
	memset(dest,0,sizeof(dest));
	wcstombs(dest, playerName.c_str(), playerName.size());
	InstantiateRakNetClasses();

	// Hook RakNet stuff into this class
	playerReplica->playerName=RakNet::RakString(dest);
	playerReplica->demo=this;
	replicaManager3->demo=this;

	CalculateSyndeyBoundingBox();

	// draw everything

	s32 now = 0;
	sceneStartTime = device->getTimer()->getTime();
	while(device->run() && driver)
	{
		// RakNet: Render even if not active, multiplayer never stops
		//if (device->isWindowActive())
		{
#ifdef USE_IRRKLANG
			// update 3D position for sound engine
			scene::ICameraSceneNode* cam = smgr->getActiveCamera();
			if (cam && irrKlang)
				irrKlang->setListenerPosition(cam->getAbsolutePosition(), cam->getTarget());
#endif

			// load next scene if necessary
			now = device->getTimer()->getTime();
			if (now - sceneStartTime > timeForThisScene && timeForThisScene!=-1)
				switchToNextScene();

			createParticleImpacts();

			driver->beginScene(timeForThisScene != -1, true, backColor);

			smgr->drawAll();
			guienv->drawAll();

			driver->endScene();

			/*
			// write statistics
			static s32 lastfps = 0;
			s32 nowfps = driver->getFPS();

			swprintf(tmp, 255, L"%ls fps:%3d triangles:%0.3f mio",
				driver->getName(),
				driver->getFPS(),
				(f32) driver->getPrimitiveCountDrawn( 1 ) * ( 1.f / 1000000.f )
				);
			if ( nowfps != lastfps )
			{
				device->setWindowCaption ( tmp );
				lastfps = nowfps;
			}
*/
			RakNet::RakString curMsg = GetCurrentMessage();
			if (curMsg.IsEmpty()==false)
			{
				wchar_t dest[1024];
				memset(dest,0,sizeof(dest));
				mbstowcs(dest, curMsg.C_String(), curMsg.GetLength());
				statusText->setText(dest);
			}
			else
			{
		//		statusText->setText(tmp);
				statusText->setText(0);
			}
		}

		// RakNet per tick update
		UpdateRakNet();
	}

	// RakNet shutdown
	DeinitializeRakNetClasses();

	device->drop();
}