Проверка на отключение игрока(Вопрос)

R1KO

fuck society
Сообщения
9,457
Реакции
7,786
  • Команда форума
  • #1
Здавствуйте. Не подкажете как в sourcepawn, при отключении игрока проверить находился ли он в игре ?

Вот, например, игрок начинает подключаться и сразу нажимает отмена. Как исключить такие случаи из проверки ?
 

KorDen

Atra esterní ono thelduin!
Сообщения
2,142
Реакции
1,424
Кстати, на каком этапе игроку назначается id? Когда делаю хук player_connect, то в этот момент получить через GetClientOfUserId клиента нельзя... Или при EventHookMode_Post уже должен назначиться? (там где я это уже испоользовал, было EventHookMode_Pre, и там его не было...)

Проще говоря, можно получить id игрока раньше вызова OnClientConnect?
 

_wS_

Участник
Сообщения
383
Реакции
760
его ответ правильный
Не совсем. Если конектишься и почти в самый последний момент жмешь "Отмена" (выход), то IsClientInGame вернет true, но игрок то полностью не вошел.

Проще говоря, можно получить id игрока раньше вызова OnClientConnect?
Наверно нет, только если с расширением каким-то, да и зачем это.

Вот, например, игрок начинает подключаться и сразу нажимает отмена. Как исключить такие случаи из проверки ?
new bool:g_InGame[MAXPLAYERS + 1];

В событии каком-нибудь, когда уверен что он зашел (spawn, team и тд), делаешь g_InGame[client] = true;
Ну а когда выходит, просто:

C-подобный:
if (g_InGame[client])
{
    g_InGame[client] = false;

    // ...
}
Или с таймером есть вариант, неужели фантазии нет.
 
  • Мне нравится
Реакции: R1KO

FrozDark

Участник
Сообщения
1,769
Реакции
2,050
Не совсем. Если конектишься и почти в самый последний момент жмешь "Отмена" (выход), то IsClientInGame вернет true, но игрок то полностью не вошел.

значит у игрока просто медленный компьютер и не успевает убрать интерфейс, потому как игрок действительно прошёл все этапы захода, даже его ник окажется в наблюдателях

Кстати, на каком этапе игроку назначается id? Когда делаю хук player_connect, то в этот момент получить через GetClientOfUserId клиента нельзя... Или при EventHookMode_Post уже должен назначиться? (там где я это уже испоользовал, было EventHookMode_Pre, и там его не было...)

Проще говоря, можно получить id игрока раньше вызова OnClientConnect?

https://forums.alliedmods.net/showthread.php?t=162489 - раньше чем даже OnClientConnect
 
  • Мне нравится
Реакции: R1KO

_wS_

Участник
Сообщения
383
Реакции
760
значит у игрока просто медленный компьютер и не успевает убрать интерфейс, потому как игрок действительно прошёл все этапы захода, даже его ник окажется в наблюдателях
Может и так, но автор просил учитывать факт нажатия кнопки отмены во время конекта, пусть даже это этот баг. Так что в его случае такой вариант с IsClientInGame может не всегда работать, если он хочет быть уверен, что покинувший сервер чел хотя бы видел motd окно-приветствие.
 
Последнее редактирование:

R1KO

fuck society
Сообщения
9,457
Реакции
7,786
  • Команда форума
  • #9
Может и так, но автор просил учитывать факт нажатия кнопки отмены во время конекта, пусть даже это этот баг. Так что в его случае такой вариант с IsClientInGame может не всегда работать, если он хочет быть уверен, что покинувший сервер чел хотя бы видел motd окно-приветствие.

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

Просто игрок нажимая отмену так же вызывает дисконнект. А нужно отловить только дисконнект игрока который был в игре.
 

V-Rico

SM Скриптер (Skype: v-rico.95)
Сообщения
22
Реакции
9
Как вариант вместо IsClientInGame использовать GetClientAvgLatency(client, NetFlow_Outgoing). Если игрок не подключен, то вернет -1 (по идее, я не проверял). Ну, или же вернет какое-то поднебесное значение (стремящееся к бесконечности; рассчет на то, что пакет будет идти ооооочень долго).
 

KorDen

Atra esterní ono thelduin!
Сообщения
2,142
Реакции
1,424
Как вариант вместо IsClientInGame использовать GetClientAvgLatency(client, NetFlow_Outgoing). Если игрок не подключен, то вернет -1 (по идее, я не проверял). Ну, или же вернет какое-то поднебесное значение (стремящееся к бесконечности; рассчет на то, что пакет будет идти ооооочень долго).

http://docs.sourcemod.net/api/index.php?fastload=show&id=437&
On error / Errors:
Invalid client index, client not in game, or fake client.
Это будет не -1, а ошибка в логи скорее всего.
 

V-Rico

SM Скриптер (Skype: v-rico.95)
Сообщения
22
Реакции
9
http://docs.sourcemod.net/api/index.php?fastload=show&id=437&

Это будет не -1, а ошибка в логи скорее всего.

Да, пожалуй ты прав. Не обратил внимание на ерроры.

Добавлено через 4 минуты
Так можно использовать гибрид
if (IsClientInGame(client))
GetClientAvgLatency(client, NetFlow_Outgoing)

Если IsClientInGame возвращает true, то проверяем задержку. По идее, в таком случае ерроров не должно быть, ведь индекс будет нормальным, игрок будет "на сервере" и он не фейковый.
 
Последнее редактирование:
  • Мне нравится
Реакции: R1KO

R1KO

fuck society
Сообщения
9,457
Реакции
7,786
  • Команда форума
  • #13
Не подкажете как это использовать ? :)

Чтобы отловить дисконнект игрока который был в игре, а тех кто нажал отмена или были забанены и попытались войти исключались.
 

FrozDark

Участник
Сообщения
1,769
Реакции
2,050
PHP:
public OnClientDisconnect(client)
{
     if (IsClientInGame(client))
     {
          // Клиент был в игре и отключился
     }
}
 

KorDen

Atra esterní ono thelduin!
Сообщения
2,142
Реакции
1,424
Так можно использовать гибрид
C-подобный:
if (IsClientInGame(client))
 GetClientAvgLatency(client, NetFlow_Outgoing)

Если IsClientInGame возвращает true, то проверяем задержку. По идее, в таком случае ерроров не должно быть, ведь индекс будет нормальным, игрок будет "на сервере" и он не фейковый.

И какой смысл этого "гибрида"??? Когда клиент - бот, тоже будет материться, так как, еще раз повторю, "On error / Errors: Invalid client index, client not in game, or fake client". А если он InGame и не фейк, то какой вообще смысл проверки на задержку, она и так должна быть...
 

V-Rico

SM Скриптер (Skype: v-rico.95)
Сообщения
22
Реакции
9
И какой смысл этого "гибрида"??? Когда клиент - бот, тоже будет материться, так как, еще раз повторю, "On error / Errors: Invalid client index, client not in game, or fake client". А если он InGame и не фейк, то какой вообще смысл проверки на задержку, она и так должна быть...

Ну еще и IsFakeClient добавить. А смысл простой. Тебе ведь объясняли: если нажать отмену в самый последний момент, то IsClientInGame будет возвращать true. Если IP клиента останется, то пинговаться будет. А так - не думаю, ведь даже кидать пакеты некуда будет.

Итог такой:
PHP:
public OnClientDisconnect(client) 
{ 
     if (IsClientInGame(client) && !IsFakeClient(client)) 
     { 
          // Клиент был в игре, не был ботом и отключился

          // Нужно попробовать запустить с этой строчкой, чтобы понять какое значение вернется
          LogError("%i", GetClientAvgLatency(client, NetFlow_Outgoing));

          // Как только мы в самый первый раз узнаем что вернет функция, то оставляем только след. строчку, которая будет проверять
          if (GetClientAvgLatency(client, NetFlow_Outgoing)) != -1 // (или > N, зависит от результатов теста)
          {
                   // Делаем то, что нужно
          }
     } 
}
 
  • Мне нравится
Реакции: R1KO

FrozDark

Участник
Сообщения
1,769
Реакции
2,050
Ну еще и IsFakeClient добавить. А смысл простой. Тебе ведь объясняли: если нажать отмену в самый последний момент, то IsClientInGame будет возвращать true. Если IP клиента останется, то пинговаться будет. А так - не думаю, ведь даже кидать пакеты некуда будет.

Итог такой:
PHP:
public OnClientDisconnect(client) 
{ 
     if (IsClientInGame(client) && !IsFakeClient(client)) 
     { 
          // Клиент был в игре, не был ботом и отключился

          // Нужно попробовать запустить с этой строчкой, чтобы понять какое значение вернется
          LogError("%i", GetClientAvgLatency(client, NetFlow_Outgoing));

          // Как только мы в самый первый раз узнаем что вернет функция, то оставляем только след. строчку, которая будет проверять
          if (GetClientAvgLatency(client, NetFlow_Outgoing)) != -1 // (или > N, зависит от результатов теста)
          {
                   // Делаем то, что нужно
          }
     } 
}

думаешь если игрок IsClientInGame, но вышел в последний момент, GetClientAvgLatency вернет 0?
 

V-Rico

SM Скриптер (Skype: v-rico.95)
Сообщения
22
Реакции
9
думаешь если игрок IsClientInGame, но вышел в последний момент, GetClientAvgLatency вернет 0?

Предполагаю, что вернет -1. Я сегодня попробую.

Добавлено через 1 час 40 минут
К сожалению, не получилось.
L 05/04/2013 - 23:36:54: [test.smx] 28.329099
L 05/04/2013 - 23:37:41: [test.smx] 67.290275

То есть пинг просто вырос в 2 раза, а это ни о чём не говорит

Добавлено через 1 час 46 минут
Кстати, если использовать OnClientDisconnect_Post вместо OnClientDisconnect, то при проверке IsClientInGame будет возвращено false. Может тебе это поможет. Если бы ты поподробнее описал цель, возможно тебе бы и помогли.

Добавлено через 1 час 48 минут
Относительно твоего случая: тебе может помочь, если т будешь менять значение переменной g_bConnected[client]. В OnClientConnect ставишь g_bConnected[client] = true, в OnClientDisconnect_Post - g_bConnected[client] = false. Если я неправильно понял твою цель, поправь меня.
 
Последнее редактирование:
  • Мне нравится
Реакции: R1KO

R1KO

fuck society
Сообщения
9,457
Реакции
7,786
  • Команда форума
  • #19
Если бы ты поподробнее описал цель, возможно тебе бы и помогли.

Цель: при отключении игрока исключить из проверки тех игроков, которые либо недоподключились или были забанены и не смогли подключится(тем самым вызвав событие дисконнект).

На примере.

PHP:
public OnClientDisconnect(client) // ну или event незнаю, что лучше использовать
{
PrintToChatAll("%N \x01отключился от сервера.", client);
}

Так когда, к примеру, забаненый игрок пытается зайти в чат пишет "ник joined the game" но тут оказывается забаненым, ему пишет "user steam id xxxx is banned" а на сервере в чат пишет "ник left the game" и + плагин выводит "ник отключился от сервера.". Так вот должно выводить только когда игрок действительно вышел, а не любой дисконнект.
 

V-Rico

SM Скриптер (Skype: v-rico.95)
Сообщения
22
Реакции
9
Цель: при отключении игрока исключить из проверки тех игроков, которые либо недоподключились или были забанены и не смогли подключится(тем самым вызвав событие дисконнект).

На примере.

PHP:
public OnClientDisconnect(client) // ну или event незнаю, что лучше использовать
{
PrintToChatAll("%N \x01отключился от сервера.", client);
}

Так когда, к примеру, забаненый игрок пытается зайти в чат пишет "ник joined the game" но тут оказывается забаненым, ему пишет "user steam id xxxx is banned" а на сервере в чат пишет "ник left the game" и + плагин выводит "ник отключился от сервера.". Так вот должно выводить только когда игрок действительно вышел, а не любой дисконнект.

Используй так:
PHP:
public OnClientDisconnect_Post(client)
{ 
    PrintToChatAll("%N \x01отключился от сервера.", client); 
}
 
  • Мне нравится
Реакции: R1KO
Сверху Снизу