Chapter 9

The Client Data Object

And they said one to another, Behold, this dreamer cometh. Come now therefore, and let us slay him, and cast him into some pit, and we will say, Some evil beast hath devoured him: and we shall see what will become of his dreams.
--Genesis 37.19-20

A client object is created when a player logs in and gets destroyed when that player logs out. Whereas a mob being used by a player and an NPC mob are treated identically by the computer, the client datum contains properties which are applicable only to players.

You may define verbs under the client data object. These are treated just like private verbs attached to the player's mob: they are accessible only to the player and the source is implicit. In addition to verbs, you may also define client variables and procs. The pre-defined ones will be described in the sections that follow.

1. Client Variables

The client variables contain information about the player and the state of the player's display. They are described in the following list:

  • key is the name of the player's key. This is used to connect the player to a mob. If a new mob is created for the player, the mob's name will be set equal to the key. By assigning this value to a mob's key, you can cause the player to switch to that mob. Any previous mob will lose the key (by having its own key set to an empty text string). The Login() and Logout() procedures are called automatically during this exchange.

  • ckey is the player's key in canonical form. All punctuation is stripped and letters are converted to lowercase. This can be used for the same purposes as key to cause players to switch mobs. The primary purpose, however, is for marking saved information about the player.

  • mob is the player's mob. It can be directly assigned to cause the player (and associated key) to get transferred to another mob. This variable is the complement of mob.client, which is a reference to the client using the mob.

  • eye is the position at the center of the player's map. By default it is equal to the player's mob. You could, however, set it equal to some other object to control what the player sees. Note, however, that visibility is still calculated from the mob's point of view. This allows for effects like "lazy eye" which will be described next.

  • lazy_eye is the amount of lag between the player's eye and the player's mob. By default it is 0 so the mob stays centered. If set to a non-zero value, the mob can walk away from the center by the specified amount before the view shifts it back to the center.

  • dir is the direction of "up" on on the player's screen. By default it is NORTH, which is the same as the map editor. Other possible values are SOUTH, EAST, and WEST. Diagonals are valid too, but will be approximated by one of the four cardinal directions. The effect of each arrow key is automatically rotated along with the map.

  • address is the network address of the player. If the world is running directly in the client (the local server) this will be an empty text string, which is sometimes useful for giving super-user access. Otherwise, this could be used to ban access from certain IP addresses if people from there always turn out to be annoying.

  • statobj is the object being viewed by the player in the stat panels.

  • statpanel is the name of the stat panel currently visible to the player.

  • verbs is the list of verbs attached to the client. Verbs could be added or removed from this list at run-time using techniques described in section 10.6.2.

  • script specifies a DM Script program to send to the client when the player connects. The use and syntax of DM Script will be discussed in section 11.5 and in the appendix (page [4]). Its primary purpose is to configure the appearance of output text by using a style sheet. Command aliases and keyboard macros can also be defined.

  • macro_mode may be set to 1 to interpret keys as macros by default. See the appendix (page [4]) for more information.

    Using the client.mob variable, we can make a better who command which only lists players who are currently logged in.

    mob/verb/who()
       var/mob/M
       usr << "Active players:"
       for(M)
          if(M.client)
             usr << M.name
    

    Mobs without a client (i.e. NPCs) are excluded from the output list.

    2. Client Procs

    There are a number of pre-defined procs which handle various forms of input from the user. These and other client procs are described in the following sections.

    2.1 Direction Procs

    When the player clicks an arrow key, this calls a corresponding client proc. There are procedures for each of the keys: North(), South(), East(), West(), Northeast(), Northwest(), Southeast(), Southwest(), and Center().

    It would be more precise to call these verbs, because that is in fact what they are. They just happen to be verbs with names starting with a dot, which means they don't show up in any expansion lists until you type the dot. So you could type ".north" instead of clicking the up arrow if you really wanted. That is all the up arrow does for you.

    By default, the directional procs call the client's Move proc, which in turn calls the mob's own Move proc. It is simply there to redefine if you want.

    Move (Loc,Dir)
    Loc is the new location to move to.
    Dir is the direction to face.
    Returns 1 on success, 0 on failure.

    The Center proc also exists primarily for you to redefine. The only default action is to stop any automated movement of the player's mob. That topic will be discussed in section 14.2.

    In some games, you might want to disallow diagonal movements. You could do that by simply redefining the relevant procs to do nothing.

    client
       //disable diagonals
       Northeast()
       Northwest()
       Southeast()
       Southwest()
    

    2.2 Click proc

    The Click proc is called when the player clicks an object on the map or in the stat panels. There is an identical proc DblClick which is activated by double-clicking. The default action simply calls the object's own Click or DblClick proc. These object procedures were described in section 7.4.

    Click (O,Panel)
    DblClick (O,Panel)
    O is the object clicked.
    Panel is the stat panel (or null if none).

    The following example tells you what you clicked.

    client/Click(O)
       usr << "You clicked [O]."
    

    Note that the default (parent) proc was not called in this example. That means the object's own Click procedure will not be called. You must remember to call ..() if you wish this to still take place.

    The client's Click procedure is convenient to use when you want to perform an action that is the same for all types of objects. When the action depends on the type of object, the object's own Click procedure is usually the better choice.

    2.3 Stat proc

    The Stat proc is called periodically by the client to refresh the stat panels. By default, this merely calls statobj.Stat(). You could generate stat output directly from this proc, but when the contents reflect the status of another object (like the player's mob), this is normally done in the object's own Stat proc. Generation of stat output was discussed in section 7.3.

    2.4 Topic proc

    The Topic proc is activated by the player clicking on a topic link embedded in the text output somewhere. You could use it to give the player more information on the indicated subject (hence the name topic). However, there is no restriction on what action you may perform. Some of the possibilities will be explored in chapter 11.

    Topic (Topic,Obj,SubTopic)
    Topic is the topic link selected by the player.
    Obj is the object referenced if any.
    SubTopic is the Obj topic.

    The Obj and SubTopic parameters are only supplied if Topic begins with an object reference (embedded with \ref). By default, the object's own Topic proc is called with SubTopic as the argument. You saw the result of that in section 7.6 when we created a link to a game object.

    Since all topic links go through the client first, you have a chance to control which objects a player may access. You may also have topics which do not really belong to any particular object. In that case, you can just handle them in the client object.

    Topic hyperlinks are created in an HTML tag. The syntax was already introduced in connection with object links, but for client topics, you do not necessarily have to insert an object reference. It is also possible to use this tag for other types of links. The general syntax will be described in section 11.2.8.

    "... <A HREF=#topic> click here </A> ..."

    As an example of a client topic link, you could give some advice to new players.

    client/Topic(T)
       if(T == "help")
          usr << "The motto here is: you are what you eat."
       else ..()
    
    mob/Login()
       ..()
       usr << "When in doubt, click here."
    

    2.5 Import and Export procs

    The Import and Export procs are used to read and write to a save file stored in the player's key file. This is useful if the same information about a player will be used in multiple worlds. In that case, rather than each world saving information about the player separately, it can be attached to the player's key and carried from world to world that way.

    Since we haven't covered save files yet, further discussion of these procs will be postponed until that time. See chapter 12.

    2.6 New and Del procs

    The New and Del procs are called at creation and destruction of the client, as they are for all objects. The default behavior of New is to connect the player to the mob with the same key as the player. If none is found, one will be created. If there is a mob defined to have the same key, that type of mob will be used; otherwise world.mob is used.

    New (Topic)
    Topic is the initial topic being accessed.
    usr is the mob with the same key as the player (if any).
    Returns the mob selected for the player.

    Normally an initial topic is not specified when a player connects. However, it may be useful in some situations. By default, once a mob has been selected, the Topic proc is called to handle it.

    You could override the New proc to ban certain keys from connecting.

    client/New()
       if(key == "Real Jerk") return //sorry pal!
       return ..()