Proxy Server

From Multiverse

(Redirected from How the Proxy Server Works)
Jump to: navigation, search

The proxy server communicates with Multiverse Clients and passes on messages to all the other servers. The class multiverse.server.plugins.ProxyPlugin implements the proxy server.

Contents

Process

When the proxy server gets a login request message (message ID 1) from a client, it:

  • Adds an entry into the PlayerManager to keep track of the player.
  • Calls the ObjectManagerPlugin to load the player object from the database. The player's sub-object state is loaded by the relevant plug-ins.
  • Returns a login "success" or "failure" indication to the client. (LoginResponse Message ID 4).
  • Requests terrain info from the WorldManager and relays that to the client.
  • Requests basic info about the player object such as the name, location, orientation, scale, and object type. Relays this information to the client. (NewObjectMessage ID 8).
  • Requests display context from the WorldManagerPlugin (model,material info), and relays to the client.
  • Sends over any display context attachments.
  • Sends over UI Theme to the client. UI theme is configured directly into the ProxyPlugin via World.setTheme().
  • Gets the skybox information from the instance server and relays to client (Skybox Message message ID 7)
  • Gets the ocean information from the instance server and relays to client (via Extension message ID 70)
  • Sends over global regions (trees, grass, and water) to client (via Fog message ID 42)
  • Adds player to proxy's PerceptionFilter
  • Spawn the player into the world via WorldManagerPlugin.
  • Sends out an updateObject message, which asks other plugins to send over any relevant information. (for example, animation plugin will send the player's current animation).

Much of the remaining work occurs as a side-effect of spawning the player into the world. The world manager determines which objects the player can perceive and generates a PerceptionMessage. This includes the basic oject information such as location and display context. For each perceivable object, the proxy sends an updateObject message to gather information from other plugins. The information from the world manager and other plug-ins is collected by the proxy and forwarded to the client.

Scripts

In addition to scripts and files it reads for messaging configuration, it reads the following scripts:

General configuration

Configure the proxy server with proxy.py.

Set the server ID with the following statement.

Engine.setServerID( server_id );

The server ID must be unique among proxy and world servers.

Set the world ID and port number as follows, where the values are integers that match the world ID and port previously defined.

Engine.setWorldID( world_id );
Engine.setPort( portNumber );

The following settings control the general behavior of the proxy server:

  • Engine.setNetworkThrottle( ) - specifies how many unacknowledged packets allowed to be outstanding.
  • Engine.EventServerThreadPoolSize - must always be one (1).

You can define multiple world servers. Define each world server as follows:

wsMgr = Engine.getWSManager();
wsMgr.addWorldServer(new WorldServer("localhost", 5090, 0));

If the world server is running on a different host, replace "localhost" with the name of the host. Specify a different port for each world server.

Messages

Login and logout messages

The proxy server sends a login message when a player logs in and a logout message when a player logs out. It sends the messages using broadcast RPC so all subscribers must respond. The proxy server waits for all responses before proceeding with login or logout.

The proxy server sends a login message after loading the player object, but before spawning.

  • Message class: LoginMessage. The message is a SubjectMessage with the player OID as the subject. The message also contains the player name and instanceOid into which the player will spawn.
  • Message type: LoginMessage.MSG_TYPE_LOGIN

The proxy server sends a logout message after despawning the player, but before unloading.

  • Message class: LogoutMessage. The message is a SubjectMessage with the player OID as the subject. The message also contains the player name.
  • Message type: LogoutMessage.MSG_TYPE_LOGOUT

For example:

   // Hooks to process login/logout messages
   getHookManager().addHook(LoginMessage.MSG_TYPE_LOGIN,
           new LoginHook());
   getHookManager().addHook(LogoutMessage.MSG_TYPE_LOGOUT,
           new LogoutHook());

   // Create responder subscription
   MessageTypeFilter filter = new MessageTypeFilter();
   filter.addType(LoginMessage.MSG_TYPE_LOGIN);
   filter.addType(LogoutMessage.MSG_TYPE_LOGOUT);
   Engine.getAgent().createSubscription(filter, this,
       MessageAgent.RESPONDER);

   // Log the login information and send a response
   class LoginHook implements Hook {
       public boolean processMessage(Message msg, int flags) {
           LoginMessage message = (LoginMessage) msg;
           Long playerOid = message.getSubject();
           Long instanceOid = message.getInstanceOid();
           Log.debug("LoginHook: playerOid=" + playerOid + " instanceOid=" + instanceOid);
           // Do something
           Engine.getAgent().sendResponse(new ResponseMessage(message));
           return true;
       }
   }

   // Log the logout information and send a response
   class LogoutHook implements Hook {
       public boolean processMessage(Message msg, int flags) {
           LogoutMessage message = (LogoutMessage) msg;
           Long playerOid = message.getSubject();
           Log.debug("LogoutHook: playerOid=" + playerOid);
           // Do something
           Engine.getAgent().sendResponse(new ResponseMessage(message));
           return true;
       }
   }

Proxy extension hooks

The proxy server includes a mechanism to register handlers for extension messages from the client. Register a handler for an extension message sub-type to make the proxy server run the handler function when it receives an extension message with that sub-type from the client.

For more information, see Using Extension Messages.

Writing a proxy extension hook

Proxy extension hooks implement interface multiverse.server.objects.ProxyExtensionHook. The interface has a single method the proxy calls to handle an extension message. The method receives the ExtensionMessageEvent and the Player object. Properties set by the client are available from the ExtensionMessageEvent. You can get the player oid with player.getOid().

public class MyProxyHook implements ProxyExtensionHook
{
   public void processExtensionEvent(ExtensionMessageEvent event,
       Player player, ProxyPlugin proxy)
   {
       Map<String,Serializable> props = event.getPropertyMap();

       if (Log.loggingDebug)
           Log.debug("MyProxyHook: received "+event.getExtensionType()+" from playerOid="+player.getOid());

       // Log the extension message properties
       if (Log.loggingDebug) {
           String propStr = "";
           for (Map.Entry<String,Serializable> entry : props.entrySet()) {
               propStr += entry.getKey() + "=" + entry.getValue() + " ";
           }
           Log.debug("MyProxyHook: "+propStr);
       }
   }
}

Note that messages from the client are processed sequentially. Subsequent messages will not be processed until processExtensionEvent() returns.

Registering proxy extension hooks

To register a proxy extension hooks, use the following method on ProxyPlugin.

proxyPlugin.addProxyExtensionHook("proxy.GENERATE_OBJECT", GenerateObjectProxyHook())

The /multiverse/config/world-name/extensions_proxy.py script is a good place to put this code.

InstanceEntryProxyHook

The platform includes a hook allowing client initiated instance entry: multiverse.server.objects.InstanceEntryProxyHook. In Sampleworld, this hook is registered to the "proxy.INSTANCE_ENTRY" extension sub-type. The sample assets include a client-side "/instance" command in Script/MarsStandardCommands.py that sends this extension message to instance the player.

For more information, see World Instancing.

GenerateObjectProxyHook

This hook will generate an object at the player's current location or on a marker. The hook expects the following extension message properties:

  • template - A registered object template name. The template must have attributes in the world manager namespace, otherwise it won't spawn.
  • marker - Marker name in the current instance. If not specified, then the player's current location and orientation are used.
  • persistent - If this integer is not 0, then the object will be persistent.

The object's location and orientation are set from the marker or current player location. If the object creation succeeds, then it will be immediately spawned.

This hook is registered in 'sampleworld' to extension sub-type "proxy.GENERATE_OBJECT". The sample assets include a client-side "/generate" command in Script/MarsStandardCommands.py that sends this extension message.

Personal tools