- This page covers the more technical aspects of an Area Server process. For more design-oriented information on how Areas are structured, see Area architecture, and to get hands-on in creating an area, see the Building Areas Tutorial.
Area Servers are one of the core building blocks of the infrastructure of HeroEngine. When a player or GameMaster logs into the game, information from their client software is passed via various other server processes (Dude Server, World Server), to the Area Server process that is appropriate for whichever area of the game that they are currently located in.
This page documents the various parts of an Area Server process (often called simply an "Area Server").
For example, in the world, there might be a forest, a castle, and a town. Each of these might be on a separate Area Server. Or, the forest might be large enough that it would require 3 Area Servers. Players in the game may notice as they pass from one Area Server to another (a "loading" screen could pop up), so this should be kept in mind when designing new areas. See also Seamless world.
There can be multiple instances of a particular area running at any one time, but each instance will be handled by a separate Area Server process. For example, if there is a mission that places players in their own private dungeon, a separate Area Server might be used for each group, and each instance of the dungeons will be a duplicate of the master dungeon area.
When modifying an area, a special "edit instance" is created of that area. Only one edit instance of an area can be in existence at one time. Any instance that is not an edit instance, is called a play instance.
The Organizer Panel
- Main page: Organizer Panel#Areas
When traveling to the instance of an area, your character will either be connected to the existing process, or if necessary, a new process will be "spun up".
The Edit Instance of an area is always instance #0, whereas Play Instance numbers are always dynamically assigned, and therefore not predictable.
From the Organizer Panel, you can also use a right-click menu. From here, you can start an instance without going to it via the Startup Instance option. Additionally you can also stop a running instance with the Shutdown Instance option.
Area server place in the infrastructure
Within the engine infrastructure of HeroEngine, an Area Server is a dynamic process which runs an Area (or part of an area). Area Server processes, created via the definitions of the Area Server Daemon, are started and stopped by the World Server process and run on any one of the machines in the Server Group, depending on load.
Area Servers are spun up (started) whenever a character enters an instance of that area, or a request is placed via the Organizer Panel. If an area is left vacant, it automatically spins down (shuts down), and it can also be shut down via the Organizer Panel. The default configuration in HeroEngine is to check once each minute to see if an area is occupied or not. If it stays unoccupied for three consecutive minutes, the Area is shut down. However, there are different ways to modify this behavior.
To keep an Area Server from stopping even if it is vacant, use the external function KeepAreaUp(). For example, Hero's Journey uses this for system areas that must stay up for our game implementation to function. Depending on the hardware you run in your own development, you may need to be judicious in your use of this command. If you specify hundreds of areas that must be up, HeroEngine will ensure those areas are always up. This may result in difficulty spinning up the world due to timeouts and may affect performance, by consuming processing power and RAM.
There is a special system to avoid the problem of "too many areas" running, and you can modify different areas to shut down at different rates. For more information, see the $HEROENGINEAREASPINDOWN system node.
Terrain surface area has no direct relationship to server load, consequently 4km or 50km does not matter per se from the perspective of the server. (Technically, the physics server does have to be able to load the collision representation of the area. Additionally, the pathmaker has to be able to generate a nav mesh the density of which is entirely under your control based on the parameters it is fed.) Area size is more commonly limited based on client or game design constraints and we generally find that people use areas that are smaller than 1 kilometer on a side with the ideal likely being in the range of 200-500 meters on a side.
- Recommended Area Size: less than one kilometer on a side
- Recommended Seamless Area Size: 200-500 meters on a side
The primary considerations from a server's perspective limiting area size are:
- CPU (primarily load from game logic) - for example, a player housing area in an MMO has generally a very minimal or nonexistent load associated with players in the area (though there are game designs that might have a high load in the same situation). Consequently, you can service a significantly larger number of players in such an area (thousands to tens of thousands).
- Bandwidth (replication traffic) - how much data do you send on average to players in the area, limited here based on your network infrastructure
- RAM - How much memory is necessary per character plus overhead (memory for area data, buffers for replication traffic etc)
All of these factors are under your control through game design, architectural decisions you make, and the quality of game logic you write. If you write systems as services when possible (utilizing system areas), that parallization of processing allows you greater flexibility in the game logic you can execute per user. Likewise refactoring/optimizing code after profiling to identify slow routines will also increase the number of users that can be serviced by a physical server.
The considerations from a client perspective limiting area size (beyond CPU/RAM) are:
- Load Time - Smaller areas load more quickly, whether the load is triggered by area transition with a loading screen or done seamlessly via Seamless World techonologies. Factors that contribute to the load time include: commonality between areas in texture/asset usage, whether or not the local repository cache has downloaded the assets already, size of the edit queue, the initial volume of data replicated.
What if my game needs larger areas?
Thats fine, but lets talk about how you do them the right way...
Lets start by defining the terms we are using:
- Gameplay Area - Designers tend to think of "areas" in terms of the geography in which the game is played. Often the expectation is that the area appears to be contiguous such that no loading screens appear while traversing it. From the perspective of the designer, they want areas that go to infinity so that the customer feels that the play area is enormous. Note that the designer definition of area is one of perception rather than an actual requirement for "area size" in pure measurements of area (meter ^ 2). Some games call gameplay areas "Zones".
- (HeroEngine) Area - From HeroEngine's perspective, an area is an arbitrary collection of geometry representing a volume of space and which runs in a single process in the server cluster. That process is what we call an "area server (process)". A gameplay area can and should generally be composed of multiple (heroengine) areas with the perception issues addressed through the use of HeroEngine's Seamless World technology. The client application loads 1...N areas for the purposes of rendering them.
Assume our designers call for 3 kilometer by 3 kilometer (9 square kilometers) gameplay area, this is larger than recommended by close to two orders of magnitude. We know that there would be issues rendering or potentially even loading that much data into memory not to mention difficulty generating or even loading a navmesh for such a huge space. Instead of making a single (HeroEngine) area that is three kilometers on a side, we can (and should) break it up into a bunch of smaller areas that are all connected together seamlessly to provide the illusion of one huge (gameplay) area.
Area Server components
Each Area Server is like a microcosm of the HeroEngine, and is comprised of the following parts:
- DOM (Data Object Model) definitions
- The GOM (Game Object Model), containing the actual nodes based on the definitions. The GOM also contains the Node Hierarchy and Ghost Classes
- Javelin System, system for communicating with the database
- AI - This controls the NPCs that are moving around
- Hero Machine - One of the larger sections of the Area Server, this is where scripts are run
- Collision Geometry System - This is handled by multiple servers. The system keeps track of who and what is where, and whether anything is running into anything else.
- FireStorm - This is the communications layer that allows the different parts of the Area Server to talk to each other
Related System Nodes
These System nodes have functionality that are useful in managing areas:
These are server-side exposed functions used by the HeroScript scripting language.
Get Area Number
function GetAreaNumber() as id
Returns the area number of the current area. Called at the world level, it returns 0.
Get Instance Number
function GetInstanceNumber() as id
Returns the instance number of the current area. If called at the world level, returns 0.
Launch Area Server
function LaunchAreaServer(areaNumber as id, areaInstance as id) as boolean
At the world server level, spins up a new, non-edit instance of the specified areaID, populating the areaInstance with that instance's ID.
Launch Edit Server
external function LaunchEditServer(areaID as ID) as Boolean
Starts the edit instance of the given area. This function only works when called by script in the world server. It returns false if called in an area server or if the area id does not correspond to an area. It returns true if the area is already running or the launch process has started.
Shut Down Area Server
function ShutdownAreaServer(areaNumber as id, areaInstance as id) as boolean
Works only at the world server level. Immediately fails if the area isn't spun up.
Get lists of Area connections
function AreaConnections(areaNumber references list of id, areaInstance references list of id)
Generates information on every single instance that's currently in the game. Fills out the lists with pairs of areaNumber and areaInstance for all the connected (spun up) areas. Only works at the world server level.
Get lists of attempted Area Connections
function AreaAttemptedConnections(areaNumber references list of id, areaInstance references list of id)
Fills out the lists with pairs of areaNumber and areaInstance for all the areas that are currently starting up. Only works at the world server level.
FullAreaList - Get list of all valid areas
function FullAreaList(areaList references list of id)
Fills out the list with all the valid area numbers. Only works at the world server level. For more details, see FullAreaList.
Get List of Instances for an Area
function AreaInstanceList(area as id, instances as list of id)
Builds a list of all the instances that are currently running in the specified area. An instance with an ID of 0 is an Edit Instance.
Get Area Attempted Instance List
external function AreaAttemptedInstanceList(areaID as ID, instanceList references List of ID)
Populates a list with a list of IDs of all the instances that are in the process of spinning up. Instances that are already running are not included in this list (for those, use AreaInstanceList). An instance with an ID of 0 is an Edit Instance. Note: If a script checks for current instances, and then for attempted instances, that will generate a full list of all appropriate instances. It won't be possible for an instance to get "lost" (like being attempted while the current list is being checked, but current while the attempted list is being checked) because the rest of the server halts execution while running a script.
Look Up Area Number
function LookupAreaNumber(areaName as String) as ID
World server exposed function. Given the name of an area, returns the ID. The name specified must be the one that appears in the Organizer panel, not the FQN.
Main Page :Lookup_Area_Number
Get Area Name
external function GetAreaName(areaNumber as ID) as String
World server exposed function. This is the name that appears in the Organizer Panel and is human-readable, which may not be the same as the name that the Area was given on creation. For example:
Michael's Area. Note: If called at the area level, this function will return the name of the current Area.
Get Area FQN
external function GetAreaFQN(areaNumber as ID) as String
Otherwise returns the name of the area of the specified ID. Note that the name returned is the name that an area was created under, and is always unique. For example:
/world/segment/DemoLand/test_area/MichaelsArea/area.dat. Note: If called at the area level, this function will return the FQN (Fully Qualified Name) of the current area.
Keep Area Up
- Main page: KeepAreaUp
KeepAreaUp(areaNumber as ID, areaInstance as ID) as boolean
Called only at world server level. Instructs the server to start the specified area, and if the area crashes, to immediately restart it. Used for vital areas that must stay running, such as system areas.
Crash If You Can Please
external function CrashIfYouCanPlease(arg as boolean)
This function might not be defined in the Clean Engine external functions script. If it is not, it can be defined in the game specific script if needed.
Calling this function will cause the server it is called on to crash. If the argument is set to true, the server will crash with an access violation. If set to false, the server crashes with an unhandled C++ exception. This function primarily exists to test the automatic bug reporting facilities of the servers.
For information on Area and World Root Nodes, please see the section on Associations.