Данный текст планировался к публикации на burgershot.gg в апреле 2019, но потом я передумал и забыл про него. А сейчас, раз уж снова поднялась шумиха по поводу SendClientCheck, то считаю полезным выложить то, что планировал, чтобы зря не пропадало. Сорри, что на английском
Since 2013 this function remained secret for most of scripters, nowhere and nobody documented it. Well, it's time to shed some light on this dark side of the SAMP.
SendClientCheck
This function sends a special request to the client, then the client sends its response to the OnClientCheckResponse callback. Response latency depends on player's ping. The function and the callback isn't declarated in includes, so you'll have to declare it by yourself, for example, in the beginning of your script:
Код:
native SendClientCheck(playerid, type, arg, offset, size);
forward OnClientCheckResponse(playerid, type, arg, response);
Take a look at SendClientCheck's arguments:
playerid - which player will be requested
type - request type
arg - special argument
offset - read memory offset
size - number of bytes to read (always must be greater or equal 2)
And OnClientCheckResponse:
playerid - who sends a response
type - response type
arg - special argument
response - yet another special argument
Now let's see what it all means. There are 6 types of requests that the client processes (the type argument): 2, 5, 69, 70, 71, 72.
Type №72
Let's start with the simple request. This request type doesn't use any arguments (arg, offset, size). It returns the uptime of player's computer into arg. Example:
Код:
#include <a_samp>
native SendClientCheck(playerid, type, arg, offset, size); forward OnClientCheckResponse(playerid, type, arg, response);
public OnPlayerConnect(playerid)
{
SendClientCheck(playerid, 72, 0, 0, 2);
return 1;
}
public OnClientCheckResponse(playerid, type, arg, response)
{
new str[128];
switch(type)
{
case 72:
{
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;
}
This example will say uptime of player computer when he enters the server.
Type №70
This type reads data from the CBaseModelInfoSA structure of specified model and returns an byte checksum. It is possible to specify from which offset start to read and how much bytes to read. For example, SendClientCheck(playerid, 70, 1598, 0, 28) request will return the checksum of first 28 bytes of 1598 model structure. More complete example:
Код:
public OnPlayerConnect(playerid)
{
SendClientCheck(playerid, 70, 1598, 0, 28); // 1598 - beachball
return 1;
}
public OnClientCheckResponse(playerid, type, arg, response)
{
new str[128];
switch(type)
{
case 70:
{
format(str, sizeof(str), "Model %d has checksum 0x%x", arg, response);
SendClientMessage(playerid, -1, str);
}
}
return 1;
}
Type №71
This one reads data from the CColModelSA structure of specified model (pointer on which one is located at offset 20 in CBaseModelInfoSA structure). The rest is similar to the previous type. Example:
Код:
public OnPlayerConnect(playerid)
{
SendClientCheck(playerid, 71, 1598, 0, 48); // 1598 - beachball
return 1;
}
public OnClientCheckResponse(playerid, type, arg, response)
{
new str[128];
switch(type)
{
case 71:
{
format(str, sizeof(str), "Col model %d has checksum 0x%x", arg, response);
SendClientMessage(playerid, -1, str);
}
}
return 1;
}
Type №2
Now we're getting close to the interesting things. This type returns 32 flags from the CPhysicalSA structure. If player is in vehicle, it returns info about vehicle, if player is on foot, it returns info about player itself. These are flags such as if the player is on grond, is in water, is touching water etc. Usage example will be below at the link
Warning: Types listed below works only on the 0.3.7-R2, 0.3.7-R3, 0.3.DL-R1 client versions!
Type №5
This one makes checksum of size bytes from arg + offset address (GTA memory) and returns it into response argument. Valid addresses are 0x400000 - 0x856E00. Valid offsets are 0 - 255. One of the most interesting and useful types. You can check is memory pactched by some cheat/hack.
Type №69
This one makes checksum of size bytes from arg + offset address (SAMP memory) and returns it into response argument. Valid addresses are 0x0 - 0xC3500. Valid offsets are 0 - 255. Also can be used for looking for installed cheats/hacks
Checksum algorithm
It's pretty stupid, and computing like that (pseudocode):
Код:
for(new i = startaddress; i < endaddress; i++)
{
result ^= ReadMemory(i) & 0xCC;
}
Conclusion
That is, in fact, all that this secret function is.
Full example-script: http://pastebin.com/vndmMgFL
© EvgeN 1137
Thanks FYP for providing some help