Exemplo n.º 1
0
/* Unpack some actions from a bit stream. Set transmitTimestamp=true for server-->client,
 * false for client-->server. If true, set the current gamecycle.
 */
void CActionFactory::unpack (NLMISC::CBitMemStream &message, std::vector <CAction *>& actions, NLMISC::TGameCycle /* currentCycle */ )
{
	actions.clear ();

	static int n = 0;
	n++;
	while ((sint32)message.length() * 8 - message.getPosInBit () >= 8)
	{
		TActionCode code;

		bool shortcode;
		message.serial (shortcode);

		if (shortcode)
		{
			code = 0;
			uint32 val;
			message.serial (val, 2);
			code = (TActionCode) val;
		}
		else
		{
			message.serial (code);
		}

		CAction *action = create (INVALID_SLOT, code);

		//nlinfo ("m%d size: p:%d s:%d c:%d (actionsize: %d) slot:%hu", n, message.getPosInBit (), message.length() * 8, code, action->size(), (uint16)action->CLEntityId);

		if (action == NULL)
		{
			nlwarning ("Unpacking an action with unknown code, skip it (%u)", code);
		}
		else
		{
			action->unpack (message);
			actions.push_back (action);
		}
	}
}
//-----------------------------------------------
//	writePermanentDelta
//
// TODO: Maybe an optimization will be required to prevent sending null properties
// when a character is added to a CCDBGroup.
//-----------------------------------------------
bool	CCDBSynchronised::writePermanentDelta( NLMISC::CBitMemStream& s )
{
	static uint nbPermaDeltaSent = 0;

	// Test the changed property count and make room to store the number of property pushed (poked later)
	uint origChangedPropertyCount = _DataContainer.getPermanentChangedPropertyCount();
	if ( origChangedPropertyCount == 0 )
		return false;
	uint bitposOfNbChanges = s.getPosInBit();
	uint32 dummy = 0;
	s.serial( dummy, CDBChangedPropertyCountBitSize ); // optimising s.reserveBits( CDBChangedPropertyCountBitSize )

	// Browse changes and write them
	uint32 nbChanges = 0;

	uint32 bitsize = CDBChangedPropertyCountBitSize; // initialize with the size of the reserved bits for the number of changes
	TCDBDataIndex dataIndex = _DataContainer.getPermanentFirstChanged();
	while ( dataIndex != CDB_LAST_CHANGED
			/*&& (bitsize < maxBitSize)*/ )
	{
		++nbPermaDeltaSent;

		// Retrieve the structure node corresponding to the index
		ICDBStructNode *node = CCDBStructBanks::instance()->getNodeFromDataIndex( _Bank, dataIndex );
		nlassert( node );

		if ( node->isAtomic() ) // counts for 1 change
		{
#ifdef NL_DEBUG
			nlassert( dynamic_cast<CCDBStructNodeBranch*>(node) ); // should not be leaf because the main tracker pushes the atom group index for atomic leaves
#endif
			// Build and push the binary atom id
			ICDBStructNode::CBinId binId;
			(static_cast<CCDBStructNodeBranch*>(node))->buildBinIdFromLeaf( binId );
			bitsize += binId.writeToBitMemStream( s );
			//nlinfo( "CDB/ATOM: Written bin id %s", binId.toString().c_str() );
			//_DataContainer.displayAtomChanges( node->getDataIndex() );

			// Make room to store the atom bitfield
			uint bitposOfAtomBitfield = s.getPosInBit();
			uint indexInAtom = 0;
			node->foreachLeafCall( cbNop, indexInAtom, NULL ); // count the number of siblings
			uint nbAtomElements = indexInAtom;
			s.reserveBits( nbAtomElements );
			bitsize += nbAtomElements;
			//nlinfo( "CDB/ATOM: Reserved %u bits (%d)", nbAtomElements, s.getPosInBit()-bitposOfAtomBitfield );

			// Browse the siblings of the atom node, and push the deltas for the properties marked as changes, updating the bitfield
			TPushAtomChangeStruct arg;
			arg.CdbSync = this;
			arg.BitSize = &bitsize;
			arg.S = &s;
			arg.AtomBitfield.resize( nbAtomElements );
			indexInAtom = 0;
			node->foreachLeafCall( cbPushDeltaOfLeafInAtomIfChangedPermanent, indexInAtom, (void*)&arg );
			
			// Fill the placeholder with the bitfield
			s.pokeBits( arg.AtomBitfield, bitposOfAtomBitfield );
			if ( VerboseDatabase )
			{
				nldebug( "CDB/ATOM: Bitfield: %s", arg.AtomBitfield.toString().c_str() );
			}

		}
		else
		{
#ifdef NL_DEBUG
			nlassert( dynamic_cast<CCDBStructNodeLeaf*>(node) );
#endif

			// Push the binary property id
			bitsize += static_cast<CCDBStructNodeLeaf*>(node)->binLeafId().writeToBitMemStream( s );

			// Push the value
			pushDeltaPermanent( s, static_cast<CCDBStructNodeLeaf*>(node), bitsize );
		}

		dataIndex = _DataContainer.getPermanentNextChanged( dataIndex );
		++nbChanges;
	}

	// Fill the placeholder with the number of changes
	s.poke( nbChanges, bitposOfNbChanges, CDBChangedPropertyCountBitSize );
	//s.displayStream( "writeDelta" );

#ifdef TRACE_SET_VALUE
	if ( VerboseDatabase )
		nldebug( "%u: CDB: Permanent Delta pushed (%u changes written, %u remaining)", CTickEventHandler::getGameCycle(), nbChanges, getChangedPropertyCount() );
#endif

	nldebug( "Filled %u permanent changes", nbPermaDeltaSent );

	return true;
}