1 /// \file
2 /// \brief Contains the second iteration of the ReplicaManager class.  This system automatically creates and destroys objects, downloads the world to new players, manages players, and automatically serializes as needed.
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_ReplicaManager2==1
10 
11 #ifndef __REPLICA_MANAGER_2_H
12 #define __REPLICA_MANAGER_2_H
13 
14 #include "Export.h"
15 #include "RakNetTypes.h"
16 #include "DS_Map.h"
17 #include "PluginInterface2.h"
18 #include "NetworkIDObject.h"
19 #include "PacketPriority.h"
20 #include "GetTime.h"
21 #include "BitStream.h"
22 #include "DS_Queue.h"
23 
24 namespace RakNet
25 {
26 class BitStream;
27 class Replica2;
28 class Connection_RM2;
29 class Connection_RM2Factory;
30 
31 /// \defgroup REPLICA_MANAGER_2_GROUP ReplicaManager2
32 /// \brief Deprecated. Second implementation of object replication
33 /// \details
34 /// \ingroup REPLICA_MANAGER_GROUP
35 
36 /// \brief These are the types of events that can cause network data to be transmitted.
37 /// \ingroup REPLICA_MANAGER_2_GROUP
38 typedef int SerializationType;
39 enum
40 {
41 	/// Serialization command initiated by the user
42 	SEND_SERIALIZATION_GENERIC_TO_SYSTEM,
43 	/// Serialization command initiated by the user
44 	BROADCAST_SERIALIZATION_GENERIC_TO_SYSTEM,
45 	/// Serialization command automatically called after sending construction of the object
46 	SEND_SERIALIZATION_CONSTRUCTION_TO_SYSTEM,
47 	/// Serialization command automatically called after sending construction of the object
48 	BROADCAST_SERIALIZATION_CONSTRUCTION_TO_SYSTEM,
49 	/// Automatic serialization of data, based on Replica2::AddAutoSerializeTimer
50 	SEND_AUTO_SERIALIZE_TO_SYSTEM,
51 	/// Automatic serialization of data, based on Replica2::AddAutoSerializeTimer
52 	BROADCAST_AUTO_SERIALIZE_TO_SYSTEM,
53 	/// Received a serialization command, relaying to systems other than the sender
54 	RELAY_SERIALIZATION_TO_SYSTEMS,
55 
56 	/// If SetAutoAddNewConnections is true, this is the command sent when sending all game objects to new connections automatically
57 	SEND_CONSTRUCTION_SERIALIZATION_AUTO_INITIAL_DOWNLOAD_TO_SYSTEM,
58 	// Automatically sent message indicating if the replica is visible or not to a new connection
59 	SEND_VISIBILITY_AUTO_INITIAL_DOWNLOAD_TO_SYSTEM,
60 	/// The data portion of the game download, preceeded by SEND_CONSTRUCTION_SERIALIZATION_AUTO_INITIAL_DOWNLOAD_TO_SYSTEM
61 	SEND_DATA_SERIALIZATION_AUTO_INITIAL_DOWNLOAD_TO_SYSTEM,
62 
63 	/// Default reason to send a destruction command
64 	SEND_DESTRUCTION_GENERIC_TO_SYSTEM,
65 	/// Triggered by ReplicaManager2::RecalculateVisibility - A replica is now never constructed, so needs to be destroyed
66 	SEND_DESTRUCTION_VISIBILITY_RECALCULATION_TO_SYSTEM,
67 	/// Triggered by Replica2::BroadcastDestruction
68 	BROADCAST_DESTRUCTION_GENERIC_TO_SYSTEM,
69 	/// Received destruction message, relaying to other systems
70 	RELAY_DESTRUCTION_TO_SYSTEMS,
71 
72 	/// Default reason to send a construction command
73 	SEND_CONSTRUCTION_GENERIC_TO_SYSTEM,
74 	/// Triggered by ReplicaManager2::RecalculateVisibility - A replica is now always constructed, so needs to be created
75 	SEND_CONSTRUCTION_VISIBILITY_RECALCULATION_TO_SYSTEM,
76 	/// Triggered by Replica2::BroadcastConstruction()
77 	BROADCAST_CONSTRUCTION_GENERIC_TO_SYSTEM,
78 	/// Replica2::QueryIsConstructionAuthority()==false yet we called ReplicaManager2::SendConstruction()
79 	SEND_CONSTRUCTION_REQUEST_TO_SERVER,
80 	/// A non-authority object was created by a client, accepted, and is now relayed to all other connected systems
81 	BROADCAST_CONSTRUCTION_REQUEST_ACCEPTED_TO_SYSTEM,
82 	/// A non-authority object was created by a client, accepted
83 	SEND_CONSTRUCTION_REPLY_ACCEPTED_TO_CLIENT,
84 	/// A non-authority object was created by a client, denied
85 	SEND_CONSTRUCTION_REPLY_DENIED_TO_CLIENT,
86 
87 	/// An object is visible
88 	SEND_VISIBILITY_TRUE_TO_SYSTEM,
89 	/// An object is visible
90 	BROADCAST_VISIBILITY_TRUE_TO_SYSTEM,
91 	/// An object is not visible
92 	SEND_VISIBILITY_FALSE_TO_SYSTEM,
93 	/// An object is not visible
94 	BROADCAST_VISIBILITY_FALSE_TO_SYSTEM,
95 	/// An object is visible, and we are telling other systems about this
96 	RELAY_VISIBILITY_TRUE_TO_SYSTEMS,
97 	/// An object is visible, and we are telling other systems about this
98 	RELAY_VISIBILITY_FALSE_TO_SYSTEMS,
99 
100 	/// Calling Replica2::Serialize() for the purpose of reading memory to compare against later. This read will not be transmitted
101 	AUTOSERIALIZE_RESYNCH_ONLY,
102 	/// Calling Replica2::Serialize() to compare against a prior call. The serialization may be transmitted
103 	AUTOSERIALIZE_DEFAULT,
104 
105 	/// Start your own reasons one unit past this enum
106 	UNDEFINED_REASON,
107 };
108 
109 /// \deprecated See RakNet::ReplicaManager3
110 
111 /// \brief A management system for your game objects and players to make serialization, scoping, and object creation and destruction easier.
112 /// \details Quick start:
113 /// <OL>
114 /// <LI>Create a class that derives from Connection_RM2, implementing the Construct() function. Construct() is a factory function that should return instances of your game objects, given a user-defined identifier.
115 /// <LI>Create a class that derives from Connection_RM2Factory, implementing AllocConnection() and DeallocConnection() to return instances of the class from step 1.
116 /// <LI>Attach ReplicaManager2 as a plugin
117 /// <LI>Call ReplicaManager2::SetConnectionFactory with an instance of the class from step 2.
118 /// <LI>For each of your game classes that use this system, derive from Replica2 and implement SerializeConstruction(), Serialize(), Deserialize(). The output of SerializeConstruction() is sent to Connection_RM2::Construct()
119 /// <LI>When these classes are allocated, call Replica2::SetReplicaManager() with the instance of ReplicaManager2 class created in step 3 (this could be done automatically in the constructor)
120 /// <LI>Creation: Use Replica2::SendConstruction() to create the object remotely, Replica2::SendDestruction() to delete the object remotely.
121 /// <LI>Scoping: Override Replica2::QueryVisibility() and Replica2::QueryConstruction() to return BQR_YES or BQR_NO if an object should be visible and in scope to a given connection. Defaults to BQR_ALWAYS
122 /// <LI>Automatic serialization: Call Replica2::AddAutoSerializeTimer() to automatically call Replica2::Serialize() at intervals, compare this to the last value, and broadcast out the object when the serialized variables change.
123 /// <\OL>
124 ///
125 /// \pre Call RakPeer::SetNetworkIDManager()
126 /// \pre This system is a server or peer: Call NetworkIDManager::SetIsNetworkIDAuthority(true).
127 /// \pre This system is a client:  Call NetworkIDManager::SetIsNetworkIDAuthority(false).
128 /// \pre If peer to peer, NETWORK_ID_SUPPORTS_PEER_TO_PEER should be defined in RakNetDefines.h
129 /// \ingroup REPLICA_MANAGER_2_GROUP
130 class RAK_DLL_EXPORT ReplicaManager2 : public PluginInterface2
131 {
132 public:
133 	// Constructor
134 	ReplicaManager2();
135 
136 	// Destructor
137 	virtual ~ReplicaManager2();
138 
139 	/// Sets the factory class used to allocate connection objects
140 	/// \param[in] factory A pointer to an instance of a class that derives from Connection_RM2Factory. This pointer it saved and not copied, so the object should remain in memory.
141 	void SetConnectionFactory(Connection_RM2Factory *factory);
142 
143 	/// \param[in] Default ordering channel to use when passing -1 to a function that takes orderingChannel as a parameter
144 	void SetDefaultOrderingChannel(char def);
145 
146 	/// \param[in] Default packet priority to use when passing NUMBER_OF_PRIORITIES to a function that takes priority as a parameter
147 	void SetDefaultPacketPriority(PacketPriority def);
148 
149 	/// \param[in] Default packet reliability to use when passing NUMBER_OF_RELIABILITIES to a function that takes reliability as a parameter
150 	void SetDefaultPacketReliability(PacketReliability def);
151 
152 	/// Auto scope will track the prior construction and serialization visibility of each registered Replica2 class, for each connection.
153 	/// Per-tick, as the visibility or construction status of a replica changes, it will be constructed, destroyed, or the visibility will change as appropriate.
154 	/// \param[in] construction If true, Connection_RM2::SetConstructionByReplicaQuery will be called once per PluginInterface::Update tick. This will call Replica2::QueryConstruction to return if an object should be exist on a particular connection
155 	/// \param[in] visibility If true, Connection_RM2::SetConstructionSerializationByReplicaQuery will be called once per PluginInterface::Update tick. This will call Replica2::QuerySerialization to return if an object should be visible to a particular connection or not.
156 	void SetAutoUpdateScope(bool construction, bool visibility);
157 
158 	/// Autoadd will cause a Connection_RM2 instance to be allocated for every connection.
159 	/// Defaults to true. Set this to false if you have connections which do not participate in the game (master server, etc).
160 	/// \param[in] autoAdd If true, all incoming connections are added as ReplicaManager2 connections.
161 	void SetAutoAddNewConnections(bool autoAdd);
162 
163 	/// If SetAutoAddNewConnections() is false, you need to add connections manually
164 	/// connections are also created implicitly if needed
165 	/// \param[in] systemAddress The address of the new system
166 	/// \return false if the connection already exists
167 	bool AddNewConnection(SystemAddress systemAddress);
168 
169 	/// Remove an existing connection. Also done automatically on ID_DISCONNECTION_NOTIFICATION and ID_CONNECTION_LOST
170 	/// \param[in] systemAddress The address of the system to remove the connection for
171 	/// \return false if the connection does not exist
172 	bool RemoveConnection(SystemAddress systemAddress);
173 
174 	/// Is this connection registered with the system?
175 	/// \param[in] systemAddress The address of the system to check
176 	/// \return true if this address is registered, false otherwise
177 	bool HasConnection(SystemAddress systemAddress);
178 
179 	/// If true, autoserialize timers added with Replica2::AddAutoSerializeTimer() will automatically decrement.
180 	/// If false, you must call Replica2::ElapseAutoSerializeTimers() manually.
181 	/// Defaults to true
182 	/// \param[in] autoUpdate True to automatically call ElapseAutoSerializeTimers(). Set to false if you need to control these timers.
183 	void SetDoReplicaAutoSerializeUpdate(bool autoUpdate);
184 
185 	/// Sends a construction command to one or more systems, which will be relayed throughout the network.
186 	/// Recipient(s) will allocate the connection via Connection_RM2Factory::AllocConnection() if it does not already exist.
187 	/// Will trigger a call on the remote system(s) to Connection_RM2::Construct()
188 	/// \note If using peer-to-peer, NETWORK_ID_SUPPORTS_PEER_TO_PEER should be defined in RakNetDefines.h.
189 	/// \note This is a low level function. Beginners may wish to use Replica2::SendConstruction() or Replica2::BroadcastConstruction(). You can also override Replica2::QueryConstruction()
190 	/// \param[in] replica The class to construct remotely
191 	/// \param[in] replicaData User-defined serialized data representing how to construct the class. Could be the name of the class, a unique identifier, or other methods
192 	/// \param[in] recipient Which system to send to. Use UNASSIGNED_SYSTEM_ADDRESS to send to all previously created connections. Connection_RM2Factory::AllocConnection will be called if this connection has not been previously used.
193 	/// \param[in] timestamp Timestamp to send with the message. Use 0 to not send a timestamp if you don't need it.
194 	/// \param[in] sendMessage True to actually send a network message. False to only register that the object exists on the remote system, useful for objects created outside ReplicaManager2, or objects that already existed in the world.
195 	/// \param[in] exclusionList Which systems to not send to. This list is carried with the messsage, and appended to at each node in the connection graph. This is used to prevent infinite cyclical sends.
196 	/// \param[in] localClientId If replica->QueryIsConstructionAuthority()==false, this number will be sent with SEND_CONSTRUCTION_REQUEST_TO_SERVER to the \a recipient. SEND_CONSTRUCTION_REPLY_ACCEPTED_TO_CLIENT or SEND_CONSTRUCTION_REPLY_DENIED_TO_CLIENT will be returned, and this number will be used to look up the local object in Replica2::clientPtrArray
197 	/// \param[in] type What kind of serialization operation this is. Use one of the pre-defined types, or create your own. This will be returned in \a type in Connection_RM2::Construct()
198 	/// \param[in] priority PacketPriority to send with. Use NUMBER_OF_PRIORITIES to use the default defined by SetDefaultPacketPriority().
199 	/// \param[in] reliability PacketReliability to send with. Use NUMBER_OF_RELIABILITIES to use the default defined by SetDefaultPacketReliability();
200 	/// \param[in] orderingChannel ordering channel to send on. Use -1 to use the default defined by SetDefaultOrderingChannel()
201 	/// \pre Call SetConnectionFactory() with a derived instance of Connection_RM2Factory.
202 	void SendConstruction(Replica2 *replica, BitStream *replicaData, SystemAddress recipient, RakNetTime timestamp, bool sendMessage,
203 		DataStructures::OrderedList<SystemAddress,SystemAddress> &exclusionList,
204 		unsigned char localClientId, SerializationType type=SEND_CONSTRUCTION_GENERIC_TO_SYSTEM,
205 		PacketPriority priority=NUMBER_OF_PRIORITIES, PacketReliability reliability=NUMBER_OF_RELIABILITIES, char orderingChannel=-1);
206 
207 	/// Sends a destruction command to one or more systems, which will be relayed throughout the network.
208 	/// Recipient(s) will allocate the connection via Connection_RM2Factory::AllocConnection() if it does not already exist.
209 	/// Will trigger a call on the remote system(s) to Replica2::ReceiveDestruction() which in turn calls Replica2::DeserializeDestruction() with the value passed in \a replicaData
210 	/// Note: This is a low level function. Beginners may wish to use Replica2::SendDestruction() or Replica2::BroadcastDestruction().
211 	/// \param[in] replica The class to destroy remotely
212 	/// \param[in] replicaData User-defined serialized data. Passed to Replica2::ReceiveDestruction()
213 	/// \param[in] recipient Which system to send to. Use UNASSIGNED_SYSTEM_ADDRESS to send to all previously created connections. Connection_RM2Factory::AllocConnection will be called if this connection has not been previously used.
214 	/// \param[in] timestamp Timestamp to send with the message. Use 0 to not send a timestamp if you don't need it.
215 	/// \param[in] sendMessage True to actually send a network message. False to only register that the object no longer exists on the remote system.
216 	/// \param[in] exclusionList Which systems to not send to. This list is carried with the messsage, and appended to at each node in the connection graph. This is used to prevent infinite cyclical sends.
217 	/// \param[in] type What kind of serialization operation this is. Use one of the pre-defined types, or create your own. This will be returned in \a type in Connection_RM2::Construct()
218 	/// \param[in] priority PacketPriority to send with. Use NUMBER_OF_PRIORITIES to use the default defined by SetDefaultPacketPriority().
219 	/// \param[in] reliability PacketReliability to send with. Use NUMBER_OF_RELIABILITIES to use the default defined by SetDefaultPacketReliability();
220 	/// \param[in] orderingChannel ordering channel to send on. Use -1 to use the default defined by SetDefaultOrderingChannel()
221 	/// \pre Replica::QueryIsDestructionAuthority() must return true
222 	/// \pre Call SetConnectionFactory() with a derived instance of Connection_RM2Factory.
223 	void SendDestruction(Replica2 *replica, BitStream *replicaData, SystemAddress recipient, RakNetTime timestamp, bool sendMessage,
224 		DataStructures::OrderedList<SystemAddress,SystemAddress> &exclusionList,
225 		SerializationType type=SEND_DESTRUCTION_GENERIC_TO_SYSTEM,
226 		PacketPriority priority=NUMBER_OF_PRIORITIES, PacketReliability reliability=NUMBER_OF_RELIABILITIES, char orderingChannel=-1);
227 
228 	/// Sends a serialized object to one or more systems, which will be relayed throughout the network.
229 	/// Recipient(s) will allocate the connection via Connection_RM2Factory::AllocConnection() if it does not already exist.
230 	/// Will trigger a call on the remote system(s) to Replica2::ReceiveSerialization() which in turn calls Replica2::Deserialize() with the value passed in \a replicaData
231 	/// Note: This is a low level function. Beginners may wish to use Replica2::SendSerialize() or Replica2::BroadcastSerialize().
232 	/// \param[in] replica The class to serialize
233 	/// \param[in] replicaData User-defined serialized data. Passed to Replica2::ReceiveSerialization()
234 	/// \param[in] recipient Which system to send to. Use UNASSIGNED_SYSTEM_ADDRESS to send to all previously created connections. Connection_RM2Factory::AllocConnection will be called if this connection has not been previously used.
235 	/// \param[in] timestamp Timestamp to send with the message. Use 0 to not send a timestamp if you don't need it.
236 	/// \param[in] exclusionList Which systems to not send to. This list is carried with the messsage, and appended to at each node in the connection graph. This is used to prevent infinite cyclical sends.
237 	/// \param[in] type What kind of serialization operation this is. Use one of the pre-defined types, or create your own. This will be returned in \a type in Connection_RM2::Construct()
238 	/// \param[in] priority PacketPriority to send with. Use NUMBER_OF_PRIORITIES to use the default defined by SetDefaultPacketPriority().
239 	/// \param[in] reliability PacketReliability to send with. Use NUMBER_OF_RELIABILITIES to use the default defined by SetDefaultPacketReliability();
240 	/// \param[in] orderingChannel ordering channel to send on. Use -1 to use the default defined by SetDefaultOrderingChannel()
241 	/// \pre Replica::QueryIsSerializationAuthority() must return true
242 	/// \pre Call SetConnectionFactory() with a derived instance of Connection_RM2Factory.
243 	void SendSerialize(Replica2 *replica, BitStream *replicaData, SystemAddress recipient, RakNetTime timestamp,
244 		DataStructures::OrderedList<SystemAddress,SystemAddress> &exclusionList,
245 		SerializationType type=SEND_SERIALIZATION_GENERIC_TO_SYSTEM,
246 		PacketPriority priority=NUMBER_OF_PRIORITIES, PacketReliability reliability=NUMBER_OF_RELIABILITIES, char orderingChannel=-1);
247 
248 	/// Sets the visibility status of an object. which will be relayed throughout the network.
249 	/// Objects that are not visible should be hidden in the game world, and will not send AutoSerialize updates
250 	/// Recipient(s) will allocate the connection via Connection_RM2Factory::AllocConnection() if it does not already exist.
251 	/// Will trigger a call on the remote system(s) to Connection_RM2::ReceiveVisibility()
252 	/// Note: This is a low level function. Beginners may wish to use Connection_RM2::SendVisibility() or override Replica2::QueryVisibility()
253 	/// \param[in] objectList The objects to send to the system.
254 	/// \param[in] replicaData User-defined serialized data. Read in Connection_RM2::ReceiveVisibility()
255 	/// \param[in] recipient Which system to send to. Use UNASSIGNED_SYSTEM_ADDRESS to send to all previously created connections. Connection_RM2Factory::AllocConnection will be called if this connection has not been previously used.
256 	/// \param[in] timestamp Timestamp to send with the message. Use 0 to not send a timestamp if you don't need it.
257 	/// \param[in] sendMessage True to actually send a network message. False to only register that the objects exist on the remote system
258 	/// \param[in] type What kind of serialization operation this is. Use one of the pre-defined types, or create your own. This will be returned in \a type in Connection_RM2::Construct()
259 	/// \param[in] priority PacketPriority to send with. Use NUMBER_OF_PRIORITIES to use the default defined by SetDefaultPacketPriority().
260 	/// \param[in] reliability PacketReliability to send with. Use NUMBER_OF_RELIABILITIES to use the default defined by SetDefaultPacketReliability();
261 	/// \param[in] orderingChannel ordering channel to send on. Use -1 to use the default defined by SetDefaultOrderingChannel()
262 	/// \pre Replica::QueryIsConstructionAuthority() must return true
263 	/// \pre Call SetConnectionFactory() with a derived instance of Connection_RM2Factory.
264 	void SendVisibility(Replica2 *replica, BitStream *replicaData, SystemAddress recipient, RakNetTime timestamp,
265 		DataStructures::OrderedList<SystemAddress,SystemAddress> &exclusionList,
266 		SerializationType type=SEND_VISIBILITY_TRUE_TO_SYSTEM,
267 		PacketPriority priority=NUMBER_OF_PRIORITIES, PacketReliability reliability=NUMBER_OF_RELIABILITIES, char orderingChannel=-1);
268 
269 	/// Returns how many Replica2 instances are registered.
270 	/// Replica2 instances are automatically registered when used, and unregistered when calling Deref (which is automatically done in the destructor).
271 	/// Used for GetReplicaAtIndex if you want to perform some object on all registered Replica objects.
272 	/// \return How many replica objects are in the list of replica objects
273 	unsigned GetReplicaCount(void) const;
274 
275 	/// Returns a previously registered Replica2 *, from index 0 to GetReplicaCount()-1.
276 	/// Replica2* objects are returned in the order they were registered.
277 	/// \param[in] index An index, from 0 to GetReplicaCount()-1.
278 	/// \return A Replica2 pointer
279 	Replica2 *GetReplicaAtIndex(unsigned index);
280 
281 	/// Returns the number of registered connections.
282 	/// Connections are registered implicitly when used.
283 	/// Connections are unregistered on disconnect.
284 	/// \return The number of registered connections
285 	unsigned GetConnectionCount(void) const;
286 
287 	/// Returns a connection pointer previously implicitly added.
288 	/// \param[in] index An index, from 0 to GetConnectionCount()-1.
289 	/// \return A Connection_RM2 pointer
290 	Connection_RM2* GetConnectionAtIndex(unsigned index) const;
291 
292 	/// Returns a connection pointer previously implicitly added.
293 	/// \param[in] systemAddress The system address of the connection to return
294 	/// \return A Connection_RM2 pointer
295 	Connection_RM2* GetConnectionBySystemAddress(SystemAddress systemAddress) const;
296 
297 	/// Returns the index of a connection, by SystemAddress
298 	/// \param[in] systemAddress The system address of the connection index to return
299 	/// \return The connection index, or -1 if no such connection
300 	unsigned int GetConnectionIndexBySystemAddress(SystemAddress systemAddress) const;
301 
302 	/// Call this when Replica2::QueryVisibility() or Replica2::QueryConstructionVisibility() changes from BQR_ALWAYS or BQR_NEVER to BQR_YES or BQR_NO
303 	/// Otherwise these two conditions are assumed to never change
304 	/// \param[in] Which replica to update
305 	void RecalculateVisibility(Replica2 *replica);
306 
307 	/// \internal
308 	static int Replica2ObjectComp( RakNet::Replica2 * const &key, RakNet::Replica2 * const &data );
309 	/// \internal
310 	static int Replica2CompByNetworkID( const NetworkID &key, RakNet::Replica2 * const &data );
311 	/// \internal
312 	static int Connection_RM2CompBySystemAddress( const SystemAddress &key, RakNet::Connection_RM2 * const &data );
313 
314 	/// Given a replica instance, return all connections that are believed to have this replica instantiated.
315 	/// \param[in] replica Which replica is being refered to
316 	/// \param[out] output List of connections, ordered by system address
317 	void GetConnectionsWithReplicaConstructed(Replica2 *replica, DataStructures::OrderedList<SystemAddress, Connection_RM2*, ReplicaManager2::Connection_RM2CompBySystemAddress> &output);
318 
319 	/// Given a replica instance, return all connections that are believed to have this replica visible
320 	/// \param[in] replica Which replica is being refered to
321 	/// \param[out] output List of connections, ordered by system address
322 	void GetConnectionsWithSerializeVisibility(Replica2 *replica, DataStructures::OrderedList<SystemAddress, Connection_RM2*, ReplicaManager2::Connection_RM2CompBySystemAddress> &output);
323 
324 	/// Gets the instance of RakPeerInterface that this plugin was attached to
325 	/// \return The instance of RakPeerInterface that this plugin was attached to
326 	RakPeerInterface *GetRakPeer(void) const;
327 
328 	/// Internally starts tracking this replica
329 	/// \internal
330 	void Reference(Replica2* replica, bool *newReference);
331 
332 	/// Stops tracking this replica. Call before deleting the Replica. Done automatically in ~Replica()
333 	/// \internal
334 	void Dereference(Replica2 *replica);
335 
336 protected:
337 	// Plugin interface functions
338 	void OnAttach(void);
339 	PluginReceiveResult OnReceive(Packet *packet);
340 	void OnClosedConnection(SystemAddress systemAddress, RakNetGUID rakNetGUID, PI2_LostConnectionReason lostConnectionReason );
341 	void OnRakPeerShutdown(void);
342 	void Update(void);
343 	virtual void OnNewConnection(SystemAddress systemAddress, RakNetGUID rakNetGUID, bool isIncoming);
344 
345 	PluginReceiveResult OnDownloadComplete(unsigned char *packetData, int packetDataLength, SystemAddress sender, RakNetTime timestamp);
346 	PluginReceiveResult OnDownloadStarted(unsigned char *packetData, int packetDataLength, SystemAddress sender, RakNetTime timestamp);
347 	PluginReceiveResult OnConstruction(unsigned char *packetData, int packetDataLength, SystemAddress sender, RakNetTime timestamp);
348 	PluginReceiveResult OnDestruction(unsigned char *packetData, int packetDataLength, SystemAddress sender, RakNetTime timestamp);
349 	PluginReceiveResult OnVisibilityChange(unsigned char *packetData, int packetDataLength, SystemAddress sender, RakNetTime timestamp);
350 	PluginReceiveResult OnSerialize(unsigned char *packetData, int packetDataLength, SystemAddress sender, RakNetTime timestamp);
351 
352 	bool AddToAndWriteExclusionList(SystemAddress recipient, RakNet::BitStream *bs, DataStructures::OrderedList<SystemAddress,SystemAddress> &exclusionList);
353 	void WriteExclusionList(RakNet::BitStream *bs, DataStructures::OrderedList<SystemAddress,SystemAddress> &exclusionList);
354 	void CullByAndAddToExclusionList(
355 		DataStructures::OrderedList<SystemAddress, Connection_RM2*,ReplicaManager2::Connection_RM2CompBySystemAddress> &inputList,
356 		DataStructures::OrderedList<SystemAddress, Connection_RM2*,ReplicaManager2::Connection_RM2CompBySystemAddress> &culledOutput,
357 		DataStructures::OrderedList<SystemAddress,SystemAddress> &exclusionList);
358 	void ReadExclusionList(RakNet::BitStream *bs, DataStructures::OrderedList<SystemAddress,SystemAddress> &exclusionList);
359 
360 	void Send(RakNet::BitStream *bs, SystemAddress recipient, PacketPriority priority, PacketReliability reliability, char orderingChannel);
361 	void Clear(void);
362 	void DownloadToNewConnection(Connection_RM2* connection, RakNetTime timestamp, PacketPriority priority, PacketReliability reliability, char orderingChannel);
363 
364 	Connection_RM2* CreateConnectionIfDoesNotExist(SystemAddress systemAddress, bool *newConnection);
365 	Connection_RM2* AutoCreateConnection(SystemAddress systemAddress, bool *newConnection);
366 	void AddConstructionReference(Connection_RM2* connection, Replica2* replica);
367 	void AddVisibilityReference(Connection_RM2* connection, Replica2* replica);
368 	void RemoveVisibilityReference(Connection_RM2* connection, Replica2* replica);
369 	void WriteHeader(RakNet::BitStream *bs, MessageID type, RakNetTime timestamp);
370 
371 	friend class Connection_RM2;
372 	friend class Replica2;
373 
374 	Connection_RM2Factory *connectionFactoryInterface;
375 	bool autoUpdateConstruction, autoUpdateVisibility;
376 
377 	char defaultOrderingChannel;
378 	PacketPriority defaultPacketPriority;
379 	PacketReliability defaultPacketReliablity;
380 	bool autoAddNewConnections;
381 	bool doReplicaAutoUpdate;
382 	RakNetTime lastUpdateTime;
383 
384 	DataStructures::List<Replica2*> fullReplicaUnorderedList;
385 	DataStructures::OrderedList<Replica2*, Replica2*, ReplicaManager2::Replica2ObjectComp> fullReplicaOrderedList;
386 	DataStructures::OrderedList<Replica2*, Replica2*, ReplicaManager2::Replica2ObjectComp> alwaysDoConstructReplicaOrderedList;
387 	DataStructures::OrderedList<Replica2*, Replica2*, ReplicaManager2::Replica2ObjectComp> alwaysDoSerializeReplicaOrderedList;
388 	// Should only be in this list if QueryIsServer() is true
389 	DataStructures::OrderedList<Replica2*, Replica2*, ReplicaManager2::Replica2ObjectComp> variableConstructReplicaOrderedList;
390 	DataStructures::OrderedList<Replica2*, Replica2*, ReplicaManager2::Replica2ObjectComp> variableSerializeReplicaOrderedList;
391 
392 	DataStructures::OrderedList<SystemAddress, Connection_RM2*, ReplicaManager2::Connection_RM2CompBySystemAddress> connectionList;
393 };
394 
395 /// \brief The result of various scope and construction queries
396 /// \ingroup REPLICA_MANAGER_2_GROUP
397 enum RAK_DLL_EXPORT BooleanQueryResult
398 {
399 	/// The query is always true, for all systems. Certain optimizations are performed here, but you should not later return any other value without first calling ReplicaManager2::RecalculateVisibility
400 	BQR_ALWAYS,
401 
402 	/// True
403 	BQR_YES,
404 
405 	/// False
406 	BQR_NO,
407 
408 	/// The query is never true, for all systems. Certain optimizations are performed here, but you should not later return any other value without first calling ReplicaManager2::RecalculateVisibility
409 	BQR_NEVER
410 };
411 
412 /// \brief Contextual information about serialization, passed to some functions in Replica2
413 /// \ingroup REPLICA_MANAGER_2_GROUP
414 struct RAK_DLL_EXPORT SerializationContext
415 {
SerializationContextSerializationContext416 	SerializationContext() {}
~SerializationContextSerializationContext417 	~SerializationContext() {}
SerializationContextSerializationContext418 	SerializationContext(SerializationType st, SystemAddress relay, SystemAddress recipient, RakNetTime _timestamp) {serializationType=st; relaySourceAddress=relay; recipientAddress=recipient; timestamp=_timestamp;}
419 
420 	/// The system that sent the message to us.
421 	SystemAddress relaySourceAddress;
422 
423 	/// The system that we are sending to.
424 	SystemAddress recipientAddress;
425 
426 	/// Timestamp to send with the message. 0 means undefined. Set to non-zero to actually transmit using ID_TIMESTAMP
427 	RakNetTime timestamp;
428 
429 	/// What type of serialization was performed
430 	SerializationType serializationType;
431 
432 	/// General category of serialization
433 	static bool IsSerializationCommand(SerializationType r);
434 	/// General category of serialization
435 	static bool IsDownloadCommand(SerializationType r);
436 	/// General category of serialization
437 	static bool IsDestructionCommand(SerializationType r);
438 	/// General category of serialization
439 	static bool IsConstructionCommand(SerializationType r);
440 	/// General category of serialization
441 	static bool IsVisibilityCommand(SerializationType r);
442 	/// General category of serialization
443 	static bool IsVisible(SerializationType r);
444 };
445 
446 
447 /// \brief Base class for game objects that use the ReplicaManager2 system
448 /// \details All game objects that want to use the ReplicaManager2 functionality must inherit from Replica2.<BR>
449 /// Generally you will want to implement at a minimum Serialize(), Deserialize(), and SerializeConstruction()
450 /// \ingroup REPLICA_MANAGER_2_GROUP
451 class RAK_DLL_EXPORT Replica2 : public NetworkIDObject
452 {
453 public:
454 	// Constructor
455 	Replica2();
456 
457 	// Destructor
458 	virtual ~Replica2();
459 
460 	/// Sets the replica manager to use with this Replica.
461 	/// Will also set the NetworkIDManager associated with RakPeerInterface::SetNetworkIDManager()
462 	/// Call this before using any of the functions below!
463 	/// \param[in] rm A pointer to your instance of ReplicaManager 2
464 	void SetReplicaManager(ReplicaManager2* rm);
465 
466 	/// Returns what was passed to SetReplicaManager(), or 0 if no value ever passed
467 	/// \return Registered instance of ReplicaManager2
468 	ReplicaManager2* GetReplicaManager(void) const;
469 
470 	/// Construct this object on other systems
471 	/// Triggers a call to SerializeConstruction()
472 	/// \note If using peer-to-peer, NETWORK_ID_SUPPORTS_PEER_TO_PEER should be defined in RakNetDefines.h
473 	/// \param[in] recipientAddress Which system to send to
474 	/// \param[in] serializationType What type of command this is. Use UNDEFINED_REASON to have a type chosen automatically
475 	virtual void SendConstruction(SystemAddress recipientAddress, SerializationType serializationType=UNDEFINED_REASON);
476 
477 	/// Destroy this object on other systems
478 	/// Triggers a call to SerializeDestruction()
479 	/// \param[in] recipientAddress Which system to send to
480 	/// \param[in] serializationType What type of command this is. Use UNDEFINED_REASON to have a type chosen automatically
481 	virtual void SendDestruction(SystemAddress recipientAddress, SerializationType serializationType=UNDEFINED_REASON);
482 
483 	/// Serialize this object to another system
484 	/// Triggers a call to Serialize()
485 	/// \param[in] recipientAddress Which system to send to
486 	/// \param[in] serializationType What type of command this is. Use UNDEFINED_REASON to have a type chosen automatically
487 	virtual void SendSerialize(SystemAddress recipientAddress, SerializationType serializationType=UNDEFINED_REASON);
488 
489 	/// Update the visibility of this object on another system
490 	/// Triggers a call to SerializeVisibility()
491 	/// \param[in] recipientAddress Which system to send to
492 	/// \param[in] serializationType What type of command this is. Use UNDEFINED_REASON to have a type chosen automatically
493 	virtual void SendVisibility(SystemAddress recipientAddress, SerializationType serializationType=UNDEFINED_REASON);
494 
495 	/// Construct this object on other systems
496 	/// \param[in] serializationContext Which system to send to, an input timestamp, and the SerializationType. 0 to use defaults, no timestamp.
497 	virtual void BroadcastConstruction(SerializationContext *serializationContext=0);
498 
499 	/// Serialize this object to all current connections
500 	/// Triggers a call to SerializeConstruction() for each connection (you can serialize differently per connection).
501 	/// \param[in] serializationContext Which system to send to, an input timestamp, and the SerializationType. 0 to use defaults, no timestamp.
502 	virtual void BroadcastSerialize(SerializationContext *serializationContext=0);
503 
504 	/// Destroy this object on all current connections
505 	/// Triggers a call to SerializeDestruction() for each connection (you can serialize differently per connection).
506 	/// \param[in] serializationContext Which system to send to, an input timestamp, and the SerializationType. 0 to use defaults, no timestamp.
507 	virtual void BroadcastDestruction(SerializationContext *serializationContext=0);
508 
509 	/// Update the visibility state of this object on all other systems
510 	/// Use SEND_VISIBILITY_TRUE_TO_SYSTEM or SEND_VISIBILITY_FALSE_TO_SYSTEM in \a serializationContext::serializationType
511 	/// Triggers a call to SerializeVisibility() for each connection (you can serialize differently per connection).
512 	/// \param[in] serializationContext Which system to send to, an input timestamp, and the SerializationType. 0 to use defaults, no timestamp, true visibility
513 	virtual void BroadcastVisibility(bool isVisible, SerializationContext *serializationContext=0);
514 
515 	/// CALLBACK:
516 	/// Override in order to write to \a bitStream data identifying this class for the class factory. Will be received by Connection_RM2::Construct() to create an instance of this class.
517 	/// \param[out] bitStream Data used to identify this class, along with any data you also want to send when constructing the class
518 	/// \param[in] serializationContext serializationType passed to Replica2::SendConstruction(), along with destination system, and a timestamp you can write to.
519 	/// \return Return false to cancel the construction, true to process
520 	virtual bool SerializeConstruction(RakNet::BitStream *bitStream, SerializationContext *serializationContext)=0;
521 
522 	/// CALLBACK:
523 	/// Override in order to write to \a bitStream data to send along with destruction requests. Will be received by DeserializeDestruction()
524 	/// \param[out] bitStream Data to send
525 	/// \param[in] serializationContext Describes which system we are sending to, and a timestamp as an out parameter
526 	/// \return Return false to cancel the operation, true to process
527 	virtual bool SerializeDestruction(RakNet::BitStream *bitStream, SerializationContext *serializationContext);
528 
529 	/// CALLBACK:
530 	/// Override in order to write to \a bitStream data to send as regular class serialization, for normal per-tick data. Will be received by Deserialize()
531 	/// \param[out] bitStream Data to send
532 	/// \param[in] serializationContext Describes which system we are sending to, and a timestamp as an out parameter
533 	/// \return Return false to cancel the operation, true to process
534 	virtual bool Serialize(RakNet::BitStream *bitStream, SerializationContext *serializationContext);
535 
536 	/// CALLBACK:
537 	/// Override in order to write to \a bitStream data to send along with visibility changes. Will be received by DeserializeVisibility()
538 	/// \param[out] bitStream Data to send
539 	/// \param[in] serializationContext Describes which system we are sending to, and a timestamp as an out parameter
540 	/// \return Return false to cancel the operation, true to process
541 	virtual bool SerializeVisibility(RakNet::BitStream *bitStream, SerializationContext *serializationContext);
542 
543 	/// CALLBACK:
544 	/// Receives data written by SerializeDestruction()
545 	/// \param[in] bitStream Data sent
546 	/// \param[in] serializationType SerializationContext::serializationType
547 	/// \param[in] sender Which system sent this message to us
548 	/// \param[in] timestamp If a timestamp was written, will be whatever was written adjusted to the local system time. 0 if not used.
549 	virtual void DeserializeDestruction(RakNet::BitStream *bitStream, SerializationType serializationType, SystemAddress sender, RakNetTime timestamp);
550 
551 	/// CALLBACK:
552 	/// Receives data written by Serialize()
553 	/// \param[in] bitStream Data sent
554 	/// \param[in] serializationType SerializationContext::serializationType
555 	/// \param[in] sender Which system sent this message to us
556 	/// \param[in] timestamp If a timestamp was written, will be whatever was written adjusted to the local system time. 0 if not used.
557 	virtual void Deserialize(RakNet::BitStream *bitStream, SerializationType serializationType, SystemAddress sender, RakNetTime timestamp);
558 
559 	/// CALLBACK:
560 	/// Receives data written by SerializeVisibility()
561 	/// \param[in] bitStream Data sent
562 	/// \param[in] serializationType SerializationContext::serializationType
563 	/// \param[in] sender Which system sent this message to us
564 	/// \param[in] timestamp If a timestamp was written, will be whatever was written adjusted to the local system time. 0 if not used.
565 	virtual void DeserializeVisibility(RakNet::BitStream *bitStream, SerializationType serializationType, SystemAddress sender, RakNetTime timestamp);
566 
567 	/// CALLBACK:
568 	/// For a given connection, should this object exist?
569 	/// Checked every Update cycle if ReplicaManager2::SetAutoUpdateScope() parameter \a construction is true
570 	/// Defaults to BQR_ALWAYS
571 	/// \note This query is NOT used for ReplicaManager2::BroadcastConstruction() or SendConstruction(), which forces the operation to occur. If you DO want to use the query, use ReplicaManager2::Reference() and the next time RakPeer::Receive() is called it will occur.
572 	/// \param[in] connection Which connection we are referring to. 0 means unknown, in which case the system is checking for BQR_ALWAYS or BQR_NEVER as an optimization.
573 	/// \return BQR_NO and the object will be destroyed. BQR_YES and the object will be created. BQR_ALWAYS is YES for all connections, and is optimized to only be checked once.
574 	virtual BooleanQueryResult QueryConstruction(Connection_RM2 *connection);
575 
576 	/// CALLBACK:
577 	/// For a given connection, should this object be visible (updatable?)
578 	/// Checked every Update cycle if ReplicaManager2::SetAutoUpdateScope() parameter \a serializationVisiblity is true
579 	/// Defaults to BQR_ALWAYS
580 	/// \note This query is NOT used for ReplicaManager2::BroadcastVisibility() or SendVisibility(), which forces the operation to occur. If you DO want to use the query, use ReplicaManager2::Reference() and the next time RakPeer::Receive() is called it will occur.
581 	/// \param[in] connection Which connection we are referring to. 0 means unknown, in which case the system is checking for BQR_ALWAYS or BQR_NEVER as an optimization.
582 	/// \return BQR_NO or BQR_YES and as this value changes per connection, you will get a call to DeserializeVisibility().
583 	virtual BooleanQueryResult QueryVisibility(Connection_RM2 *connection);
584 
585 	/// CALLBACK:
586 	/// Does this system have control over construction of this object?
587 	/// While not strictly required, it is best to have this consistently return true for only one system. Otherwise systems may fight and override each other.
588 	/// Defaults to NetworkIDManager::IsNetworkIDAuthority();
589 	/// \return True if an authority over this operation, for this object instance
590 	virtual bool QueryIsConstructionAuthority(void) const;
591 
592 	/// CALLBACK:
593 	/// Does this system have control over deletion of this object?
594 	/// While not strictly required, it is best to have this consistently return true for only one system. Otherwise systems may fight and override each other.
595 	/// Defaults to NetworkIDManager::IsNetworkIDAuthority();
596 	/// \return True if an authority over this operation, for this object instance
597 	virtual bool QueryIsDestructionAuthority(void) const;
598 
599 	/// CALLBACK:
600 	/// Does this system have control over visibility of this object?
601 	/// While not strictly required, it is best to have this consistently return true for only one system. Otherwise systems may fight and override each other.
602 	/// Defaults to NetworkIDManager::IsNetworkIDAuthority();
603 	/// \return True if an authority over this operation, for this object instance
604 	virtual bool QueryIsVisibilityAuthority(void) const;
605 
606 	/// CALLBACK:
607 	/// Does this system have control over serialization of object members of this object?
608 	/// It is reasonable to have this be true for more than one system, but you would want to serialize different variables so those systems do not conflict.
609 	/// Defaults to NetworkIDManager::IsNetworkIDAuthority();
610 	/// \return True if an authority over this operation, for this object instance
611 	virtual bool QueryIsSerializationAuthority(void) const;
612 
613 	/// CALLBACK:
614 	/// If QueryIsConstructionAuthority() is false for a remote system, should that system be able to create this kind of object?
615 	/// \param[in] sender Which system sent this message to us? Also happens to be the system that is requesting to create an object
616 	/// \param[in] replicaData Construction data used to create this object
617 	/// \param[in] type Which type of serialization operation was performed
618 	/// \param[in] timestamp Written timestamp with the packet. 0 if not used.
619 	/// \return True to allow remote construction of this object. If true, we will reply with SEND_CONSTRUCTION_REPLY_ACCEPTED_TO_CLIENT and the network ID will be set on the requester.
620 	virtual bool AllowRemoteConstruction(SystemAddress sender, RakNet::BitStream *replicaData, SerializationType type, RakNetTime timestamp);
621 
622 	/// Adds a timer that will elapse every \a countdown milliseconds, calling Serialize with AUTOSERIALIZE_DEFAULT or whatever value was passed to \a serializationType
623 	/// Every time this timer elapses, the value returned from Serialize() will be compared to the last value returned by Serialize().
624 	/// If different, SendSerialize() will be called automatically.
625 	/// It is possible to create your own AUTOSERIALIZE enumerations and thus control which parts of the object is serialized
626 	/// Use CancelAutoSerializeTimer() or ClearAutoSerializeTimers() to stop the timer.
627 	/// If this timer already exists, it will simply override the existing countdown
628 	/// This timer will automatically repeat every \a countdown milliseconds
629 	/// \note The same data is sent to all participants when the autoserialize timer completes. If the data sent depends on the system to be sent to, do not use autoserialize. This is an optimization to save memory.
630 	/// \param[in] interval Time in milliseconds between autoserialize ticks. Use 0 to process immediately, and every tick
631 	/// \param[in] serializationType User-defined identifier for what type of serialization operation to perform. Returned in Deserialize() as the \a serializationType parameter.
632 	/// \param[in] countdown Amount of time before doing the next autoserialize. Defaults to interval
633 	virtual void AddAutoSerializeTimer(RakNetTime interval, SerializationType serializationType=AUTOSERIALIZE_DEFAULT, RakNetTime countdown=(RakNetTime)-1 );
634 
635 	/// Elapse time for all timers added with AddAutoSerializeTimer()
636 	/// Only necessary to call this if you call Replica2::SetDoReplicaAutoSerializeUpdate(false) (which defaults to true)
637 	/// \param[in] timeElapsed How many milliseconds have elapsed since the last call
638 	/// \param[in] resynchOnly True to only update what was considered the last send, without actually doing a send.
639 	virtual void ElapseAutoSerializeTimers(RakNetTime timeElapsed, bool resynchOnly);
640 
641 	/// Returns how many milliseconds are remaining until the next autoserialize update
642 	/// \param[in] serializationType User-defined identifier for what type of serialization operation to perform. Returned in Deserialize() as the \a serializationType parameter.
643 	/// \return How many milliseconds are remaining until the next autoserialize update. Returns -1 if no such autoserialization timer is in place.
644 	RakNetTime GetTimeToNextAutoSerialize(SerializationType serializationType=AUTOSERIALIZE_DEFAULT);
645 
646 	/// Do the actual send call when needed to support autoSerialize
647 	/// If you want to do different types of send calls (UNRELIABLE for example) override this function.
648 	/// \param[in] serializationContext Describes the recipient, sender. serializationContext::timestamp is an [out] parameter which if you write to, will be send along with the message
649 	/// \param[in] serializedObject Data to pass to ReplicaManager2::SendSerialize()
650 	virtual void BroadcastAutoSerialize(SerializationContext *serializationContext, RakNet::BitStream *serializedObject);
651 
652 	/// Stop calling an autoSerialize timer previously setup with AddAutoSerializeTimer()
653 	/// \param[in] serializationType Corresponding value passed to serializationType
654 	virtual void CancelAutoSerializeTimer(SerializationType serializationType=AUTOSERIALIZE_DEFAULT);
655 
656 	/// Remove and deallocate all previously added autoSerialize timers
657 	virtual void ClearAutoSerializeTimers(void);
658 
659 	/// A timer has elapsed. Compare the last value sent to the current value, and if different, send the new value
660 	/// \internal
661 	virtual void OnAutoSerializeTimerElapsed(SerializationType serializationType, RakNet::BitStream *output, RakNet::BitStream *lastOutput, RakNetTime lastAutoSerializeCountdown, bool resynchOnly);
662 
663 	/// Immediately elapse all autoserialize timers
664 	/// Used internally when a Deserialize() event occurs, so that the deserialize does not trigger an autoserialize itself
665 	/// \internal
666 	/// \param[in] resynchOnly If true, do not send a Serialize() message if the data has changed
667 	virtual void ForceElapseAllAutoserializeTimers(bool resynchOnly);
668 
669 	/// A call to Connection_RM2 Construct() has completed and the object is now internally referenced
670 	/// \param[in] replicaData Whatever was written \a bitStream in Replica2::SerializeConstruction()
671 	/// \param[in] type Whatever was written \a serializationType in Replica2::SerializeConstruction()
672 	/// \param[in] replicaManager ReplicaManager2 instance that created this class.
673 	/// \param[in] timestamp timestamp sent with Replica2::SerializeConstruction(), 0 for none.
674 	/// \param[in] networkId NetworkID that will be assigned automatically to the new object after this function returns
675 	/// \param[in] networkIDCollision True if the network ID that should be assigned to this object is already in use. Usuallly this is because the object already exists, and you should just read your data and return 0.
676 	virtual void OnConstructionComplete(RakNet::BitStream *replicaData, SystemAddress sender, SerializationType type, ReplicaManager2 *replicaManager, RakNetTime timestamp, NetworkID networkId, bool networkIDCollision);
677 
678 protected:
679 
680 	virtual void ReceiveSerialize(SystemAddress sender, RakNet::BitStream *serializedObject, SerializationType serializationType, RakNetTime timestamp, DataStructures::OrderedList<SystemAddress,SystemAddress> &exclusionList );
681 	virtual void ReceiveDestruction(SystemAddress sender, RakNet::BitStream *serializedObject, SerializationType serializationType, RakNetTime timestamp, DataStructures::OrderedList<SystemAddress,SystemAddress> &exclusionList );
682 	virtual void DeleteOnReceiveDestruction(SystemAddress sender, RakNet::BitStream *serializedObject, SerializationType serializationType, RakNetTime timestamp, DataStructures::OrderedList<SystemAddress,SystemAddress> &exclusionList );
683 	virtual void ReceiveVisibility(SystemAddress sender, RakNet::BitStream *serializedObject, SerializationType serializationType, RakNetTime timestamp, DataStructures::OrderedList<SystemAddress,SystemAddress> &exclusionList);
684 	virtual Replica2 * ReceiveConstructionReply(SystemAddress sender, BitStream *replicaData, bool constructionAllowed);
685 	void DereferenceFromDestruction(void);
686 
687 	friend class ReplicaManager2;
688 	friend class Connection_RM2;
689 
690 	static unsigned char clientSharedID;
691 	static Replica2* clientPtrArray[256];
692 
693 	bool hasClientID;
694 	unsigned char clientID;
695 	ReplicaManager2 *rm2;
696 
697 	struct AutoSerializeEvent
698 	{
699 		SerializationType serializationType;
700 		RakNetTime initialCountdown;
701 		RakNetTime remainingCountdown;
702 		bool writeToResult1;
703 		RakNet::BitStream lastAutoSerializeResult1;
704 		RakNet::BitStream lastAutoSerializeResult2;
705 	};
706 
707 	DataStructures::Map<SerializationType, AutoSerializeEvent*> autoSerializeTimers;
708 
709 };
710 
711 /// \brief Implement this factory class to return instances of your Connection_RM2 derived object. This is used as a class factory and exposes functionality related to the connection and the system
712 /// \ingroup REPLICA_MANAGER_2_GROUP
713 class RAK_DLL_EXPORT Connection_RM2Factory
714 {
715 public:
Connection_RM2Factory()716 	Connection_RM2Factory() {}
~Connection_RM2Factory()717 	virtual ~Connection_RM2Factory() {}
718 	virtual Connection_RM2* AllocConnection(void) const=0;
719 	virtual void DeallocConnection(Connection_RM2* s) const=0;
720 };
721 
722 /// \brief This class represents a connection between two instances of ReplicaManager2
723 /// \details Represents a connection. Allocated by user supplied factory interface Connection_RM2Factory.<BR>
724 /// Implicitly created as needed.<BR>
725 /// Generally you will want to implement at a minimum the Construct() function, used as a factory function to create your game objects.
726 /// \ingroup REPLICA_MANAGER_2_GROUP
727 class RAK_DLL_EXPORT Connection_RM2
728 {
729 public:
730 	// Constructor
731 	Connection_RM2();
732 
733 	// Destructor
734 	virtual ~Connection_RM2();
735 
736 	/// Factory function, used to create instances of your game objects
737 	/// Encoding is entirely up to you. \a replicaData will hold whatever was written \a bitStream in Replica2::SerializeConstruction()
738 	/// One efficient way to do it is to use StringTable.h. This allows you to send predetermined strings over the network at a cost of 9 bits, up to 65536 strings
739 	/// \note The object is not yet referenced by ReplicaManager2 in this callback. Use Replica2::OnConstructionComplete() to perform functionality such as AutoSerialize()
740 	/// \param[in] replicaData Whatever was written \a bitStream in Replica2::SerializeConstruction()
741 	/// \param[in] type Whatever was written \a serializationType in Replica2::SerializeConstruction()
742 	/// \param[in] replicaManager ReplicaManager2 instance that created this class.
743 	/// \param[in] timestamp timestamp sent with Replica2::SerializeConstruction(), 0 for none.
744 	/// \param[in] networkId NetworkID that will be assigned automatically to the new object after this function returns
745 	/// \param[in] networkIDCollision True if the network ID that should be assigned to this object is already in use. Usuallly this is because the object already exists, and you should just read your data and return 0.
746 	/// \return Return 0 to signal that construction failed or was refused for this object. Otherwise return the object that was created. A reference will be held to this object, and SetNetworkID() and SetReplicaManager() will be called automatically.
747 	virtual Replica2* Construct(RakNet::BitStream *replicaData, SystemAddress sender, SerializationType type, ReplicaManager2 *replicaManager, RakNetTime timestamp, NetworkID networkId, bool networkIDCollision)=0;
748 
749 	/// CALLBACK:
750 	/// Called before a download is sent to a new connection, called after ID_REPLICA_MANAGER_DOWNLOAD_STARTED is sent.
751 	/// Gives you control over the list of objects to be downloaded. For greater control, you can override ReplicaManager2::DownloadToNewConnection
752 	/// Defaults to send everything in the default order
753 	/// \param[in] fullReplicaUnorderedList The list of all known objects in the order they were originally known about by the system (the first time used by any function)
754 	/// \param[out] orderedDownloadList An empty list. Copy fullReplicaUnorderedList to this list to send everything. Leave elements out to not send them. Add them to the list in a different order to send them in that order.
755 	virtual void SortInitialDownload( const DataStructures::List<Replica2*> &orderedDownloadList, DataStructures::List<Replica2*> &initialDownloadList );
756 
757 
758 	/// CALLBACK:
759 	/// Called before a download is sent to a new connection
760 	/// \param[out] objectData What data you want to send to DeSerializeDownloadStarted()
761 	/// \param[in] replicaManager Which replica manager to use to perform the send
762 	/// \param[in/out] serializationContext Target recipient, optional timestamp, type of command
763 	virtual void SerializeDownloadStarted(RakNet::BitStream *objectData, ReplicaManager2 *replicaManager, SerializationContext *serializationContext);
764 
765 	/// CALLBACK:
766 	/// Called after a download is sent to a new connection
767 	/// \param[out] objectData What data you want to send to DeSerializeDownloadComplete()
768 	/// \param[in] replicaManager Which replica manager to use to perform the send
769 	/// \param[in/out] serializationContext Target recipient, optional timestamp, type of command
770 	virtual void SerializeDownloadComplete(RakNet::BitStream *objectData, ReplicaManager2 *replicaManager, SerializationContext *serializationContext);
771 
772 	/// CALLBACK:
773 	/// A new connection was added. All objects that are constructed and visible for this system will arrive immediately after this message.
774 	/// Write data to \a objectData by deriving from SerializeDownloadStarted()
775 	/// \note Only called if SetAutoUpdateScope is called with serializationVisiblity or construction true. (This is the default)
776 	/// \param[in] objectData objectData Data written through SerializeDownloadStarted()
777 	/// \param[in] replicaManager Which replica manager to use to perform the send
778 	/// \param[in] timestamp timestamp sent, 0 for none
779 	/// \param[in] serializationType Type of command
780 	virtual void DeserializeDownloadStarted(RakNet::BitStream *objectData, SystemAddress sender, ReplicaManager2 *replicaManager, RakNetTime timestamp, SerializationType serializationType);
781 
782 	/// CALLBACK:
783 	/// A new connection was added. All objects that are constructed and visible for this system have now arrived.
784 	/// Write data to \a objectData by deriving from SerializeDownloadComplete
785 	/// \note Only called if SetAutoUpdateScope is called with serializationVisiblity or construction true. (This is the default)
786 	/// \param[in] objectData objectData Data written through SerializeDownloadComplete()
787 	/// \param[in] replicaManager Which replica manager to use to perform the send
788 	/// \param[in] timestamp timestamp sent, 0 for none
789 	/// \param[in] serializationType Type of command
790 	virtual void DeserializeDownloadComplete(RakNet::BitStream *objectData, SystemAddress sender, ReplicaManager2 *replicaManager, RakNetTime timestamp, SerializationType serializationType);
791 
792 	/// Given a list of objects, compare it against lastConstructionList.
793 	/// BroadcastConstruct() is called for objects that only exist in the new list.
794 	/// BroadcastDestruct() is called for objects that only exist in the old list.
795 	/// This is used by SetConstructionByReplicaQuery() for all Replica2 that do not return BQR_ALWAYS from Replica2::QueryConstruction()
796 	/// If you want to pass your own, more efficient list to check against, call ReplicaManager2::SetAutoUpdateScope with construction=false and call this function yourself when desired
797 	/// \param[in] List of all objects that do not return BQR_ALWAYS from Replica2::QueryConstruction() that should currently be created on this system
798 	/// \param[in] replicaManager Which replica manager to use to perform the send
799 	virtual void SetConstructionByList(DataStructures::OrderedList<Replica2*, Replica2*, ReplicaManager2::Replica2ObjectComp> &currentVisibility, ReplicaManager2 *replicaManager);
800 
801 	/// Given a list of objects, compare it against lastSerializationList.
802 	/// Replica2::BroadcastVisibility(true) is called for objects that only exist in the new list.
803 	/// Replica2::BroadcastVisibility(false) is called for objects that only exist in the old list.
804 	/// This is used by SetVisibilityByReplicaQuery() for all Replica2 that do not return BQR_ALWAYS from Replica2::QueryVisibility()
805 	/// If you want to pass your own, more efficient list to check against, call ReplicaManager2::SetAutoUpdateScope with construction=false and call this function yourself when desired
806 	/// \param[in] List of all objects that do not return BQR_ALWAYS from Replica2::QueryConstruction() that should currently be created on this system
807 	/// \param[in] replicaManager Which replica manager to use to perform the send
808 	virtual void SetVisibilityByList(DataStructures::OrderedList<Replica2*, Replica2*, ReplicaManager2::Replica2ObjectComp> &currentVisibility, ReplicaManager2 *replicaManager);
809 
810 	/// Go through all registered Replica2 objects that do not return BQR_ALWAYS from Replica2::QueryConstruction()
811 	/// For each of these objects that return BQR_YES, pass them to currentVisibility in SetConstructionByList()
812 	/// Automatically called every tick if ReplicaManager2::SetAutoUpdateScope with construction=true is called (which is the default)
813 	/// \param[in] replicaManager Which replica manager to use to perform the send
814 	virtual void SetConstructionByReplicaQuery(ReplicaManager2 *replicaManager);
815 
816 	/// Go through all registered Replica2 objects that do not return BQR_ALWAYS from Replica2::QueryVisibility()
817 	/// For each of these objects that return BQR_YES, pass them to currentVisibility in SetVisibilityByList()
818 	/// Automatically called every tick if ReplicaManager2::SetAutoUpdateScope with construction=true is called (which is the default)
819 	/// \param[in] replicaManager Which replica manager to use to perform the send
820 	virtual void SetVisibilityByReplicaQuery(ReplicaManager2 *replicaManager);
821 
822 	/// Set the system address to use with this class instance. This is set internally when the object is created
823 	void SetSystemAddress(SystemAddress sa);
824 
825 	/// Get the system address associated with this class instance.
826 	SystemAddress GetSystemAddress(void) const;
827 
828 	/// Set the guid to use with this class instance. This is set internally when the object is created
829 	void SetGuid(RakNetGUID guid);
830 
831 	/// Get the guid associated with this class instance.
832 	RakNetGUID GetGuid(void) const;
833 
834 protected:
835 	void Deref(Replica2* replica);
836 
837 	void CalculateListExclusivity(
838 		const DataStructures::OrderedList<Replica2*, Replica2*, ReplicaManager2::Replica2ObjectComp> &listOne,
839 		const DataStructures::OrderedList<Replica2*, Replica2*, ReplicaManager2::Replica2ObjectComp> &listTwo,
840 		DataStructures::OrderedList<Replica2*, Replica2*, ReplicaManager2::Replica2ObjectComp> &exclusiveToListOne,
841 		DataStructures::OrderedList<Replica2*, Replica2*, ReplicaManager2::Replica2ObjectComp> &exclusiveToListTwo
842 		) const;
843 
844 	virtual Replica2 * ReceiveConstruct(RakNet::BitStream *replicaData, NetworkID networkId, SystemAddress sender, unsigned char localClientId, SerializationType type,
845 		ReplicaManager2 *replicaManager, RakNetTime timestamp, DataStructures::OrderedList<SystemAddress,SystemAddress> &exclusionList);
846 
847 	friend class ReplicaManager2;
848 
849 	// Address of this participant
850 	SystemAddress systemAddress;
851 	RakNetGUID rakNetGuid;
852 
853 	DataStructures::OrderedList<Replica2*, Replica2*, ReplicaManager2::Replica2ObjectComp> lastConstructionList;
854 	DataStructures::OrderedList<Replica2*, Replica2*, ReplicaManager2::Replica2ObjectComp> lastSerializationList;
855 };
856 
857 }
858 
859 #endif
860 
861 #endif // _RAKNET_SUPPORT_*
862