Форум Pawn.Wiki - Воплоти мечту в реальность!: Использование SendClientCheck - Форум Pawn.Wiki - Воплоти мечту в реальность!

Перейти к содержимому

Страница 1 из 1
  • Вы не можете создать новую тему
  • Вы не можете ответить в тему

[ Урок ]
Использование SendClientCheck
Оценка: -----

#1
Пользователь офлайн   Макс 

  • Местный
  • Вставить ник
  • Раскрыть информацию
До сих пор эта функция оставалась тайной для многих скриптеров сампа, нигде и никто её не документировал. Что ж, пора пролить свет на эту тёмную сторону сампа.

SendClientCheck

Эта функция отправляет специальный запрос на клиент, затем клиент присылает свой ответ в колбэк OnClientCheckResponse. Задержка ответа зависит в основном от пинга игрока. Функция и паблик не объявлены в стандартных инклудах, так что их придётся объявить самостоятельно в начале скрипта (например, после подключения всех инклудов):

native SendClientCheck(playerid, type, arg, offset, size);
forward OnClientCheckResponse(playerid, type, arg, response);


Разберем аргументы SendClientCheck:
playerid - кому мы отправим запрос
type - тип запроса
arg - специальный аргумент
offset - оффсет чтения памяти
size - размер для чтения (всегда должен быть равен или больше 2)
Разберём подробнее, что всё это значит, чуть позже.

Теперь OnClientCheckResponse:
playerid - от кого пришёл ответ
type - тип ответа
arg - специальный аргумент
response - ещё один аргумент (крутое описание, да?)

Теперь разберёмся, что всё это значит. Есть только 4 типа запросов, которые клиент обрабатывает (аргумент type). Это 0x2, 0x46, 0x47, 0x48.

Тип 0x48
Начнём с простого. Данный запрос не нуждается ни в каких дополнительных аргументах (arg, offset, size). Он возвращает количество секунд с момента запуска компьютера в arg. Пример:
#include <a_samp>

native SendClientCheck(playerid, type, arg, offset, size);
forward OnClientCheckResponse(playerid, type, arg, response);

public OnPlayerConnect(playerid)
{
	SendClientCheck(playerid, 0x48, 0, 0, 2);
	return 1;
}

public OnClientCheckResponse(playerid, type, arg, response)
{
	new str[128];
	switch(type)
	{
		case 0x48:
		{
			format(str, sizeof(str), "Your computer has been running for %s!", Convert(arg / 1000));
			SendClientMessage(playerid, -1, str);
		}
	}
	return 1;
}

Convert(number)
{
    new hours = 0, mins = 0, secs = 0, string[100];
    hours = floatround(number / 3600);
    mins = floatround((number / 60) - (hours * 60));
    secs = floatround(number - ((hours * 3600) + (mins * 60)));
    if(hours > 0)
    {
        format(string, 100, "%d:%02d:%02d", hours, mins, secs);
    }
    else
    {
        format(string, 100, "%d:%02d", mins, secs);
    }
    return string;
}


При входе на сервер игроку напишет, сколько запущен его комп.

Тип 0x46
Этот тип читает данные структуры CBaseModelInfoSA указанной модели и возвращает однобайтовую чексумму. Можно указать, с какого оффсета начать чтение и сколько байт прочитать. Например, запрос SendClientCheck(playerid, 0x46, 1598, 0, 28) вернёт чексумму первых 28 байт структуры модели 1598. Более полный пример:
public OnPlayerConnect(playerid)
{
	SendClientCheck(playerid, 0x46, 1598, 0, 28); // 1598 - beachball
	return 1;
}

public OnClientCheckResponse(playerid, type, arg, response)
{
	new str[128];
	switch(type)
	{
	 	case 0x46:
		{
		    format(str, sizeof(str), "Model %d has checksum 0x%x", arg, response);
			SendClientMessage(playerid, -1, str);
		}
	}
	return 1;
}


Тип 0x47
Этот тип уже читает данные структуры CColModelSA указанной модели (указатель на которую лежит по оффсету 20 в структуре CBaseModelInfoSA). Остальное всё аналогично предыдущему типу. Пример:
public OnPlayerConnect(playerid)
{
	SendClientCheck(playerid, 0x47, 1598, 0, 48); // 1598 - beachball
	return 1;
}

public OnClientCheckResponse(playerid, type, arg, response)
{
	new str[128];
	switch(type)
	{
	    case 0x47: 
		{
		    format(str, sizeof(str), "Col model %d has checksum 0x%x", arg, response);
			SendClientMessage(playerid, -1, str);
		}
	}
	return 1;
}


Тип 0x2
Вот мы и подобрались к самому интересному! Данный тип возвращает 32 (правда больше половины неизвестны/бесполезны) флага из структуры CPhysicalSA. Если игрок в транспорте, то возвращает информацию транспорта, а если пешком - то информацию о самом игроке. Это такие флаги как стоит ли игрок на земле, находится ли он в воде, касается ли воды, уязвим ли к различным типам урона (вот вам и античит на гм). Правда записывать данные мы не можем, только читать.
Пример использования будет ниже по ссылке.

Заключение
Вот, собственно, и всё, что из себя представляет эта секретная функция. К сожалению, сейчас она почти бесполезна. В 0.3x был ещё один тип - 0x5, он позволял читать указанный участок памяти сампа и тем самым проверять, установлены ли там патчи собейта и других читов, но его выпилили в 0.3z.

Полный скрипт-пример: http://pastebin.com/vndmMgFL

Скрипт-пример:
Скрытый текст [Показать]

Автор урока: EvgeN 1137
Реверсинг: FYP, EvgeN 1137

--------------------------------------------------------------------------------------------------

Присутствует баг (или специальная фича), из-за которой OnClientCheckResponse не вызывается в моде, а только в последнем загруженном фс. Для этого нужно подгрузить следующий фс, а затем в моде использовать OnClientCheckResponseFix вместо OnClientCheckResponse:
#include <a_samp>

forward OnClientCheckResponse(playerid, type, arg, response);
public OnClientCheckResponse(playerid, type, arg, response)
	CallRemoteFunction("OnClientCheckResponseFix", "dddd", playerid, type, arg, response);

Pastebin: http://pastebin.com/DG4PDGgg
6

#2
Пользователь офлайн   VVWVV 

  • jited
  • Вставить ник
  • Раскрыть информацию
Молодец.

Сообщение отредактировал VVWVV: 06 февраля 2016 - 16:55

0

#3
Пользователь офлайн   Island 

  • Banned
  • Вставить ник
  • Раскрыть информацию
Красавчик

Поделиться темой:


Страница 1 из 1
  • Вы не можете создать новую тему
  • Вы не можете ответить в тему

1 человек читают эту тему
0 пользователей, 1 гостей, 0 скрытых пользователей


Яндекс.Метрика