Пример #1
0
//----------------------------------------------------------------------------------------------
// Protected : OnLine
//----------------------------------------------------------------------------------------------
void CObjMesh::OnLine()
{
	char *sToken = GetToken();

	// It's possible to have an integer "modifier" appended to a command
	EOb2Command eCmd = ParseCommandString( sToken );

	switch (eCmd)
	{
	case eVertexCoord:
		{
			float fX = GetFloatToken();
			float fY = GetFloatToken();
			float fZ = GetFloatToken();
			OnVertexCoordinate( fX, fY, fZ );
		}
		break;
	case eTextureCoord:
		{
			float fX = GetFloatToken();
			float fY = GetFloatToken();

			OnVertexTextureCoordinate( fX, fY );
		}
		break;
	case eNormalCoord:
		{
			float fX = GetFloatToken();
			float fY = GetFloatToken();
			float fZ = GetFloatToken();
			OnVertexNormal( fX, fY, fZ );
		}
		break;
	case eFace:
		{
			int pVertexCoords[128];
			int pTexCoords[128];
			int pNormal[128];

			// Initialize to -1
			for (int i = 0; i < 128; i++)
				pNormal[i] = pTexCoords[i] = -1;

			// Tokens can be of the form <vertex>/<texture>/<normal>, or <vertex>/<texture> or <vertex>
			int nNumCoords = 0;
			while ( sToken = GetToken() )
			{
				string sVertexString( sToken );

				int nStart = 0;
				for ( int nNum = 0; nNum < 3; nNum++ )
				{
					unsigned int nEnd = (int)sVertexString.find_first_of("/", nStart);

					bool bExit = false;
					if ( nEnd == string::npos)
					{
						nEnd = sVertexString.size();
						bExit = true;
					}

					string sNumber = sVertexString.substr( nStart, nEnd-nStart );

					if ( nNum == 0 )
						pVertexCoords[nNumCoords] = atoi(sNumber.c_str());
					else if ( nNum == 1 )
						pTexCoords[nNumCoords] = atoi(sNumber.c_str());
					else if ( nNum == 2 )
						pNormal[nNumCoords] = atoi(sNumber.c_str());

					if ( bExit )
						break;

					nStart = nEnd + 1;
				}
				nNumCoords++;
			}
			OnFace( pVertexCoords, pTexCoords, pNormal, nNumCoords );

		}
		break;
	}
}
Пример #2
0
bool udtBaseParser::ParseServerMessage()
{
	_outMsg.Init(_outMsgData, sizeof(_outMsgData));

	_outMsg.SetHuffman(_outProtocol >= udtProtocol::Dm66);
	_inMsg.SetHuffman(_inProtocol >= udtProtocol::Dm66);

	//
	// Using the message sequence number as acknowledge number will help avoid 
	// the command overflow playback error for dm3 and dm_48 demos converted to dm_68.
	// For reference in the Q3 source code: "Client command overflow".
	//
	s32 reliableSequenceAcknowledge = _inServerMessageSequence;
	if(_inProtocol > udtProtocol::Dm3)
	{
		const s32 sequAck = _inMsg.ReadLong(); // Reliable sequence acknowledge.
		if(_inProtocol >= udtProtocol::Dm68)
		{
			reliableSequenceAcknowledge = sequAck;
		}
	}
	_inReliableSequenceAcknowledge = reliableSequenceAcknowledge;
	if(ShouldWriteMessage())
	{
		_outMsg.WriteLong(_inReliableSequenceAcknowledge);
	}

	if(EnablePlugIns && !PlugIns.IsEmpty())
	{
		udtMessageBundleCallbackArg info;
		info.ReliableSequenceAcknowledge = reliableSequenceAcknowledge;
		for(u32 i = 0, count = PlugIns.GetSize(); i < count; ++i)
		{
			PlugIns[i]->ProcessMessageBundleStart(info, *this);
		}
	}

	for(;;)
	{
		if(_inMsg.Buffer.readcount > _inMsg.Buffer.cursize) 
		{
			_context->LogError("udtBaseParser::ParseServerMessage: Read past the end of the server message (in file: %s)", GetFileNamePtr());
			return false;
		}

		if(_inMsg.Buffer.readcount == _inMsg.Buffer.cursize)
		{
			break;
		}

		const s32 command = _inMsg.ReadByte();
		if(command == svc_EOF || (_inProtocol <= udtProtocol::Dm48 && command == svc_bad))
		{
			break;
		}

		// @NOTE: We don't write the command byte already, we leave that decision for later.

		switch(command) 
		{
		case svc_nop:
			if(ShouldWriteMessage())
			{
				_outMsg.WriteByte(svc_nop);
			}
			break;

		case svc_serverCommand:
			if(!ParseCommandString()) return false;
			break;

		case svc_gamestate:
			if(!ParseGamestate()) return false;
			break;

		case svc_snapshot:
			if(!ParseSnapshot()) return false;
			break;

		case svc_download:
		case svc_voip:
		default:
			_context->LogError("udtBaseParser::ParseServerMessage: Unrecognized server message command byte: %d (in file: %s)", command, GetFileNamePtr());
			return false;
		}

		if(_inProtocol <= udtProtocol::Dm48)
		{
			_inMsg.GoToNextByte();
		}
	}

	if(ShouldWriteMessage())
	{
		_outMsg.WriteByte(svc_EOF);
	}

	if(EnablePlugIns && !PlugIns.IsEmpty())
	{
		udtMessageBundleCallbackArg info;
		info.ReliableSequenceAcknowledge = reliableSequenceAcknowledge;
		for(u32 i = 0, count = PlugIns.GetSize(); i < count; ++i)
		{
			PlugIns[i]->ProcessMessageBundleEnd(info, *this);
		}
	}

	if(_cuts.GetSize() > 0)
	{
		const udtCutInfo cut = _cuts[0];
		const s32 gameTime = _inServerTime;

		if(_inGameStateIndex == cut.GameStateIndex && !_outWriteMessage &&
		   gameTime >= cut.StartTimeMs && gameTime <= cut.EndTimeMs)
		{
			const bool wroteMessage = _outWriteMessage;
			_outWriteMessage = true;
			_outWriteFirstMessage = _outWriteMessage && !wroteMessage;
		}
		else if((_inGameStateIndex == cut.GameStateIndex && _outWriteMessage && gameTime > cut.EndTimeMs) ||
				(_inGameStateIndex > cut.GameStateIndex && _outWriteMessage))
		{
			WriteLastMessage();
			_outWriteMessage = false;
			_outWriteFirstMessage = false;
			_outServerCommandSequence = 0;
			_outSnapshotsWritten = 0;
			_outFile.Close();
			_cuts.Remove(0);
			if(_cuts.GetSize() == 0)
			{
				// It was the last cut, we're done parsing the file now.
				return false;
			}
		}
	}

	if(_outWriteFirstMessage)
	{
		udtCutInfo& cut = _cuts[0];
		udtString filePath;
		if(cut.FilePath != NULL)
		{
			filePath = udtString::NewConstRef(cut.FilePath);
		}
		else
		{
			udtDemoStreamCreatorArg info;
			memset(&info, 0, sizeof(info));
			info.StartTimeMs = cut.StartTimeMs;
			info.EndTimeMs = cut.EndTimeMs;
			info.Parser = this;
			info.VeryShortDesc = cut.VeryShortDesc;
			info.UserData = cut.UserData;
			info.TempAllocator = &_tempAllocator;
			info.FilePathAllocator = &_persistentAllocator;
			filePath = (*cut.StreamCreator)(info);
		}
		_outFile.Close();
		if(_outFile.Open(filePath.GetPtr(), udtFileOpenMode::Write))
		{
			_outFilePath = filePath;
			udtPath::GetFileName(_outFileName, _persistentAllocator, filePath);
			_outMsg.SetFileName(_outFileName);
			WriteFirstMessage();
			_outWriteFirstMessage = false;
		}
		else
		{
			_cuts.Remove(0);
		}
	}
	else if(_outWriteMessage)
	{
		WriteNextMessage();
	}

	return true;
}