Replication Script Interface
HeroScript controls and responds to Replication through GOM Nodes. To do this, one creates a GOM Node of class
_replicationGroup for each replication group from HeroScript. This special node has fields to define what is replicated as well as methods to handle events. Replicated nodes receive events related to field updates, node structure changes, and group changes.
Essentially each Replication Group contains a list of Nodes that need to be replicated on some other GOM and a list of other GOMs (usually Clients but can be other Area Servers too) that are the target of the replication.
Therefore, to create a new replication group:
rg as NodeRef of Class _ReplicationGroup = createNodeFromClass("_replicationGroup")
Various external functions and fields on the Replication Group Node control replication. Adding clients and nodes to the group make them available for replication, though which classes and fields are replicated and at what priority is specified in the DOM (see Replication Priority).
Replication Group Fields
|Field name||Field type||Description|
|_replicationPrimaryNode||NodeRef||An optional node to include in the nodes replicated for this group which will receive group level script callbacks.|
|_replicationNodesAndReverseClient||LookupList indexed by ID of ID||The keys are the nodes that are replicated for this group (in addition to the primary). The values, when not NONE, designated which client (account node) is the source of reverse replication.|
|_replicationSpatialAwareness||NodeRef||The Spatial Awareness System to be used for determining distances between this group and its clients|
|_replicationSpatialEntity||ID||Identification of the entity representing this group's position in the Spatial Awareness System.|
|_replicationClientDestinations||List of class _ClientAndSpatialEntity||Identification of the clients to receive this group's replicated nodes.|
|_replicationServerDestinations||List of class instancekey||Identification of the servers to receive this group's replicated nodes.|
There are a few external functions for replication.
// This is meant to be called once on application startup. When a node is replicated but the // initial class doesn't have replication defined, the replica is instantiated using this prototype. external function SetDefaultPrototypeForReplication( name as String) // Each element gives the area, instance, and group node ID that is replicating the parameter node. external function GetReplicationOrigins(replica as NodeRef) as list of String external function QueryReplicationGroups() as List of NodeRef external function RestartReplicationGroups( groups as List of NodeRef) external function SetPlayerBandwidthSettings(playerAccount as ID, bandwidthLimit as Integer, maxBurst as Integer) // The callbackNode must implement: // method _PlayerBandwidthSettings(player as ID, bandwidthLimit as Integer, maxBurst as Integer) external function GetPlayerBandwidthSettings(playerAccount as ID, callbackNode as NodeRef)
// This is for replicating a single node to a single client without any distance prioritization. function replicateNode( n as NodeRef, clientAccount as ID) rg as NodeRef of Class _ReplicationGroup = createNodeFromClass("_replicationGroup") rg._replicationPrimaryNode = n rg._AddClientDestination(clientAccount, None) .
// This is for replicating a single node to a single client with potential distance prioritization. function replicateNode( n as NodeRef, spatialSystem as NodeRef, groupEntity as ID, clientAccount as ID, clientEntity as ID) rg as NodeRef of Class _ReplicationGroup = createNodeFromClass("_replicationGroup") rg._replicationSpatialAwareness = spatialSystem rg._replicationSpatialEntity = groupEntity rg._replicationPrimaryNode = n rg._AddClientDestination(clientAccount, clientEntity) .
// To add a client to receive a group of replicated nodes. // Does not add account if already in. // account - id of the client whom you wish to receive replication traffic // spatialEntity - id of the spatial entity that should be used for distance calculations by the Dude Server during // distance attenuation by bandwidth shaping rg._AddClientDestination(account as ID, spatialEntity as ID)
// To add additional nodes to be replicated as part of a group. // Does not add node if already in. rg._ReplicateNode( the_node as NodeRef )
// To enable reverse replication (client to server) for a node. // Does not add node if already in. // node_id - ID of the node to reverse replicate // client_id - ID of the client to which control of the reverse replication should be // assigned. Note, this assumes you have a reference to that client // either by virtue of them being connected to the current area or // via a player reference token. // Returns: Whether or not control was successfully assigned, returns false if the node // is already assigned to another client or not replicated by this group. rg._SetReverseReplicationForNode( node_id as ID, client_id as ID ) as Boolean
Restarting to pick up definition changes
Field and class definition information is used as things are added to replication groups. During development, it is common to make changes to the definitions and want to see the results. The following HSL will tear down and rebuild each replication group:
function restartAreaReplication() RestartReplicationGroups( QueryReplicationGroups()) .
Replication Received Events
method _OnReplicationNodeAdded( n as NodeRef)
|Called on primary node. The primary node itself (n == me) is the first callback when the group is first introduced. Initial field data is present when this is called.|
|Called on primary node after all initial nodes have been added.|
shared function _OnReplicationFieldUpdated( n as NodeRef, fieldName as String)
|Called on ClassMethods scripts for classes (OR the first ancestor class that implements it) on the node that contain the field. Only called when the source field definition has Change Callback set to true. These callbacks happen for value changes after _OnReplicationNodeAdded (i.e. they are not called for Initial Set updates) is called and will happen no more than 1 time per class that makes up the node (i.e. the base class and each GLOMmed class assuming they or one of their ancestors implements the function).|
shared function _OnReplicationClassAdded( n as NodeRef)
|Called on ClassMethods script for the class or ancestors if the class does not have this function. These callbacks happen for class additions after _OnReplicationNodeAdded is called.|
shared function _OnReplicationClassRemove( n as NodeRef)
|Called on ClassMethods script for the class or ancestors if the class does not have this function. Only called when the class is being removed but the node is still replicated.|
method _OnReplicationReverseBegin( n as NodeRef)
|Called on node commencing replication of reverse fields from the client to the server.|
method _OnReplicationReverseEnd( n as NodeRef)
|Called on node ending reverse replication.|
method _OnReplicationNodeRelease(n as NodeRef) as Boolean
|Called on primary node when the parameter node is no longer part of replication. Return false to prevention node destruction.|
method _OnReplicationGroupRehomed(oldArea as ID, ...)
|When a client changes areas seamlessly, this is called on each replication group's primary node on that client.|
Replication Error Events
// many potentially come back from multiple destinations // The destination class specified by the sourceClassName did not exist in the destination DOM method _replicationServerDestinationClassNotFound(nodeID as ID, sourceClassName as String, area as ID, instance as ID) method _replicationClientDestinationClassNotFound(nodeID as ID, sourceClassName as String, account as ID) // A class failed to glom onto the remote node (due to method conflicts, class does not exist in the destination DOM etc) method _replicationServerDestinationGlomFailed(nodeID as ID, sourceClassName as String, area as ID, instance as ID) method _replicationClientDestinationGlomFailed(nodeID as ID, sourceClassName as String, account as ID) // A field was not found on the remote node (either it was mapped incorrectly, it wasn't in the mapped class, or a class was removed from the node). method _replicationServerDestinationFieldNotFound(nodeID as ID, sourceFieldName as String, area as ID, instance as ID) method _replicationClientDestinationFieldNotFound(nodeID as ID, sourceFieldName as String, account as ID) // A field update failed on the remote node (typically this is due to tampering of the replica). method _replicationServerDestinationFieldDataProblem(nodeID as ID, sourceFieldName as String, area as ID, instance as ID) method _replicationClientDestinationFieldDataProblem(nodeID as ID, sourceFieldName as String, account as ID) // An error occured trying to create the remote node. method _replicationServerDestinationNodeCreateFailed(nodeID as ID, area as ID, instance as ID) method _replicationClientDestinationNodeCreateFailed(nodeID as ID, account as ID) println("_replicationClientDestinationNodeCreateFailed node="+nodeID+" account="+account) // The remote node created by this replication was not found. method _replicationServerDestinationNodeLost(nodeID as ID, area as ID, instance as ID) method _replicationClientDestinationNodeLost(nodeID as ID, account as ID) // Replication traffic sent to the server specified by AreaNumber and InstanceNUmber parameters but was returned undeliverable. method _replicationServerCommunicationFailed(areaNumber as ID, instanceNumber as ID) // A client is no longer connected. method _replicationClientNotConnected(account as ID) // Replication Group contained client destination entry in the _replicationClientDestination list with an invalid _ClientReference. method _replicationClientAccountNotFound( listIndex as Integer ) // The _replicationClientDestination entry at the specified index was not found in the Spatial Awareness System specified by _replicationSpatialAwareness. method _replicationClientEntityNotFound( listIndex as Integer ) // A node ID replicated by this replicated group no longer exists in the local GOM. method _replicationNodeNotFound(nodeID as ID) // The client specified as being in control of a reverse replicated node has disappeared (disconnected possibly) without removing them as the controller // of the replicated node in the lookuplist. method _replicationReverseClientNotFound( nodeID as ID, account as ID ) // The Spatial Awareness System for the Replication Group as specified by the field // _replicationSpatialAwareness node has gone away. method _replicationSpatialAwarenessNotFound() // The Entity specified by the field _replicationSpatialEntity for use by Replication in determining Distances // is no longer part of the Spatial Awareness System specified by the field _replicationSpatialAwareness. method _replicationSpatialEntityNotFound()