########################################################################
# LinkTool, V2.0        Dec, 1992, Written by Zalcor@Singlenesia
#
# To make this file ready for uploading to the mush, it should be filtered
# with the "strip" program. The effects of this filter are as follows:
#
#   Removes all lines that have a '#' in the first column.
#   Strips leading whitespace from all lines.
#   Concatenates all lines, up until it reaches a line with a '-' in the
#      first column.
#########################################################################
# This file creates an object, "LinkTool", that must be in the MUDLINK
# player's inventory. Running this file will create the object, set
# the necessary flags and @teleport the new object to MUDLINK.
#
# LinkTool performs two major tasks. It processes and delivers incoming
# remote pages, and it performs the required tasks to accomplish
# remote looking from conference rooms.
#
# None of the commands this object implements are designed for general
# use.  You can generally ignore the fact that this object exists, with
# one possible exception... read the comments just for the DELAY attribute,
# toward the end of this file.
##########################################################################
# Changes from previous version:
#
#    Code added to support remote looking from a conference room.
#
#    The structure of the commands were altered, to provide greater
#    security, and eliminate the need for MUDLINK to be able to
#    @pemit far.
##########################################################################
#
# NOTE: This object *must* inherit Wizard powers.
#
# Please report any comments, suggestions or bugs to:
#
#      johnm@cajal.uoregon.edu
######################################################################

@create LinkTool
-
@va LinkTool=$@pmud *=*@* *:

# Implements @pmud. @pmud is issued by MUDLINK to process and deliver
# incoming remote pages. The calling format is:
#
#    @pmud <to-player>=<from-player>@<mud> <msg>

   @switch type(*%0)=
      #-1*,@pemit *MUDLINK=
         @rtrans %2=@pemit %1=No such player,
      player,{
         @switch hasflag(*%0,connect)=
            0,@pemit *MUDLINK=
               @rtrans %2=@pemit %1=
                  That player is not connected.,
            {
               @switch [member(get(*%0/rwho_refuse),ucstr(%1))]+
                       [member(get(*%0/rwho_refuse),[ucstr(%1)]@[ucstr(%2)])]+
                       [member(get(*%0/rwho_refuse),*@[ucstr(%2)])]=
                  0+0+0,{
                     @pemit *%0=%1@%2 %3;
                     @pemit *mudlink=@rtrans %2=@pemit %1=
                              Remote page to [name(*%0)] successful.
                  },
                  {
                     @pemit *mudlink=
                        @rtrans %2=@pemit %1=
                           [switch(words(get(*%0/rwho_reject)),
                              0,That player is not accepting remote pages.,

                              Reject message from [name(*%0)]: 
                                 [get(*%0/rwho_reject)]
                           )]
                  }
            }
      }
-
# @mudlook
#
# This command is issued to process a request from a remote site to
# Look at something in a conference room.
#
# Format: @mudlook <player>@<mud>=<dbref>@[<object>]
#
#    <player> is the name of the looker
#    <mud> is the name of the mud the looker is at
#    <dbref> is the dbref# of the target conference room
#    <object> is the name of the thing to look at. Defaults to 
#      the target conference room itself.

@vb LinkTool=$@mudlook *@*=*@*:

# As a security measure, the code ensures that there is indeed a non-halted
# podium in the conference room named.
#
# We must take into account that the object's name and description may not
# be that of the Podium, it can morph freely, or even become dark. So the
# LinkTool must actively search for it. The podium must always have the
# MLFOOTPRINT attribute, so all the objects in the room are checked
# and when one is found, it is assumed to be the Podium.
#
# Note that the room itself, as well as exits and players in the room, are
# never checked.

   &L#%0@%1 me=;

   @dolist lcon(%2)={
      @switch match(type(##),PLAYER)=

# Ignore the players

         0,{
            @switch strlen(get(##/MLFOOTPRINT))=
               >0,{
                  @switch hasflag(##,HALTED)=
                     0,&L#%0@%1 me=##
               }
         }
   };

# This following wait bit is a kludge. The idea is that we want let the
# looker know why they can't look, if that's the case. At this point, it
# is because we couldn't find a Podium, so we use a flag to indicate when
# one was found. 
#
# Unfortunately, the @dolist will run concurrently with the following code,
# so we wait before executing it, long enough to make it likely that the
# dolist has completed.
         
   @wait [v(delay)]={
      @switch or(match(v(L#%0@%1),#-1*),not(words(v(L#%0@%1))))=
         1,{
            @pemit *MUDLINK=
               @rtrans %1=
                  @pemit %0=MUDLINK Error: Could not look at requested mud.;
         },
         {

# OK, we found sn unhalted podium, so we go on to take care of business.

            @switch strlen(%3)=
               0,{

# The fourth argument is missing, so assume look at the room

                  @pemit *MUDLINK=@rtrans %1=@pemit %0=[name(%2)];
                  @pemit *MUDLINK=@rtrans %1=@pemit %0=[get(%2/desc)];
                  @switch hasflag(%2,DARK)=
                     0,{
                        @switch words(lcon(%2))=
                           >0,{
                              @fo me=@pemit *MUDLINK=@rtrans %1=@pemit %0=Contents:; 
                              @fo me=
                                 [iter(lcon(%2),
                                    [switch([hasflag(##,DARK)]+
                                            [hasflag(##,CONNECTED)]+
                                            [not(match(type(##),PLAYER))],
                                       0+1+*,@pemit *MUDLINK=@rtrans %1=
                                                      @pemit %0=[name(##)]\;,
                                       0+0+1,@pemit *MUDLINK=@rtrans %1=
                                                      @pemit %0=[name(##)]\;
                                    )]
                                 )]
                           };
                        @switch words(lexits(%2))=
                           >0,{
                              @fo me=@pemit *MUDLINK=@rtrans %1=@pemit %0=
                                                             Obvious Exits:;
                              @fo me=
                                 [iter(lexits(%2),
                                    [switch(hasflag(##,DARK),
                                       0,@pemit *MUDLINK=@rtrans %1=
                                                     @pemit %0=[name(##)]\;
                                    )]
                                 )]
                           }
                     }
               },
               {

# Ok, we want to look at a specific object.

                  @switch match(ucstr(%3),ME)=
                     >0,
                       @pemit *mudlink=
                          @rtrans %1=
                             @pemit %0=Please type "look me" to look at yourself
                     ,
                     {

                        &O#%0@%1 me=[locate(v(L#%0@%1),%3,hn)];
                        @switch v(L#%0@%1)=
                           #-1,{
                              @pemit *mudlink=
                                 @rtrans %1=
                                    @pemit %0=
                                       You can't see that there.
                           },
                           #-2,{
                              @pemit *mudlink=
                                 @rtrans %1=
                                    @pemit %0=
                                       I don't know which one you mean!
                           },
                           
                           {
                              @switch hasflag(v(O#%0@%1),DARK)=
                                 0,{
                                    @pemit *mudlink=
                                       @rtrans %1=@pemit %0=[name(v(O#%0@%1))];
                                    @switch strlen(get(v(O#%0@%1)/desc))=
                                       0,@pemit *MUDLINK=@rtrans %1=@pemit %0=
                                                   You see nothing special.,

                                       {

# The following statement is a mess. Hopefully, I can find a way to
# improve it. If anyone else does, please drop me a line!
#
# The idea is this... we want to execute any code and % subs that the
# object being looked at may have. The problem is LinkTool can't do it,
# since LinkTool is a Wizard-inherit object. The solution I've
# devised is to @force the podium in the room that contains the object,
# make *it* do all the work. The Podiums do not inherit Wizard powers,
# so there is no security problem there.
#
# The added catch, though is that two levels of command interpretation
# need to be done. First, the correct get_eval() statement, and then
# to execute that line. This is the reason that the podium gets
# @forced twice.

                                          @fo [v(L#%0@%1)]=
#                                             @fo me=
                                                @pemit *MUDLINK=
                                                   @rtrans %1=
                                                      @pemit %0=
                                                         [get(
                                                            [v(O#%0@%1)]/desc
                                                         )]
                                       };
                                      
                                    @switch hasflag(v(O#%0@%1),OPAQUE)=
                                       0,{
                                          @switch words(lcon(v(O#%0@%1)))=
                                             >0,{
                                                @fo me=@pemit *MUDLINK=
                                                   @rtrans %1=
                                                      @pemit %0=Carrying:;
                                                @fo me=
                                                   [iter(lcon(v(O#%0@%1)),
                                                      [switch(
                                                            hasflag(##,DARK),
                                                         0,@pemit *MUDLINK=
                                                           @rtrans %1=
                                                           @pemit %0=
                                                              [name(##)]\;
                                                      )]
                                                   )]
                                             }
                                       }
                                 }
                           }
                     }
               }
         };
         @wait [v(delay)]={
            &L#%0@%1 me=;
            &O@%0@%1 me=;
         }
   }
-
@vc LinkTool=$ML#PEMIT *=*:
   @pemit %0=%1
-
@vd LinkTool=$ML#REMIT *=*:
   @pemit/contents %0=%1
-
# This delay holds the number of seconds the LinkTool will wait for, when
# searching for the Podium (See the comments above). I picked 2
# seconds as a shot in the dark guess, and it's probably not optimal. I
# think that 1 second would work on my MUSH, but a machine that lags a
# lot may require a higher delay time. Experiment! I put this in it's
# own attribute to make it easy to change if required.
#
# If this time is too short, it will cause the error message to be sent
# to the looker, and the look to fail. If the setting is only a little
# off, then this problem will be intermittant in nature, fluctuating
# with the amound of server lag. 

@set LinkTool=DELAY:2
-
@set LinkTool=INHERIT
-
@tel LinkTool=*MUDLINK
--
