Exception reported: Client index 0 is invalid

galaktica

Участник
Сообщения
57
Реакции
9
Помогите с плагином. Флудит ошибкой, а как исправить - не знаю. [css v34]

L 04/13/2021 - 14:22:05: [SM] Call stack trace:
L 04/13/2021 - 14:22:05: [SM] [0] IsClientInGame
L 04/13/2021 - 14:22:05: [SM] [1] Line 305, C:\Users\Александр\Desktop\Новая папка (2)\Compiler 1.10.0.6490\scripting\sm_jail_warden.sp::Timer_Func
L 04/13/2021 - 14:22:05: [SM] Exception reported: Client index 0 is invalid
L 04/13/2021 - 14:22:05: [SM] Blaming: sm_jail_warden.smx

if (all_votes < 1)
{
new last_cmd[65];
new ct_count = 0;
for(new z = 1; z <= GetMaxClients(); z++)
{
if(IsClientInGame(z) && !IsFakeClient(z) && GetClientTeam(z) == CS_TEAM_CT && IsPlayerAlive(z))
{
last_cmd[z] = z;
ct_count++;
}
}
new random_cmd = last_cmd[GetRandomInt(1,ct_count)];
CT_Vote_cmd = 0;
if(IsClientInGame(random_cmd) && !IsFakeClient(random_cmd) && GetClientTeam(random_cmd) == CS_TEAM_CT && IsPlayerAlive(random_cmd)) //проверка проверка проверка :D
{
SetTheWarden(random_cmd);
ShowMyPanel(random_cmd);
}
else if(ct_count == 0)
{
CPrintToChatAll("\x01[\x04КМД\x01] Голосование провалилось!");
CT_Vote_cmd = 0;
return Plugin_Stop;
}

CPrintToChatAll("\x01[\x04КМД\x01] Голосов нет, \x04КМД \x03становится \x04%N", random_cmd);
//
}
else
{
CT_Vote_cmd = 0;
}


Исходник приложил
 

Вложения

  • sm_jail_warden.sp
    31.8 КБ · Просмотры: 16

Dark_Legend

Добрая душа
Сообщения
9
Реакции
9
У тебя сначала создаётся массив целых чисел размером с количество игроков( по умолчанию значение каждой ячейки равно 0 ). Далее у тебя идёт цикл с условием, что z - индекс существующего живого игрока за команду КТ. Значит часть ячеек last_cmd может останется нетронутыми(= 0). После этого ты рандомно выбираешь число от 1 до 64, и в условии появляется ошибка. Возникла она из-за того, что случайное число стало индексом одной из нетронутых ячеек, значение которой равно нулю, соответственно и в условие попадает 0. Если перевести ошибку, то он как раз ругается на то, что индекс игрока 0 недопустим.
Нужно не допускать того, чтобы мог выпасть индекс, неизменённой ячейки.

Можно создать дополнительную переменную, с помощью которой правильные индексы игроков будут записываться в массив последовательно, избегая нетронутых промежутков. У тебя такая имеется - ct_count. Нужно поставить её вместо z.

C-подобный:
new last_cmd[65];
new ct_count = 0;
for(new z = 1; z <= GetMaxClients(); z++)
{
   if(IsClientInGame(z) && !IsFakeClient(z) && GetClientTeam(z) == CS_TEAM_CT && IsPlayerAlive(z))
   {
      last_cmd[ct_count] = z;
      ct_count++;
   }
}
 

galaktica

Участник
Сообщения
57
Реакции
9
У тебя сначала создаётся массив целых чисел размером с количество игроков( по умолчанию значение каждой ячейки равно 0 ). Далее у тебя идёт цикл с условием, что z - индекс существующего живого игрока за команду КТ. Значит часть ячеек last_cmd может останется нетронутыми(= 0). После этого ты рандомно выбираешь число от 1 до 64, и в условии появляется ошибка. Возникла она из-за того, что случайное число стало индексом одной из нетронутых ячеек, значение которой равно нулю, соответственно и в условие попадает 0. Если перевести ошибку, то он как раз ругается на то, что индекс игрока 0 недопустим.
Нужно не допускать того, чтобы мог выпасть индекс, неизменённой ячейки.

Можно создать дополнительную переменную, с помощью которой правильные индексы игроков будут записываться в массив последовательно, избегая нетронутых промежутков. У тебя такая имеется - ct_count. Нужно поставить её вместо z.

C-подобный:
new last_cmd[65];
new ct_count = 0;
for(new z = 1; z <= GetMaxClients(); z++)
{
   if(IsClientInGame(z) && !IsFakeClient(z) && GetClientTeam(z) == CS_TEAM_CT && IsPlayerAlive(z))
   {
      last_cmd[ct_count] = z;
      ct_count++;
   }
}
Спасибо за ответ! Можно слегка попроще объяснить для рядовых любителей, которые могут только PrintToChat и другое простенькое изменить в исходнике 🙂 Если еще и помощь в написании будет, то вообще волшебно
 

Dark_Legend

Добрая душа
Сообщения
9
Реакции
9
Спасибо за ответ! Можно слегка попроще объяснить для рядовых любителей, которые могут только PrintToChat и другое простенькое изменить в исходнике 🙂 Если еще и помощь в написании будет, то вообще волшебно
Плагин ищет игроков, которые живые и играют за команду КТ. Для этого используется цик for где с числа 1 по число 64(максимально возможное количество игроков на сервере) включительно проводятся проверки в if: принадлежит ли вообще это число индексу игрока? не является ли игрок ботом? играет ли он за КТ? жив ли он?
Если число проходит эти проверки, то оно записывается в массив.

После выполнения цикла по игрокам, по задумке плагин должен получать случайный проверенный индекс игрока(число от 1 до 64), после выполнить с ним какие-то действия. Для этого нужно из того массива, в который мы записывали проверенные индексы игроков, получить случайно выбранное записанное значение, коим будет является случайный проверенный индекс игрока. И уже потом с этим случайным индексом выполняются нужные действия.

Но по факту из этого массива можно получить не только проверенный индекс, а вообще что угодно. Происходит это из-за того, что случайный номер ячейки, в которой будет находится проверенный индекс нужно выбирать в конкретном диапазоне, который определяется количеством проверенных индексов. В том коде это было сделать невозможно, потому что там эти индексы записывались непоследовательно( например: 34, 54, 0, 24, 0, 0, 15 и т.д.), то есть были промежутки в которых значение не было заменено.

Это исправить можно максимально просто. Я это показал в своём первом ответе: 299 строка: last_cmd[z] = z; -> last_cmd[ct_count] = z;

Прикрепил на всякий случай исправленный вариант
 

Вложения

  • sm_jail_warden.sp
    31.8 КБ · Просмотры: 9

galaktica

Участник
Сообщения
57
Реакции
9
Плагин ищет игроков, которые живые и играют за команду КТ. Для этого используется цик for где с числа 1 по число 64(максимально возможное количество игроков на сервере) включительно проводятся проверки в if: принадлежит ли вообще это число индексу игрока? не является ли игрок ботом? играет ли он за КТ? жив ли он?
Если число проходит эти проверки, то оно записывается в массив.

После выполнения цикла по игрокам, по задумке плагин должен получать случайный проверенный индекс игрока(число от 1 до 64), после выполнить с ним какие-то действия. Для этого нужно из того массива, в который мы записывали проверенные индексы игроков, получить случайно выбранное записанное значение, коим будет является случайный проверенный индекс игрока. И уже потом с этим случайным индексом выполняются нужные действия.

Но по факту из этого массива можно получить не только проверенный индекс, а вообще что угодно. Происходит это из-за того, что случайный номер ячейки, в которой будет находится проверенный индекс нужно выбирать в конкретном диапазоне, который определяется количеством проверенных индексов. В том коде это было сделать невозможно, потому что там эти индексы записывались непоследовательно( например: 34, 54, 0, 24, 0, 0, 15 и т.д.), то есть были промежутки в которых значение не было заменено.

Это исправить можно максимально просто. Я это показал в своём первом ответе: 299 строка: last_cmd[z] = z; -> last_cmd[ct_count] = z;

Прикрепил на всякий случай исправленный вариант
Спасибо, проведу тесты 👍

Если не сложно, помоги понять ошибку:

L 04/13/2021 - 03:00:17: [SM] Exception reported: Invalid database Handle 0 (error: 4)
L 04/13/2021 - 03:00:17: [SM] Blaming: sm_ctban.smx
L 04/13/2021 - 03:00:17: [SM] Call stack trace:
L 04/13/2021 - 03:00:17: [SM] [0] SQL_TQuery
L 04/13/2021 - 03:00:17: [SM] [1] Line 204, sm_ctban.sp::OnClientAuthorized

Если ошибка из-за неправильного написания в databases.cfg, то все в этом файле прописал верно, все работает, но одна и та же ошибка. Не понимаю о чем речь вообще.

#if USESQL == 1
// check if the Steam ID is in the Timed Ban list
decl String:query[255];
Format(query, sizeof(query), "SELECT ctbantime FROM %s WHERE steamid = '%s'", g_sTimesTableName, sSteamID);
SQL_TQuery(gH_BanDatabase, DB_Callback_OnClientAuthed, query, _:client);
 

Dark_Legend

Добрая душа
Сообщения
9
Реакции
9
Спасибо, проведу тесты 👍

Если не сложно, помоги понять ошибку:

L 04/13/2021 - 03:00:17: [SM] Exception reported: Invalid database Handle 0 (error: 4)
L 04/13/2021 - 03:00:17: [SM] Blaming: sm_ctban.smx
L 04/13/2021 - 03:00:17: [SM] Call stack trace:
L 04/13/2021 - 03:00:17: [SM] [0] SQL_TQuery
L 04/13/2021 - 03:00:17: [SM] [1] Line 204, sm_ctban.sp::OnClientAuthorized

Если ошибка из-за неправильного написания в databases.cfg, то все в этом файле прописал верно, все работает, но одна и та же ошибка. Не понимаю о чем речь вообще.

#if USESQL == 1
// check if the Steam ID is in the Timed Ban list
decl String:query[255];
Format(query, sizeof(query), "SELECT ctbantime FROM %s WHERE steamid = '%s'", g_sTimesTableName, sSteamID);
SQL_TQuery(gH_BanDatabase, DB_Callback_OnClientAuthed, query, _:client);
Проблема с переменной типа Database, которая является соединением с базой. Причин может быть несколько. Самые очевидные - потеря соединения с базой данных, либо проблема соединения с ней при старте плагина(по-хорошему в таком случае плагин должен выдать собственную ошибку и выгрузиться)

Может помочь перезагрузка плагина. Введи в консоли сервера sm plugins unload sm_ctban. Далее смени карту на сервере. Если проблема не решилась - нужно писать автору плагина.
 

galaktica

Участник
Сообщения
57
Реакции
9
Плагин ищет игроков, которые живые и играют за команду КТ. Для этого используется цик for где с числа 1 по число 64(максимально возможное количество игроков на сервере) включительно проводятся проверки в if: принадлежит ли вообще это число индексу игрока? не является ли игрок ботом? играет ли он за КТ? жив ли он?
Если число проходит эти проверки, то оно записывается в массив.

После выполнения цикла по игрокам, по задумке плагин должен получать случайный проверенный индекс игрока(число от 1 до 64), после выполнить с ним какие-то действия. Для этого нужно из того массива, в который мы записывали проверенные индексы игроков, получить случайно выбранное записанное значение, коим будет является случайный проверенный индекс игрока. И уже потом с этим случайным индексом выполняются нужные действия.

Но по факту из этого массива можно получить не только проверенный индекс, а вообще что угодно. Происходит это из-за того, что случайный номер ячейки, в которой будет находится проверенный индекс нужно выбирать в конкретном диапазоне, который определяется количеством проверенных индексов. В том коде это было сделать невозможно, потому что там эти индексы записывались непоследовательно( например: 34, 54, 0, 24, 0, 0, 15 и т.д.), то есть были промежутки в которых значение не было заменено.

Это исправить можно максимально просто. Я это показал в своём первом ответе: 299 строка: last_cmd[z] = z; -> last_cmd[ct_count] = z;

Прикрепил на всякий случай исправленный вариант
Ошибка по-прежнему осталась
 
Сверху Снизу