Introduction Manual Class Reference Header Reference

ZCom_ReplicatorAdvanced Class Reference

Inheritance diagram for ZCom_ReplicatorAdvanced:

Inheritance graph
[legend]
Collaboration diagram for ZCom_ReplicatorAdvanced:

Collaboration graph
[legend]
List of all members.

Detailed Description

Interface for advanced replicators which need high level of control.

As opposed to basic replicators (ZCom_ReplicatorBasic) which are aided by Zoidcom a lot, the advanced replicator interface allows replicators to fully control when data has to be sent, to whom, in which manner and how often. This results in extremely high flexibility and on the other hand requires more work to get it working.

One restriction remains, though. The replicator cannot surpass the owning node's priority. It is only able to send when the owning node is allowed to send.

Note:
Unlike the basic replicators, advanced replicators have to perform timing on their own. That means, the min- and maxdelay parameters in ZCom_ReplicatorSetup are not enforced by Zoidcom for advanced replicators. Use getLastUpdateTime(), or the _lastupdate parameter to onPreSendData() to handle this.
See also:
Custom Replicators


Interceptor peek support.

The methods getPeekData() and clearPeekData() need to be implemented when the replicator is supposed to be intercepted. Using these methods, the interceptor callback can ask the replicator to peek into the stream, without altering it's read position. Inspecting the data provided by the peekData() method, the callback can then decide if the update should be let through or not.

A interceptor trying to see what is in the stream only needs to call the peekData() method. Everything else is handled by the replicator itself.

A replicator that should support peeking has to implement peekData(), using getPeekStream() to get the currently processed bitstream. If it needs to allocate memory to hold the data, it has to make use of peekDataStore() in peekData(), and peekDataRetrieve() in clearPeekData().

      class MyReplicator : public ZCom_Replicator {
      void * peekData() {
        int size = getPeekStream()->getStringSize();
        char *string = new char[size];
        getPeekStream()->getString(string, size);
        // store it so it can be deleted later
        peekDataStore(buf);
        return (void*) buf;
      }

      void  clearPeekData() {
        char *str = peekDataRetrieve();
        if (str) delete []str;
      }

Zoidcom automatically notices if data has been stored and calls clearPeekData() after the interceptor has completed.

If the stream contains very simple data for which no memory allocation is needed, this will do:

      void *MyReplicator::peekData() {
        return (void*) getPeekStream()->getInt(32);
      }
      void MyReplicator::clearPeekData() {}

More information can be found in the documentation of each peek method.

virtual void clearPeekData ()=0
 If peekData() has allocated memory, clear it here.
virtual void * peekData ()=0
 Unpack data from the stream, but don't update the local data.
ZCom_BitStreamgetPeekStream () const
 Get stream currently processed for peeking the data.
void * peekDataRetrieve ()
 Retrieve the peekbuffer pointer currently stored.
void peekDataStore (void *_ptr)
 Store pointer to allocated peekbuffer, so it can be deleted again.

Public Member Functions

zU32getLastUpdateTime (ZCom_ConnID _cid)
 Get pointer to time of last update to given connection.
ZCom_NodegetNode () const
 Get the node in which this replicator is registered.
virtual void onConnectionAdded (ZCom_ConnID _cid, eZCom_NodeRole _remoterole)=0
 A node has become relevant on the specified connection and thus to this replicator, too.
virtual void onConnectionRemoved (ZCom_ConnID _cid, eZCom_NodeRole _remoterole)=0
 The node on this connection is no longer relevant.
virtual void onDataReceived (ZCom_ConnID _cid, eZCom_NodeRole _remoterole, ZCom_BitStream &_stream, bool _store, zU32 _estimated_time_sent)=0
 Data has been received from the replicator of a remote node.
virtual void onLocalRoleChanged (eZCom_NodeRole _oldrole, eZCom_NodeRole _newrole)=0
 The role of the local node which owns this replicator has changed.
virtual void onPacketReceived (ZCom_ConnID _cid)=0
 The given connection has received a packet.
virtual void onPreSendData (ZCom_ConnID _cid, eZCom_NodeRole _remoterole, zU32 *_lastupdate)=0
 Zoidcom is about to transmit data to the given client.
virtual void onRemoteRoleChanged (ZCom_ConnID _cid, eZCom_NodeRole _oldrole, eZCom_NodeRole _newrole)=0
 The role of a node on a remote connection has changed it's role.
virtual void Process (eZCom_NodeRole _localrole, zU32 _simulation_time_passed)=0
 Do any kind of processing.
void sendData (eZCom_SendMode _mode, ZCom_BitStream *_stream, zU32 _reference_id=0)
 Sends an event to peer replicators.
void sendDataDirect (eZCom_SendMode _mode, ZCom_ConnID _dest, ZCom_BitStream *_stream, zU32 _reference_id=0)
 Same as sendData(), but with single destination.
void setNode (ZCom_Node *_node)
 Set the node in which this replicator is registered.

Protected Attributes

zU8 m_flags
 Additional replicator flags. ZCom_Replicator() c'tor will set this to 0. (ZCOM_REPLICATOR_*).
ZCom_ReplicatorSetupm_setup
 pointing to an instance of the setup class - all replication parameters are stored here


Member Function Documentation

ZCom_Node* ZCom_ReplicatorAdvanced::getNode  )  const
 

Get the node in which this replicator is registered.

Returns:
A pointer to the node.

zU32* ZCom_ReplicatorAdvanced::getLastUpdateTime ZCom_ConnID  _cid  ) 
 

Get pointer to time of last update to given connection.

Parameters:
_cid Id of connection.
Returns:
Pointer(!!) to time in msecs.
This method should be used for implementing min- and maxdelay enforcement.

If the result is non-NULL, writing to this pointer is encouraged, as advanced replicators have to manage timing on their own.

Attention:
This is only available (i.e. non-NULL) if at least one replicator in the node has a mindelay or maxdelay activated. If this is not the case, the method returns NULL.
Code example:
 zU32* lastupdate = getLastUpdateTime(id_of_connection_which_is_currently_processed);
 if (lastupdate) {
   if (ZoidCom::getTime() - *lastupdate < m_setup->getMinDelay())
     // don't send data if last update to this happened too recent
     return;
   else
     // store the current time because an update gets sent now
     *lastupdate = ZoidCom::getTime();
 }

void ZCom_ReplicatorAdvanced::sendData eZCom_SendMode  _mode,
ZCom_BitStream _stream,
zU32  _reference_id = 0
 

Sends an event to peer replicators.

Parameters:
_mode eZCom_SendMode. eZCom_ReliableOrdered is not supported in this context.
_stream The event data.
_reference_id If send mode is eZCom_UnreliableNotify, this id will be given back to the application through onDataLost() or onDataAcked().
This event will be received by all replicators which normally receive data from this replicator, too. If this replicator is owned by an authority node and the replicator is flagged ZCOM_REPFLAG_AUTH_2_PROXY, all replicators owned by a proxy of this replicators node will receive this event.

In order to handle the event, overload ZCom_ReplicatorAdvanced::onDataReceived().

Replicator events are sent reliable unordered or unreliable.

Attention:
Make sure that onDataReceived() reads the same amount of bits sendEvent() has written, otherwise the stream can't be extracted any further.

Please note that calling sendData() won't ensure the data is sent immediately. The data will be sent as soon as the owning node's priority allows the node to send. If you want to generate data which is sent immediately, wait for the onPreSendData() callback.

void ZCom_ReplicatorAdvanced::sendDataDirect eZCom_SendMode  _mode,
ZCom_ConnID  _dest,
ZCom_BitStream _stream,
zU32  _reference_id = 0
 

Same as sendData(), but with single destination.

Parameters:
_mode eZCom_SendMode. eZCom_ReliableOrdered is not supported in this context.
_dest Connection ID of destination.
_stream The event data.
_reference_id If send mode is eZCom_UnreliableNotify, this id will be given back to the application through onDataLost() or onDataAcked().
In order to handle the event, overload ZCom_ReplicatorAdvanced::onDataReceived().

Replicator events are sent reliable unordered or unreliable.

Attention:
Make sure that onDataReceived() reads the same amount of bits sendEvent() has written, otherwise the stream can't be extracted any further.

Please note that calling sendData() won't ensure the data is sent immediately. The data will be sent as soon as the owning node's priority allows the node to send. If you want to generate data which is sent immediately, wait for the onPreSendData() callback.

virtual void ZCom_ReplicatorAdvanced::onPreSendData ZCom_ConnID  _cid,
eZCom_NodeRole  _remoterole,
zU32 _lastupdate
[pure virtual]
 

Zoidcom is about to transmit data to the given client.

Parameters:
_cid Connection ID of destination connection.
_remoterole Role of remote node that will receive the data.
_lastupdate Time of last sent update to this connection. The replicator implementation is responsible for updating that value when it sends data. This is only available (i.e. non-NULL) if at least one replicator in the node has a mindelay or maxdelay activated, otherwise this parameter is NULL.
Sending data from inside this callback via sendData() or sendDataDirect() will result in immediate transmission of sent data to the client.

Example code for _lastupdate usage:

 if (_lastupdate) {
   // don't update
   if (ZoidCom::getTime() - *_lastupdate < m_setup->getMinDelay())
     return;

   // after update was sent, store the current time
   *_lastupdate = ZoidCom::getTime();
 }

virtual void ZCom_ReplicatorAdvanced::onDataReceived ZCom_ConnID  _cid,
eZCom_NodeRole  _remoterole,
ZCom_BitStream _stream,
bool  _store,
zU32  _estimated_time_sent
[pure virtual]
 

Data has been received from the replicator of a remote node.

Parameters:
_cid Connection ID of source.
_remoterole Role of remote node whose replicator has sent the data.
_stream The data that has been sent.
_store This is false if a node replication interceptor denied to accept the data. This method still has been called because it is necessary to forward the bitstream, otherwise the rest of the data in the packet becomes unusable.
_estimated_time_sent Estimated time in msecs for when the data was originally sent. The time is comparable to the time returned by ZoidCom::getTime().
Attention:
Make sure that this method forwards the bitstream by the exact amount of bytes originally sent by sendData() or sendDataDirect().

The m_node/getNode() might return NULL when the parent node got deleted but data is received after that, so check for getNode() == NULL before calling anything on the node. This is only true for this callback, other callbacks are safe.

virtual void ZCom_ReplicatorAdvanced::onPacketReceived ZCom_ConnID  _cid  )  [pure virtual]
 

The given connection has received a packet.

Parameters:
_cid Connection ID of connection that received a packet.
This will only get called for connections whose node is linked to this replicator's owning node. It is used by ZCom_MovementReplicator to synchronize the extrapolation.

virtual void ZCom_ReplicatorAdvanced::onConnectionAdded ZCom_ConnID  _cid,
eZCom_NodeRole  _remoterole
[pure virtual]
 

A node has become relevant on the specified connection and thus to this replicator, too.

Parameters:
_cid Id of the connection with the node.
_remoterole Role of the remote node.

virtual void ZCom_ReplicatorAdvanced::onConnectionRemoved ZCom_ConnID  _cid,
eZCom_NodeRole  _remoterole
[pure virtual]
 

The node on this connection is no longer relevant.

Parameters:
_cid Id of connection.
_remoterole Role of remote node.

virtual void ZCom_ReplicatorAdvanced::onLocalRoleChanged eZCom_NodeRole  _oldrole,
eZCom_NodeRole  _newrole
[pure virtual]
 

The role of the local node which owns this replicator has changed.

Parameters:
_oldrole Old role of the node.
_newrole New role of the node.

virtual void ZCom_ReplicatorAdvanced::onRemoteRoleChanged ZCom_ConnID  _cid,
eZCom_NodeRole  _oldrole,
eZCom_NodeRole  _newrole
[pure virtual]
 

The role of a node on a remote connection has changed it's role.

Parameters:
_cid Id of connection.
_oldrole Old role of remote node.
_newrole New role of remote node.

void ZCom_ReplicatorAdvanced::setNode ZCom_Node _node  ) 
 

Set the node in which this replicator is registered.

Parameters:
_node The node pointer.
This will get called automatically by ZCom_Node::addReplicator(). There is normally no reason to call this method.

void* ZCom_Replicator::operator new size_t  _size  )  [inherited]
 

Overloaded memory operator ensuring that always Zoidcom's new gets called.

Attention:
Don't overload this unless you are 100% sure what you are doing.

void ZCom_Replicator::operator delete void *  _p  )  [inherited]
 

Overloaded memory operator ensuring that always Zoidcom's delete gets called.

Attention:
Don't overload this unless you are 100% sure what you are doing.

virtual void* ZCom_Replicator::peekData  )  [pure virtual, inherited]
 

Unpack data from the stream, but don't update the local data.

Returns:
void* Pointer to peeked data.
Interceptors need to call this if they want to know what the update contains without really applying that update. The replicator's peekData() implementation should extract the data from the stream and return it as void*. In case peekData() needs memory to store the peeked data (if the data is a string for example), it can be allocated normally with new or malloc. The resulting pointer should be stored by calling peekDataStore() prior to returning it. When peekDataStore() has been used to store the data pointer, Zoidcom will call clearPeekData() on the replicator as soon as the interceptor, which initiated the call to peekData(), returned. Alternatively, it is also possible to just return the pointer to the allocated memory, and make sure that the interceptors free the memory themselves, afterwards.

The bitstream to peek from must be acquired with getPeekStream(). It will be restored to it's previous read position after peekData() has returned.

Attention:
This may only be called from inside ZCom_NodeReplicationInterceptor::inPreUpdateItem().

Implemented in ZCom_Interpolate< T, SIZE >, and ZCom_Replicate_Numeric< T, SIZE >.

virtual void ZCom_Replicator::clearPeekData  )  [pure virtual, inherited]
 

If peekData() has allocated memory, clear it here.

This has to be implemented in order to clear up any memory allocated by peekData(). Use peekDataRetrieve() to acquire the pointer stored by peekDataStore() earlier. It is not necessary to call peekDataStore(NULL) to clear the pointer as Zoidcom will do this automatically.

This method will get called right after ZCom_NodeReplicationInterceptor::inPreUpdateItem() returned but only if peekDataStore() has been used inside the interceptor.

This method will also get called from inside peekDataStore() if it holds a pointer from a previous call to peekDataStore().

ZCom_BitStream* ZCom_Replicator::getPeekStream  )  const [protected, inherited]
 

Get stream currently processed for peeking the data.

Returns:
Pointer to current ZCom_BitStream.
As you might have noticed, peekData() does not have a ZCom_BitStream parameter. That's the case because peekData() must be called from inside ZCom_NodeReplicationInterceptor::inPreUpdateItem(), and this interceptor callback has no access to the currently processed stream. Use this method to get a pointer to the currently processed stream instead.

This will only return a valid result when called from inside the above mentioned interceptor callback.

void ZCom_Replicator::peekDataStore void *  _ptr  )  [protected, inherited]
 

Store pointer to allocated peekbuffer, so it can be deleted again.

Parameters:
_ptr Pointer to the allocated memory.
The pointer will get stored in a global Thread Local Storage, so that multiple ZCom_Controls can safely operate simultaneously in different threads. When a replicator's peekData() makes use of this method, expect to get a call to clearPeekData() sometime soon, which is supposed to free the allocated memory again.

When you call peekDataStore() more than once with a pointer != NULL, clearPeekData() will get called automatically.

Thread Local Storage means, there is one variable for each thread of the program. Replicators could as well declare a member variable used for that purpose instead, but that would waste a lot of memory when peeking interceptors are not used.

void* ZCom_Replicator::peekDataRetrieve  )  [protected, inherited]
 

Retrieve the peekbuffer pointer currently stored.

Returns:
Pointer previously stored with peekDataStore().

virtual void ZCom_Replicator::Process eZCom_NodeRole  _localrole,
zU32  _simulation_time_passed
[pure virtual, inherited]
 

Do any kind of processing.

Parameters:
_localrole States the role of the local node.
_simulation_time_passed Time given to ZCom_Control::ZCom_processReplicators()
This is intended for replicators that need to perform constant processing like interpolators and extrapolators. Called once everytime ZCom_Control::ZCom_processReplicators() is called.

This method will only get called when the replicator has the ZCOM_REPLICATOR_CALLPROCESS flag set.


Member Data Documentation

zU8 ZCom_Replicator::m_flags [protected, inherited]
 

Additional replicator flags. ZCom_Replicator() c'tor will set this to 0. (ZCOM_REPLICATOR_*).

ZCom_ReplicatorSetup* ZCom_Replicator::m_setup [protected, inherited]
 

pointing to an instance of the setup class - all replication parameters are stored here


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:50 2008 for Zoidcom by doxygen 1.4.6-NO