☰ Contents ‹ Previous Next ›

General SunNET programming

The more versatile of the two programming models is the remote evaluation/verb calling. Many applications which involve only a few sites are better programmed using this model. One example of this is the $vravatar program developed by the WizTraveller on the SenseMedia MOOs. Here, I will attempt to show how two rooms can be linked together.

Planning

What should be the goal of the project? Obviously textual activity between the two sites should be transmitted. This involves hooking into :announce, :announce_all, and :announce_all_but. We also want to keep the appearance of a rooms contents consistent between the two sites. This involves hooking into :enterfunc and :exitfunc on the room. A property will also need to be created to hold remote object information, and :tell_contents will need to be overridden to display objects on the other site. Each of the two objects will be a mirror image of the other site. Note that unless otherwise specified, these verbs are all +x with the args this, none, this.

Creating

To start off, we need to create a $room on each of the two sites with whatever name you wish. Mark down the number, #A for Site1 and #B for Site 2. Create a property named .remote_contents on each site set to {}. The property will hold the names of objects on the opposite site. Create the properties .remote_site and .remote_room. For Site 1, the properties will hold "Site 2" and #B respectively and for Site 2, they will hold "Site 1" and #A. This is to prevent hard-coding site information in the objects.

Programming to Receive Actions

First write a verb for receiving information from remote :announce* calls. We will call this verb :remote_announce. We must be careful here. We can not call :announce* without having :announce* do some special checking to see if :remote_announce is the calling verb (which will be the route taken for this example). Note that there are some reasons for not having a :remote_announce_all and :remote_announce_all_but, so feel free to ponder this question or ask me about it.

Security checks on :remote_announce will need to ensure that the caller_perms() control the object or that the caller is SunNET. The following code snippet performs this check and raises an error if the conditions are not met. $sunnet_protocols is used here because the remote functions are driven on RCALL. $sunnet_protocols is responsible for dispatching RCALL events.

if (caller != $sunnet_protocols && !$perm_utils:controls(caller_perms(), this))
  raise(E_PERM);
endif

All that’s needed from here is to simply call :tell on all the real contents with the argument(s) provided. The following lines do this for you:

for x in (this:contents())
  x:tell(@args);
endfor

Combine the two to program :remote_announce

Programming to Send Actions

Of the three forms of :announce, :announce_all_but has a special argument for an exemption list. Other than that, all three forms will be programmed identically. The announce verbs usually have no security checks, so they are omitted here as well.

:announce and :announce_all can be combined into one verb named "announce announce_all" and programmed as follows:

pass(@args);
$sunnet_utils:verb_call(this.remote_site, this.remote_room, 
          "remote_announce", @args);

:announce_all_but can be programmed as follows:

pass(@args);
$sunnet_utils:send(this.remote_site, this.remote_room, 
          "remote_announce", @listdelete(args, 1));

Note that had we wanted the result from the call, we would replace :send with :verb_call above. Using :send can save SunNET bandwidth when you do not really need the result of the verb call.

Programming to Receive Contents

In MOO, the move() function calls exitfunc on an objects old location and enterfunc on the object’s new location. As such these two verbs will be used below to send object names to the opposite moo to the verbs in this section. .remote_contents stores this information and is just a list of object names in the room on the remote site. Rather than send the entire list whenever the contents change, we will just send additions and subtractions to the room’s contents to the remote site. Therefore we will need two verbs, one to add an object name and one to remove an object name from the .remote_contents property. The verbs will be called :remote_add and :remote_remove. Both use the same security check as described in the action receiving verb. They both take a single argument, which is the name of the object to add or remove respectively.

To add an object, the following line does the trick in :remote_add:

this.remote_contents={@this.remote_contents, args[1]};

To remove an object, use the following line in :remote_remove:

  this.remote_contents = `listdelete(this.remote_contents,
          args[1] in this.remote_contents) ! ANY =>
          this.remote_contents’;

Combine the security check above with these lines to create the respective verbs.

Programming to Send Contents

This involves overriding the enterfunc and exitfunc verbs to send the information. These verbs receive the object number of the object passing in or out of the location.

:enterfunc can be programmed as follows:

$sunnet_utils:send(this.remote_site, this.remote_room, 
          "remote_add", args[1].name);
pass(@args);

And :exitfunc can be programmed as:

$sunnet_utils:send(this.remote_site, this.remote_room, 
          "remote_add", args[1].name);
pass(@args);

No security checks are used in $room:enterfunc and :exitfunc, so should be unnecessary here.

Programming to Display Contents

A room is displayed with the :look_self verb with tells information to the player. :look_self, in turn, calls upon utility verbs to display various aspects of the room, such as the contents and exits. For this section, we will override the :tell_contents verb to incorporate the remote object names. By default, #3:tell_contents recognizes four different object list layouts. For the purpose of this tutorial we will simply print out a list of the objects. This is simple enough to accomplish using the following code, again without the need for security checks.
lst=this.remote_contents;
for x in (this:contents())
  lst={@lst, x == player ? "you" | x.name};
endfor
player:tell("  ", $string_utils:english_list(lst));

That’s all you need.

Done

This concludes the example. This code is untested, so if anyone wishes to implement it, please let me know if it works or not. For further exploration, you may wish to look into how to prevent an objects departure or arrival from being spoofed on the opposite site, how to fake stage talk into thinking the players are `real’ and how to privately whisper remotely in the same room.
☰ Contents ‹ Previous Next ›