Generic selectors
Exact matches only
Search in title
Search in content
Search in project

Process

The Proxy Server handles communication with clients passing on messages to the other servers. The proxy server is implemented by the atavism.server.plugins.ProxyPlugin class.

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

  • Adds an entry into the atavism.server.plugins.PlayerManager class 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 (prefab) from the WorldManagerPlugin, and relays to the client.
  • 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 object 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:

  • atavism_server/bin/proxy.py
  • atavism_server/config/common/events.py
  • atavism_server/config/common/proxy.py
  • atavism_server/config/world/extensions_proxy.py

General configuration

The proxy server is configured with settings from 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: atavism.server.messages.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: atavism.server.messages.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.

 

Writing a proxy extension hook

Proxy extension hooks implement interface atavism.server.objects.ProxyExtensionHook. The interface has a single method the proxy calls to handle an extension message. The method receives the atavism.server.events.ExtensionMessageEvent and the atavism.server.objects.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 /atavism/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: atavism.server.objects.InstanceEntryProxyHook.

 

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 the demo to extension sub-type “proxy.GENERATE_OBJECT”. The sample assets include a client-side “/generate” command in the StandardCommands script that sends this extension message.