Resolve "Toggle Free Look with Hotkey"
[ryzomcore.git] / ryzom / server / src / frontend_service / impulse_encoder.h
blob261f059d90965d8c1c5e867d29cf353516a8b1a1
1 // Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
2 // Copyright (C) 2010 Winch Gate Property Limited
3 //
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.
8 //
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/>.
19 #ifndef NL_IMPULSE_ENCODER_H
20 #define NL_IMPULSE_ENCODER_H
22 #include <vector>
23 #include <deque>
25 #include "nel/misc/types_nl.h"
26 #include "nel/misc/bit_mem_stream.h"
27 #include "nel/misc/debug.h"
28 #include "nel/misc/time_nl.h"
30 //#include "../common/action.h"
31 #include "game_share/action_factory.h"
33 extern bool verboseImpulsions;
35 #ifdef NL_RELEASE
36 #define LOG_IMPULSION_INFO ;
37 #define LOG_IMPULSION_DEBUG ;
38 #else
39 #define LOG_IMPULSION_INFO if (!verboseImpulsions) {} else nlinfo
40 #define LOG_IMPULSION_DEBUG if (!verboseImpulsions) {} else nldebug
41 #endif
44 class CClientHost;
46 namespace CLFECOMMON
48 class CAction;
51 typedef void (*TImpulseReceivedCallback)(CClientHost *, CLFECOMMON::CAction *);
54 // CActionFactory header + CActionGeneric header + 1/8 (the follow bit)
55 const sint IMPULSE_ACTION_HEADER_BITSIZE = 4*8 + 4*8 + 1;
56 extern uint MaxImpulseBitSizes [3];
59 class CClientImpulseStat
61 public:
65 const uint IMPULSE_STAT_MEAN_TIME = 30; // seconds
66 const double IMPULSE_STAT_SMOOTH = 2.0;
69 class CTimedSize
71 public:
73 CTimedSize() {}
74 CTimedSize(NLMISC::TTime t, uint32 s) : Time(t), Size(s) {}
76 NLMISC::TTime Time;
77 uint32 Size;
79 void serial(NLMISC::IStream& s);
81 typedef std::deque<CTimedSize> TSendRateQueue;
84 /**
85 * An Impulse Queue
86 * \author Benjamin Legros
87 * \author Nevrax France
88 * \date 2001
90 class CImpulseQueue
92 public:
93 typedef std::deque<CLFECOMMON::CActionImpulsion *> TActionQueue;
94 TActionQueue Queue;
97 /// \name Stat Part
98 // @{
100 TSendRateQueue SendRateQueue;
101 uint64 SentData;
102 uint32 FlushTimes;
104 // @}
106 uint32 MaxBitSize;
107 uint TotalBitsInImpulseQueue;
108 uint FirstSent;
110 uint32 Level, Channel;
112 public:
113 CImpulseQueue() : TotalBitsInImpulseQueue(0), FirstSent(0), SentData(0), FlushTimes(0) {}
115 /// Destructor
116 ~CImpulseQueue();
118 void setup(uint maxBitSize, uint level, uint channel) { MaxBitSize = maxBitSize; Level = level; Channel = channel; }
119 void add(CLFECOMMON::CActionImpulsion *action) { Queue.push_back(action); }
121 void flush(uint packet, CClientHost *client, std::vector<uint8> &impcounts);
123 uint32 send(TActionQueue& sourceQueue, uint32 packet, NLMISC::CBitMemStream &outbox, uint32 &sentActions);
125 void reinit() { FirstSent = 0; }
127 void reset()
129 reinit();
130 uint i;
131 for (i=0; i<Queue.size(); ++i)
133 CLFECOMMON::CActionFactory::getInstance()->remove(Queue[i]);
135 Queue.clear();
136 TotalBitsInImpulseQueue = 0;
137 SentData = 0;
140 void removeReferences(CLFECOMMON::TCLEntityId id)
142 TActionQueue::iterator it;
143 for (it=Queue.begin(); it<Queue.end(); )
144 if ((*it)->Slot == id)
146 CLFECOMMON::CActionFactory::getInstance()->remove(*it);
147 it = Queue.erase(it);
149 else
151 ++it;
156 /// \name Stat Part
157 // @{
159 /// Count next effective sent
160 void countEffectiveSent(uint bitSent)
162 NLMISC::TTime ctime = NLMISC::CTime::getLocalTime();
163 flushSendRateQueue(ctime);
165 if (bitSent == 0)
166 return;
168 //nlinfo("sent effectively %d bits in level %d, channel %d", bitSent, Level, Channel);
170 SendRateQueue.push_back(CTimedSize(ctime, bitSent));
171 SentData += bitSent;
174 /// Flush SendRateQueue
175 void flushSendRateQueue(NLMISC::TTime ctime)
177 while (!SendRateQueue.empty() && ctime > SendRateQueue.front().Time+(IMPULSE_STAT_MEAN_TIME*1000))
178 SendRateQueue.pop_front();
181 /// Get Current Effective Send Rate (based on flush rate) (in bits per second)
182 uint effectiveSendRate();
184 /// Total send data in this queue (based on flush rate) (in bits per second)
185 uint64 totalSentData();
187 /// Dump queue to xml stream
188 void dump(NLMISC::IStream& s);
190 // @}
197 * The impulse encoder, used to post important actions the client must receive.
198 * \author Benjamin Legros
199 * \author Nevrax France
200 * \date 2001
202 class CImpulseEncoder
204 private:
207 * Warning: the numbers of queues by channels is hardcoded in the acknowledgement system
210 CImpulseQueue _Level0[1];
211 CImpulseQueue _Level1[2];
212 CImpulseQueue _Level2[4];
214 CClientHost *_ClientHost;
216 //uint _MaxBitSizes[4];
218 std::vector<uint8> _QueuedImpulses;
220 typedef std::deque<CLFECOMMON::CActionImpulsion *> TActionQueue;
222 TActionQueue _MainQueues[3];
224 uint32 _TotalPackets;
226 protected:
227 friend class CImpulseQueue;
229 static TImpulseReceivedCallback _Callbacks[256];
231 TSendRateQueue _AddRateQueues[3];
233 public:
235 /// Constructor
236 CImpulseEncoder();
238 /// Destructor
239 ~CImpulseEncoder();
241 /// Return the number of bits that the specified level can manage (biggest action it can manage) (no bound check)
242 static uint maxBitSize( uint level ) { return MaxImpulseBitSizes[level]; }
244 /// Return the number of bits that can be sent at most using all levels
245 static uint maxBitSizeTotal() { return MaxImpulseBitSizes[0]+MaxImpulseBitSizes[1]+MaxImpulseBitSizes[2] - - (IMPULSE_ACTION_HEADER_BITSIZE*3/8); }
248 void setClientHost(CClientHost *clientHost) { _ClientHost = clientHost; }
250 /// Adds an action at a given level of priority.
251 void add(CLFECOMMON::CActionImpulsion *action, uint level);
253 /// Packs/sends impulse on the given outbox, using the previously added actions
254 uint32 send(uint32 packet, NLMISC::CBitMemStream &outbox, uint32 &sentActions);
256 /// Acknowledges a message and flushes involved queues (only positive acks).
257 void ack(uint32 packet);
259 /// Reinits the whole queues
260 void reset();
262 /// Unmarks all queues (act as if the awaiting actions were cleared up and readded at once)
263 void unmarkAll();
265 /// Gets the total number of messages still to be sent
266 uint queueSize() const;
268 /// Gets the number of messages still to be sent at a given level
269 uint queueSize(uint level) const;
271 /// Sets a callback for a specific type of action (-1 for all types of action)
272 static void setReceivedCallback(TImpulseReceivedCallback cb, sint actionCode = -1);
274 /// Gets the maximum bit size that can be sent through a channel (specific for a given level)
275 //uint getMaxBitSize(uint level) const { return _MaxBitSizes[level]; }
277 /// Returns true if the encoder has actions referencing a given entity (by its client entity id)
278 bool hasEntityReferences(CLFECOMMON::TCLEntityId id) const
280 return (_QueuedImpulses[id] != 0);
283 /// Removes all actions referencing a given entity (if there are some)
284 void removeEntityReferences(CLFECOMMON::TCLEntityId id);
286 /// \name Stats part
287 // @{
289 /// Get Enqueued actions size in bits for a specified level
290 uint getEnqueuedSize(uint level) const;
292 /// Dump stats to XML stream
293 void dump(NLMISC::IStream& s);
295 /// Count Added action
296 void countAddedAction(CLFECOMMON::CActionImpulsion *action, uint level);
298 /// Effective Add Rate
299 uint effectiveAddRate(uint level);
301 /// Effective Send Rate (cumulated send of each channel)
302 uint effectiveSendRate(uint level);
304 /// Efficiency Ratio
305 float efficiencyRatio(uint level);
307 /// Get least efficiency
308 float leastEfficiencyRatio();
310 /// Get biggest queue size
311 uint biggestQueueSize();
313 // @}
317 #endif // NL_IMPULSE_ENCODER_H
319 /* End of impulse_encoder.h */