Introduction Manual Class Reference Header Reference

Custom Replicators

Introduction

If the provided replicators are not enough, there is always the possibility to implement your own. For that, two interface classes are defined.

ZCom_ReplicatorBasic is the right choice if you want to perform normal variable replication. It takes care of almost everything and only needs customization for data change detection, packing and unpacking. All replicators discussed so far use this interface. zoidcom_replicator_memblock.h contains the complete source for a simple replicator.

ZCom_ReplicatorAdvanced on the other hand gives you total control over what is sent to whom and when. This interface is used for ZCom_Replicate_Movement, where custom timing plays a special role.

In order to implement a custom replicator one of the two interfaces needs to be chosen first. The chosen one needs to be subclassed and all virtual methods need to be implemented. After that, it can be instanciated and registered to a node just like all other replicators with a call to ZCom_Node::addReplicator().

Replicator Base Functions

All replicators need to implement at least the following set of virtual functions, regardless if they are using the basic or the advanced interface.

Initialization

All replicators need to have the ZCOM_REPLICATOR_INITIALIZED flag set before they can be used. Set it in the constructor with
m_flags |= ZCOM_REPLICATOR_INITIALIZED;
when the replicator initialized successfully.

Peek Support

Peek support is needed to allow replication interceptors to peek at incoming updates without accepting them. The peeking interface is defined in ZCom_Replicator itself, so both interfaces do inherit it's two virtual functions:

and the three helper functions:

Extensive documentation and an example is provided in the documentation for ZCom_Replicator.

Processing

In case the replicator needs to perform periodic computations, these can be done in ZCom_Replicator::Process(). In order for Zoidcom to call the function, the replicator's constructor needs to set the flag ZCOM_REPLICATOR_CALLPROCESS with
m_flags |= ZCOM_REPLICATOR_CALLPROCESS;

The Basic Interface

The ZCom_ReplicatorBasic interface adds three more virtual methods to the ones provided by ZCom_Replicator:

Implementing these methods suffices to have a working replicator for most needs. Zoidcom will automatically enforce min- and maxdelay parameters, replication directions and overall control of dataflow.

State Checking

ZCom_ReplicatorBasic::checkState() is called on a regular basis by Zoidcom. It is supposed to return 'true' when the replicator needs to send updates. Usually this is implemented by keeping an internal copy of the data and comparing the actual data to the copy. When this method is called, it has to make sure that it doesn't return true again on another call, unless the data has changed between the two calls. This is the common scheme:
bool MyReplicator::checkState()
{
  bool changed = (internalcopy == actualdata);
  internalcopy = actualdata;
  return changed;
}

The method will be called at most once per replicator per call to ZCom_Control::ZCom_processOutput().

Update Packing

ZCom_ReplicatorBasic::packData(ZCom_BitStream *_stream) is called whenever Zoidcom wants to send an update of this replicator. It is called once for every peer receiving an update, as opposed to once for all peers. The _stream parameter points to the bitstream currently being filled for a peer host, and packData() is supposed to write it's update into the stream, for example like so:
_stream->addInt(someint, 9);

When some aspect of the data packing and unpacking code depends on external parameters, a subclass of ZCom_ReplicatorSetup should be made which can hold the parameters. For example using ZCom_RSetupNumeric:

_stream->addInt(someint, ((ZCom_RSetupNumeric*)m_setup)->getRelevantBits());

Update Unpacking

When an update is received, ZCom_ReplicatorBasic::unpackData() gets called. The parameters provide a pointer to the incoming stream, a boolean called _store, and a timestamp.

The boolean tells the unpack method whether it should unpack and apply the update, or just unpack it. Latter case can happen when a replication interceptor decided that this update should be dropped. Due to the way Zoidcom works, the bitstream still needs to be brought to the correct streamposition so that the next replicator can unpack.

If _store is false, one or more of the various skipdata methods in ZCom_BitStream can be used, as they are slightly faster than the getdata methods.

The timestamp is an estimated value representing the time of when the update has been sent. This stamp is in the system's local time. The delta between this value and the returnvalue from ZoidCom::getTime() equals the estimated time passed since the update was sent in milliseconds.

The common scheme for this method is:

if (_store)
  localdata = _stream->getInt(9);
else
  _stream->skipInt(9);

Attention:
It is absolutely crucial that the unpackData() method advances the bitstream by the exact amount of bits that were added by the packData() method. Zoidcom does not embed enough metainformation to reposition the stream for further use, at least not in the release build. The debug build adds this metadata and will assert when asymmetrical reads are detected.

The Advanced Interface

The advanced interface works completely different. While basic replicators are controlled and steered by Zoidcom, advanced replicators have to do everything on their own. They have to keep track of peers, who needs updates and when to send them. To make this possible, a large set of callbacks are defined in the interface which keep the replicator updated about everything which might be important to them.

They send their updates by sending events whenever they see fit. More documentation pending.


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