Arbitrary Root Node

From HEWIKI
Jump to: navigation, search

Contents


Overview

When persisted Nodes from the server GOM are saved to the database, they are generally part of some hierarchical organization of nodes. For example, the hierarchy of nodes that make up an Area. Or the hierarchy of nodes that make up a character. The node that forms the first concrete part of a hierarchy is called the "root node". So when that root node loads, all nodes hard-associated with it load too. And nodes hard-associated with those nodes load as well. This is how a node hierarchy loads (and saves).

Many of these "root nodes" are established by the way HeroEngine functions, such as the root node for an Area or for a character. It would be useful, however, to load and save any arbitrary hierarchy of nodes to/from the database. This can be done by establishing an Arbitrary Root Node. In this way, one can save a collection of nodes independent of the Area or Character (or other) fixed root node definitions.

What problem(s) does this solve?

Arbitrary root nodes allow the scripting environment to store and retrieve arbitrary data to and from the GOM database, in the form of persisted node hierarchies. This mechanism of data storage is best suited for:

What problem(s) does this not solve?

Concepts

Example systems that take advantage of this functionality:

Usage

At its core, using arbitrary root nodes is very straight forward. Simply create a persisted node hierarchy that stores your data, and then call the CreateRootNode() external function on topmost parent of the hierarchy. This will transform it into an arbitrary root node and unload it.

By storing the node's ID somewhere convenient, like on an associated character or a persisted node in an area, you can asynchronously retrieve the root node at a later time when its data is needed.

Atomic presence

Like all Nodes (except Prototypes), an Arbitrary Root Node and it's hierarchy of nodes can only be loaded into one Area Instance at a time. Attempting to load a Root Node when it has already been loaded in another area will fail. On the server, each root node's loaded location (which Area Instance it is loaded into, if any) is maintained by a coordinating process.

Further, they must be manually unloaded when they are no longer needed (via UnloadRootNode()).

Reference

External functions

Creating

// Converts an unassociated persistent node into a root node, unloading it in the process.
// Select an existing root node hierarchy as the parent (Area, account, character or another arbitrary root)
external function CreateRootNode( root as NodeRef, parentRootNode as ID, errorReason references String ) as Boolean

CreateRootNode() converts an unassociated persistent node into a root node, unloading it in the process.

Reparenting

// Change the parent of an arbitrary root node to another root hierarchy
external function ReparentRootNode(rootNode as ID, newParentRootNode as ID, errorReason references String) as Boolean

ReparentRootNode() changes the parent for the specified root node to another root.

Loading

As a Persistent Root Node Hierarchy

external function RequestRootNodeLoad(rootID as ID, callbackNode as NodeRef)

RequestRootNodeLoad() asynchronously attempts to load an arbitrary root node and its hard associated hierarchy of persistent nodes. When the operation is complete the appropriate method is called on the specified callback node, depending on whether or not the operation was successful. If the operation is successful, the following is called:

method _RootNodeLoadedNotification( rootID as ID )

otherwise this method is called.

method _RootNodeLoadFailedNotification( rootID as ID, areaID as ID, areaInstance as ID, failureReason as String )

Reasons for failure include:


As a Non-Persistent Root Node Hierarchy Copy

external function RequestNonPersistentRootNodeLoad( rootID as ID, callbackNode as NodeRef )

RequestNonPersistentRootNodeLoad() asynchronously attempts to load an arbitrary root node and its hard associated hierarhcy of persistent nodes. As they are loaded, the nodes are changed to be non-persistent so that no changes will be persisted. If the operation is successful, the following is called:

method _RootNodeLoadedNotification( rootID as ID )

otherwise this method is called.

method _RootNodeLoadFailedNotification( rootID as ID, areaID as ID, areaInstance as ID, failureReason as String )

Reasons for failure include:

It is important to understand that any subsequent changes to the persisted version will not be reflected by any non-persisted copies loaded in other GOMs.

Unloading

external function UnloadRootNode( root as NodeRef, callbackNode as NodeRef )

UnloadRootNode() asynchronously attempts to unload an arbitrary root node and its hard associated hierarchy of persistent nodes. When the operation is complete, the following method is called on the specified callback node:

method _RootNodeUnloadedNotification( rootID as ID )

Root nodes that are loaded in area-instances that spin down are automatically unloaded, making them available to be loaded elsewhere.

Checking and finding

external function IsRootNodeLoaded( rootID as ID ) as Boolean

IsRootNodeLoaded() returns true if the specified root node is loaded in current area-instance, false otherwise.

external function WhereIsRootNodeLoadedInWorld( rootID as ID, area as ID, instance as ID ) as Boolean

WhereIsRootNodeLoadedInWorld() returns true if the specified root node is loaded somewhere in the world, false otherwise. When returning true, AREA and INSTANCE will be populated with that area and instance IDs where the root node is loaded. This function can only be called from the world server without throwing a script error.

Querying

external function QueryLoadedRootNodes() as List of ID

QueryLoadedRootNodes() returns a list of arbitrary root node IDs loaded in the current area-instance.

external function QueryLoadedRootNodesInWorld() as LookupList indexed by ID of Class instancekey

QueryLoadedRootNodesInWorld() returns a mapping of arbitrary root node IDs to the area-instance where they are currently loaded. This function can only be called from the world server without throwing a script error.

// Finds the parent of an arbitrary root node, those without parents will have None as the parent ID
// calls back to method _GotRootNodeParent(requestID as ID, parentRootNodeID as ID, parentBaseClass as String)
// or on error to method _RootNodeQueryFailure(requestID as ID, failureReason as String)
external function QueryRootNodeParent(rootNode as ID, requestID as ID, callbackNode as NodeRef)

QueryRootNodeParent() asynchronously query the database for the parent root of the specified root

// Finds the children of an arbitrary root node, set the fields of the query filter to restrict the search
//   queryFilter._className - name of the class to restrict results to
//   queryFilter._useIsExactly - test the class of the child root node to match exactly, default is a is kindof match
//   queryFilter._checkGlommedClasses - match the class against any classes glommed on the root node
// calls back to method _GotRootNodeChildren(requestID as ID, children as LookupList indexed by ID of String)
//   the children parameter will contain all matching children and their base classes
// or on error to method _RootNodeQueryFailure(requestID as ID, failureReason as String)
external function QueryRootNodeChildren(rootNode as ID, requestID as ID, callbackNode as NodeRef, queryFilter as Class _nodeQueryFilter)

QueryRootNodeChildren() asynchronously retrieve a list of children root node IDs for a parent based on the filters specified.

Destroying

external function DestroyRootNode( root as NodeRef )

DestroyRootNode() destroys an arbitrary root node and its hierarchy of children nodes. The specified node must be an arbitrary root node, or DestroyRootNode() will throw a script error. There is one exception to the use of this function to destroy root nodes and that is character root nodes that have been named must be deleted using DeleteCharacter().

Personal tools
Namespaces
Variants
Actions
Navigation
Toolbox