Add infos into target window
[ryzomcore.git] / ryzom / server / src / frontend_service / packet_history.cpp
blob0dd74bb0daa32f2db3b5598d2d94fd7591612d49
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 #include "stdpch.h"
21 #include "nel/misc/debug.h"
23 #include "packet_history.h"
24 #include "property_history.h"
25 #include "game_share/action.h"
27 #include "frontend_service.h"
28 #include "vision_array.h"
30 using namespace CLFECOMMON;
33 * Constructor
35 CPacketHistory::CPacketHistory()
40 void CPacketHistory::clear()
42 uint32 num = (uint32)_ClientsHistories.size();
43 _ClientsHistories.clear();
44 _ClientsHistories.resize(num);
47 void CPacketHistory::setMaximumClient(uint maxClient)
49 _ClientsHistories.resize(maxClient);
55 void CPacketHistory::store(TClientId clientId, uint packetNumber, CLFECOMMON::CAction *action)
57 // nlassert(clientId < _ClientsHistories.size() && _ClientsHistories[clientId].EntryUsed);
59 // get the packet queue of the client
60 TPacketQueue &queue = _ClientsHistories[clientId].Queue;
62 nlassert(queue.empty() || packetNumber >= queue.back().Number);
64 if (queue.empty() || packetNumber>queue.back().Number)
66 queue.push_back(CPacketEntry());
67 queue.back().Number = packetNumber;
70 queue.back().Packet.push_back(CMessageEntry(action->Slot, action->PropertyCode));
74 void CPacketHistory::storeDisassociation(TClientId clientId, CLFECOMMON::TCLEntityId slot, uint packetNumber )
76 // get the packet queue of the client
77 TPacketQueue &queue = _ClientsHistories[clientId].Queue;
79 nlassert(queue.empty() || packetNumber >= queue.back().Number);
81 if (queue.empty() || packetNumber>queue.back().Number)
83 queue.push_back(CPacketEntry());
84 queue.back().Number = packetNumber;
87 queue.back().Packet.push_back(CMessageEntry(slot, PROPERTY_DISASSOCIATION));
93 void CPacketHistory::ack(TClientId clientId, uint32 packet, uint32 bits, uint ackBitWidth)
95 //nlassert(clientId < _ClientsHistories.size() && _ClientsHistories[clientId].EntryUsed);
97 TPacketQueue &queue = _ClientsHistories[clientId].Queue;
99 if ( queue.empty() )
100 return;
102 uint32 firstAck = (sint32)(queue.front().Number);
104 // nothing to ack ? just leave...
105 if (packet < firstAck)
106 return;
108 uint totalUnreceived = packet-firstAck;
109 uint totalRecoverable = std::min(totalUnreceived, ackBitWidth);
110 uint firstRecoverable = packet-totalRecoverable;
111 uint j;
113 // negAck all unrecoverable acks
114 while (!queue.empty() && queue.front().Number<firstRecoverable)
116 uint thisPacket = queue.front().Number;
117 CPacket &apacket = queue.front().Packet;
118 for (j=0; j<apacket.size(); ++j)
119 negativeAck(clientId, apacket[j].EntityId, apacket[j].PropIndex, thisPacket);
120 queue.pop_front();
123 // ack all recoverable acks depending on the bit
124 while (!queue.empty() && queue.front().Number<packet)
126 uint thisPacket = queue.front().Number;
127 uint bitNum = packet-queue.front().Number-1;
129 CPacket &apacket = queue.front().Packet;
130 if (bits & (1<<bitNum))
131 for (j=0; j<apacket.size(); ++j)
132 positiveAck(clientId, apacket[j].EntityId, apacket[j].PropIndex, thisPacket);
133 else
134 for (j=0; j<apacket.size(); ++j)
135 negativeAck(clientId, apacket[j].EntityId, apacket[j].PropIndex, thisPacket);
137 queue.pop_front();
140 // ack current packet
141 if (queue.empty() || queue.front().Number>packet)
142 return;
144 nlassert(!queue.empty() && queue.front().Number == packet);
146 CPacket &apacket = queue.front().Packet;
147 for (j=0; j<apacket.size(); ++j)
148 positiveAck(clientId, apacket[j].EntityId, apacket[j].PropIndex, packet);
149 queue.pop_front();
152 void CPacketHistory::ack(TClientId clientId, uint32 packet, bool ackvalue)
154 TPacketQueue &queue = _ClientsHistories[clientId].Queue;
156 while (!queue.empty() && queue.front().Number<packet)
158 nlwarning("FEPKHIST: removed a packet awaiting ack (client %d, packet %d, packet %d being acked)", clientId, queue.front().Number, packet);
159 queue.pop_front();
162 if (!queue.empty() && queue.front().Number==packet)
164 uint thisPacket = queue.front().Number;
165 uint j;
166 CPacket &apacket = queue.front().Packet;
167 if (ackvalue)
168 for (j=0; j<apacket.size(); ++j)
169 positiveAck(clientId, apacket[j].EntityId, apacket[j].PropIndex, thisPacket);
170 else
171 for (j=0; j<apacket.size(); ++j)
172 negativeAck(clientId, apacket[j].EntityId, apacket[j].PropIndex, thisPacket);
174 queue.pop_front();
178 void CPacketHistory::positiveAck(TClientId clientId, TCLEntityId entityId, TPropIndex propindex, uint32 packet)
180 /*TPropState& propstate = CFrontEndService::instance()->PrioSub.VisionArray.propState( clientId, entityId, propindex );
181 if ( propstate.UpdateStatus == Updating )
182 propstate.UpdateStatus = Unchanged;*/
184 //if (_PropertyHistory->isContinuousProperty(propertyId))
185 // _PropertyHistory->ackProperty(clientId, entityId, packet, propertyId);
188 void CPacketHistory::negativeAck(TClientId clientId, TCLEntityId entityId, TPropIndex propindex, uint32 packet)
190 TPairState& pairState = CFrontEndService::instance()->PrioSub.VisionArray.getPairState( clientId, entityId );
192 // Empty the history for each property (to force the sending of the current value)
193 if ( _PropertyHistory->resetValue( clientId, entityId, propindex, (uint8)pairState.AssociationChangeBits ) )
195 //if ( pairState.AssociationChangeBits & 0x80 == 0 )
197 // Set high priority
198 LOG_PACKET_LOST( "%u: Reverting prio for C%hu S%hu (packet %u)", CTickEventHandler::getGameCycle(), clientId, (uint16)entityId, packet );
199 pairState.revertPrio();
201 // Set "negative-acked" bit
202 //pairState.AssociationChangeBits |= 0x80;
205 else // association has changed
207 if ( pairState.associationSuppressed() )
209 // Set high priority for whole slot (all properties at once)
210 LOG_PACKET_LOST( "%u: Reverting prio for disassociation C%hu S%hu (packet %u)", CTickEventHandler::getGameCycle(), clientId, (uint16)entityId, packet );
212 //pairState.revertPrio();
213 // Set "negative-acked" bit to resend at least the disassociation
214 //pairState.AssociationChangeBits |= 0x80;
215 pairState.PrevAssociationBits = pairState.AssociationChangeBits - 1; // force them different
217 CFrontEndService::instance()->PrioSub.Prioritizer.pushDissociationToResend( clientId, entityId );
224 void CPacketHistory::addClient(TClientId clientId)
226 //nlassert(!_ClientsHistories[clientId].EntryUsed);
228 _ClientsHistories[clientId].EntryUsed = true;
229 _ClientsHistories[clientId].Queue.clear();
232 void CPacketHistory::removeClient(TClientId clientId)
234 //nlassert(_ClientsHistories[clientId].EntryUsed);
236 _ClientsHistories[clientId].EntryUsed = false;
237 _ClientsHistories[clientId].Queue.clear();
240 void CPacketHistory::resetClient(TClientId clientId)
242 //nlassert(_ClientsHistories[clientId].EntryUsed);
243 _ClientsHistories[clientId].Queue.clear();
246 bool CPacketHistory::isValidClient(TClientId clientId)
248 return (clientId < _ClientsHistories.size() && _ClientsHistories[clientId].EntryUsed);