/* 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; }