alliedmodders / amxmodx

AMX Mod X - Half-Life 1 Scripting and Administration
http://www.amxmodx.org/
489 stars 197 forks source link

Problem with %n #1036

Open TheKrytyk opened 2 years ago

TheKrytyk commented 2 years ago

This code returns an error Client index 10 is invalid L 02/06/2022 - 08:25:42: [AMXX] Run time error 10 (plugin "test_stats.amxx") (native "formatex") - debug not enabled!

public displayHud(taskIndex)
{
    new index = taskIndex - TASK_HUD;

    if( !is_user_alive( index ) )
    {
        index = pev( index, pev_iuser2 );
        if( !index || is_user_bot(index) || !is_user_connected(index) )
            return;
    }

    new message[ 2 << 7 ];

    formatex(message, charsmax(message), "Player: %n^n", index);

    if(userData[index][dataKillsRequired])
        format(message, charsmax(message), "%s^nFrags: %i", message, userData[index][dataKills]);

    set_hudmessage(0, 196, 255, 0.01, 0.18, 0, 1.0, hudInterval);
    ShowSyncHudMsg(index, hudObject, message);
}

I don't understand why it sometimes returns an error with "Invalid index", because it is checking if the index is connected is_user_connected(index). If I used get_user_name I never had this problem... The problem may be that AMXMODX internally does not check whether player "%n" exists (?).

WPMGPRoSToTeMa commented 2 years ago

Is this code inside client_disconnect or something like this?

TheKrytyk commented 2 years ago

No, it's a task every 1 second. In client_disconnected it happens:

public client_disconnected(index)
{
    if(task_exists(index + TASK_HUD))
        remove_task(index + TASK_HUD);
}

and:

public client_authorized(index)
{
    if(is_user_bot(index) || is_user_hltv(index))
        return; 

    set_task(hudInterval, "displayHud", index + TASK_HUD, .flags = "b");
}
WPMGPRoSToTeMa commented 2 years ago
  1. Could you please check if this happens for the spectated player (iuser2) or for the player themself?
  2. Does this happen during the map change?
  3. Is it a single error or it happens multiple times in a row?
TheKrytyk commented 2 years ago
  1. It is not just the case of the player being watched. In the second plugin, it throws an error in client_print_color (id, id, "% n", id) even though there was no problem with get_user_name.
  2. The error logs do not coincide with the map change, so it happens during the map duration.
  3. It happens from time to time, but when he throws an error, it is up to 2-3 times in a row (the same time, e.g. 6:45:20, 6:45:20).

Additionally, I don't know if it has to do with bots. It's hard to say.

WPMGPRoSToTeMa commented 2 years ago

The error logs do not coincide with the map change, so it happens during the map duration.

Are there any log lines related to connected or disconnected players few seconds before or after the error?

Also, how much times the error appears in the logs per day?

TheKrytyk commented 2 years ago

Are there any log lines related to connected or disconnected players few seconds before or after the error?

Nope.

Also, how much times the error appears in the logs per day?

Several times (sometimes 3, sometimes 5).

WPMGPRoSToTeMa commented 2 years ago

As a workaround could you please try to use client_connect instead of client_authorized? I suspect it may be called after the player is disconnected.

WPMGPRoSToTeMa commented 2 years ago

If I used get_user_name I never had this problem...

get_user_name does only range checking (1 to max players). Same goes for ShowSyncHudMsg and client_print_color, but they do nothing if the player is not ingame (aka is_user_connected).

I actually suspect 3 things:

  1. client_authorized is called after the client was disconnected.
  2. client_disconnected is not called sometimes.
  3. Desync between ingame and initialized variables of CPlayer (PutInServer was called after the client was disconnected).

But given that it happens only 2-3 times in a row and there are no connects/disconnects at that time they all are unlikely.

wilianmaique commented 2 years ago

'client_authorized' is called when the player has a valid 'steamid', the player is not yet connected to the server, if you try to use 'is_user_connected' it will return 'false', trying to use 'is_user_alive' will have errors.

WPMGPRoSToTeMa commented 2 years ago

@wilianmaique %n checks if the player is initialized - it includes the connecting state, so that's not a problem.

djearthquake commented 2 years ago

What I see is a space in between % and n. it throws an error in client_print_color (id, id, "% n", id) even though there was no problem with get_user_name. Try %n over % n. Slight of hand might be all that is needed with this one too. The bots were already filtered out.


public displayHud(taskIndex)
{
    new message[ 2 << 7 ];
    new index = taskIndex - TASK_HUD;

    if(is_user_connected(index))
    {   
        index = is_user_alive(index) ? index : pev(index, pev_iuser2)

        formatex(message, charsmax(message), "Player: %n^n", index);

        if(userData[index][dataKillsRequired])
            format(message, charsmax(message), "%s^nFrags: %i", message, userData[index][dataKills]);

        set_hudmessage(0, 196, 255, 0.01, 0.18, 0, 1.0, hudInterval);
        ShowSyncHudMsg(index, hudObject, message);
    }   
}

/*
public displayHud(taskIndex)
{
    new index = taskIndex - TASK_HUD;

    if( !is_user_alive( index ) )
    {
        index = pev( index, pev_iuser2 );
        if( !index || is_user_bot(index) || !is_user_connected(index) )
            return;
    }

    new message[ 2 << 7 ];

    formatex(message, charsmax(message), "Player: %n^n", index);

    if(userData[index][dataKillsRequired])
        format(message, charsmax(message), "%s^nFrags: %i", message, userData[index][dataKills]);

    set_hudmessage(0, 196, 255, 0.01, 0.18, 0, 1.0, hudInterval);
    ShowSyncHudMsg(index, hudObject, message);
}*/