World Manager

From Multiverse

Jump to: navigation, search

Contents

Overview

The world manager controls general world properties and overal world management. In addition to scripts and files it reads for messaging configuration, it reads the following scripts:

Configuration

The following statements set the size and geometry of the world:

worldGeo = Geometry.maxGeometry()
World.setGeometry(worldGeo)

localGeo = Geometry.maxGeometry()
World.setLocalGeometry(localGeo)

The following statements set scaling parameters. For more information, see Server scaling and performance tuning:

  • Scheduled threadpool size: Number of threads available for running scheduled operations.
  • World fixed perceiver radius (in millimeters)
  • Location tolerance in millimeters. The server resets client location to that location if the distance is less than this.
Engine.ExecutorThreadPoolSize = 10;
World.perceiverRadius = 100000;
World.setLocTolerance(20000);

Setting Perceiver Radius

Mob perceiver radius
Enlarge
Mob perceiver radius

Every mob and PC has a square perceiver radius around it that determines which objects it can perceive, as illustrated in the figure to the left for a mob. The dotted line represents the object's perceiver radius. The mob perceives all objects in quadtree nodes that overlap its perceiver radius. Thus, in the figure, the mob can perceive objects in all the shaded nodes because its perceiver radius overlaps with them.

As a PC, when you move around in a world, you will notice that objects "pop into view" when they come within your perceiver radius.

For more information on how the server quadtree works, see The Quadtree.


Setting default perceiver radius

To set perceiver radius for all PCs and mobs in a world, use the following Python code in your worldname/extensions_wmgr.py file:

World.perceiverRadius = radiusInMM;

The default value is 100000 (100 m).

You can also set perceiver radius in other scripts, for example, you can set the value in a character creation script to set a character-specific value, as described in the next section.

Setting perceiver radius for a character

To set the perceiver radius for a player character, add code such as the following to mv-home/config/world/character_factory.py:

override.put( WorldManagerClient.NAMESPACE, 
            WorldManagerClient.TEMPL_PERCEPTION_RADIUS, 
            Integer(5000) ) 

where override is an object of type multiverse.server.objects.Template that represents the override template for character creation.

Extent-based perceivers

Extent-based perceivers permit PCs to perceive a static object even though it is farther away than the standard perceiver radius. This is useful, for example, for large or prominent buildings or objects that should be visible much farther away than other buildings.

To set an extent-based perceiver radius for an object, in World Editor add a name/value property called "perceptionRadius". Set the value of the property to an integer specifying the number of millimeters away that the object should be perceived. For example, if you want a building to be perceived at all distances up to 1000 meters, add the name/value pair (perceptionRadius , 1000000). The effect of this is that all quadtree nodes within that distance will perceive the building.

If you don't specify the name/value property, the default value of perceptionRadius is zero, which means that the standard algorithm applies.

Object generation

This section describes how the World Editor creates an object and associates it with the correct world manager plugin. You can use the same techniques to generate objects in your own code.

The InstancePlugin reads in files (.mvw and .mwc files) created by the World Editor. When it sees a static object in the world file, it gathers all the associated data about it and puts it into a dynamic template. It then calls ObjectManagerClient.generateObject() to create the object. The generateObject() method takes in two templates: the "base" template and an "override" template. The base template is stored in the object manager and identified by name. The override template is built dynamically and sent with the generate object message. The object manager merges the two templates together, giving precedence to the override template where there are conflicts. The call to generateObject() below uses base template ObjectManagerClient.BASE_TEMPLATE. This is an empty template that is convenient to use when creating fully dynamic objects. This way, the overrideTemplate is the full template.

The World Editor can't assume the existence of any registered base templates, so must place all properties in the override template. Registered base templates are recommended for all other situations.

Template overrideTemplate = new Template();
overrideTemplate.put(WorldManagerClient.NAMESPACE, 
                     WorldManagerClient.TEMPL_NAME, 
                     name);
overrideTemplate.put(WorldManagerClient.NAMESPACE, 
                     WorldManagerClient.TEMPL_OBJECT_TYPE, 
                     "STRUCTURE");
overrideTemplate.put(WorldManagerClient.NAMESPACE, 
                     WorldManagerClient.TEMPL_DISPLAY_CONTEXT, 
                     dc);
overrideTemplate.put(WorldManagerClient.NAMESPACE, 
                     WorldManagerClient.TEMPL_LOC, 
                     loc);
overrideTemplate.put(WorldManagerClient.NAMESPACE, 
                     WorldManagerClient.TEMPL_ORIENT, 
                     orient);
overrideTemplate.put(WorldManagerClient.NAMESPACE, 
                     WorldManagerClient.TEMPL_SCALE, 
                     scale);
overrideTemplate.put(WorldManagerClient.NAMESPACE, 
                     WorldManagerClient.TEMPL_PERCEPTION_RADIUS, 
                     perceptionRadius);
overrideTemplate.put(WorldManagerClient.NAMESPACE, 
                     WorldManagerClient.TEMPL_FOLLOWS_TERRAIN, 
                     Boolean.FALSE);

if (anim != null) {
    overrideTemplate.put(AnimationClient.NAMESPACE, 
    AnimationClient.TEMPL_ANIM, 
    anim);
}
if (soundData.size() > 0)  {
    overrideTemplate.put(WorldManagerClient.NAMESPACE, 
    WorldManagerClient.TEMPL_SOUND_DATA_LIST, 
    soundData);
}
Long objOid = ObjectManagerClient.generateObject(ObjectManagerClient.BASE_TEMPLATE,
							overrideTemplate);
if (objOid != null) {
    WorldManagerClient.spawn(objOid);
}

The spawn() call at the end tells the WorldManagerPlugin to enter the objects into the spatial data structures. This enables other objects to "see" the new object.

generateObject() sends a message to the object manager plugin, which creates the master object. It then sends out one GenerateSubObjectMessage message per namespace represented in the template. In the above case, two messages may be sent, one for the WorldManagerClient.NAMESPACE, and another for the AnimationClient.NAMESPACE (if a static animation exists). For more information about master and sub-objects, see Distributed Component Model.

The namespace to plug-in linkage is important to understand. All plug-ins extend multiverse.server.engine.EnginePlugin, which subscribes to GenerateSubObjectMessage messages. This happens when you call

 EnginePlugin.registerPluginNamespace(String namespace, Hook genSubObjHook);

This method actually calls:

 public void registerPluginNamespaces(Collection<Namespace> namespaces, 
         Hook genSubObjHook,
         Hook loadSubObjHook,
         Hook saveSubObjHook,
         NamespaceFilter nsFilter)

passing null values for the other hooks and filter, which will then use the defaults.

The world manager plugin uses the long form of this call, and passes in a new NamespaceFilter. Its namespace filter takes a look at the object's instance and location. The filter only matches if the instance is hosted by the world manager plugin and the location is within the instance's local geometry, accessed via World.getLocalGeometry(). This ensures that the WorldManagerPlugin only receives GenerateSubObjectMessages destined for it.

The world manager plugin has the OID for the object and creates object-specific subscriptions, such as incoming chat messages, movement requests, etc. These messages will never get delivered to other world manager plugins since they never subscribed for those messages.

Personal tools