From 3abd8429022833f93f18d1f08abaff8204f53306 Mon Sep 17 00:00:00 2001 From: connorr Date: Thu, 1 Aug 2013 00:55:44 +0200 Subject: [PATCH] Fix possible out of bound error and apply general optimizations in timeleft plugin (bug 5818, r=arkshine) --- plugins/timeleft.sma | 129 +++++++++++++++++++++++++------------------ 1 file changed, 74 insertions(+), 55 deletions(-) diff --git a/plugins/timeleft.sma b/plugins/timeleft.sma index 28255213..fe91fb5b 100755 --- a/plugins/timeleft.sma +++ b/plugins/timeleft.sma @@ -34,40 +34,56 @@ #include +const TASK_TIMEREMAIN_SHORT = 8648458 // 0.8s repeat task +const TASK_TIMEREMAIN_LARGE = 34543 // 1.0s repeat task + +// time display flags +const TD_BOTTOM_WHITE_TEXT = 1 // a - display white text on bottom +const TD_USE_VOICE = 2 // b - use voice +const TD_NO_REMAINING_VOICE = 4 // c - don't add "remaining" (only in voice) +const TD_NO_HOURS_MINS_SECS_VOICE = 8 // d - don't add "hours/minutes/seconds" (only in voice) +const TD_SHOW_SPEAK_VALUES_BELOW = 16 // e - show/speak if current time is less than this set in parameter + new g_TimeSet[32][2] new g_LastTime new g_CountDown new g_Switch +// pcvars +new g_amx_time_voice, g_amx_timeleft +new g_mp_timelimit + public plugin_init() { register_plugin("TimeLeft", AMXX_VERSION_STR, "AMXX Dev Team") register_dictionary("timeleft.txt") - register_cvar("amx_time_voice", "1") + g_amx_time_voice = register_cvar("amx_time_voice", "1") register_srvcmd("amx_time_display", "setDisplaying") - register_cvar("amx_timeleft", "00:00", FCVAR_SERVER|FCVAR_EXTDLL|FCVAR_UNLOGGED|FCVAR_SPONLY) + g_amx_timeleft = register_cvar("amx_timeleft", "00:00", FCVAR_SERVER|FCVAR_EXTDLL|FCVAR_UNLOGGED|FCVAR_SPONLY) register_clcmd("say timeleft", "sayTimeLeft", 0, "- displays timeleft") register_clcmd("say thetime", "sayTheTime", 0, "- displays current time") - set_task(0.8, "timeRemain", 8648458, "", 0, "b") + set_task(0.8, "timeRemain", TASK_TIMEREMAIN_SHORT, "", 0, "b") + + g_mp_timelimit = get_cvar_pointer("mp_timelimit") } public sayTheTime(id) { - if (get_cvar_num("amx_time_voice")) + if (get_pcvar_num(g_amx_time_voice)) { new mhours[6], mmins[6], whours[32], wmins[32], wpm[6] - get_time("%H", mhours, 5) - get_time("%M", mmins, 5) + get_time("%H", mhours, charsmax(mhours)) + get_time("%M", mmins, charsmax(mmins)) new mins = str_to_num(mmins) new hrs = str_to_num(mhours) if (mins) - num_to_word(mins, wmins, 31) + num_to_word(mins, wmins, charsmax(wmins)) else - wmins[0] = 0 + wmins[0] = EOS if (hrs < 12) wpm = "am " @@ -78,7 +94,7 @@ public sayTheTime(id) } if (hrs) - num_to_word(hrs, whours, 31) + num_to_word(hrs, whours, charsmax(whours)) else whours = "twelve " @@ -87,7 +103,7 @@ public sayTheTime(id) new ctime[64] - get_time("%m/%d/%Y - %H:%M:%S", ctime, 63) + get_time("%m/%d/%Y - %H:%M:%S", ctime, charsmax(ctime)) client_print(0, print_chat, "%L: %s", LANG_PLAYER, "THE_TIME", ctime) return PLUGIN_CONTINUE @@ -95,14 +111,14 @@ public sayTheTime(id) public sayTimeLeft(id) { - if (get_cvar_float("mp_timelimit")) + if (get_pcvar_float(g_mp_timelimit)) { new a = get_timeleft() - if (get_cvar_num("amx_time_voice")) + if (get_pcvar_num(g_amx_time_voice)) { new svoice[128] - setTimeVoice(svoice, 127, 0, a) + setTimeVoice(svoice, charsmax(svoice), 0, a) client_cmd(id, "%s", svoice) } client_print(0, print_chat, "%L: %d:%02d", LANG_PLAYER, "TIME_LEFT", (a / 60), (a % 60)) @@ -119,11 +135,11 @@ setTimeText(text[], len, tmlf, id) new mins = tmlf / 60 if (secs == 0) - format(text, len, "%d %L", mins, id, (mins > 1) ? "MINUTES" : "MINUTE") + formatex(text, len, "%d %L", mins, id, (mins > 1) ? "MINUTES" : "MINUTE") else if (mins == 0) - format(text, len, "%d %L", secs, id, (secs > 1) ? "SECONDS" : "SECOND") + formatex(text, len, "%d %L", secs, id, (secs > 1) ? "SECONDS" : "SECOND") else - format(text, len, "%d %L %d %L", mins, id, (mins > 1) ? "MINUTES" : "MINUTE", secs, id, (secs > 1) ? "SECONDS" : "SECOND") + formatex(text, len, "%d %L %d %L", mins, id, (mins > 1) ? "MINUTES" : "MINUTE", secs, id, (secs > 1) ? "SECONDS" : "SECOND") } setTimeVoice(text[], len, flags, tmlf) @@ -132,14 +148,14 @@ setTimeVoice(text[], len, flags, tmlf) new secs = tmlf % 60 new mins = tmlf / 60 - for (new a = 0;a < 7;++a) - temp[a][0] = 0 + // for (new a = 0;a < 7;++a) // we just created it, already null + // temp[a][0] = 0 if (secs > 0) { - num_to_word(secs, temp[4], 31) + num_to_word(secs, temp[4], charsmax(temp[])) - if (!(flags & 8)) + if ( ~flags & TD_NO_HOURS_MINS_SECS_VOICE ) temp[5] = "seconds " /* there is no "second" in default hl */ } @@ -147,9 +163,9 @@ setTimeVoice(text[], len, flags, tmlf) { new hours = mins / 60 - num_to_word(hours, temp[0], 31) + num_to_word(hours, temp[0], charsmax(temp[])) - if (!(flags & 8)) + if ( ~flags & TD_NO_HOURS_MINS_SECS_VOICE ) temp[1] = "hours " mins = mins % 60 @@ -157,37 +173,38 @@ setTimeVoice(text[], len, flags, tmlf) if (mins > 0) { - num_to_word(mins, temp[2], 31) + num_to_word(mins, temp[2], charsmax(temp)) - if (!(flags & 8)) + if ( ~flags & TD_NO_HOURS_MINS_SECS_VOICE ) temp[3] = "minutes " } - if (!(flags & 4)) + if ( ~flags & TD_NO_REMAINING_VOICE ) temp[6] = "remaining " - return format(text, len, "spk ^"vox/%s%s%s%s%s%s%s^"", temp[0], temp[1], temp[2], temp[3], temp[4], temp[5], temp[6]) + return formatex(text, len, "spk ^"vox/%s%s%s%s%s%s%s^"", temp[0], temp[1], temp[2], temp[3], temp[4], temp[5], temp[6]) } -findDispFormat(time) +findDispFormat(_time) { - for (new i = 0; g_TimeSet[i][0]; ++i) + // it is important to check i time) + if (g_TimeSet[i][0] > _time) { if (!g_Switch) { - g_CountDown = g_Switch = time - remove_task(8648458) - set_task(1.0, "timeRemain", 34543, "", 0, "b") + g_CountDown = g_Switch = _time + remove_task(TASK_TIMEREMAIN_SHORT) + set_task(1.0, "timeRemain", TASK_TIMEREMAIN_LARGE, "", 0, "b") } return i } } - else if (g_TimeSet[i][0] == time) + else if (g_TimeSet[i][0] == _time) { return i } @@ -202,17 +219,19 @@ public setDisplaying() new argc = read_argc() - 1 new i = 0 - while (i < argc && i < 32) + while (i < argc && i < sizeof(g_TimeSet)) { - read_argv(i + 1, arg, 31) - parse(arg, flags, 31, num, 31) + read_argv(i + 1, arg, charsmax(arg)) + parse(arg, flags, charsmax(flags), num, charsmax(num)) g_TimeSet[i][0] = str_to_num(num) g_TimeSet[i][1] = read_flags(flags) i++ } - g_TimeSet[i][0] = 0 + + if( i < sizeof(g_TimeSet) ) + g_TimeSet[i][0] = 0 // has to be zeroed in case command is sent twice return PLUGIN_HANDLED } @@ -223,14 +242,14 @@ public timeRemain(param[]) new tmlf = g_Switch ? --g_CountDown : gmtm new stimel[12] - format(stimel, 11, "%02d:%02d", gmtm / 60, gmtm % 60) - set_cvar_string("amx_timeleft", stimel) + formatex(stimel, charsmax(stimel), "%02d:%02d", gmtm / 60, gmtm % 60) + set_pcvar_string(g_amx_timeleft, stimel) if (g_Switch && gmtm > g_Switch) { - remove_task(34543) + remove_task(TASK_TIMEREMAIN_LARGE) g_Switch = 0 - set_task(0.8, "timeRemain", 8648458, "", 0, "b") + set_task(0.8, "timeRemain", TASK_TIMEREMAIN_SHORT, "", 0, "b") return } @@ -245,28 +264,28 @@ public timeRemain(param[]) new flags = g_TimeSet[tm_set][1] new arg[128] - if (flags & 1) + if (flags & TD_BOTTOM_WHITE_TEXT) { - new players[32], pnum + new players[32], pnum, plr get_players(players, pnum, "c") - + + if (flags & TD_SHOW_SPEAK_VALUES_BELOW) // yes this is correct flag, just because message should be shorter if it is shown every seconds + set_hudmessage(255, 255, 255, -1.0, 0.85, 0, 0.0, 1.1, 0.1, 0.5, -1) + else + set_hudmessage(255, 255, 255, -1.0, 0.85, 0, 0.0, 3.0, 0.0, 0.5, -1) + for (new i = 0; i < pnum; i++) { - setTimeText(arg, 127, tmlf, players[i]) - - if (flags & 16) - set_hudmessage(255, 255, 255, -1.0, 0.85, 0, 0.0, 1.1, 0.1, 0.5, -1) - else - set_hudmessage(255, 255, 255, -1.0, 0.85, 0, 0.0, 3.0, 0.0, 0.5, -1) - - show_hudmessage(players[i], "%s", arg) + plr = players[i] + setTimeText(arg, charsmax(arg), tmlf, plr) + show_hudmessage(plr, "%s", arg) } } - if (flags & 2) + if (flags & TD_USE_VOICE) { - setTimeVoice(arg, 127, flags, tmlf) + setTimeVoice(arg, charsmax(arg), flags, tmlf) client_cmd(0, "%s", arg) } }