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> ¤tVisibility, 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> ¤tVisibility, 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