Introduction Manual Class Reference Header Reference

Replicator Usage

Introduction

Data synchronization is implemented in ZCom_Node. That means, that all synchronized variables are conceptually attached to a replicated object.

Making use of data replication and synchronization can be achieved in two ways. The first and simple way can be used for most standard data types. ZCom_Node provides a set of functions to register single variables for synchronization. Supported types are char*, integer, float and bool. Additionally, the numeric types can be registered for interpolation. For each variable, one function needs to be called. The second way is to create a ZCom_Replicator instance manually, setup the parameters and register the ready for duty replicator to the node.

In both cases, the whole data synchronization setup needs to be enclosed by calls to ZCom_Node::beginReplicationSetup() and ZCom_Node::endReplicationSetup(). Once set up and in operation, the synchronization setup is fixed and cannot be changed. Both, client and server implementations of the same replicated object class, need to have the same replication setup. Zoidcom does not embed any type information into the data streams. When a client node receives an update from a server node, it uses it's own local replication setup to determine in which order the data needs to be unpacked. Obviously, when the client object registers it's variables in a different order, data will get unpacked into the wrong variables.

Simple Usage

Let's assume you have an object class 'Player' and it contains a variable 'health', a variable 'name' and a variable 'ammo', all of which should be transfered from server to clients. Layer 3: Object Replication showed how to add a node to objects and how to set them up.

class Player
{
public:
  int health;
  int ammo;
  char name[25];
  ZCom_Node *node;
  
  void setupReplication();
};

Two integers and a c-string need to get registered to each Player's node. We assume that the node is already set up and registered to a ZCom_Control as explained in previous chapters and dive right into the replication setup:

void Player::setupReplication() 
{
  // we want to register 3 variables
  node->beginReplicationSetup(3);

  // the highest health value possible is 100
  node->addReplicationInt(
    &health,  // pointer to the variable
    7,        // amount of bits (7 bits allow values up to 127
              // 100 is max for the health)
    false,    // unsigned
    ZCOM_REPFLAG_MOSTRECENT, // always send the most recent value only
    ZCOM_REPRULE_AUTH_2_ALL  // server sends to all clients
    );

  // the highest ammo value is 300
  node->addReplicationInt(
    &ammo,    // pointer to the variable
    9,        // amount of bits (9 bits allow values up to 511
              // 300 is max for the ammo)
    false,    // unsigned
    ZCOM_REPFLAG_MOSTRECENT, // always send the most recent value only
    ZCOM_REPRULE_AUTH_2_ALL  // server sends to all clients
    );

  node->addReplicationString(
    name,     // pointer to the variable
    25,       // size of string array
    ZCOM_REPFLAG_MOSTRECENT, // always send the most recent value only
    ZCOM_REPRULE_AUTH_2_ALL  // server sends to all clients
    );
  
  // we are done
  node->endReplicationSetup();
}

This code needs to be executed right after creation of the node and before Zoidcom gets the chance to send updates for it, i.e. before the next call to ZCom_Control::ZCom_processOutput(). When the object gets replicated to a client, the client needs to create the node and the same replication setup within the respective callback (see The Announcement). It is especially important that client and server register the variables in the same order.

The replication methods in ZCom_Node have a few more parameters than shown here. Please look them up in the API docs for full reference.

This is everything you need to let Zoidcom send the content of the variables from the server to all clients automatically. Data updates are only transmitted each time the variables change their values.

For a list of replication functions look here: Replication Setup Methods.
For a list of replication flags look here: Replication Setup Flags.
For a list of replication rules look here: Replication Setup Rules.

Advanced Usage

All replicators can, and some of them even need to be created manually. Especially if you are going to replicate vectors or use your own replicator implementations, you are going down this road. All replicators are derived from ZCom_Replicator and can be registered to a node by calling ZCom_Node::addReplicator().

The Replicator Setup Object

Setup objects hold parameters for replicators. They have been invented to save memory by sharing the parameter sets between replicators. Each replicator needs a ZCom_ReplicatorSetup object assigned to it. One setup object can be assigned to several replicators, they can also be static or global.

When you create replicators through the Simple Usage, these setup objects are created and managed transparently behind the scenes. Also, most replicator classes provide constructors which also create the setup object for you. If you do not care about memory that much, you can mostly ignore the setup objects and skip this section.

Setup objects hold the parameters and flags relevant to it's replicator. But two of the flags are relevant to the setup objects themselves:

These flags are in the same flagset that is used to control replicator behaviour and can be set through the replicator setup constructors or the replicator constructors. The use of ZCOM_REPFLAG_SETUPAUTODELETE indicates, that the setup object is to be deleted when the replicator gets deleted. Do NOT use it when the setup object is shared between several replicators! ZCOM_REPFLAG_SETUPPERSISTS tells the replicator that the setup object is static or persists longer than the rest of Zoidcom. In this case, everyone will use a reference to the persistent object and no replicator will duplicate or delete it.

Example: Creating A String Replicator

Creating replicators by hand is in the best case one additional line of code. The following example creates the replicator for the above 'name' variable manually:

ZCom_Replicate_Stringp *stringrep = new ZCom_Replicate_Stringp(
    name,     // pointer to the variable
    25,       // size of string array
    ZCOM_REPFLAG_MOSTRECENT, // always send the most recent value only
    ZCOM_REPRULE_AUTH_2_ALL  // server sends to all clients
    );
node->addReplicator(
    stringrep,
    true // autodelete = on
    );

As you can see, the parameters needed by the constructor are the same parameters given to ZCom_Node::addReplicationString().

External vs. Internal Storage

The replicators ZCom_Replicate_Bool and ZCom_Replicate_Boolp both replicate boolean variables. The difference is, that former stores the bool internally and in addition to replicating the bool, it does represent it.

When using the Boolp (with p = pointer) version, you always need an additional boolean variable somewhere. The nonpointer version has an internal bool variable, which can be set and read through overloaded operators or get/set methods.

// using boolp, which only keeps a pointer to an external bool
bool thebool; // needs to exist as long as the replicator
ZCom_Replicate_Boolp *bp_rep = new ZCom_Replicate_Boolp(&thebool, other_params);
thebool = true; // bp_rep reads from this variable, as it has the pointer to it

// using bool without p, which has it's internal bool
ZCom_Replicate_Bool *boolrep = new ZCom_Replicate_Bool(initial_value, other_params);
// assignment using overloaded operators
bool value = *boolrep;  // reads the internal bool
*boolrep = value; // writes the internal bool
// or using the get/set methods
value = boolrep->getValue();
boolrep->setValue(value);
The initial_value parameter should be true or false. Other_params should be replaced by the correct parameter list for the constructors.

ZCom_Interpolate and ZCom_Replicate_Numeric also both support internal and external storage.

Array & Vector Replication

Numeric array replication, as well as single value numeric replication, both internally and externally stored, is handled by ZCom_Replicate_Numeric. This class is so versatile because it is implemented as a template. (The same for ZCom_Interpolate, which is very similar). The template is defined as
template class ZCom_Replicate_Numeric<TYPE, SIZE>;

TYPE and SIZE are template parameters, where TYPE can be one of zU32, zU32*, zS32, zS32*, zFloat or zFloat*. SIZE defines the size of the array that should be replicated, supported are values from 1-12, where 1 should be used for single variables.

Here are some example usages, where other_params should be replaced by the correct parameter list for the constructors:

Replicate single zFloat value with internal storage:

zFloat thefloat; // can be local
ZCom_Replicate_Numeric<zFloat, 1> *repnum = new ZCom_Replicate_Numeric<zFLoat, 1>(&thefloat, other_params);
node->addReplicator(repnum, true);

Although the constructor always expects a pointer to the data, the above code will use it only for assigning the initial value to the internally stored float.

Replicate single zFloat value, but this time with external storage:

zFloat thefloat; // must be global, static or class member
ZCom_Replicate_Numeric<zFloat*, 1> *repnum = new ZCom_Replicate_Numeric<zFLoat*, 1>(&thefloat, other_params);
node->addReplicator(repnum, true);

The only difference here is, that the parameter to the template is not 'zFloat' anymore, but 'zFloat*'. Changes to 'thefloat' will be detected by the replicator automatically.

Replicate array of zU32, internal storage:

zU32 velocity[3]; // can be local
ZCom_Replicate_Numeric<zU32, 3> *repnum = new ZCom_Replicate_Numeric<zU32, 3>(velocity, other_params);
node->addReplicator(repnum, true);
repnum->setValue(1, 55); // set single value
repnum->setValue(velocity); // set value of complete array

Internally stored arrays or single values can be get and set through ZCom_Replicate_Numeric::getValue() and ZCom_Replicate_Numeric::setValue(). Both methods expect an array index as first parameter. In case of single value replication, the array index of the single value is 0.

Replicate array of zU32, external storage:

zU32 velocity[3]; // must be global, static or class member
ZCom_Replicate_Numeric<zU32*, 3> *repnum = new ZCom_Replicate_Numeric<zU32*, 3>(velocity, other_params);
node->addReplicator(repnum, true);

Externally stored arrays can be manipulated at will. The replicator will detect any changes by comparing it to an internal backup.


This file is part of the documentation for Zoidcom. Documentation copyright © 2004-2008 by Jörg Rüppel. Generated on Sat Aug 16 15:26:51 2008 for Zoidcom by doxygen 1.4.6-NO