» SmaugMuds » Bugfix Lists » AFKMud Bugfix List » AFKMud Bug Archive » [Bug] Exit creation stumbles ...
Pages:<< prev 1 next >>
#1 Dec 2, 2006 6:53 pm
Last edited Dec 2, 2006 6:53 pm by 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:
Change to:
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.
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
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 >>