//----------------------------------------------- // setChatMode // //----------------------------------------------- void CClientChatManager::setChatMode(CChatGroup::TGroupType group, TChanID dynamicChannelId) { uint8 mode = group; // mode really changed ? if (mode == _ChatMode && dynamicChannelId==_ChatDynamicChannelId) return; // Chat team don't need swap mode if (group != CChatGroup::team) { CBitMemStream bms; string msgType = "STRING:CHAT_MODE"; if( GenericMsgHeaderMngr.pushNameToStream(msgType,bms) ) { bms.serial( mode ); bms.serial( dynamicChannelId ); NetMngr.push( bms ); //nlinfo("impulseCallBack : %s %d sent", msgType.c_str(), mode); } else { nlwarning("<CClientChatManager::setChatMode> unknown message name : STRING:CHAT_MODE"); } } // update cache _ChatMode = mode; _ChatDynamicChannelId = dynamicChannelId; if (UserEntity != NULL) UserEntity->setAFK(false); } // filter //
//----------------------------------------------- // tell // //----------------------------------------------- void CClientChatManager::tell( const string& receiverIn, const ucstring& strIn ) { // Truncate to 255 chars max (because of server restriction) string receiver= receiverIn.substr(0,255); ucstring str= strIn.substr(0,255); // *** send str CBitMemStream bms; string msgType = "STRING:TELL"; if( GenericMsgHeaderMngr.pushNameToStream(msgType,bms) ) { bms.serial( receiver ); bms.serial( str ); NetMngr.push( bms ); //nlinfo("impulseCallBack : %s %s %s sent", msgType.c_str(), receiver.c_str(), str.toString().c_str()); } else { nlwarning("<CClientChatManager::tell> unknown message name : STRING:TELL"); } // *** manage list of last telled people // remove the telled people from list (if present) std::list<ucstring>::iterator it = _TellPeople.begin(); while(it != _TellPeople.end()) { if (*it == ucstring(receiver)) { it = _TellPeople.erase(it); nlassert(_NumTellPeople != 0); -- _NumTellPeople; } else { ++it; } } // readd to back of the list (most recent telled people) _TellPeople.push_back(receiver); ++ _NumTellPeople; // if too much people, remove the older one if (_NumTellPeople > _MaxNumTellPeople) { -- _NumTellPeople; _TellPeople.pop_front(); } // tell => the user is no more AFK. if (UserEntity != NULL) UserEntity->setAFK(false); } // tell //
// *************************************************************************** void CGuildManager::launchAscensor() { // Start the huge list exchange Ascensors.start(); // Increment session id Ascensors.incrementSessionID(); // Send request of the first page to the server specifying the session id CBitMemStream out; if(GenericMsgHeaderMngr.pushNameToStream("GUILD:FIRST_ASCENSOR_PAGE", out)) { uint16 session = Ascensors.getSessionID(); out.serial(session); NetMngr.push(out); //nlinfo("impulseCallBack : GUILD:FIRST_ASCENSOR_PAGE %d sent",session); } else { nlwarning("impulseCallBack : unknown message name : 'GUILD:FIRST_ASCENSOR_PAGE'."); } // Start Ascensor Interface CInterfaceManager *pIM = CInterfaceManager::getInstance(); CGroupContainer *pAC = dynamic_cast<CGroupContainer*>(pIM->getElementFromId(WIN_ASCENSOR)); if (pAC == NULL) return; pAC->setActive(true); pIM->setTopWindow(pAC); }
//----------------------------------------------- // chat // //----------------------------------------------- void CClientChatManager::chat( const ucstring& strIn, bool isChatTeam ) { // Truncate to 255 chars max (because of server restriction) ucstring str= strIn.substr(0,255); // send str to IOS CBitMemStream bms; string msgType; if (isChatTeam) { if (NLGUI::CDBManager::getInstance()->getDbProp("SERVER:GROUP:0:PRESENT")->getValueBool()) msgType = "STRING:CHAT_TEAM"; else return; // don't display team chat message if there is no team chat } else msgType = "STRING:CHAT"; if( GenericMsgHeaderMngr.pushNameToStream(msgType,bms) ) { bms.serial( str ); NetMngr.push( bms ); //nlinfo("impulseCallBack : %s %s sent", msgType.c_str(), str.toString().c_str()); } else { nlwarning("<CClientChatManager::chat> unknown message name : %s", msgType.c_str()); } if (UserEntity != NULL) UserEntity->setAFK(false); } // chat //
void execute (CCtrlBase * /* pCaller */, const std::string &/* sParams */) { CInterfaceManager *pIM= CInterfaceManager::getInstance(); // Copy SERVER DB to Local selection uint32 outpostSheet= 0; CCDBNodeLeaf *node= NLGUI::CDBManager::getInstance()->getDbProp("LOCAL:TARGET:CONTEXT_MENU:OUTPOST"); if(node) outpostSheet= node->getValue32(); node= NLGUI::CDBManager::getInstance()->getDbProp("UI:TEMP:OUTPOST:BOT_SELECTION"); if(node) node->setValue32(outpostSheet); // Send a msg to server if(outpostSheet) { string sMsg= "OUTPOST:SELECT"; CBitMemStream out; if(GenericMsgHeaderMngr.pushNameToStream(sMsg, out)) { //nlinfo("impulseCallBack : %s %d sent", sMsg.c_str(), outpostSheet); out.serial(outpostSheet); NetMngr.push(out); } else { nlwarning("command : unknown message name : '%s'.", sMsg.c_str()); } } }
void CImpulseDecoder::decode(CBitMemStream &inbox, TPacketNumber receivedPacket, TPacketNumber receivedAck, TPacketNumber nextSentPacket, vector<CLFECOMMON::CAction *> &actions) { uint level; for (level=0; level<3; ++level) { TPacketNumber *lAck; uint channel; switch (level) { case 0: lAck = _LastAck0; channel = 0; break; case 1: lAck = _LastAck1; channel = receivedPacket&1; break; case 2: lAck = _LastAck2; channel = receivedPacket&3; break; } bool keep = true; bool checkOnce = false; uint num = 0; TPacketNumber lastAck = lAck[channel]; for(;;) { bool next; inbox.serial(next); if (!next) break; if (!checkOnce) { checkOnce = true; keep = (receivedAck >= lAck[channel]); if (keep) lAck[channel] = nextSentPacket; } ++num; CAction *action = CActionFactory::getInstance()->unpack(inbox, false); if (keep) { actions.push_back(action); nlinfo("CLIMPD: received new impulsion %d (len=%u) at level %d (channel %d)", action->Code, CActionFactory::getInstance()->size(action), level, channel, num, (keep) ? "" : " (discarded)", lastAck, nextSentPacket); } else { nlinfo("CLIMPD: discarded action %d (len=%u) at level %d (channel %d)", action->Code, CActionFactory::getInstance()->size(action), level, channel, num, (keep) ? "" : " (discarded)", lastAck, nextSentPacket); CActionFactory::getInstance()->remove(action); } } if (checkOnce) nldebug("CLIMPD: at level %d (channel %d), %d actions%s (ReceivedAck=%d/lastAck=%d/nextSentPacket=%d)", level, channel, num, (keep) ? "" : " (discarded)", receivedAck, lastAck, nextSentPacket); } }
// *************************************************************************** void COutpostManager::endPvpJoinProposal(bool bNeutral, OUTPOSTENUMS::TPVPSide pvpSide) { // send msg string sMsg= "OUTPOST:SIDE_CHOSEN"; CBitMemStream out; if(GenericMsgHeaderMngr.pushNameToStream(sMsg, out)) { //nlinfo("impulseCallBack : %s %d %s sent", sMsg.c_str(), bNeutral, OUTPOSTENUMS::toString(pvpSide).c_str()); out.serial(bNeutral); uint8 sideAsInt = (uint8)pvpSide; out.serial(sideAsInt); NetMngr.push(out); } else { nlwarning("command : unknown message name : '%s'.", sMsg.c_str()); } // Abort any timer _EndTickForPvpJoinProposal= 0; }
void execute (CCtrlBase * /* pCaller */, const std::string &/* sParams */) { CInterfaceManager *pIM= CInterfaceManager::getInstance(); // read current outpost sheet uint32 outpostSheet= 0; CCDBNodeLeaf *node= NLGUI::CDBManager::getInstance()->getDbProp("SERVER:OUTPOST_SELECTED:SHEET", false); if(node) outpostSheet= node->getValue32(); // read wanted GMT attack period uint8 wantedAttHour= 0; node= NLGUI::CDBManager::getInstance()->getDbProp("UI:TEMP:OUTPOST:DECLARE_WAR_ATTACK_PERIOD", false); if(node) wantedAttHour= (uint8)node->getValue32(); // read result Att Period Time (NB: for final server check: ensure that the user will get what it sees) uint32 startAttackTime= 0; node= NLGUI::CDBManager::getInstance()->getDbProp("UI:TEMP:OUTPOST:DECLARE_WAR_ACK_TIME_RANGE_ATT", false); if(node) startAttackTime= node->getValue32(); // send a DECLARE_WAR_VALIDATE message to server string sMsg= "OUTPOST:DECLARE_WAR_VALIDATE"; CBitMemStream out; if(GenericMsgHeaderMngr.pushNameToStream(sMsg, out)) { //nlinfo("impulseCallBack : %s %d %d %d sent", sMsg.c_str(), outpostSheet, wantedAttHour, startAttackTime); out.serial(outpostSheet); out.serial(wantedAttHour); out.serial(startAttackTime); NetMngr.push(out); } else { nlwarning("command : unknown message name : '%s'.", sMsg.c_str()); } }
//----------------------------------------------- // readDelta // //----------------------------------------------- void CCDBSynchronised::readDelta( NLMISC::TGameCycle gc, CBitMemStream& s, TCDBBank bank ) { nldebug("Update DB"); if( _Database == 0 ) { nlwarning("<CCDBSynchronised::readDelta> the database has not been initialized"); return; } //displayBitStream2( f, f.getPosInBit(), f.getPosInBit() + 64 ); uint16 propertyCount = 0; s.serial( propertyCount ); if ( VerboseDatabase ) nlinfo( "CDB: Reading delta (%hu changes)", propertyCount ); NbDatabaseChanges += propertyCount; for( uint i=0; i!=propertyCount; ++i ) { _Database->readAndMapDelta( gc, s, bank ); } /*// Read "client only" property changes bool hasCOPropChanges; s.serialBit( hasCOPropChanges ); if ( hasCOPropChanges ) { uint32 nbCOPropChanges; s.serial( nbCOPropChanges, 4 ); if ( nbCOPropChanges == 15 ) { s.serial( nbCOPropChanges ); } for ( uint i=0; i!=nbCOPropChanges; ++i ) { string propName; //TEMP sint64 value; //TEMP s.serial( propName ); s.serial( value ); setProp( propName, value ); } }*/ } // readDelta //
//----------------------------------------------- // filter // //----------------------------------------------- void CClientChatManager::filter( uint8 filter ) { CBitMemStream bms; string msgType = "STRING:FILTER"; if( GenericMsgHeaderMngr.pushNameToStream(msgType,bms) ) { bms.serial( filter ); NetMngr.push( bms ); //nlinfo("impulseCallBack : %s %d sent", msgType.c_str(), filter); } else { nlwarning("<CClientChatManager::filter> unknown message name : STRING:FILTER"); } if (UserEntity != NULL) UserEntity->setAFK(false); } // filter //
//----------------------------------------------- // readDelta //----------------------------------------------- void CCDBNodeLeaf::readDelta(TGameCycle gc, CBitMemStream & f ) { // If the property Type is valid. if(_Type > UNKNOWN && _Type < Nb_Prop_Type) { // Read the Property Value according to the Property Type. uint64 recvd = 0; uint bits; if (_Type == TEXT) bits = 32; else if (_Type <= I64) bits = _Type; else bits = _Type - 64; f.serial(recvd, bits); // if the DB update is older than last DB update, abort (but after the read!!) if(gc<_LastChangeGC) return; // bkup _oldProperty _oldProperty = _Property; // setup new one _Property = (sint64)recvd; // if signed if (! ((_Type == TEXT) || (_Type <= I64))) { // extend bit sign sint64 mask = (((sint64)1)<<bits)-(sint64)1; if( (_Property >> (bits-1))==1 ) { _Property |= ~mask; } }
// **************************************************************************** void CHugeListObs::update(ICDBNode * /* node */) { nlassert((uint) _Category < ListTypeCount); // must call setListType // if botchat is not active, dont care with update if ((_Category == Trading) || (_Category == ItemForMissions) || (_Category == Missions)) { if (!CBotChatManager::getInstance()->getCurrPage()) return; } if (!init()) { nlwarning("Can't do init"); return; } // check if good session if (_Session->getValue16() != _CurrentSessionNb) { // msg from a previous session, dont care return; } TItemVect *itemPages = &_ItemsPages; uint pageID = (uint) _PageID->getValue16(); if (pageID >= TRADE_MAX_NUM_PAGES) return; // bad page index if (pageID >= itemPages->size()) { // expand items list itemPages->resize(pageID + 1); } // if 'has_next' flag is set, then ask server for more pages (if it is not a page update) if (_HasNext->getValueBool()) { static const char *msgItemForMoney = "BOTCHAT:NEXT_PAGE_ITEM"; static const char *msgItemForMission = "TRADE:NEXT_PAGE_MISSION_ITEM"; static const char *msgAscensor = "GUILD:NEXT_ASCENSOR_PAGE"; static const char *msgMissions; if(_MType==MISSION_DESC::ZCCharge) msgMissions= "BOTCHAT:NEXT_PAGE_DUTY"; else msgMissions= "BOTCHAT:NEXT_PAGE_MISSION"; const char* msgName; switch(_Category) { case Trading: msgName = msgItemForMoney; break; case ItemForMissions: msgName = msgItemForMission; break; case Ascensor: msgName = msgAscensor; break; case Missions: msgName = msgMissions; break; default: nlassert(0); // You have to provide message for ping-pong behavior break; } CBitMemStream out; if(GenericMsgHeaderMngr.pushNameToStream(msgName, out)) { out.serial(_CurrentSessionNb); NetMngr.push(out); //nlinfo("impulseCallBack : %s %d sent", msgName, _CurrentSessionNb); } else { nlwarning("<CHandlerAcceptExchange::execute> unknown message name '%s'", msgName); } } else { _DownloadComplete = true; } CItemPage &page = (*itemPages)[pageID]; uint k; // copy items page into temporary stuff for (k = 0; k < TRADE_PAGE_NUM_ITEMS; ++k) { switch(_Category) { case Trading: { page.Items[k].SlotType = (TRADE_SLOT_TYPE::TTradeSlotType) _Items[k].SlotType->getValue32(); page.Items[k].Quality = (uint16) _Items[k].Quality->getValue16(); page.Items[k].SheetIDOrSkill = (uint32) _Items[k].SheetIDOrSkill->getValue32(); page.Items[k].Price = (uint32) _Items[k].Price->getValue32(); page.Items[k].Weight= (uint16) _Items[k].Weight->getValue16(); page.Items[k].NameId= (uint32) _Items[k].NameId->getValue32(); page.Items[k].UserColor = _Items[k].UserColor->getValue32(); page.Items[k].Enchant = _Items[k].Enchant->getValue32(); page.Items[k].RMClassType = _Items[k].RMClassType->getValue32(); page.Items[k].RMFaberStatType = _Items[k].RMFaberStatType->getValue32(); page.Items[k].PrerequisitValid = _Items[k].PrerequisitValid->getValue32(); page.Items[k].InfoVersion= (uint16) _Items[k].InfoVersion->getValue16(); page.Items[k].Quantity= (uint16) _Items[k].Quantity->getValue16(); page.Items[k].PriceRetire= (uint32) _Items[k].PriceRetire->getValue32(); page.Items[k].ResaleTimeLeft= (uint32) _Items[k].ResaleTimeLeft->getValue32(); page.Items[k].VendorNameId= (uint32) _Items[k].VendorNameId->getValue32(); page.Items[k].FactionType= (uint32) _Items[k].FactionType->getValue32(); page.Items[k].FactionPointPrice= (uint32) _Items[k].FactionPointPrice->getValue32(); page.Items[k].SellerType= (uint32) _Items[k].SellerType->getValue32(); // is the sheet is a phrase sheet, discard it if already known /* CEntitySheet *sheet = SheetMngr.get(CSheetId(page.Items[k].SheetIDOrSkill)); if (sheet && sheet->Type == CEntitySheet::SPHRASE) { CSPhraseSheet *ps = (CSPhraseSheet *) sheet; CSPhraseCom pc; pc.Bricks.swap(ps->Bricks); // substitute brick in the object (for the time of comparison) if (CSPhraseManager::getInstance()->isPhraseKnown(pc)) { page.Items[k].SheetIDOrSkill = 0; // already known, do not show in list } pc.Bricks.swap(ps->Bricks); // restore list of sheet } */ } break; case ItemForMissions: page.Items[k].SlotType = (TRADE_SLOT_TYPE::TTradeSlotType) _Items[k].SlotType->getValue32(); page.Items[k].Quality = (uint16) _Items[k].Quality->getValue16(); page.Items[k].SheetIDOrSkill = (uint32) _Items[k].SheetIDOrSkill->getValue32(); page.Items[k].LogicTextID = (uint32) _Items[k].LogicTextID->getValue32(); page.Items[k].DescTextID = (uint32) _Items[k].DescTextID->getValue32(); page.Items[k].Weight= (uint16) _Items[k].Weight->getValue16(); page.Items[k].NameId= (uint32) _Items[k].NameId->getValue32(); page.Items[k].UserColor = _Items[k].UserColor->getValue32(); page.Items[k].Enchant = _Items[k].Enchant->getValue32(); page.Items[k].RMClassType = _Items[k].RMClassType->getValue32(); page.Items[k].RMFaberStatType = _Items[k].RMFaberStatType->getValue32(); page.Items[k].InfoVersion= (uint16) _Items[k].InfoVersion->getValue16(); break; case Ascensor: page.Items[k].GuildIcon = (uint64) _Items[k].GuildIcon->getValue64(); page.Items[k].GuildName = (uint32) _Items[k].GuildName->getValue32(); break; case Missions: page.Items[k].MissionText = (uint32) _Items[k].MissionText->getValue64(); page.Items[k].MissionDetailText = (uint32) _Items[k].MissionDetailText->getValue64(); page.Items[k].MissionIcon = (uint32) _Items[k].MissionIcon->getValue32(); page.Items[k].MissionPreReqState = (uint32) _Items[k].MissionPreReqState->getValue32(); break; default: nlassert(0); // You have to provide code for element that you want to be copied break; } } page.PageLoaded = true; page.PageVisible = false; // force update, even if shown before uint numLoadedPages; // In the display we want a contiguous set of items. Not For Trading, because of Resale if(_Category==Trading) { numLoadedPages= (uint)itemPages->size(); } else { for(numLoadedPages = 0; numLoadedPages < itemPages->size(); ++numLoadedPages) { if ((*itemPages)[numLoadedPages].PageLoaded == false && numLoadedPages != pageID) break; } } // for(k = 0; k < numLoadedPages; ++k) { // still must test if page really loaded if ( (*itemPages)[k].PageLoaded && (*itemPages)[k].PageVisible == false) { updateUIItemPage(k); (*itemPages)[k].PageVisible = true; } } // **** Special RoleMaster Trading _PhraseClientFillNumPhrase= 0; _PhraseClientFillFlags= 0; _PhraseClientFillRace= 0; _PhraseClientFill= false; // clientFill must at least be possible if(_Category==Trading && _PhrasePriceUpdateAndMaybeClientFill && _RoleMasterFlagDB && _RoleMasterRaceDB) { _PhraseClientFillFlags= _RoleMasterFlagDB->getValue32(); _PhraseClientFillRace= _RoleMasterRaceDB->getValue32(); _PhraseClientFill= _PhraseClientFillFlags!=0; if(_PhraseClientFill) { clientGenerateAllPhrases(); recomputeAllPhrasePrices(); } } }
//----------------------------------------------- // getString // //----------------------------------------------- ucstring CClientChatManager::getString( CBitMemStream& bms, ucstring& ucstr ) { // deal with parameters uint32 dynParamIdx = 0; bool dynParamSearch = true; char chTmp[1024]; while( dynParamSearch ) { // search if a parameter exists in the string sprintf(chTmp,"$%d",dynParamIdx); ucstring ucstrTmp( chTmp ); ucstring::size_type idx = ucstr.find(ucstrTmp); // if there's a parameter in the string if( idx != ucstring::npos ) { char c = (char)ucstr[idx+ucstrTmp.size()]; switch( c ) { // parameter is an entry in the dynamic database case 'e': { bool huff; bms.serialBit(huff); const ucstring dynStr("???"); if( huff ) { nldebug("<CClientChatManager::getString> receiving huffman dynamic parameter in static string"); // #ifdef OLD_STRING_SYSTEM // _DynamicDB.decodeString( dynStr, bms ); // #endif } else { //if( (sint32)bms.length()*8 - bms.getPosInBit() >= 32 ) { uint32 nameIndex; bms.serial(nameIndex); // #ifdef OLD_STRING_SYSTEM // dynStr = _DynamicDB.getDynamicStringInfos(nameIndex)->Str; // #endif } } ucstr.replace( idx, ucstrTmp.size()+1, dynStr ); } break; // parameter is a string case 's': { string dynStr; bms.serial( dynStr ); ucstring ucDynStr(dynStr); ucstr.replace( idx, ucstrTmp.size()+1, ucDynStr ); } break; // parameter is an unsigned integer case 'u': { uint32 nb; bms.serial( nb ); ucstr.replace( idx, ucstrTmp.size()+1, ucstring(toString(nb)) ); } break; /* case 'u': { uint i = idx + strTmp.size() + 1; string bitCountStr; while( isdigit(str[i]) ) { bitCountStr += str[i]; i++; } nlassert( !bitCountStr.empty() ); uint32 bitCount; fromString(bitCountStr, bitCount); nlassert( bitCount <= 64 ); uint64 nb; bms.serial( nb, bitCount ); str.replace( idx, strTmp.size() + 1 + bitCountStr.size(), toString(nb) ); } break; */ // parameter is a signed integer case 'i': { sint32 nb; bms.serial( nb ); ucstr.replace( idx, ucstrTmp.size()+1, ucstring(toString(nb)) ); } break; /* case 'i': { uint i = idx + strTmp.size() + 1; string bitCountStr; while( isdigit(str[i]) ) { bitCountStr += str[i]; i++; } nlassert( !bitCountStr.empty() ); uint32 bitCount; fromString(bitCountStr, bitCount); nlassert( bitCount <= 64 ); uint64 nb; bms.serial( nb, bitCount ); str.replace( idx, strTmp.size() + 1 + bitCountStr.size(), toString(nb) ); } break; */ // parameter is a float case 'f': { float nb; bms.serial( nb ); ucstr.replace( idx, ucstrTmp.size()+1, ucstring(toString(nb)) ); } break; // parameter type is unknown default : { nlwarning("<CClientChatManager::getString> The dynamic type %c is unknown",c); } } dynParamIdx++; } else { dynParamSearch = false; } }; return ucstr; } // getString //
//----------------------------------------------- // writeDelta // //----------------------------------------------- bool CCDBSynchronised::writeDelta( CBitMemStream& s, uint32 maxBitSize ) { //if ( ! _DataStructRoot ) // nlwarning("<CCDBSynchronised::writeDelta> the database has not been initialized"); // return; // Test the changed property count and make room to store the number of property pushed (poked later) uint origChangedPropertyCount = getChangedPropertyCount(); 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 bitsize = CDBChangedPropertyCountBitSize; // initialize with the size of the reserved bits for the number of changes TCDBDataIndex dataIndex; while ( ((dataIndex = _DataContainer.getFirstChanged()) != CDB_LAST_CHANGED) && (bitsize < maxBitSize) ) { // 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( cbPushDeltaOfLeafInAtomIfChanged, 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() ); } // Pop the changes out of the tracker TCDBDataIndex atomGroupIndex = node->getDataIndex(); TCDBDataIndex leafDataIndex; while ( (leafDataIndex = _DataContainer.popChangedIndexInAtom( atomGroupIndex )) != CDB_LAST_CHANGED ); } 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 pushDelta( s, static_cast<CCDBStructNodeLeaf*>(node), bitsize ); } _DataContainer.popFirstChanged(); } // Fill the placeholder with the number of changes uint32 nbChanges = origChangedPropertyCount - getChangedPropertyCount(); s.poke( nbChanges, bitposOfNbChanges, CDBChangedPropertyCountBitSize ); //s.displayStream( "writeDelta" ); NbDatabaseChanges += nbChanges; // Check if all has been popped _DataContainer.quickCleanChanges(); _NotSentYet = false; #ifdef TRACE_SET_VALUE if ( VerboseDatabase ) nldebug( "%u: CDB: Delta pushed (%u changes written, %u remaining)", CTickEventHandler::getGameCycle(), nbChanges, getChangedPropertyCount() ); #endif return true; } // writeDelta //
//--------------------------------------------------- // leagueJoinProposal : //--------------------------------------------------- void CTeamManager::joinLeagueProposal( CCharacter * leader, const CEntityId &targetId) { //check already done nlassert(leader); const NLMISC::CEntityId &leaderId = leader->getId(); if (targetId == leaderId ) { CCharacter::sendDynamicSystemMessage( leader->getId(),"INVALID_LEAGUE_TARGET" ); return; } // get targeted player CCharacter *invitedPlayer = PlayerManager.getOnlineChar( targetId ); if ( invitedPlayer == NULL ) { CCharacter::sendDynamicSystemMessage( leader->getId(),"INVALID_LEAGUE_TARGET" ); return; } // god player are forbidden to team if (leader->godMode() || invitedPlayer->godMode()) { nlwarning("<CTeamManager joinLeagueProposal> Player %s invited %s, but at least on of them is god, forbidden", leaderId.toString().c_str(), targetId.toString().c_str()); CCharacter::sendDynamicSystemMessage( leader->getId(),"TEAM_GOD_FORBIDDEN" ); return; } TInviteRetCode code = isLeagueInvitableBy(invitedPlayer,leader); if ( code == AlreadyInvited ) { CCharacter::sendDynamicSystemMessage( leader->getId(),"LEAGUE_ALREADY_INVITED" ); return; } else if ( code == AlreadyInLeague ) { CTeam * team = getRealTeam( invitedPlayer->getTeamId() ); CCharacter::sendDynamicSystemMessage( leader->getId(),"LEAGUE_ALREADY_IN_LEAGUE" ); return; } else if ( code == NotLeader ) { CTeam * team = getRealTeam( invitedPlayer->getTeamId() ); joinLeagueProposal(leader, team->getLeader()); return; } else if ( code == CantInvite ) { CCharacter::sendDynamicSystemMessage( leader->getId(),"LEAGUE_INVITOR_NOT_LEADER" ); return; } /// the invitor must not be in the ignore list of the target if(invitedPlayer->hasInIgnoreList(leaderId)) { SM_STATIC_PARAMS_1( params1, STRING_MANAGER::player ); params1[0].setEIdAIAlias( targetId, CAIAliasTranslator::getInstance()->getAIAlias( targetId) ); // Use the standard "player declines your offer". Don't use specific message because // maybe not a good idea to inform a player that someone ignores him CCharacter::sendDynamicSystemMessage( leaderId, "TEAM_DECLINE", params1 ); return; } //set the target's invitor invitedPlayer->setLeagueInvitor(leaderId); CEntityId msgTargetEId = targetId; //send the appropriate string to the client SM_STATIC_PARAMS_1(params, STRING_MANAGER::player); params[0].setEIdAIAlias( leaderId, CAIAliasTranslator::getInstance()->getAIAlias(leaderId) ); uint32 txt = STRING_MANAGER::sendStringToClient(TheDataset.getDataSetRow(targetId), "LEAGUE_PROPOSAL", params ); CMessage msgout( "IMPULSION_ID" ); msgout.serial( const_cast<CEntityId&>(msgTargetEId) ); CBitMemStream bms; nlverify ( GenericMsgManager.pushNameToStream( "PVP_CHALLENGE:INVITATION", bms) ); bms.serial( txt ); msgout.serialBufferWithSize((uint8*)bms.buffer(), bms.length()); sendMessageViaMirror( NLNET::TServiceId(msgTargetEId.getDynamicId()), msgout ); params[0].setEIdAIAlias( targetId, CAIAliasTranslator::getInstance()->getAIAlias( targetId ) ); PHRASE_UTILITIES::sendDynamicSystemMessage(leader->getEntityRowId(), "LEAGUE_INVITE", params); leader->updateTarget(); }
//--------------------------------------------------- // joinProposal : //--------------------------------------------------- void CTeamManager::joinProposal( CCharacter * leader, const CEntityId &targetId) { //check already done nlassert(leader); const NLMISC::CEntityId &leaderId = leader->getId(); if (targetId == leaderId ) { nlwarning("<CTeamManager joinProposal> Player %s invited himself in his team, cancel", leaderId.toString().c_str() ); return; } // get targeted player CCharacter *invitedPlayer = PlayerManager.getOnlineChar( targetId ); if ( invitedPlayer == NULL ) { CCharacter::sendDynamicSystemMessage( leader->getId(),"INVALID_LEAGUE_TARGET" ); return; } // god player are forbidden to team if (leader->godMode() || invitedPlayer->godMode()) { nlwarning("<CTeamManager joinProposal> Player %s invited %s, but at least on of them is god, forbidden", leaderId.toString().c_str(), targetId.toString().c_str()); CCharacter::sendDynamicSystemMessage( leader->getId(),"TEAM_GOD_FORBIDDEN" ); return; } TInviteRetCode code = isInvitableBy(invitedPlayer,leader); if ( code == AlreadyInvited ) { CCharacter::sendDynamicSystemMessage( leader->getId(),"TEAM_ALREADY_INVITED" ); return; } else if ( code == AlreadyInTeam ) { CCharacter::sendDynamicSystemMessage( leader->getId(),"TEAM_TARGET_ALREADY_IN_TEAM" ); return; } else if ( code == CantInviteEnemy ) { CCharacter::sendDynamicSystemMessage( leader->getId(),"TEAM_CANT_INVITE_ENEMY" ); return; } else if ( code == CantInvite ) { CCharacter::sendDynamicSystemMessage( leader->getId(),"TEAM_CANT_INVITE" ); return; } /// the invitor must not be in the ignore list of the target if(invitedPlayer->hasInIgnoreList(leaderId)) { SM_STATIC_PARAMS_1( params1, STRING_MANAGER::player ); params1[0].setEIdAIAlias( targetId, CAIAliasTranslator::getInstance()->getAIAlias( targetId) ); // Use the standard "player declines your offer". Don't use specific message because // maybe not a good idea to inform a player that someone ignores him CCharacter::sendDynamicSystemMessage( leaderId, "TEAM_DECLINE", params1 ); return; } //set the target's invitor invitedPlayer->setTeamInvitor(leaderId); //send the appropriate string to the client SM_STATIC_PARAMS_1(params, STRING_MANAGER::player); params[0].setEIdAIAlias( leaderId, CAIAliasTranslator::getInstance()->getAIAlias( leaderId ) ); uint32 strId = STRING_MANAGER::sendStringToClient(TheDataset.getDataSetRow(targetId),"TEAM_PROPOSAL", params); //send the invitation msg to the target, with the id of the built string CMessage msgout( "IMPULSION_ID" ); CBitMemStream bms; CEntityId targetIdToSerial = targetId; msgout.serial( targetIdToSerial ); if ( ! GenericMsgManager.pushNameToStream( "TEAM:INVITATION", bms) ) { nlwarning("<CTeamManager joinProposal> Msg name TEAM:INVITATION not found"); return; } bms.serial(strId); msgout.serialBufferWithSize((uint8*)bms.buffer(), bms.length()); sendMessageViaMirror( NLNET::TServiceId(targetId.getDynamicId()), msgout ); // TVectorParamCheck params; // params.resize(1); // inform the team leader // params[0].Type = STRING_MANAGER::player; params[0].setEIdAIAlias( targetId, CAIAliasTranslator::getInstance()->getAIAlias( targetId ) ); PHRASE_UTILITIES::sendDynamicSystemMessage(leader->getEntityRowId(), "TEAM_INVITE", params); leader->updateTarget(); } // joinProposal //