Login
User Name:

Password:



Register

Forgot your password?
do_owhere recursive
Author: Khonsu
Submitted by: Khonsu
Changes list / Addchange
Author: Khonsu
Submitted by: Khonsu
6Dragons mp3 sound pack
Author: Vladaar
Submitted by: Vladaar
AFKMud 2.2.3
Author: AFKMud Team
Submitted by: Samson
SWFOTEFUSS 1.5
Author: Various
Submitted by: Samson
Users Online
AhrefsBot, Bing

Members: 0
Guests: 7
Stats
Files
Topics
Posts
Members
Newest Member
489
3,793
19,649
597
Aileenutz

Today's Birthdays
There are no member birthdays today.
» SmaugMuds » Bugfix Lists » AFKMud Bugfix List » AFKMud Bug Archive » [Bug] Exit creation stumbles ...
Forum Rules | Mark all | Recent Posts

[Bug] Exit creation stumbles on flags in the argument
< Newer Topic :: Older Topic > AFKMud 1.77

Pages:<< prev 1 next >>
Post is unread #1 Dec 2, 2006 6:53 pm   Last edited Dec 2, 2006 6:53 pm by Samson
Go to the top of the page
Go to the bottom of the page

Samson
Black Hand
GroupAdministrators
Posts3,685
JoinedJan 1, 2002

 
Bug: Exit creation stumbles on flags in the argument
Danger: Low - Ending up with partly broken exits makes more work for people to fix.
Discovered in: AFKMud 1.77
Found by: pstone
Fixed by: Samson

---

build.c, do_redit

Locate:
   if( !str_cmp( arg, "exit" ) )
   {
      bool addexit, numnotdir;

      argument = one_argument( argument, arg2 );
      argument = one_argument( argument, arg3 );
      if( !arg2 || arg2[0] == '\0' )
      {
         send_to_char( "Create, change or remove an exit.\n\r", ch );
         send_to_char( "Usage: redit exit  [room] [flags] [key] [keywords] \n\r", ch );
         return;
      }
      addexit = numnotdir = FALSE;
      switch ( arg2[0] )
      {
         default:
            edir = get_dir( arg2 );
            break;
         case '+':
            edir = get_dir( arg2 + 1 );
            addexit = TRUE;
            break;
         case '#':
            edir = atoi( arg2 + 1 );
            numnotdir = TRUE;
            break;
      }
      if( !arg3 || arg3[0] == '\0' )
         evnum = 0;
      else
         evnum = atoi( arg3 );
      if( numnotdir )
      {
         if( ( xit = get_exit_num( location, edir ) ) != NULL )
            edir = xit->vdir;
      }
      else
         xit = get_exit( location, edir );
      if( !evnum )
      {
         if( xit )
         {
            extract_exit( location, xit );
            send_to_char( "Exit removed.\n\r", ch );
            return;
         }
         send_to_char( "No exit in that direction.\n\r", ch );
         return;
      }
      if( evnum < 1 || evnum > ( sysdata.maxvnum - 1 ) )
      {
         send_to_char( "Invalid room number.\n\r", ch );
         return;
      }
      if( ( tmp = get_room_index( evnum ) ) == NULL )
      {
         if( evnum < ch->pcdata->low_vnum || evnum > ch->pcdata->hi_vnum )
         {
            ch_printf( ch, "Room #%d does not exist.\n\r", evnum );
            return;
         }
         tmp = make_room( evnum, ch->pcdata->area );
         if( !tmp )
         {
            bug( "%s: make_room failed", __FUNCTION__ );
            return;
         }
      }
      if( addexit || !xit )
      {
         if( numnotdir )
         {
            send_to_char( "Cannot add an exit by number, sorry.\n\r", ch );
            return;
         }
         if( addexit && xit && get_exit_to( location, edir, tmp->vnum ) )
         {
            send_to_char( "There is already an exit in that direction leading to that location.\n\r", ch );
            return;
         }
         xit = make_exit( location, tmp, edir );
         xit->key = -1;
         xCLEAR_BITS( xit->exit_info );
         act( AT_IMMORT, "$n reveals a hidden passage!", ch, NULL, NULL, TO_ROOM );
      }
      else
         act( AT_IMMORT, "Something is different...", ch, NULL, NULL, TO_ROOM );
      if( xit->to_room != tmp )
      {
         xit->to_room = tmp;
         xit->vnum = evnum;
         texit = get_exit_to( xit->to_room, rev_dir[edir], location->vnum );
         if( texit )
         {
            texit->rexit = xit;
            xit->rexit = texit;
         }
      }
      argument = one_argument( argument, arg3 );
      if( arg3 && arg3[0] != '\0' )
      {
         int fl;

         fl = get_exflag( arg3 );

         if( fl < 0 || fl > MAX_BITS )
            send_to_char( "Bad exit flag!\n\r", ch );
         else
            SET_EXIT_FLAG( xit, fl );
      }
      if( argument && argument[0] != '\0' )
      {
         one_argument( argument, arg3 );
         ekey = atoi( arg3 );
         if( ekey != 0 || arg3[0] == '0' )
         {
            argument = one_argument( argument, arg3 );
            xit->key = ekey;
         }
         if( argument && argument[0] != '\0' )
         {
            STRFREE( xit->keyword );
            xit->keyword = STRALLOC( argument );
         }
      }
      send_to_char( "New exit added.\n\r", ch );
      return;
   }


Change to:
   if( !str_cmp( arg, "exit" ) )
   {
      bool addexit, numnotdir;

      argument = one_argument( argument, arg2 );
      argument = one_argument( argument, arg3 );
      if( !arg2 || arg2[0] == '\0' )
      {
         send_to_char( "Create, change or remove an exit.\r\n", ch );
         send_to_char( "Usage: redit exit  [room] [key] [keyword] [flags]\r\n", ch );
         return;
      }

      // Pick a direction. Variable edir assumes this value once set.
      addexit = numnotdir = FALSE;
      switch( arg2[0] )
      {
         default:
            edir = get_dir( arg2 );
            break;
         case '+':
            edir = get_dir( arg2 + 1 );
            addexit = TRUE;
            break;
         case '#':
            edir = atoi( arg2 + 1 );
            numnotdir = TRUE;
            break;
      }

      // Pick a target room number for the exit. Set to 0 if not found.
      if( !arg3 || arg3[0] == '\0' )
         evnum = 0;
      else
         evnum = atoi( arg3 );

      if( numnotdir )
      {
         if( ( xit = get_exit_num( location, edir ) ) != NULL )
            edir = xit->vdir;
      }
      else
         xit = get_exit( location, edir );

      // If the evnum value is 0, delete this exit and ignore all other arguments to the command.
      if( !evnum )
      {
         if( xit )
         {
            extract_exit( location, xit );
            send_to_char( "Exit removed.\r\n", ch );
            return;
         }
         send_to_char( "No exit in that direction.\r\n", ch );
         return;
      }

      // Validate the target room vnum is within allowable maximums.
      if( evnum < 1 || evnum > ( sysdata.maxvnum - 1 ) )
      {
         send_to_char( "Invalid room number.\r\n", ch );
         return;
      }

      // Check for existing target room....
      if( !( tmp = get_room_index( evnum ) ) )
      {
         // If outside the person's vnum range, bail out. FIXME: Check for people who can edit globally.
         if( evnum < ch->pcdata->low_vnum || evnum > ch->pcdata->hi_vnum )
         {
            ch_printf( ch, "Room #%d does not exist.\r\n", evnum );
            return;
         }

         // Create the target room if the vnum did not exist yet.
         tmp = make_room( evnum, ch->pcdata->area );
         if( !tmp )
         {
            bug( "%s: make_room failed", __FUNCTION__ );
            return;
         }
      }

      // Actually add or change the exit affected.
      if( addexit || !xit )
      {
         if( numnotdir )
         {
            send_to_char( "Cannot add an exit by number, sorry.\r\n", ch );
            return;
         }
         if( addexit && xit && get_exit_to( location, edir, tmp->vnum ) )
         {
            send_to_char( "There is already an exit in that direction leading to that location.\r\n", ch );
            return;
         }
         xit = make_exit( location, tmp, edir );
         xit->key = -1;
         xCLEAR_BITS( xit->exit_info );
         act( AT_IMMORT, "$n reveals a hidden passage!", ch, NULL, NULL, TO_ROOM );
      }
      else
         act( AT_IMMORT, "Something is different...", ch, NULL, NULL, TO_ROOM );

      // A sanity check to make sure it got sent to the proper place.
      if( xit->to_room != tmp )
      {
         xit->to_room = tmp;
         xit->vnum = evnum;
         texit = get_exit_to( xit->to_room, rev_dir[edir], location->vnum );
         if( texit )
         {
            texit->rexit = xit;
            xit->rexit = texit;
         }
      }

      // Set the vnum of the key required to unlock this exit.
      argument = one_argument( argument, arg3 );
      if( arg3 && arg3[0] != '\0' )
      {
         ekey = atoi( arg3 );
         if( ekey != 0 || arg3[0] == '0' )
            xit->key = ekey;
      }

      // Set a keyword on this exit. "door", "gate", etc. Only accepts *ONE* keyword.
      argument = one_argument( argument, arg3 );
      if( arg3 && arg3[0] != '\0' )
      {
         STRFREE( xit->keyword );
         xit->keyword = STRALLOC( arg3 );
      }

      // And finally set any flags which have been specified.
      if( argument && argument[0] != '\0' )
      {
         while( argument[0] != '\0' )
         {
            argument = one_argument( argument, arg3 );
            value = get_exflag( arg3 );
            if( value < 0 || value > MAX_BITS )
               ch_printf( ch, "Unknown exit flag: %s\r\n", arg3 );
            else
               xTOGGLE_BIT( xit->exit_info, value );
         }
      }

      // WOO! Finally done. Inform the user.
      send_to_char( "New exit added.\r\n", ch );
      return;
   }


As written in the code, the redit command has a flaw which will not properly permit the creation of exit flags when generating a new exit. It boils down to "redit exit ..." trying to allow too much at once to be done. Thus this fix reorganizes the code section responsible for it to make it work as it was intended.

It was also suggested that putting single quotes around the flags was the best way to fix this, but it still leaves it open for mistakes by users who forget to do this. But I personally see being forced to use single quotes around a set of arguments as a flaw in design, and will seek to correct those as time permits.

Pages:<< prev 1 next >>