- Posts: 157
- Thank you received: 17
do_commands
- Fizban
- Topic Author
- Offline
- Administrator
-
It doesn't appear to be an issue with do_commands itself, it seems to be an issue with the string being passed to column_list already having info in it when it is being substantiated. When you use social or commands, the pre-existing information in the string is being overwritten and thus hidden from view, but because mortals don't have any access to immortal commands, nothing is being added to the string when wizhelp is called as the subcommand so it's showing whatever content it had still stored in it.
On a brand new character wizhelp <name> shows nothing.
If the mortal uses the socials or commands, commands, then wizhelp <mortal> then shows you the info they most recently saw. If however the mortals most recent commands were something entirely different then it often shows corrupted nonsensical info, such as the name of mobs from zones the mortal has never been to, or random characters.
ACMD(do_commands)
{
int no, i, cmd_num;
int wizhelp = 0, socials = 0;
struct char_data *vict;
char arg[MAX_INPUT_LENGTH];
char buf[MAX_STRING_LENGTH];
const char *commands[1000];
int overflow = sizeof(commands) / sizeof(commands[0]);
if (!ch->desc)
return;
one_argument(argument, arg);
if (*arg) {
if (!(vict = get_char_vis(ch, arg, NULL, FIND_CHAR_WORLD)) || IS_NPC(vict)) {
send_to_char(ch, "Who is that?\r\n");
return;
}
} else
vict = ch;
if (subcmd == SCMD_SOCIALS)
socials = 1;
else if (subcmd == SCMD_WIZHELP)
wizhelp = 1;
sprintf(buf, "The following %s%s are available to %s:\r\n",
wizhelp ? "privileged " : "",
socials ? "socials" : "commands",
vict == ch ? "you" : GET_NAME(vict));
/* cmd_num starts at 1, not 0, to remove 'RESERVED' */
for (no = 0, cmd_num = 1;
complete_cmd_info[cmd_sort_info[cmd_num]].command[0] != '\n';
++cmd_num) {
i = cmd_sort_info[cmd_num];
if (complete_cmd_info[i].minimum_level < 0 || GET_LEVEL(vict) < complete_cmd_info[i].minimum_level)
continue;
if ((complete_cmd_info[i].minimum_level >= LVL_IMMORT) != wizhelp)
continue;
if (!wizhelp && socials != (complete_cmd_info[i].command_pointer == do_action))
continue;
if (wizhelp && complete_cmd_info[i].command_pointer == do_action)
continue;
if (--overflow < 0)
continue;
/* matching command: copy to commands list */
commands[no++] = complete_cmd_info[i].command;
}
/* display commands list in a nice columnized format */
column_list(ch, 0, commands, no, FALSE);
}
The only issue I see with do_commands itself is there's a completely useless buf char created, that has info put inside of it, but is never actually sent anywhere. I'd just remove the buf and send the string via send_to_char, but that part really isn't important as it's not related to the corrupted info winding up inside of commands.
Please Log in or Create an account to join the conversation.
- Fizban
- Topic Author
- Offline
- Administrator
-
- Posts: 157
- Thank you received: 17
void column_list(struct char_data *ch, int num_cols, const char **list, int list_length, bool show_nums)
{
size_t max_len = 0, len = 0, temp_len;
int num_per_col, col_width, r, c, i, offset = 0;
char buf[MAX_STRING_LENGTH];
/* Work out the longest list item */
for (i=0; i<list_length; i++)
if (max_len < strlen(list[i]))
max_len = strlen(list[i]);
/* auto columns case */
if (num_cols == 0) {
num_cols = (IS_NPC(ch) ? 80 : GET_SCREEN_WIDTH(ch)) / (max_len + (show_nums ? 5 : 1));
}
/* Ensure that the number of columns is in the range 1-10 */
num_cols = MIN(MAX(num_cols,1), 10);
/* Work out the longest list item */
for (i=0; i<list_length; i++)
if (max_len < strlen(list[i]))
max_len = strlen(list[i]);
/* Calculate the width of each column */
if (IS_NPC(ch)) col_width = 80 / num_cols;
else col_width = (GET_SCREEN_WIDTH(ch)) / num_cols;
if (show_nums) col_width-=4;
if (col_width < 0 || (size_t)col_width < max_len)
log("Warning: columns too narrow for correct output to %s in simple_column_list (utils.c)", GET_NAME(ch));
/* Calculate how many list items there should be per column */
num_per_col = (list_length / num_cols) + ((list_length % num_cols) ? 1 : 0);
/* Fill 'buf' with the columnised list */
for (r=0; r<num_per_col; r++)
{
for (c=0; c<num_cols; c++)
{
offset = (c*num_per_col)+r;
if (offset < list_length)
{
if (show_nums)
temp_len = snprintf(buf+len, sizeof(buf) - len, "%2d) %-*s", offset+1, col_width, list[(offset)]);
else
temp_len = snprintf(buf+len, sizeof(buf) - len, "%-*s", col_width, list[(offset)]);
len += temp_len;
}
}
temp_len = snprintf(buf+len, sizeof(buf) - len, "\r\n");
len += temp_len;
}
if (len >= sizeof(buf))
snprintf((buf + MAX_STRING_LENGTH) - 22, 22, "\r\n*** OVERFLOW ***\r\n");
/* Send the list to the player */
page_string(ch->desc, buf, TRUE);
}
Here's sample output:
Please Log in or Create an account to join the conversation.
- thomas
-
- Offline
- Administrator
-
- Posts: 818
- Thank you received: 159
char buf[MAX_STRING_LENGTH];
+ *buf='\0';
/* Work out the longest list item */
Please Log in or Create an account to join the conversation.
- Fizban
- Topic Author
- Offline
- Administrator
-
- Posts: 157
- Thank you received: 17
Please Log in or Create an account to join the conversation.
- WhiskyTest
-
- Offline
- Platinum Member
-
- Posts: 345
- Thank you received: 73
Please Log in or Create an account to join the conversation.
- thomas
-
- Offline
- Administrator
-
- Posts: 818
- Thank you received: 159
No. The cause is that buf is allocated on calling the function. But while the memory is made ready to use on the stack, it isn't cleared. So, if you don't write anything to it, you get what's in it.Fizban wrote: That does fix the output, but isn't that just fixing the symptom rather than the actual cause?
The correct solution is to add a NULL as the first byte before starting to treat it like a (null-terminated) string. Which this does.
Please Log in or Create an account to join the conversation.
- JTP
- Offline
- Platinum Member
-
- Posts: 937
- Thank you received: 17
Mine Seem to look ok
Please Log in or Create an account to join the conversation.
- Fizban
- Topic Author
- Offline
- Administrator
-
- Posts: 157
- Thank you received: 17
Please Log in or Create an account to join the conversation.
- JTP
- Offline
- Platinum Member
-
- Posts: 937
- Thank you received: 17
Please Log in or Create an account to join the conversation.
- JTP
- Offline
- Platinum Member
-
- Posts: 937
- Thank you received: 17
It just returns, no output. Mortals should not have Any wiz commands
Please Log in or Create an account to join the conversation.
- Sascha
-
- Offline
- Elite Member
-
i1 510H 110M 92V >
wizhelp vivtest
ツヘᄄ1
i1 510H 110M 92V >
Thanks for the catch, I'll be making the change this afternoon.
Will you stand against the coming Storm? After the Breaking: STORMRIDERS MUD - atbmud.dune.net port 4000
Please Log in or Create an account to join the conversation.
- JTP
- Offline
- Platinum Member
-
- Posts: 937
- Thank you received: 17
Please Log in or Create an account to join the conversation.
- JTP
- Offline
- Platinum Member
-
- Posts: 937
- Thank you received: 17
Please Log in or Create an account to join the conversation.
- JTP
- Offline
- Platinum Member
-
- Posts: 937
- Thank you received: 17
Please Log in or Create an account to join the conversation.
- Fizban
- Topic Author
- Offline
- Administrator
-
- Posts: 157
- Thank you received: 17
Please Log in or Create an account to join the conversation.
- JTP
- Offline
- Platinum Member
-
- Posts: 937
- Thank you received: 17
Until i have typed wizhelp myownname...and Then If i again type wizhelp testchar, Then it shows my wiz commands ?
Where when i try on tbamud, wizhelp testchar, it from the first time shows wiz commands, but its a level 1 i tried on...but at the very end of the wizcommands it Then writes: peacThe Propagandist
Now where did that Come from.
Please Log in or Create an account to join the conversation.