X-Git-Url: http://de.git.xonotic.org/?a=blobdiff_plain;f=cmd.c;h=82a98ae5e56dc947e22bffcc9760781804536266;hb=018792046effbf5f5743d6ef9569f6c3a2480ae9;hp=a59a46f6189e86fe3ed91c5ee282f31100ec107a;hpb=3b27c0e3bc751cbf1f7c562c2bebfd3ec9b18f58;p=xonotic%2Fdarkplaces.git diff --git a/cmd.c b/cmd.c index a59a46f6..82a98ae5 100644 --- a/cmd.c +++ b/cmd.c @@ -216,7 +216,7 @@ qboolean host_stuffcmdsrun = false; void Cmd_StuffCmds_f (void) { int i, j, l; - // this is per command, and bounds checked (no buffer overflows) + // this is for all commandline options combined (and is bounds checked) char build[MAX_INPUTLINE]; if (Cmd_Argc () != 1) @@ -230,11 +230,12 @@ void Cmd_StuffCmds_f (void) return; host_stuffcmdsrun = true; + build[0] = 0; + l = 0; for (i = 0;i < com_argc;i++) { - if (com_argv[i] && com_argv[i][0] == '+' && (com_argv[i][1] < '0' || com_argv[i][1] > '9')) + if (com_argv[i] && com_argv[i][0] == '+' && (com_argv[i][1] < '0' || com_argv[i][1] > '9') && l + strlen(com_argv[i]) - 1 <= sizeof(build) - 1) { - l = 0; j = 1; while (com_argv[i][j]) build[l++] = com_argv[i][j++]; @@ -245,20 +246,24 @@ void Cmd_StuffCmds_f (void) continue; if ((com_argv[i][0] == '+' || com_argv[i][0] == '-') && (com_argv[i][1] < '0' || com_argv[i][1] > '9')) break; - if (l + strlen(com_argv[i]) + 5 > sizeof(build)) + if (l + strlen(com_argv[i]) + 4 > sizeof(build) - 1) break; build[l++] = ' '; - build[l++] = '\"'; + if (strchr(com_argv[i], ' ')) + build[l++] = '\"'; for (j = 0;com_argv[i][j];j++) build[l++] = com_argv[i][j]; - build[l++] = '\"'; + if (strchr(com_argv[i], ' ')) + build[l++] = '\"'; } build[l++] = '\n'; - build[l++] = 0; - Cbuf_InsertText (build); i--; } } + // now terminate the combined string and prepend it to the command buffer + // we already reserved space for the terminator + build[l++] = 0; + Cbuf_InsertText (build); } @@ -1164,6 +1169,7 @@ Sends an entire command string over to the server, unprocessed */ void Cmd_ForwardStringToServer (const char *s) { + char temp[128]; if (cls.state != ca_connected) { Con_Printf("Can't \"%s\", not connected\n", s); @@ -1180,7 +1186,105 @@ void Cmd_ForwardStringToServer (const char *s) MSG_WriteByte(&cls.netcon->message, qw_clc_stringcmd); else MSG_WriteByte(&cls.netcon->message, clc_stringcmd); - SZ_Write(&cls.netcon->message, (const unsigned char *)s, (int)strlen(s) + 1); + if ((!strncmp(s, "say ", 4) || !strncmp(s, "say_team ", 9)) && cl_locs_enable.integer) + { + // say/say_team commands can replace % character codes with status info + while (*s) + { + if (*s == '%' && s[1]) + { + // handle proquake message macros + temp[0] = 0; + switch (s[1]) + { + case 'l': // current location + CL_Locs_FindLocationName(temp, sizeof(temp), cl.movement_origin); + break; + case 'h': // current health + dpsnprintf(temp, sizeof(temp), "%i", cl.stats[STAT_HEALTH]); + break; + case 'a': // current armor + dpsnprintf(temp, sizeof(temp), "%i", cl.stats[STAT_ARMOR]); + break; + case 'x': // current rockets + dpsnprintf(temp, sizeof(temp), "%i", cl.stats[STAT_ROCKETS]); + break; + case 'c': // current cells + dpsnprintf(temp, sizeof(temp), "%i", cl.stats[STAT_CELLS]); + break; + // silly proquake macros + case 'd': // loc at last death + CL_Locs_FindLocationName(temp, sizeof(temp), cl.lastdeathorigin); + break; + case 't': // current time + dpsnprintf(temp, sizeof(temp), "%.0f:%.0f", floor(cl.time / 60), cl.time - floor(cl.time / 60) * 60); + break; + case 'r': // rocket launcher status ("I have RL", "I need rockets", "I need RL") + if (!(cl.stats[STAT_ITEMS] & IT_ROCKET_LAUNCHER)) + dpsnprintf(temp, sizeof(temp), "I need RL"); + else if (!cl.stats[STAT_ROCKETS]) + dpsnprintf(temp, sizeof(temp), "I need rockets"); + else + dpsnprintf(temp, sizeof(temp), "I have RL"); + break; + case 'p': // powerup status (outputs "quad" "pent" and "eyes" according to status) + if (cl.stats[STAT_ITEMS] & IT_QUAD) + { + if (temp[0]) + strlcat(temp, " ", sizeof(temp)); + strlcat(temp, "quad", sizeof(temp)); + } + if (cl.stats[STAT_ITEMS] & IT_INVULNERABILITY) + { + if (temp[0]) + strlcat(temp, " ", sizeof(temp)); + strlcat(temp, "pent", sizeof(temp)); + } + if (cl.stats[STAT_ITEMS] & IT_INVISIBILITY) + { + if (temp[0]) + strlcat(temp, " ", sizeof(temp)); + strlcat(temp, "eyes", sizeof(temp)); + } + break; + case 'w': // weapon status (outputs "SSG:NG:SNG:GL:RL:LG" with the text between : characters omitted if you lack the weapon) + if (cl.stats[STAT_ITEMS] & IT_SUPER_SHOTGUN) + strlcat(temp, "SSG", sizeof(temp)); + strlcat(temp, ":", sizeof(temp)); + if (cl.stats[STAT_ITEMS] & IT_NAILGUN) + strlcat(temp, "NG", sizeof(temp)); + strlcat(temp, ":", sizeof(temp)); + if (cl.stats[STAT_ITEMS] & IT_SUPER_NAILGUN) + strlcat(temp, "SNG", sizeof(temp)); + strlcat(temp, ":", sizeof(temp)); + if (cl.stats[STAT_ITEMS] & IT_GRENADE_LAUNCHER) + strlcat(temp, "GL", sizeof(temp)); + strlcat(temp, ":", sizeof(temp)); + if (cl.stats[STAT_ITEMS] & IT_ROCKET_LAUNCHER) + strlcat(temp, "RL", sizeof(temp)); + strlcat(temp, ":", sizeof(temp)); + if (cl.stats[STAT_ITEMS] & IT_LIGHTNING) + strlcat(temp, "LG", sizeof(temp)); + break; + default: + // not a recognized macro, print it as-is... + temp[0] = s[0]; + temp[1] = s[1]; + temp[2] = 0; + break; + } + // write the resulting text + SZ_Write(&cls.netcon->message, (unsigned char *)temp, strlen(temp)); + s += 2; + continue; + } + MSG_WriteByte(&cls.netcon->message, *s); + s++; + } + MSG_WriteByte(&cls.netcon->message, 0); + } + else // any other command is passed on as-is + SZ_Write(&cls.netcon->message, (const unsigned char *)s, (int)strlen(s) + 1); } /*