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/>.
22 #include "nel/misc/debug.h"
23 #include "nel/misc/vector.h"
25 #include "property_history.h"
27 #include "game_share/action.h"
28 #include "game_share/continuous_action.h"
29 #include "game_share/action_position.h"
31 #include <nel/misc/hierarchical_timer.h>
34 using namespace NLMISC
;
35 using namespace CLFECOMMON
;
40 CPropertyHistory::CPropertyHistory()
42 _MaxDeltaSend
= DefaultMaxDeltaSend
;
45 void CPropertyHistory::clear()
47 uint32 num
= (uint32
)_ClientEntries
.size();
48 _ClientEntries
.clear();
49 _ClientEntries
.resize(num
);
52 void CPropertyHistory::setMaximumClient(uint maxClient
)
54 _ClientEntries
.resize(maxClient
);
59 void CPropertyHistory::addClient(TClientId clientId
)
61 nlassert(clientId
< _ClientEntries
.size() && !_ClientEntries
[clientId
].EntryUsed
);
63 CClientEntry
&entry
= _ClientEntries
[clientId
];
65 entry
.EntryUsed
= true;
68 void CPropertyHistory::removeClient(TClientId clientId
)
70 nlassert(clientId
< _ClientEntries
.size() && _ClientEntries
[clientId
].EntryUsed
);
71 _ClientEntries
[clientId
].reset();
74 void CPropertyHistory::resetClient(TClientId clientId
)
76 nlassert(clientId
< _ClientEntries
.size() && _ClientEntries
[clientId
].EntryUsed
);
78 CClientEntry
&entry
= _ClientEntries
[clientId
];
80 for (i
=0; i
<MAX_SEEN_ENTITIES_PER_CLIENT
; ++i
)
81 entry
.Entities
[i
].clearEntityEntry();
84 bool CPropertyHistory::isValidClient(TClientId clientId
)
86 return (clientId
< _ClientEntries
.size() && _ClientEntries
[clientId
].EntryUsed
);
91 bool CPropertyHistory::addEntityToClient(TCLEntityId entityId
, TClientId clientId
)
93 nlassert(clientId
< _ClientEntries
.size() && _ClientEntries
[clientId
].EntryUsed
);
95 // adds entity to the table in the client entry
96 CEntityEntry
&entity
= _ClientEntries
[clientId
].Entities
[entityId
];
101 entity
.resetEntityEntry();
106 void CPropertyHistory::removeEntityOfClient(TCLEntityId entityId
, TClientId clientId
)
108 nlassert(clientId
< _ClientEntries
.size() && _ClientEntries
[clientId
].EntryUsed
);
110 CEntityEntry
&entity
= _ClientEntries
[clientId
].Entities
[entityId
];
112 nlwarning( "Removing entity S%hu of client C%hu in history, but not used", (uint16
)entityId
, clientId
);
113 entity
.resetEntityEntry();
118 bool CPropertyHistory::packDelta(TClientId clientId, CAction &action, bool allowPack)
120 nlassert(clientId < _ClientEntries.size() && _ClientEntries[clientId].EntryUsed);
122 if (!action.isContinuous())
128 CContinuousAction &act = static_cast<CContinuousAction &>(action);
135 // search if entity is already used
136 CEntityEntry &entity = _ClientEntries[clientId].Entities[action.CLEntityId];
137 nlassert(entity.Used);
139 // This asumes the continuous properties are the same for everyone
140 uint16 propIndex = act.PropertyCode;
141 CPropertyEntry &entry = entity.Properties[propIndex];
143 if (entry.AllowDelta > 0 && allowPack)
145 if (--entry.AllowDelta > 0)
147 act.packDelta(entry.Garanted);
152 // disable next incoming garanted packets
153 // until we send a garanted packet
154 entry.Packet = 0xFFFFFFFF;
166 bool CPropertyHistory::packDelta(TClientId clientId, CActionPosition &action, bool allowPack)
168 nlassert(clientId < _ClientEntries.size() && _ClientEntries[clientId].EntryUsed);
170 if (action.isDelta())
175 // search if entity is already used
176 CEntityEntry &entity = _ClientEntries[clientId].Entities[action.CLEntityId];
177 nlassert(entity.Used);
179 CPropertyEntry &ex = entity.Properties[PROPERTY_POSX];
181 if (ex.AllowDelta > 0 && allowPack)
183 if (--ex.AllowDelta > 0)
185 action.packDelta(entity.Properties[PROPERTY_POSX].Garanted,
186 entity.Properties[PROPERTY_POSY].Garanted,
187 entity.Properties[PROPERTY_POSZ].Garanted);
192 // disable next incoming garanted packets
193 // until we send a garanted packet
194 ex.Packet = 0xFFFFFFFF;
211 void CPropertyHistory::ackProperty(TClientId clientId
, TCLEntityId entityId
, uint32 packet
, TPropIndex propId
)
213 //nlassert(clientId < _ClientEntries.size() && _ClientEntries[clientId].EntryUsed);
215 if (!isContinuousProperty(propId))
218 CEntityEntry &entity = _ClientEntries[clientId].Entities[entityId];
220 // search if entity exists already
224 CPropertyEntry &entry = entity.Properties[propId];
226 // assume all previous packet have been ack'ed (ack- or ack+)
227 if (packet == entry.Packet)
229 if (entry.AllowDelta == 0)
230 entry.AllowDelta = _MaxDeltaSend;
232 if (propId == PROPERTY_POSITION)
234 entity.garantyPosition();
238 entry.Garanted = entry.ToGaranty;
241 entry.Packet = 0xFFFFFFFF;
242 // nldebug("FECONTH: Ack Garanted CL=%d CEId=%d Pk=%d (%.2f,%.2f)", clientId, entityId, packet, entry.Garanted.Float);
247 void CPropertyHistory::negAckProperty(TClientId clientId
, TCLEntityId entityId
, uint32 packet
, TPropIndex propId
)
250 nlassert(clientId < _ClientEntries.size() && _ClientEntries[clientId].EntryUsed);
252 CEntityEntry &entity = _ClientEntries[clientId].Entities[entityId];
254 // search if entity exists already
258 CPropertyEntry &entry = entity.Properties[propId];
260 if (packet == entry.Packet)
262 entry.Packet = 0xFFFFFFFF;
263 // nldebug("FECONTH: negAcked CL=%d CEId=%d Pk=%d", entityId, propId, packet);
269 void CPropertyHistory::ackProperties(TClientId clientId
, TCLEntityId entityId
, uint32 packet
, const vector
<TPropIndex
> &ids
)
272 nlassert(clientId < _ClientEntries.size() && _ClientEntries[clientId].EntryUsed);
274 CEntityEntry &entity = _ClientEntries[clientId].Entities[entityId];
276 // search if entity exists already
277 nlassert(entity.Used);
280 for (i=0; i<ids.size(); ++i)
282 TPropIndex id = ids[i];
283 if (!isContinuousProperty(id))
286 if (packet == entity.Properties[id].Packet)
288 entity.Properties[id].Garanted = entity.Properties[id].ToGaranty;
289 entity.Properties[id].Packet = 0xFFFFFFFF;
298 void CPropertyHistory::setPropertyConversion(uint32 property, sint8 conversion)
300 _PropertiesTranslation[property] = (conversion >= 0 ? conversion : -1);
303 void CPropertyHistory::setPropertyConversion(CPropertyTranslation *properties, sint numProperties)
306 for (i=0; i<numProperties; ++i)
307 _PropertiesTranslation[properties[i].Property] = (properties[i].Translation >= 0 ? properties[i].Translation : -1);