1 // Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
2 // Copyright (C) 2010 Winch Gate Property Limited
4 // This program is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU Affero General Public License as
6 // published by the Free Software Foundation, either version 3 of the
7 // License, or (at your option) any later version.
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU Affero General Public License for more details.
14 // You should have received a copy of the GNU Affero General Public License
15 // along with this program. If not, see <http://www.gnu.org/licenses/>.
18 #include "cdb_group.h"
19 #include "game_share/generic_xml_msg_mngr.h"
20 #include "nel/net/unified_network.h"
21 #include "game_item_manager/guild_inv.h"
23 using namespace NLMISC
;
24 using namespace NLNET
;
27 extern CGenericXmlMsgHeaderManager GenericMsgManager
;
30 CBitMemStream
DBOutput( false, 2048 ); // global to avoid reallocation
34 * Handy logging macros & variables
37 CVariable
<bool> VerboseCDBGroup("egs", "VerboseCDBGroup", "Flag to enable or dissable verbose logging in cdb_group.cpp", true,0,true);
38 #define LOG if (VerboseCDBGroup==false) {} else nldebug
42 * Add a recipient (recipient must not move in memory after calling addRecipient! Beware vectors
44 void CCDBGroup::addRecipient( const CCDBRecipient
& recipient
)
46 // Add to list of new recipients (will be moved to normal list in sendDelta()
47 // because if doing it here, the new recipient will receive twice the changes
48 // done since the latest sendDeltas(), one of which is from the 'permanent
50 _NewRecipients
.push_back( recipient
);
52 LOG( "CDB: %s added into group", recipient
.toString().c_str() );
59 void CCDBGroup::removeRecipient( const CCDBRecipient
& recipient
)
62 if ( _Recipients
.erase( recipient
) == 0 )
64 // Not found in normal list, search in the list of new recipients
65 std::vector
<CCDBRecipient
>::iterator inr
= std::find( _NewRecipients
.begin(), _NewRecipients
.end(), recipient
);
66 if ( inr
!= _NewRecipients
.end() )
68 _NewRecipients
.erase( inr
);
69 // The group database was not sent to recipient yet => return (don't send reset bank)
73 nlwarning( "Recipient %s not found when removing from CDBGroup", recipient
.toString().c_str() );
78 // Send message for the client to clear its properties corresponding to the bank
79 // If it did that when receving a new INIT_BANK, he would lose any database update
80 // that occur after addRecipient() but arrive before INIT_BANK (because the impulsion
81 // arriving order is not guaranteed).
82 DBOutput
.resetBufPos();
83 GenericMsgManager
.pushNameToStream( "DB_GROUP:RESET_BANK", DBOutput
);
84 // write the server tick, to ensure old DB update are not applied after newer
85 TGameCycle serverTick
= CTickEventHandler::getGameCycle();
86 DBOutput
.serial(serverTick
);
88 uint32 bank
= (uint32
)Database
.bank();
90 FILL_nbits_WITH_NB_BITS_FOR_CDBBANK
91 DBOutput
.serial( bank
, nbits
);
92 CMessage
msgout( "CDB_IMPULSION" );
93 msgout
.serial( const_cast<CEntityId
&>(recipient
) );
94 msgout
.serialBufferWithSize( (uint8
*)DBOutput
.buffer(), DBOutput
.length() );
95 CUnifiedNetwork::getInstance()->send( NLNET::TServiceId(recipient
.getDynamicId()), msgout
);
97 LOG( "CDB: %s removed from group", recipient
.toString().c_str() );
105 void CCDBGroup::sendDeltas( uint32 maxBitSize
, IDataProvider
& dataProvider
, uint8 sendFlags
)
107 // Check if there are changes
108 if ( (Database
.getChangedPropertyCount() != 0) ||
109 dataProvider
.nonEmpty() )
111 // Send a message to all frontends, for multiple delivery to recipients (except new ones)
112 DBOutput
.resetBufPos();
113 GenericMsgManager
.pushNameToStream( "DB_GROUP:UPDATE_BANK", DBOutput
);
114 // Write the server tick, to ensure old DB update are not applied after newer
115 TGameCycle serverTick
= CTickEventHandler::getGameCycle();
116 DBOutput
.serial( serverTick
);
118 uint32 bank
= (uint32
)Database
.bank();
120 FILL_nbits_WITH_NB_BITS_FOR_CDBBANK
121 DBOutput
.serial( bank
, nbits
);
122 // Write the shared database delta
123 if ( Database
.getChangedPropertyCount() != 0 )
125 Database
.writeDelta( DBOutput
, maxBitSize
);
130 DBOutput
.serial( noChange
, CDBChangedPropertyCountBitSize
);
132 // Write additional provided data (for guild inventory)
133 dataProvider
.provideUpdate( DBOutput
);
135 CMessage
msgout( "CDB_MULTI_IMPULSION" );
136 msgout
.serial (sendFlags
);
137 if (sendFlags
& SendDeltasToAll
) // Broadcasting event; no need to include recipient list
139 // All users; bypass recipient list
143 msgout
.serialCont( _Recipients
); // Explicit multi-recipients
146 msgout
.serialBufferWithSize( (uint8
*)DBOutput
.buffer(), DBOutput
.length() );
147 CUnifiedNetwork::getInstance()->send( "FS", msgout
, false ); // viaMirror not needed because sending entity ids instead of datasetrows
148 LOG( "Sent CDB_MULTI_IMPULSION to all FS (%u bytes)", msgout
.length() );
150 // Send a message to each new recipient, with the history (including the latest changes)
151 // and move them to the normal recipient list
152 for ( std::vector
<CCDBRecipient
>::const_iterator inr
=_NewRecipients
.begin(); inr
!=_NewRecipients
.end(); ++inr
)
154 const CCDBRecipient
& recipient
= (*inr
);
156 // Sent history of what was modified before its arrival in the group
157 // As this is a specific message, the client can react differently from an update
158 DBOutput
.resetBufPos();
159 GenericMsgManager
.pushNameToStream( "DB_GROUP:INIT_BANK", DBOutput
);
160 // Write the server tick, to ensure old DB update are not applied after newer
161 TGameCycle serverTick
= CTickEventHandler::getGameCycle();
162 DBOutput
.serial( serverTick
);
164 uint32 bank
= (uint32
)Database
.bank();
166 FILL_nbits_WITH_NB_BITS_FOR_CDBBANK
167 DBOutput
.serial( bank
, nbits
);
168 // Write the shared database delta (from the beginning)
169 if ( ! Database
.writePermanentDelta( DBOutput
) )
171 uint32 noInitialDelta
= 0;
172 DBOutput
.serial( noInitialDelta
, 16 );
174 // Write additional provided data (for guild inventory)
175 dataProvider
.provideContents( DBOutput
); // provideUpdate() must have been called before, otherwise would not be empty()
177 CMessage
msgout( "CDB_IMPULSION" );
178 msgout
.serial( const_cast<CEntityId
&>(recipient
) );
179 msgout
.serialBufferWithSize( (uint8
*)DBOutput
.buffer(), DBOutput
.length() );
180 CUnifiedNetwork::getInstance()->send( NLNET::TServiceId(recipient
.getDynamicId()), msgout
);
182 // Add to normal recipient list
183 if ( ! _Recipients
.insert( recipient
).second
)
184 nlwarning( "Recipient %s added twice into CDBGroup", recipient
.toString().c_str() );
186 _NewRecipients
.clear();