From lily-dev-owner@rpi.edu Mon Nov 7 11:09:20 1994 Received: from hermes.acm.rpi.edu (hermes.acm.rpi.edu [128.213.5.14]) by helios.acm.rpi.edu (8.6.4/8.6.4) with ESMTP id LAA00471; Mon, 7 Nov 1994 11:09:19 -0500 Received: from mail1.its.rpi.edu (root@mail1.its.rpi.edu [128.113.100.7]) by hermes.acm.rpi.edu (8.6.4/8.6.4) with ESMTP id QAA04576; Mon, 7 Nov 1994 16:02:41 GMT Received: from eclipse.its.rpi.edu (root@eclipse.its.rpi.edu [128.113.24.33]) by mail1.its.rpi.edu (8.6.4/8.6.4) with SMTP id LAA13054; Mon, 7 Nov 1994 11:05:35 -0500 Received: from mail1.its.rpi.edu by eclipse.its.rpi.edu (NX5.67e/NX3.0M) id AA04041; Mon, 7 Nov 94 11:05:11 -0500 Received: from ctron.com (ctron.com [134.141.197.25]) by mail1.its.rpi.edu (8.6.4/8.6.4) with SMTP id LAA12883 for ; Mon, 7 Nov 1994 11:04:30 -0500 Received: from stealth.ctron.com by ctron.com (4.1/SMI-4.1) id AA13720; Mon, 7 Nov 94 11:04:07 EST Received: from indikos by stealth.ctron.com (4.1/SMI-4.1) id AA15610; Mon, 7 Nov 94 11:04:03 EST Received: by indikos via SMTP (920330.SGI/920502.SGI.AUTO) for @stealth.ctron.com:lily-dev@rpi.edu id AA11541; Mon, 7 Nov 94 11:03:15 -0500 Message-Id: <9411071603.AA11541@indikos> To: lily-dev@rpi.edu Reply-To: ratlifc@ctron.com (Christian A. Ratliff) Subject: lilyCore internals volume 3 X-Mailer: exmh version 1.5omega 10/6/94 Date: Mon, 07 Nov 1994 11:03:15 -0500 From: "Christian A. Ratliff" Status: OR Authoring a lily command A seminal idea in Lily (and later lily) was dynamic command sets*. Under Clover to add or alter a command you had to rewrite four parts of the server and three parts of the client _and_ get _every_single_ client upgraded. An unknown packet type would cause lots of internal damage to the client. In Lily the new idea was to have an interpretive language to hold commands on a different server, it would act as a mediator between the client and the database server. In the design I had ignored certain network communication and complexity issues, and they were back to haunt me long before the first code was finished. lily gave me the chance to have dynamic command sets in a manner that didn't boggle the mind with complexity. As we recall from volume 2, $command_mode is the clearinghouse for all commands. $command_mode:/who() is the real /who command in lily. The commands are invoked by calls in #0:do_command() and $player:do_command(). As an example we will create a command called '/foo'. The first step is to add the '/foo' verb to $command_mode. We must give it permissions (the second argument) and the typical permissions are 'read', 'execute', and 'debug'. The debug bit allows us to see tracebacks when the code has a fault. The owner (the last parameter) is $admin so that the verb has absolute power over any property on any object on the system. It is clear that lily sacrificed internal security for speed, which is why I review, by hand, every new piece of code that goes into the Core. @verb $command_mode:/foo "rdx" $admin Verb added (74). <* "@verb" took 254 ticks *> Dynamic command sets can easily suffer big performance problems as they grow (since each command typed must be matched against a runtime dynamic list). I hedged my bets by reusing the $sset data structure to store the list of available commands. This allows me to match very quickly, while not overly lessening the dynamic properties of the command set. You will need to rebuild the $sset_c every time you add or remove a command. $rebuild commands (done rebuilding commands) <* "$rebuild" took 10789 ticks *> Now when you run /foo you get and error message that is an esoteric MOO way of saying, "Hey, there ain't no code!" Obviously we need to do some programming. /foo #6:do_command (this == #8), line 9: Verb not found ... called from #0:do_command, line 6 (End of traceback) Just as a starter I added some code to this verb 'player:notify("(you have typed the foo command)");'. Doing /foo now returns: /foo (you have typed the foo command) <* "/foo" took 93 ticks *> Since I cannot find a non-contrived purpose for '/foo', I will just enable you with tools to make it do whatever you want. Nearly every command will use $lily_utils:sendlist() and $lily_utils:event_broadcast(). If your command takes as a parameter a name or a list of names that need resolved into objects, then you will have need for $lily_utils:sendlist(). The parameters are as follows: $lily_utils:sendlist(STR-LIST names, NUM multi_match, NUM match_unconnected[, NUM match_group[, NUM special_arg]]); names: a list of names to resolve (ie {"bar","baz","blech"}) multi_match: a number when equal to 1 requests that the command match whatever it can (ie /who, /names); when equal to 0 it tries to match as as precisely as possible (ie messaging, /block, /ignore) match_un...: a number when equal to 1 it permits matches on users not logged in (ie /ignore, /block, etc...), when equal to 0 it will only match logged in users (ie messaging, /who, /idle). match_group: yet another number which indicates what objects to match; if it is 1 then matches are for users only (ie /ignore, /where), if it is 2 matches are only on discussions (ie /what, /retitle), lastly if it is 0 then matches are allowed on either type (ie messaging, /block). This parameter is OPTIONAL, and defaults to 0. special_arg: YAN which requests _special_ behaviour from the parser. In the messaging code '2' is passed to ask that the parser only match against discussions in which the player object is a member. The return value is a list of object numbers or the empty list {}. Do not bother printing a failure message since $lily_utils:sendlist() will print failures during the matching process. Often you will take a _LIST_ of names instead of just one (this, BTW, is mandated by the 'lily Style Guide' in volume 4 or 5**). To quickly resolve a comma delimited list of names (or whatever), into a list for $lily_utils:sendlist() to use call $lily_utils:namelist(). $lily_utils:namelist(STR raw_namelist[, STR delimiter]) raw_namelist: A list of names to be parsed in raw format. delimiter: A string defining the delimiter character (ie ":", ",", ";") The return value is a list of strings ("_"'s are translated to spaces). If you find yourself needing to tell lots of other people about whatever your command has done the $lily_utils:event_broadcast() command is right for you. This verb will broadcast the message to everyone _but_ the sender and add it to each player's reviewing buffers. If a discussion is involved (ie /permit) this verb will add it to the discussions reviewing buffers. $lily_utils:event_broadcast(STR event, STR-LIST messages, OBJ-LIST recips, OBJ-LIST discs[, OBJ sender]) event: The event being broacast (ie "sysmsg", "permit", "connect"). messages: A list of messages to display (often {"*** some message ***"}, it is a list of strings to accomidate multiline stuff like messages and sysalerts and sysmsgs. recips: A list of recipients for the messages, or the empty list to send to $players_on (all detached and connected players). Whether using the {} list or something you pass in the sender is _ALWAYS_ dropped from the list. Also note that each player in the list has the event added to their review buffers. discs: If any, a list of the discussions "involved"; this implies the event should be added to their review buffers (ie /permit, /retitle) sender: This is nearly always not supplied, only in situations where the 'player' variable is not filled in (ie #0:checkpoint_started()) will it hold some substitute value. At this point you should be able to add commands which take list-oriented parameters and broadcast event messages to other people. * The idea was first put forth by Prisoner in early 1992. ** The unformed 'lily Style Guide' will also mandate that messages being displayed to the user come in one of six forms: An acknowlegement of an action should be in parentheses (message sent to Bob) (you are now ignoring Matt {privately}) Any public event NOT caused by the current user and NOT a message should be in familiar CONNECT ***s *** Bob has entered lily *** *** Christian is ignoring you *** Any system oriented message that is destined for DBAs or Admins should be in ###s ### lily has dumped the database ### ### the detach count is inconsistent [-1:1] ### Any file-oriented output (ie /info) should be prefixed with * * Today is Monday November 7, 1994 * The world is concluded today. Any emotes, public, private, or consulting messages should be in the appropriate form (I won't bother enumerating those now) Any gaming messages should be 'GameName [in discussion]> message'. If the user is participating in or monitoring 'GameName' in more than one discussion the '[in discussion]' part of the message should be filled in. (This is a proposal that is still to be finalized). christian PS. I'll try and get the style guide out by Wednesday. ----------- "He didn't look to be an official | Christian Ratliff type to go around dropping off | Sales Programmer/Analyst lawnmowers..." | Cabletron Systems, Inc. -Robin Aber | (MIME and NeXTmail accepted)