Jenkins Software

Replica Manager 3 Plugin Interface Implementation

Replica Manager 3 Implementation Overview

Any game that has objects that are created and destroyed while the game is in progress, almost all non-trivial games, faces a minimum of 3 problems:

  • How to broadcast existing game objects to new players
  • How to broadcast new game objects to existing players
  • How to broadcast deleted game objects to existing players

Additional potential problems, depending on complexity and optimization

  • How to create and destroy objects dynamically as the player moves around the world
  • How to allow the client to create objects locally when this is necessary right away for programming or graphical reasons (such as shooting a bullet).
  • How to update objects as they change over time

The solution to most of these problems is usually straightforward, yet still requires a significant amount of work and debugging, with several dozen lines of code per object.

ReplicaManager3 is designed to be a generic, overridable plugin that handles as many of these details as possible automatically. ReplicaManager3 automatically creates and destroys objects, downloads the world to new players, manages players, and automatically serializes as needed. It also includes the advanced ability to automatically relay messages, and to automatically serialize your objects when the serialized member data changes.

Quick start:

  1. Derive from Connection_RM3 and implement Connection_RM3::AllocReplica(). This is a factory function where given an identifier for a class (such as name) return an instance of that class. Should be able to return any networked object in your game.
  2. Derive from ReplicaManager3 and implement AllocConnection() and DeallocConnection() to return the class you created in step 1.
  3. Derive your networked game objects from Replica3. All pure virtuals have to be implemented, however defaults are provided for Replica3::QueryConstruction() and Replica3::QueryRemoteConstruction() depending on your network architecture.
  4. When a new game object is created on the local system, pass it to ReplicaManager3::Reference().
  5. When a game object is destroyed on the local system, and you want other systems to know about it, call Replica3::BroadcastDestruction()
  6. Attach ReplicaManager3 as a plugin

For a full list of functions with detailed documentation on each parameter, see ReplicaManager3.h.

The primary sample is located at Samples\ReplicaManager3.

Differences between ReplicaManager3 and ReplicaManager2
ReplicaManager3 should be simpler and more transparent
  1. Connection_RM2::Construct is now two functions: Connection_RM3::AllocReplica and Connection_RM3::DeserializeConstruction. Previously, you were given raw data in Connection_RM2::Construct and expected to both create and deserialize construction yourself. Now, AllocReplica will create the object. DeserializeConstruction will fill out the data for the object.
  2. Because of the change above, NetworkID, creatingSystemGUID, and replicaManager are already set as member variables before you get the DeserializeConstruction callback. This simplies usage because the object is already ready to use.
  3. Objects created the same tick were previously sent in individual messages. This means it was possible for the two objects to arrive on different remote game ticks for recipients already connected. This is a problem if two objects depend on each other before either will work. Now, all objects created the same tick (defined by calls to RakPeerInterface::Receive(), which calls PluginInterface2::Update() are sent in the same message.
  4. Previously, you would call ReplicaManager2::SetConnectionFactory with a special connection factory class to create instances of Connection_RM2. Now, ReplicaManager3 itself has pure virtual functions AllocConnection() and DeallocConnection()
  5. Previously, object references were implicit. A call to ReplicaManager2::SendConstruction, ReplicaManager2::SendSerialize, or ReplicaManager2::SendVisibility would register the instance if it didn't already exist. Now, references are explicit, with ReplicaManager3::Reference replacing all three of those ReplicaManager2 calls. This was a previous source of confusion, where those Send functions (or the Broadcast equivalents) did not check the corresponding Replica2::Query* functions. The Construction and Serialization functions are now gone, and happen soley through the automatic update tick.
  6. ReplicaManager2 did not support different serializations per-connection. ReplicaManager3 does, by returning RM3SR_SERIALIZED_UNIQUELY from ReplicaManager3::Serialize. It is still more efficient to return RM3SR_SERIALIZED_IDENTICALLY if serializations are the same for all connections.
  7. ReplicaManager3 does not support the visiblity commands, such as ReplicaManager2::SendVisibility, to keep the system simpler and more transparent. To support this, add a boolean visiblity flag. Transmit it once in Serialize, using RM3SR_SERIALIZED_UNIQUELY. On the remote system, if the visibility flag is false, hide the object. On the sending system, if the visibility flag is false, return RM3SR_DO_NOT_SERIALIZE from ReplicaManager3::Serialize. You can check if the visibility flag for this replica / connection pair has changed by reading SerializeParameters::lastSerializationSent, which will contain the last transmitted value of SerializeParameters::outputBitstream
  8. ReplicaManager3 does not support Connection_RM2::SerializeDownloadStarted to keep the system simpler and more transparent. You can check the equivalent in the function ReplicaManager3::SerializeConstruction withthe value of destinationConnection->IsInitialDownload(). For more complex behavior, you can also send data before registering the remote system. Call ReplicaManager3::SetAutoManageConnections with the autoCreate parameter as false. Send your data. Then call ReplicaManager3::PushConnection.
  9. QueryDestruction no longer exists. QueryConstruction now has a return value that indicates destruction.
  10. QueryIs*Authority no longer exists. Return values from the existing functions in ReplicaManager3 achieve the same results.
See Also

Index
PluginInterface