1 /// \file
2 /// \brief Contains class ReplicaManager.  This system provides management for your game objects and players to make serialization, scoping, and object creation and destruction easier.
3 ///
4 /// This file is part of RakNet Copyright 2003 Jenkins Software LLC
5 ///
6 /// Raknet is available under the terms of the GPLv3 license, see /usr/local/share/licenses/raknet-3.9.2_10,1/GPLv3.
7 
8 #include "NativeFeatureIncludes.h"
9 #if _RAKNET_SUPPORT_ReplicaManager==1
10 
11 #ifndef __REPLICA_MANAGER_H
12 #define __REPLICA_MANAGER_H
13 
14 #include "Export.h"
15 #include "RakNetTypes.h"
16 #include "DS_OrderedList.h"
17 #include "PluginInterface2.h"
18 #include "NetworkIDObject.h"
19 #include "DS_Queue.h"
20 #include "ReplicaEnums.h"
21 
22 /// Forward declarations
23 namespace RakNet
24 {
25 	class BitStream;
26 };
27 class Replica;
28 class ReplicaManager;
29 
30 /// \defgroup REPLICA_MANAGER_GROUP ReplicaManager
31 /// \brief Automatic game object replication
32 /// \details
33 /// \ingroup PLUGINS_GROUP
34 
35 /// \defgroup REPLICA_MANAGER_GROUP1 ReplicaManager
36 /// \brief Deprecated. First implementation of object replication
37 /// \details
38 /// \ingroup REPLICA_MANAGER_GROUP
39 
40 /// An interface for a class that handles the construction callback from the network
41 /// See ReplicaManager::SetReceiveConstructionCB
42 /// \ingroup REPLICA_MANAGER_GROUP1
43 class ReceiveConstructionInterface
44 {
45 public:
ReceiveConstructionInterface()46 	ReceiveConstructionInterface() {}
~ReceiveConstructionInterface()47 	virtual ~ReceiveConstructionInterface() {}
48 
49 	/// Called when a network object needs to be created by the ReplicaManager class
50 	/// \param[in] inBitStream The bitstream that was written to in Replica::SendConstruction
51 	/// \param[in] timestamp If in Replica::SendConstruction you set sendTimestamp to true, this is the time the packet was sent.  Otherwise it is 0.
52 	/// \param[in] networkID If the remote object had an NetworkID set by the time Replica::SendConstruction was called it is here.
53 	/// \param[in] existingNetworkObject If networkID is already in use, existingNetworkObject is the pointer to that object.  If existingReplica is non-zero, you usually shouldn't create a new object, unless you are reusing networkIDs, such as having the client and server both on the same computer
54 	/// \param[in] senderId Which SystemAddress sent this packet.
55 	/// \param[in] caller Which instance of ReplicaManager is calling this interface
56 	/// \return See ReplicaReturnResult
57 	virtual ReplicaReturnResult ReceiveConstruction(RakNet::BitStream *inBitStream, RakNetTime timestamp, NetworkID networkID, NetworkIDObject *existingObject, SystemAddress senderId, ReplicaManager *caller)=0;
58 };
59 
60 /// An interface for a class that handles the call to send the download complete notification
61 /// See ReplicaManager::SetDownloadCompleteCB
62 /// \ingroup REPLICA_MANAGER_GROUP1
63 class SendDownloadCompleteInterface
64 {
65 public:
SendDownloadCompleteInterface()66 	SendDownloadCompleteInterface() {}
~SendDownloadCompleteInterface()67 	virtual ~SendDownloadCompleteInterface() {}
68 
69 	/// \param[out] outBitStream Write whatever you want to this bitstream.  It will arrive in the receiveDownloadCompleteCB callback.
70 	/// \param[in] currentTime The current time that would be returned by RakNet::GetTime().  That's a slow call I do already, so you can use the parameter instead of having to call it yourself.
71 	/// \param[in] senderId Who we are sending to
72 	/// \param[in] caller Which instance of ReplicaManager is calling this interface
73 	/// \return See ReplicaReturnResult
74 	virtual ReplicaReturnResult SendDownloadComplete(RakNet::BitStream *outBitStream, RakNetTime currentTime, SystemAddress senderId, ReplicaManager *caller)=0;
75 };
76 
77 /// An interface for a class that handles the call to receive the download complete notification
78 /// See ReplicaManager::SetDownloadCompleteCB
79 /// \ingroup REPLICA_MANAGER_GROUP
80 class ReceiveDownloadCompleteInterface
81 {
82 public:
ReceiveDownloadCompleteInterface()83 	ReceiveDownloadCompleteInterface() {}
~ReceiveDownloadCompleteInterface()84 	virtual ~ReceiveDownloadCompleteInterface() {}
85 
86 	/// \param[in] inBitStream The bitstream that was written to in SendDownloadCompleteInterface::SendDownloadComplete
87 	/// \param[in] senderId The SystemAddress of the system that send the datagram
88 	/// \param[in] caller Which instance of ReplicaManager is calling this interface
89 	/// \return See ReplicaReturnResult
90 	virtual ReplicaReturnResult ReceiveDownloadComplete(RakNet::BitStream *inBitStream, SystemAddress senderId, ReplicaManager *caller)=0;
91 };
92 
93 /// \deprecated See RakNet::ReplicaManager3
94 
95 /// ReplicaManager is a system manager for your game objects that performs the following tasks:
96 /// 1. Tracks all locally registered game objects and players and only performs operations to and for those objects and players
97 /// 2. Allows you to automatically turn off unneeded local and remote functions for your game objects, thus providing convenience and security against unauthorized sends.
98 /// 3. Sends notifications of existing game objects to new connections, including a download complete message.
99 /// 4. Sends notifications of new game objects to existing players.
100 ///  A. Serialize and scoping calls are not sent to objects that were not notified of that object.
101 ///  B. Notification calls can be canceled on a per-object basis.  Object notification sends are tracked on a per-system per-object basis.
102 /// 5. Configurable per-system per-object scoping.
103 ///  A. Scoping provides a mechanism to hide and unhide remote objects without destroying the whole object, used when when entities should not be destroyed but are currently not visible to systems.
104 ///  B. Serialize calls are not sent to hidden objects.
105 ///  C. Scoping calls can be canceled on a per-object basis.  Scope is tracked on a per-system per-object basis.
106 /// 6. Replicate, SetScope, SignalSerializeNeeded, and the corresponding Replica interfaces are processed in RakPeer::Receive, rather than immediately.
107 ///  A. This allows the ReplicaManager to reorganize function calls in order by dependency.  This allows out of order calls, per-object call cancellation (which also cancels dependencies), and per-object call delays (which also delays dependencies)
108 ///  B. For example, although SetScope and SignalSerializeNeeded have a dependency on SetNetworkID(), you can still call them in the constructor and call SetNetworkID() later, as long as it happens before calling RakPeer::Receive()
109 /// 7. The system is fast, uses little memory, and is intentionally hands off such that it can work with any game architecture and network topology
110 ///
111 /// What the ReplicaManager system does NOT do for you
112 /// 1. Actually create or destroy your game objects
113 /// 2. Associate object destruction events with remote system disconnects.
114 /// 3. Set networkIDs via SetNetworkID() on newly created objects.
115 /// 4. Object sub-serialization.  Serialize only granular on the level of entire objects.  If you want to serialize part of the object, you need to set your own flags and indicate in the BitStream which parts were sent and which not.
116 /// \brief A management system for your game objects and players to make serialization, scoping, and object creation and destruction easier.
117 /// \pre You must call RakPeer::SetNetworkIDManager to use this plugin.
118 /// \ingroup REPLICA_MANAGER_GROUP1
119 class RAK_DLL_EXPORT ReplicaManager : public PluginInterface2
120 {
121 public:
122 	// Constructor
123 	ReplicaManager();
124 
125 	// Destructor
126 	virtual ~ReplicaManager();
127 
128 	/// If you think all objects should have been removed, call this to assert on any that were not.
129 	/// Useful for debugging shutdown or restarts
130 	void AssertReplicatedObjectsClear(void);
131 
132 	/// If you think all participants should have been removed, call this to assert on any that were not.
133 	/// Useful for debugging shutdown or restarts
134 	void AssertParticipantsClear(void);
135 
136 	/// Do or don't automatically call AddParticipant when new systems connect to us.
137 	/// Won't add automatically add connections that already exist before this was called
138 	/// Defaults to false
139 	/// \param[in] autoAdd True or false, to add or not
140 	void SetAutoParticipateNewConnections(bool autoAdd);
141 
142 	/// Adds a participant to the ReplicaManager system.  Only these participants get packets and we only accept ReplicaManager packets from these participants.
143 	/// This way you can have connections that have nothing to do with your game - for example remote console logins
144 	/// \param[in] systemAddress Which player you are referring to
145 	/// \return True on success, false on participant already exists
146 	bool AddParticipant(SystemAddress systemAddress);
147 
148 	/// Removes a participant from the data replicator system
149 	/// This is called automatically on ID_DISCONNECTION_NOTIFICATION and ID_CONNECTION_LOST messages, as well as CloseConnection() calls.
150 	/// \param[in] systemAddress Which player you are referring to
151 	/// \return True on success, false on participant does not exist
152 	bool RemoveParticipant(SystemAddress systemAddress);
153 
154 	/// Construct the specified object on the specified system
155 	/// Replica::SendConstruction will be called immediately, this is a change from before, because otherwise if you later send other packets that refer to this object, this object won't exist yet.
156 	/// The other system will get Replica::ReceiveConstruction
157 	/// If your system assigns NetworkIDs, do so before calling Replicate as the NetworkID is automatically included in the packet.
158 	/// Replicate packets that are sent to systems that already have this NetworkID are ignored.
159 	/// \note Objects which are replicated get exactly one call to SendConstruction for every player / object permutation.
160 	/// \note To perform scoping and serialize updates on an object already created by another system, call Construct with \a isCopy true.
161 	/// \note Setting \a isCopy true will consider the object created on that system without actually trying to create it.
162 	/// \note If you don't need to send updates to other systems for this object, it is more efficient to use ReferencePointer instead.
163 	/// \note In a client / server environment, be sure to call Construct() with isCopy true to let the ReplicaManager know that the server has this object.  Otherwise you won't be able to send Scope or Serialize changes to the server.
164 	/// \param[in] replica A pointer to your object
165 	/// \param[in] isCopy True means that this is a copy of an object that already exists on the systems specified by \a systemAddress and \a broadcast.  If true, we will consider these systems as having the object without sending a datagram to them.  SendConstruction will NOT be called for objects which \a isCopy is true.
166 	/// \param[in] systemAddress The participant to send the command to, or the one to exclude if broadcast is true.
167 	/// \param[in] broadcast True to send to all.  If systemAddress!=UNASSIGNED_SYSTEM_ADDRESS then this means send to all but that participant
168 	void Construct(Replica *replica, bool isCopy, SystemAddress systemAddress, bool broadcast);
169 
170 	/// Call this with your game objects to have them send Replica::SendDestruction.
171 	/// This will be sent immediately to all participants that have this object.  Those participants will get Replica::ReceiveDestruction
172 	/// All pending calls for this object, for this player, are canceled.
173 	/// Nothing is actually deleted - this just signals that the other system called this function.  It is up to you to actually delete your object.
174 	/// \pre Call Replicate with this object first.
175 	/// \pre For the other system to get the network message, SetNetworkID on that object must have been called with the same value as GetNetworkID for this object.
176 	/// \note Call Destruct before DereferencePointer if you plan on calling both, since Destruct will fail with no pointer reference.
177 	/// \note Calling ( with systemAddress==UNASSIGNED_SYSTEM_ADDRESS and broadcast true is equivalent to calling DereferencePointer except that Destruct also sends the destruct packet.
178 	/// \note It is important to call this before deleting your object.  Otherwise this system will crash the next Update call.
179 	/// \param[in] replica A pointer to your object
180 	/// \param[in] systemAddress The participant to send the command to, or the one to exclude if broadcast is true.
181 	/// \param[in] broadcast True to send to all systems that have the object.  If systemAddress!=UNASSIGNED_SYSTEM_ADDRESS then this means send to all but that participant
182 	void Destruct(Replica *replica, SystemAddress systemAddress, bool broadcast);
183 
184 	/// This makes sure the object is tracked, so you can get calls on it.
185 	/// This will automatically happen if you call Construct, SetScope, or SignalSerializeNeeded with \a replica
186 	/// Otherwise you need to call this, or for security the system will ignore calls that reference this object, even if given a valid NetworkID
187 	/// Duplicate calls are safe and are simply ignored.
188 	/// Best place to put this is in the SetReceiveConstructionCB callback so that all your objects are registered.
189 	/// \param[in] replica A pointer to your object
190 	void ReferencePointer(Replica *replica);
191 
192 	/// Call this before you delete \a replica.  This locally removes all references to this pointer.
193 	/// No messages are sent.
194 	/// Best place to put this is in the destructor of \a replica
195 	/// \param[in] replica A pointer to your object
196 	void DereferencePointer(Replica *replica);
197 
198 	/// Sets the scope of your object in relation to another participant.
199 	/// Objects that are in-scope for that participant will send out Replica::Serialize calls.  Otherwise Serialize calls are not sent.
200 	/// Scoping is useful when you want to disable sends to an object temporarily, without deleting that object.
201 	/// Calling this results in Replica::SendScopeChange being called on the local object and Replica::ReceiveScopeChange on the remote object if that object has been created on that remote system.
202 	/// Your game should ensure that objects not in scope are hidden, but not deallocated, on the remote system.
203 	/// Replica::SendScopeChange with \a inScope as true will automatically perform Replica::Serialize
204 	/// \pre Call Replicate with this object first.
205 	/// \pre For the other system to get the network message, that object must have an NetworkID (set by SetNetworkID()) the same as our object's NetworkID (returned from GetNetworkID()).
206 	/// \note You can set the default scope with SetDefaultScope()
207 	/// \note Individual objects can refuse to perform the SendScopeChange call by not writing to the output bitstream while returning true.
208 	/// \param[in] replica An object previously registered with Replicate
209 	/// \param[in] inScope in scope or not.
210 	/// \param[in] systemAddress The participant to send the command to, or the one to exclude if broadcast is true.
211 	/// \param[in] broadcast True to send to all.  If systemAddress!=UNASSIGNED_SYSTEM_ADDRESS then this means send to all but that participant
212 	void SetScope(Replica *replica, bool inScope, SystemAddress systemAddress, bool broadcast);
213 
214 	/// Signal that data has changed and we need to call Serialize() on the \a replica object.
215 	/// This will happen if the object has been registered, Replica::SendConstruction wrote to outBitStream and returned true, and the object is in scope for this player.
216 	/// \pre Call Replicate with this object first.
217 	/// \pre For the other system to get the network message, that object must have an NetworkID (set by SetNetworkID()) the same as our object's NetworkID (returned from GetNetworkID()).
218 	/// \param[in] replica An object previously registered with Replicate
219 	/// \param[in] systemAddress The participant to send the command to, or the one to exclude if broadcast is true.
220 	/// \param[in] broadcast True to send to all.  If systemAddress!=UNASSIGNED_SYSTEM_ADDRESS then this means send to all but that participant
221 	void SignalSerializeNeeded(Replica *replica, SystemAddress systemAddress, bool broadcast);
222 
223 	/// Required callback
224 	/// Set your callback to parse requests to create new objects.  Specifically, when Replica::SendConstruction is called and the networkID of the object is either unset or can't be found, this callback will get that call.
225 	/// How do you know what object to create?  It's up to you, but I suggest in Replica::SendConstruction you encode the class name.  The best way to do this is with the StringTable class.
226 	/// \note If you return true from NetworkIDManager::IsNetworkIDAuthority, which you should do for a server or peer, I recommend also encoding the value returned by GetNetworkID() within Replica::SendConstruction into that bitstream and reading it here.  Then set that value in a call to SetNetworkID.  Dereplicate, SetScope, and SignalSerializeNeeded all rely on being able to call GET_OBJECT_FROM_ID which requires that SetNetworkID be called on that object.
227 	/// \param[in] ReceiveConstructionInterface An instance of a class that implements ReceiveConstructionInterface
228 	void SetReceiveConstructionCB(ReceiveConstructionInterface *receiveConstructionInterface);
229 
230 	/// Set your callbacks to be called when, after connecting to another system, you get all objects that system is going to send to you when it is done with the first iteration through the object list.
231 	/// Optional if you want to send and receive the download complete notification
232 	/// \param[in] sendDownloadComplete A class that implements the SendDownloadCompleteInterface interface.
233 	/// \param[in] receiveDownloadComplete A class that implements the ReceiveDownloadCompleteInterface interface.
234 	/// \sa SendDownloadCompleteInterface , ReceiveDownloadCompleteInterface
235 	void SetDownloadCompleteCB( SendDownloadCompleteInterface *sendDownloadComplete, ReceiveDownloadCompleteInterface *receiveDownloadComplete );
236 
237 	/// This channel will be used for all RakPeer::Send calls
238 	/// \param[in] channel The channel to use for internal RakPeer::Send calls from this system.  Defaults to 0.
239 	void SetSendChannel(unsigned char channel);
240 
241 	/// This means automatically construct all known objects to all new participants
242 	/// Has no effect on existing participants
243 	/// Useful if your architecture always has all objects constructed on all systems all the time anyway, or if you want them to normally start constructed
244 	/// Defaults to false.
245 	/// \param[in] autoConstruct true or false, as desired.
246 	void SetAutoConstructToNewParticipants(bool autoConstruct);
247 
248 	/// Set the default scope for new objects to all players.  Defaults to false, which means Serialize will not be called for new objects automatically.
249 	/// If you set this to true, then new players will get existing objects, and new objects will be sent to existing players
250 	/// This only applies to players that connect and objects that are replicated after this call.  Existing object scopes are not affected.
251 	/// Useful to set to true if you don't use scope, or if all objects normally start in scope
252 	/// \param[in] scope The default scope to use.
253 	void SetDefaultScope(bool scope);
254 
255 	/// When an object goes in scope for a system, you normally want to serialize that object to that system.
256 	/// Setting this flag to true will call Serialize for you automatically when SendScopeChange returns REPLICA_PROCESSING_DONE and the scopeTrue parameter is true
257 	/// Defaults to false
258 	/// \param[in] autoSerialize True or false as needed.
259 	void SetAutoSerializeInScope(bool autoSerialize);
260 
261 	/// Processes all pending commands and does sends as needed.
262 	/// This is called automatically when RakPeerInterface::Receive is called.
263 	/// Depending on where you call RakPeerInterface::Receive you may also wish to call this manually for better responsiveness.
264 	/// For example, if you call RakPeerInterface::Receive at the start of each game tick, this means you would have to wait a render cycle, causing
265 	/// \param[in] peer Pointer to a valid instance of RakPeerInterface used to perform sends
266 	void Update(void);
267 
268 	/// Lets you enable calling any or all of the interface functions in an instance of Replica
269 	/// This setting is the same for all participants for this object, so if you want per-participant permissions you will need to handle that inside your implementation
270 	/// All functions enabled by default.
271 	/// \param[in] replica The object you are referring to
272 	/// \param[in] interfaceFlags A bitwise-OR of REPLICA_SEND_CONSTRUCTION ... REPLICA_SET_ALL corresponding to the function of the same name
273 	void EnableReplicaInterfaces(Replica *replica, unsigned char interfaceFlags);
274 
275 	/// Lets you disable calling any or all of the interface functions in an instance of Replica
276 	/// This setting is the same for all participants for this object, so if you want per-participant permissions you will need to handle that inside your implementation
277 	/// All functions enabled by default.
278 	/// \note Disabling functions is very useful for security.
279 	/// \note For example, on the server you may wish to disable all receive functions so clients cannot change server objects.
280 	/// \param[in] replica The object you are referring to
281 	/// \param[in] interfaceFlags A bitwise-OR of REPLICA_SEND_CONSTRUCTION ... REPLICA_SET_ALL corresponding to the function of the same name
282 	void DisableReplicaInterfaces(Replica *replica, unsigned char interfaceFlags);
283 
284 	/// Tells us if a particular system got a SendConstruction() message from this object.  e.g. does this object exist on this remote system?
285 	/// This is set by the user when calling Replicate and sending (any) data to outBitStream in Replica::SendConstruction
286 	/// \param[in] replica The object we are checking
287 	/// \param[in] systemAddress The system we are checking
288 	bool IsConstructed(Replica *replica, SystemAddress systemAddress);
289 
290 	/// Tells us if a particular object is in scope for a particular system
291 	/// This is set by the user when calling SetScope and sending (any) data to outBitstream in Replica::SendScopeChange
292 	/// \param[in] replica The object we are checking
293 	/// \param[in] systemAddress The system we are checking
294 	bool IsInScope(Replica *replica, SystemAddress systemAddress);
295 
296 	/// Returns how many Replica instances are registered.
297 	/// This number goes up with each non-duplicate call to Replicate and down with each non-duplicate call to Dereplicate
298 	/// Used for GetReplicaAtIndex if you want to perform some object on all registered Replica objects.
299 	/// \return How many replica objects are in the list of replica objects
300 	unsigned GetReplicaCount(void) const;
301 
302 	/// Returns a previously registered Replica *, from index 0 to GetReplicaCount()-1.
303 	/// The order that Replica * objects are returned in is arbitrary (it currently happens to be ordered by pointer address).
304 	/// Calling Dereplicate immediately deletes the Replica * passed to it, so if you call Dereplicate while using this function
305 	/// the array will be shifted over and the current index will now reference the next object in the array, if there was one.
306 	/// \param[in] index An index, from 0 to GetReplicaCount()-1.
307 	/// \return A Replica * previously passed to Construct()
308     Replica *GetReplicaAtIndex(unsigned index);
309 
310 	/// Returns the number of unique participants added with AddParticipant
311 	/// As these systems disconnect, they are no longer participants, so this accurately returns how many participants are using the system
312 	/// \return The number of unique participants added with AddParticipant
313 	unsigned GetParticipantCount(void) const;
314 
315 	/// Returns a SystemAddress previously added with AddParticipant
316 	/// \param[in] index An index, from 0 to GetParticipantCount()-1.
317 	/// \return A SystemAddress
318 	SystemAddress GetParticipantAtIndex(unsigned index);
319 
320 	/// Returns if a participant has been added
321 	/// \return If this participant has been added
322 	bool HasParticipant(SystemAddress systemAddress);
323 
324 	/// Each participant has a per-remote object bitfield passed to the Replica::Serialize call.
325 	/// This function can set or unset these flags for one or more participants at the same time.
326 	/// Flags are NOT automatically cleared on serialize.  You must clear them when you want to do so.
327 	/// \param[in] replica An object previously registered with Replicate
328 	/// \param[in] systemAddress The participant to set the flags for
329 	/// \param[in] broadcast True to apply to all participants.  If systemAddress!=UNASSIGNED_SYSTEM_ADDRESS then this means send to all but that participant
330 	/// \param[in] set True set the bits set in \a flags with the per-object per-system serialization flags.  False to unset these bits.
331 	/// \param[in] flags Modifier to the Per-object per-system flags sent to Replica::Serialize.  See the parameter /a set
332 	void SignalSerializationFlags(Replica *replica, SystemAddress systemAddress, bool broadcast, bool set, unsigned int flags);
333 
334 	/// Each participant has a per-remote object bitfield passed to the Replica::Serialize call.
335 	/// This function is used to read and change these flags directly for a single participant.
336 	/// It gives more control than SignalSerializationFlags but only works for a single participant at a time.
337 	/// \param[in] replica An object previously registered with Replicate
338 	/// \param[in] systemAddress The participant to read/write the flags for
339 	/// \return A pointer to the per-object per-system flags sent to Replica::Serialize.  You can read or modify the flags directly with this function. This pointer is only valid until the next call to RakPeer::Receive
340 	unsigned int* AccessSerializationFlags(Replica *replica, SystemAddress systemAddress);
341 
342 	// ---------------------------- ALL INTERNAL AFTER HERE ----------------------------
343 
344 	enum
345 	{
346 		// Treat the object as on the remote system, and send a packet
347 		REPLICA_EXPLICIT_CONSTRUCTION=1<<0,
348 		// Treat the object as on the remote system, but do not send a packet. Overridden by REPLICA_EXPLICIT_CONSTRUCTION.
349 		REPLICA_IMPLICIT_CONSTRUCTION=1<<1,
350 		REPLICA_SCOPE_TRUE=1<<2, // Mutually exclusive REPLICA_SCOPE_FALSE
351 		REPLICA_SCOPE_FALSE=1<<3, // Mutually exclusive REPLICA_SCOPE_TRUE
352 		REPLICA_SERIALIZE=1<<4,
353 	};
354 
355 	/// \internal
356 	/// One pointer and a command to act on that pointer
357 	struct CommandStruct
358 	{
359 		Replica *replica; // Pointer to an external object - not allocated here.
360 		unsigned char command; // This is one of the enums immediately above.
361 		unsigned int userFlags;
362 	};
363 
364 	struct RegisteredReplica
365 	{
366 		Replica *replica; // Pointer to an external object - not allocated here.
367 		RakNetTime lastDeserializeTrue; //   For replicatedObjects it's the last time deserialize returned true.
368 		unsigned char allowedInterfaces; // Replica interface flags
369 		unsigned int referenceOrder; // The order in which we started tracking this object.  Used so autoconstruction can send objects in-order
370 	};
371 
372 	struct RemoteObject
373 	{
374 		Replica *replica; // Pointer to an external object - not allocated here.
375         bool inScope; // Is replica in scope or not?
376 		RakNetTime lastSendTime;
377 		unsigned int userFlags;
378 	};
379 
380 	struct ReceivedCommand
381 	{
382 		SystemAddress systemAddress;
383 		NetworkID networkID;
384 		unsigned command; // A packetID
385 		unsigned u1;
386 		RakNet::BitStream *userData;
387 	};
388 
389 
390 	static int RegisteredReplicaComp( Replica* const &key, const ReplicaManager::RegisteredReplica &data );
391 	static int RegisteredReplicaRefOrderComp( const unsigned int &key, const ReplicaManager::RegisteredReplica &data );
392 	static int RemoteObjectComp( Replica* const &key, const ReplicaManager::RemoteObject &data );
393 	static int CommandStructComp( Replica* const &key, const ReplicaManager::CommandStruct &data );
394 
395 	/// \internal
396 	/// One remote system
397 	struct ParticipantStruct
398 	{
399 		~ParticipantStruct();
400 
401 		// The player this participant struct represents.
402 		SystemAddress systemAddress;
403 
404 		// Call sendDownloadCompleteCB when REPLICA_SEND_CONSTRUCTION is done for all objects in commandList
405 		// This variable tracks if we did it yet or not.
406 		bool callDownloadCompleteCB;
407 
408 		// Sorted list of Replica*, sorted by pointer, along with a command to perform on that pointer.
409 		// Ordering is just for fast lookup.
410 		// Nothing is allocated inside this list
411 		// DataStructures::OrderedList<Replica *, CommandStruct, ReplicaManager::CommandStructComp> commandList;
412 		// June 4, 2007 - Don't sort commands in the command list.  The game replies on processing the commands in order
413 		DataStructures::List<CommandStruct> commandList;
414 
415 		// Sorted list of Replica*, sorted by pointer, along with if that object is inScope or not for this system
416 		// Only objects that exist on the remote system are in this list, so not all objects are necessarily in this list
417 		DataStructures::OrderedList<Replica *, RemoteObject, ReplicaManager::RemoteObjectComp> remoteObjectList;
418 
419 		// List of pending ReceivedCommand to process
420 		DataStructures::Queue<ReceivedCommand*> pendingCommands;
421 	};
422 
423 	static int ParticipantStructComp( const SystemAddress &key, ReplicaManager::ParticipantStruct * const &data );
424 
425 protected:
426 	/// Frees all memory
427 	void Clear(void);
428 	// Processes a struct representing a received command
429 	ReplicaReturnResult ProcessReceivedCommand(ParticipantStruct *participantStruct, ReceivedCommand *receivedCommand);
430 	unsigned GetCommandListReplicaIndex(const DataStructures::List<ReplicaManager::CommandStruct> &commandList, Replica *replica, bool *objectExists) const;
431 
432 	// Plugin interface functions
433 	PluginReceiveResult OnReceive(Packet *packet);
434 	void OnClosedConnection(SystemAddress systemAddress, RakNetGUID rakNetGUID, PI2_LostConnectionReason lostConnectionReason );
435 	void OnRakPeerShutdown(void);
436 	void OnNewConnection(SystemAddress systemAddress, RakNetGUID rakNetGUID, bool isIncoming);
437 
438 	/// List of objects replicated in the Replicate function.
439 	/// Used to make sure queued actions happen on valid pointers, since objects are removed from the list in Dereplicate
440 	/// Sorted by raw pointer address using the default sort
441 	DataStructures::OrderedList<Replica *, RegisteredReplica, ReplicaManager::RegisteredReplicaComp> replicatedObjects;
442 
443 	/// List of participants
444 	/// Each participant has several queues of pending commands
445 	/// Sorted by systemAddress
446 	/// The only complexity is that each participant also needs a list of objects that mirror the variable replicatedObjects so we know per-player if that object is in scope
447 	DataStructures::OrderedList<SystemAddress, ParticipantStruct *, ReplicaManager::ParticipantStructComp> participantList;
448 
449 	// Internal functions
450 	ParticipantStruct* GetParticipantBySystemAddress(const SystemAddress systemAddress) const;
451 
452 	// Callback pointers.
453 
454 	// Required callback to handle construction calls
455 	ReceiveConstructionInterface *_constructionCB;
456 
457 	// Optional callbacks to send and receive download complete.
458 	SendDownloadCompleteInterface *_sendDownloadCompleteCB;
459 	ReceiveDownloadCompleteInterface *_receiveDownloadCompleteCB;
460 
461 	// Channel to do send calls on.  All calls are reliable ordered except for Replica::Serialize
462 	unsigned char sendChannel;
463 
464 	// Stores what you pass to SetAutoParticipateNewConnections
465 	bool autoParticipateNewConnections;
466 	bool autoSerializeInScope;
467 
468 	bool defaultScope;
469 	bool autoConstructToNewParticipants;
470 	unsigned int nextReferenceIndex;
471 
472 #ifdef _DEBUG
473 	// Check for and assert on recursive calls to update
474 	bool inUpdate;
475 #endif
476 };
477 
478 
479 #endif
480 
481 #endif // _RAKNET_SUPPORT_*
482