|This feature is a part of HeroEngine release 1.19.|
System Node $HEROENGINEAREASPINDOWN implements the MMO Foundation Framework's area spindown mechanics.
The logic for determining when area spin down should occur in HeroEngine was designed to be in the hands of the HSL developers (scripters). Initially, no system was included in Clean Engine to handle these kinds of Area Server mechanics, because it was one of those systems that each game is likely to handle in totally different ways.
However, when we reviewed how our licensees were using the engine in the first weeks, we found that none of their teams really wanted to be concerned with this kind of low level mechanic. Consequently, areas were just left running, and their machine would run out of physical resources as they spun more and more areas up without ever shutting one down. So the $HEROENGINEAREASPINDOWN system node was tasked with implementing spindown mechanics. The default behavior is for areas to spin down after 20 minutes of being unoccupied, but this length of time is easily changed (see below).
What problem(s) does this solve?
- Known pattern for extension of the system (a system node)
- Common game-specific functionality is easily implemented by overriding the appropriate method
- Reduces, but does not eliminate, the need to implement game-specific code
What problem(s) does this not solve?
- Does not eliminate the necessity for additional code to support alternate behaviors
Area Spin Down is handled by HSL systems
The HeroEngine C++ server processes for areas do not have their own built-in behavior for shutting down an area process when not "in-use", because it is difficult for us to generically and arbitrarily determine what "in-use" means. Rather than limiting your game design, we opted to place the control of these processes under HSL systems to provide flexibility to your developers.
Why is spinning down areas important?
Each running area is a process running on a physical machine, taking up RAM and processing which may, depending on your game implementation, take up significant amounts of resources even when no one is "using" the area. Consequently, the implementation of some kind of spin down mechanic for areas is important to manage your game's resources.
What is the spin down mechanic?
During the area spin up process, the AreaSpinDown system is notified and it factories an _areaSpinDownHandler from a spec specified by the area or using the default spec for your game. The handler is then in charge of the actual mechanics of deciding when and how the area should spin down.
By default, areas that are not registered with the engine as KeepAreaUp areas, will be spun down using the default spec for your game or the HeroEngine default spec (#1) if you have not specified a different one.
The default behavior (Spec #1) is to spin down the area after a period of twenty minutes passes with no players in the area. This is done via four separate checks, five minutes apart. If there are still no players after the fourth check, the spindown is initiated.
Spindown behaviors are defined by specs
The Area Spindown System uses the Spec System to define spindown behaviors. When an area spins up, the system checks the Area Root Node to determine the spec that is to be used to factory an Area Spindown Handler. Using specs allows for easy expansion of the system to other game-specific behaviors as needed by your game's developers.
- _AreaSpindownSpecClassMethods (this instantiates an _AreaSpindownHandler which is controlled by the _AreaSpindownHandlerClassMethods script)
There are multiple ways to modify the spindown of your game's areas.
Adding game-specific functionality
As a required class/script, it is not permissible to make changes to the _heroengineAreaSpinDownClassMethods script. Instead, extension/overriding the script is accomplished by the creation of a game-specific class (and class methods script) that is GLOMmed onto the HEROENGINEAREASPINDOWN prototype.
- Create a new class
- Create a class method script for the class
- GLOM the class onto the prototype
Create a game-specific class
Using the DOM Editor create a new (server|client) class. Our recommendation is that you use a class name that incorporates the _heroengineAreaSpinDown as a suffix to the name (ex. HJ_heroengineAreaSpinDown), this makes it easier to locate the pair of classes (the required script prefixed in _heroengineAreaSpinDown and your game-specific class).
Once you have created the game-specific class, create a new client class methods script for that class.
Adding a game-specific class
Adding your game-specific class to the HEROENGINEAREASPINDOWN prototype is achieved using the System Node Configuration GUI or the CLI server command \mpac or client |mpac in the Console Panel. The System Node Configuration GUI is the preferred method because it handles the communication to update any instantiations of a system node to reflect the changes you have made.
Using the System Node Configuration GUI
Opening the System Node Configuration GUI requires you to access the hidden Utilities Interface toolbox, located in the top left corner of the render window with
ctrl-shift-click (or press
F5), which will open the Interface. On the Tools tab within the menu, is an option to open the System Nodes Configuration GUI.
See also: Adapting Clean Engine
Using the CLI
It is important to recognize that modification of the prototype from which a system node is instantiated will not update any instantiations that have already been made in various local GOMs. That means your changes will not take effect until the area (in the case of server system nodes) restarts, or the client (in the case of client system nodes), restarts.
\mpac HEROENGINEAREASPINDOWN, hj_heroengineAreaSpinDown;
|mpac HEROENGINEAREASPINDOWN, hj_heroengineAreaSpinDown;
Disable the HeroEngineAreaSpinDown System
If you already have a mechanism managing the spindown of areas, or you do not wish to have areas spun down automatically, you can disable the system by implementing the following method in your game-specific override class.
method HE_HeroEngineAreaSpinDownEnabled( enabled references Boolean ) as Boolean // Used by the $HEROENGINEAREASPINDOWN system node // // Determines whether or not the the default area spindown system should be used // // To disable the system as a whole, set enabled to false and return handled as true // enabled = false return true .
Specify a SpinDown Spec for an area
The command /HESPINDOWN may be used in the edit instance of an area to set the spindown spec to be used for the area.
/HESPINDOWN SET <specKey>
Optionally, if you wish to set the spec for an area from script:
$HEROENGINEAREASPINDOWN._setAreaSpinDownSpecKey( specKey )
The next time an instance of the area spins up, it will use the specified spec to generate the area spindown handler for the instance.
Specify a game-specific default spec
The Area SpinDown System uses a default spec for the spin down behavior if none has been specified. By default, spec #1 is used; however you may implement a game-specific override in a class you have added to the system node to specify an alternate default spec.
// Implemented in your game specific class for the $HEROENGINEAREASPINDOWN System node method HE_getAreaSpinDownDefaultSpec( spec references NodeRef of Class _AreaSpinDownSpec ) as Boolean // Used by the $HEROENGINEAREASPINDOWN system node // // Expects the spec be set to a valid _areaSpinDownSpec that should be used by default to handle // area spindown for areas in your game. // return false .
Add new base spec class for the AreaSpinDownSpecOracle
Base spec classes are used to specify the classes from which a spec prototype may be instantiated. Adding your own game-specific classes to the list is accomplished by implementing the following method in your game-specific override class.
method HE_AreaSpindownSpecOracleGetValidBaseClasses( validClasses references List of String ) as Boolean // Used by the $HEROENGINEAREASPINDOWN system node // to extend the classes the _AreaSpinDownSpecOracle uses as base classes // // add your classes to the list passed in by reference and mark handled as true if you do not want // the Clean Engine classes to be added to the list. add back <yourClass> to validClasses return false .
Add new Decorator Class for the AreaSpinDownSpecOracle
Adding your own game-specific decorator classes to the list of valid decorators for the AreaSpinDownSpecOracle is done by implementing the following method in your game specific override class.
method HE_AreaSpindownSpecOracleGetSpecDecoratorClasses( validClasses references List of String ) as Boolean // Used by the $HEROENGINEAREASPINDOWN system node // to extend the classes the _AreaSpinDownSpecOracle uses as decorator classes // // add your classes to the list passed in by reference and mark handled as true if you do not want // the Clean Engine classes to be added to the list. add back <yourDecoratorClass> to validClasses return false .
Create a new SpinDown behavior with a new Decorator
Assuming your spec was instantiated using the MMO Foundation Framework class _areaSpinDownSpec, a new decorator is as simple as:
- Create a new Class using the DOM Editor (server and client)
- Add any supporting fields (server and client)
- Create a class that the decorator will GLOM onto an _areaSpinDownHandler
- Add Decorator in HE_AreaSpindownSpecOracleGetSpecDecoratorClasses as detailed above
- Implement the shared function OnInstantiationFromSpec( derivedObject as NodeRef ), in which you GLOM a supporting class onto the handler instance
- Implement the
// This example is taken from the _AreaSpindownTimerDecorator shared function OnInstantiationFromSpec( derivedObject as NodeRef ) // Shared function called in each decorator class when an object is instantiated // do any initialization/setup required by the decorator class where me is kindof _AreaSpinDownTimerDecorator glomClass( "_areaSpinDownTimerData", derivedObject ) . .
When a handler is instantiated, it performs a callback to a shared function in all of the class method scripts of the node in the shared function HE_OnInstantiationOfAreaSpinDownHandler. It is in this callback that you can start timers, or otherwise initialize your behavior.
// From the _areaSpinDownTimerData shared function HE_OnInstantiationOfAreaSpinDownHandler( n as NodeRef ) // Shared function is called in the class methods scripts for the classes that make up a spindown handler // initialization that you choose not to do during instantiation from the spec could happen here. where n is kindof _areaSpinDownTimerData spec as NodeRef of Class _areaSpinDownTimerDecorator = me.getMySpec() if n._areaSpinDownTimer.timerState = OFF if spec._areaSpindownCheckInterval > 0:00:00.00 n._areaSpinDownTimer.fireRate = spec._areaSpindownCheckInterval else // sanity default of one minute n._areaSpinDownTimer.fireRate = 0:01:00.00 . n._areaSpinDownTimer.start() . . .
The default spindown method, is for an area to automatically shut down if it has no occupants after 20 consecutive minutes.
A quick and painless way to change this, is to simply use the existing system to create a spec, that does basically nothing.
- Using the AreaSpindownSpecOracle, create a new spec and name it something like No Spin Down
- Open the Utilities Interface (Ctrl-Shift-Left click in the upper lefthand corner of HeroBlade Viewport)
- Click on the "Tools" tab
- Under "Spec Oracles", select "Area Spin Down"
- In the Spec Oracle Editor, click on Add
- In the displayName field, enter No Spin Down
- Click "Save" (no other field data is necessary, since it's an empty spec)
- Note the SpecNumber of the new spec that you just created.
- Go to the edit instance of an area whose spindown behavior you want to change.
- In the Chat Panel, use the /HESPINDOWN command. Type /hespindown set <specKey> to change the spindown behavior of an area you do not want to spindown using the normal mechanics.
- It should reply with "The current area will now use the area spindown spec(#) for any new instances spun up."
Note: Ultimately, simply not spinning down may not be the right thing to do. This depends on how you implement "common areas". For example, you may need to spin down extra ones based on some player population load balancing heuristic, so you might want to implement a spec that knows how to do that.
- Adapting Clean Engine - Detailing the replacement/extension of Clean Engine via game specific classes and the GUI created for that purpose.
- System Nodes - Primary mechanism for enabling the extension/overriding of the required Clean Engine implementations and a game-specific implementation of a licensee.