十、起源引擎序列化和反序列化之元数据处理
460人浏览 / 0人评论
游戏逻辑类的属性元数据定义好以后,引擎还需要处理后才能使用。在服务端引擎SV_InitGameDLL方法里有如下代码:
COM_TimestampedLog( "SV_InitSendTables" );
// Make extra copies of data tables if they have SendPropExcludes.
SV_InitSendTables( serverGameDLL->GetAllServerClasses() );
这个方法获取到游戏逻辑定义的所有类,然后拿到每个类关联的属性定义表,依次处理,处理逻辑如下:
static bool SendTable_InitTable( SendTable *pTable )
{
if( pTable->m_pPrecalc )
return true;
// Create the CSendTablePrecalc.
CSendTablePrecalc *pPrecalc = new CSendTablePrecalc;
pTable->m_pPrecalc = pPrecalc;
pPrecalc->m_pSendTable = pTable;
pTable->m_pPrecalc = pPrecalc;
SendTable_CalcNextVectorElems( pTable );
// Bind the instrumentation if -dti was specified.
pPrecalc->m_pDTITable = ServerDTI_HookTable( pTable );
// Setup its flat property array.
if ( !pPrecalc->SetupFlatPropertyArray() )
return false;
SendTable_Validate( pPrecalc );
return true;
}
这个m_pPrecalc用来存储了处理后的数据,主要处理过程在SetupFlatPropertyArray 中
bool CSendTablePrecalc::SetupFlatPropertyArray()
{
SendTable *pTable = GetSendTable();
// First go through and set SPROP_INSIDEARRAY when appropriate, and set array prop pointers.
SetupArrayProps_R<SendTable, SendTable::PropType>( pTable );
// Make a list of which properties are excluded.
ExcludeProp excludeProps[MAX_EXCLUDE_PROPS];
int nExcludeProps = 0;
if( !SendTable_GetPropsExcluded( pTable, excludeProps, nExcludeProps, MAX_EXCLUDE_PROPS ) )
return false;
// Now build the hierarchy.
CBuildHierarchyStruct bhs;
bhs.m_pExcludeProps = excludeProps;
bhs.m_nExcludeProps = nExcludeProps;
bhs.m_nProps = bhs.m_nDatatableProps = 0;
bhs.m_nPropProxies = 0;
SendTable_BuildHierarchy( GetRootNode(), pTable, &bhs );
SendTable_SortByPriority( &bhs );
// Copy the SendProp pointers into the precalc.
MEM_ALLOC_CREDIT();
m_Props.CopyArray( bhs.m_pProps, bhs.m_nProps );
m_DatatableProps.CopyArray( bhs.m_pDatatableProps, bhs.m_nDatatableProps );
m_PropProxyIndices.CopyArray( bhs.m_PropProxyIndices, bhs.m_nProps );
// Assign the datatable proxy indices.
SetNumDataTableProxies( 0 );
SetDataTableProxyIndices_R( this, GetRootNode(), &bhs );
int nProxyIndices = 0;
SetRecursiveProxyIndices_R( pTable, GetRootNode(), nProxyIndices );
SendTable_GenerateProxyPaths( this, nProxyIndices );
return true;
}
SetupArrayProps_R方法就是专门处理数组属性类型的,数组属性定义时外层属性和内层属性紧挨着定义的,在这里将内层属性放到外层属性内部,去掉并列的内层属性。SendTable_GetPropsExcluded是收集属性定义里的排除属性,将会在之后的属性遍历里过滤掉这些属性。在实现某个逻辑类时有可能不想让继承的上级某个属性通过网络传输,就需要使用属性排除。SendTable_BuildHierarchy这个是主要的处理方法,这里引入了CSendNode这个类存储处理后的属性上下级关系等多种信息,这个类和属性定义类型中的嵌套类型是对应的,一个有多层继承关系,多个属性的逻辑类的属性定义好以后,所有的属性形成一个树形结构,每一个嵌套属性就是一个分支,这个方法就是遍历属性树的所有属性,将属性按遍历顺序依次编号,最终编解码时是使用列表循环处理属性的,而编号也将作为服务器和客户端编解码数据查找客户端属性的依据,遍历过程中对于它内部的末级属性在父级CSendNode记录下属性的开始索引和属性数量,对于内部的嵌套属性生成子级CSendNode放在父级CSendNode的child字段里,子级CSendNode还记录了嵌套属性的索引。
全部评论