Question
#1

Hello,

I have a question regarding this code:
Код:
new Spawned[SCRIPT_MAX_PLAYERS];
new Float:ScriptHealth[SCRIPT_MAX_PLAYERS];

Check_Health(playerid)
{
	new Float:fHealth = GetPlayerHealth(playerid);

	if (fHealth > ScriptHealth[playerid])
		return 0;

	return 1;
}

public OnPlayerSpawn(playerid)
{
	ScriptHealth[playerid] = 50;
	SetPlayerHealth(playerid, ScriptHealth[playerid]);

	Spawned[playerid] = 1;

	return 1;
}

public OnPlayerUpdate(playerid)
{
	if (Spawned[playerid] == 1 && !Check_Health())
	{
		Kick(playerid);
	}

	return 1;
}
My question is: If the player has a high ping, could this cause the player to be kicked for having incorrect health as soon as they spawn because their health didn't change in time? Or is the networking for sa-mp set up in such a way it should be okay?

Also, would it make a difference if I put it in a timer instead of OnPlayerUpdate as far as the possibility of false kicking from ping?

Thanks.
Reply
#2

I highly doubt of this code kicking a player falsely.

'Spawned[playerid] = 1' and 'SetPlayerHealth' are getting called on the same callback at the same time, so you would not get kicked.
Reply
#3

Quote:
Originally Posted by Shetch
Посмотреть сообщение
I highly doubt of this code kicking a player falsely.

'Spawned[playerid] = 1' and 'SetPlayerHealth' are getting called on the same callback at the same time, so you would not get kicked.
Logically it seems that way, but the reason I ask is that even if SetPlayerHealth is called at the same time Spawned is set, if they have 1000 ping, what if the server check their health before the players client has received the SetPlayerHealth message.

-> SetPlayerHealth(playerid, ScriptHealth[playerd]);

<- Client has 1k ping and has not responded yet ...

-> Server continues execution and checks the players health anyway and kicks them because it thinks their health is still 100.0 (i think)
Reply
#4

They will receive the SetPlayerHealth message before being kicked, but it is possible that their health is not synced due to lag as you stated. The Spawned[playerid] = 1 is being called AFTER their health is being set, so that does indeed prevent getting falsely kicked. Must you put the anticheat under OnPlayerUpdate? I think it would be more reasonable to have it on a timer of some sort. Alternatively, you could set a variable that changes whether the player has experienced the health change or not. Something along the lines of this:

pawn Код:
new Spawned[SCRIPT_MAX_PLAYERS];
new Float:ScriptHealth[SCRIPT_MAX_PLAYERS];
new bool:HasBeenSynced[SCRIPT_MAX_PLAYERS];

Check_Health(playerid)
{
    new Float:fHealth = GetPlayerHealth(playerid);
    if(!HasBeenSynced[playerid])
    {
        if(fHealth <= ScriptHealth[playerid]) HasBeenSynced[playerid] = true;
        return 1;
    }
    if(fHealth > ScriptHealth[playerid]) return 0;
    return 1;
}

public OnPlayerSpawn(playerid)
{
    HasBeenSynced[playerid] = false;
    ScriptHealth[playerid] = 50;
    SetPlayerHealth(playerid, ScriptHealth[playerid]);
    Spawned[playerid] = 1;
    return 1;
}

public OnPlayerUpdate(playerid)
{
    if(Spawned[playerid] == 1 && !Check_Health())
    {
        Kick(playerid);
    }
    return 1;
}
Reply
#5

Quote:
Originally Posted by BenzoAMG
Посмотреть сообщение
The Spawned[playerid] = 1 is being called AFTER their health is being set
I'd imagine if the player's health hasn't been set due to lag, 'Spawned[playerid] = 1' wouldn't be set either, would it?

I'll run some tests with a high ping and see what happens.
Reply
#6

Quote:
Originally Posted by BenzoAMG
Посмотреть сообщение
...
Thank you for your taking the time to respond to my question.

So when the client calls "GetPlayerHealth", does it actually send a message to the client and wait for a response back? Or does the server store the 'last known' health of each player. I don't understand what stops the player for getting kicked if the code is in a timer.

Quote:

The ~xMS is a timeline of the server executing code. (milliseconds)



~10ms | Server -> Client: I'm setting your health to 50.0
~10ms | Server -> Spawned[playerid] = 1;



~11ms | -> Server now calls a timer that checks if the GetPlayerHealth()> ScriptHealth[playerid], but the server still hasn't received a response from the client that their health is now 50.0.
~11ms | -> Server kicks player.

(One second later)

~1011ms | Client -> Server: Okay, my health is 50.0 now

This is the scenario I am wondering about.

OR

when the server calls SetPlayerHealth, does it IMMEDIATELY affect the return of GetPlayerHealth?
Reply
#7

If I am not mistaken the games are run by the clients and the server only transmit data
Therefore it needs some time till the health is synced

pawn Код:
/*
Dont use custom MAX_PLAYERS definitions because (if you use include from other people) the value of MAX_PLAYERS won't change accordingly
Undef it and redefine it with your new value as the old value isn't needed anymore
*/


#undef MAX_PLAYERS
#define MAX_PLAYERS 50

new
    Float: gScriptHealth[MAX_PLAYERS],
    bool: gSyncHealth[MAX_PLAYERS char]
;

Check_Health(playerid) {
    new
        Float: health
    ;
    if(GetPlayerHealth(playerid, health)) {
        if(!gSyncHealth{playerid}) {
            if(fHealth <= gScriptHealth[playerid]) {
                gSyncHealth{playerid} = true;
            }
            return true;
        }
        return (fHealth <= gScriptHealth[playerid]);
    }
    return false;
}

stock SetPlayerHealthSync(playerid, Float: health) {
    if(SetPlayerHealth(playerid, health) {
        gScriptHealth[playerid] = health;
        gSyncHealth{playerid} = false;
        return true;
    }
    return false;
}

//OnPlayerSpawn
    SetPlayerHealthSync(playerid, 50.0);


//OnPlayerUpdate
    if(!Check_Health()) {
        Kick(playerid);
    }
Reply


Forum Jump:


Users browsing this thread: 1 Guest(s)