[Tutorial] Configurable anti-spam with variables and tickcount() [DETAILED]
#1

initialize antiSpam_tutorial( );


greentarch: Hello and welcome to my tutorial!
greentarch: In this tutorial I will show you how to make an ...
greentarch: ... anti-spam system!
greentarch: Let's start!

Show(TUTORIAL);

greentarch: Firstly, we need to create some variables and defines.
greentarch: I recommend you placing at top of your script.
pawn Код:
#define CHAT_DELAY  ( 750 )
#define MAX_WARNS   ( 3 )

new
    pChatTick[ MAX_PLAYERS ],
    pChatWarns[ MAX_PLAYERS ];
newbie: But, what does that do? I don't understand!
greentarch: Don't worry, I'll explain the code. Take a look at the comments placed on the code!
pawn Код:
// First, we will create some define(s) and variable(s)
// In this tutorial, the define(s) are used to make settings.
// Take a look at these :

#define CHAT_DELAY  ( 750 ) // This is a define, stored as "CHAT_DELAY" -> with value ( 750 )
// 750 is the value of milliseconds, which the player must wait before typing.

#define MAX_WARNS   ( 3 ) // This is another define, stored as "MAX_WARNS" -> with value ( 3 )
// 3 is the maximum amount of spam warnings, before the player gets kicked.

// Now, we will create 2 variable(s) to store player information.

new
    pChatTick[ MAX_PLAYERS ], // Variable pChatTick; What does this mean?
    // tick is what I believe, is time. So it's the time when the player last sent a chat (+CHAT_DELAY)
    // Q: How does it work for this anti-spam?
    // A: Simple. It stores the current server's running time (in milliseconds) + CHAT_DELAY,
    //    and the server will check if the server's running time is higher (not a spam) or lower (spammer) than current pChatTick
   
    pChatWarns[ MAX_PLAYERS ]; // pChatWarns; self-explanatory
    // Q: How does this work?
    // A: Simple, too! The script will increase player's warning each time they spam. Then, the server checks if the player has
    //    reached maximum amount of MAX_WARNS, server will kick the spammer.
newbie: I understand now. What's next?
greentarch: We will reset player's variables at OnPlayerConnect, so they will not conflict with the last value. I also put informations on comments, too.
pawn Код:
public OnPlayerConnect( playerid ) // When a player connects...
{
    pChatTick[ playerid ] = -1; // Reset player's pChatTick
    pChatWarns[ playerid ] = 0; // Reset player's pChatWarns
     
    return 1;
}
newbie: That was easy, now the next part is OnPlayerText, right?
greentarch: Yes! The next part that will be called, is OnPlayerText. I also added a delayed "Kick" function which allows you to send client messages before kicking the player.
greentarch: The script looks like this:
pawn Код:
public OnPlayerText( playerid, text[ ] )
{
    if ( ( tickcount( ) - pChatTick[ playerid ] ) > CHAT_DELAY )
    {
        pChatTick[ playerid ] = tickcount( );
    }
   
    else
    {
        ++ pChatWarns[ playerid ];
       
        if ( pChatWarns[ playerid ] < MAX_WARNS )
        {
            SendClientMessage( playerid, -1, "{FF3333}[ANTI-SPAM]: {FFFFFF}Please stop spamming!" );
            pChatTick[ playerid ] += CHAT_DELAY;
            return 0;
        }
       
        else
        {
            SendClientMessage( playerid, -1, "{FF3333}[ANTI-SPAM]: {FFFFFF}You have been kicked from the server because you didn't stop spamming." );
            SetTimerEx( "_Kick", 200, false, "i", playerid );
            return 0;
        }
    }
   
    return 1;
}

forward _Kick( playerid );
public _Kick( playerid )
    return Kick( playerid );
newbie: *brain explodes*What does that mean? Can you put explanations?
greentarch: Sorry! Explanations are in the code below:
pawn Код:
public OnPlayerText( playerid, text[ ] ) // When a player sends a text to the world (server).
{
    // We've come so far! Now we are at OnPlayerText
    // There is a simple math under here
    // tickcount - pChatTick[ playerid ]
    // [tickcount -> server time in ms] and [pChatTick is old server time in ms + CHAT_DELAY]
    // We will check, if the tick is larger or smaller than CHAT_DELAY
    // If it's smaller, then the player is spamming
    // If it's bigger, then the player is not spamming.
   
    if ( ( tickcount( ) - pChatTick[ playerid ] ) > CHAT_DELAY ) // This check is explained above, please read the comment above.
    {
        pChatTick[ playerid ] = tickcount( ); // Update pChatTick to the current tickcount (server time in ms)
    }
   
    else // Backwards check of the top function, so it checks if the player spams (tickcount - pChatTick is lower than CHAT_DELAY)
    {
        ++ pChatWarns[ playerid ]; // Increase player's warnings
       
        if ( pChatWarns[ playerid ] < MAX_WARNS ) //  Player still has not reached MAX_WARNS, send a warning
        {
            // Warn the player by a client message.
            SendClientMessage( playerid, -1, "{FF3333}[ANTI-SPAM]: {FFFFFF}Please wait before each message!" );
            // Update pChatTick to current tickcount (server time in ms). This avoids another spam being made.
            pChatTick[ playerid ] = tickcount( );
            return 0; // Don't send message.
        }
       
        else // Player has reached MAX_WARNS, then kick the player
        {
            // Send kick message to player before kicking the spammer.
            SendClientMessage( playerid, -1, "{FF3333}[ANTI-SPAM]: {FFFFFF}You have been kicked from the server because you didn't stop spamming." );
            // A delay to "Kick" function so you can SendClientMessage before kicking the player.
           
            SetTimerEx( "_Kick", 200, false, "i", playerid ); // Tell the server to create a timer that kicks the player in 200ms.
            // Q: What's the difference? SetTimerEx --> SetTimer
            // A: SetTimerEx allows you putting parameters (i, d, s, x, etc.) at the called function.
            // Q: What is 200, false, and "i"
            // A: 200 is the delay before calling the function (in ms)
            //    false means the timer doesn't play back after it's called
            //    "i" is the parameter, it means integer (as playerid is a number/integer)
           
            return 0; // Don't send message.
        }
    }
   
    return 1; // Passed the check, send the message!
}

// Now, making a timer
// The function "forward" below tells the compiler that a callback has been registered to the script.
forward _Kick( playerid );
// When the callback calls
public _Kick( playerid )
    return Kick( playerid ); // We kick the player.
newbie: Oh.. okay, I think I got it. But maybe you should be more detailed.
greentarch: That's why I need feedbacks from readers that read this tutorial!
newbie: That is true. Okay, I've got to go now. That is all, right?
greentarch: Yes, that is all. I've got to go too. See you later!

unload antiSpam_tutorial( );

p.s: No, I am not crazy, I am not talking to myself.
I need your feedbacks so I can improve

Thank you for reading.

Final script for lazy copy+paste master
pawn Код:
#include < a_samp >

// First, we will create some define(s) and variable(s)
// In this tutorial, the define(s) are used to make settings.
// Take a look at these :

#define CHAT_DELAY  ( 750 ) // This is a define, stored as "CHAT_DELAY" -> with value ( 750 )
// 750 is the value of milliseconds, which the player must wait before typing.

#define MAX_WARNS   ( 3 ) // This is another define, stored as "MAX_WARNS" -> with value ( 3 )
// 3 is the maximum amount of spam warnings, before the player gets kicked.

// Now, we will create 2 variable(s) to store player information.

new
    pChatTick[ MAX_PLAYERS ], // Variable pChatTick; What does this mean?
    // tick is what I believe, is time. So it's the time when the player last sent a chat (+CHAT_DELAY)
    // Q: How does it work for this anti-spam?
    // A: Simple. It stores the current server's running time (in milliseconds) + CHAT_DELAY,
    //    and the server will check if the server's running time is higher (not a spam) or lower (spammer) than current pChatTick
   
    pChatWarns[ MAX_PLAYERS ]; // pChatWarns; self-explanatory
    // Q: How does this work?
    // A: Simple, too! The script will increase player's warning each time they spam. Then, the server checks if the player has
    //    reached maximum amount of MAX_WARNS, server will kick the spammer.
   
public OnPlayerConnect( playerid ) // When a player connects...
{
    pChatTick[ playerid ] = -1; // Reset player's pChatTick
    pChatWarns[ playerid ] = 0; // Reset player's pChatWarns
     
    return 1;
}

public OnPlayerText( playerid, text[ ] ) // When a player sends a text to the world (server).
{
    // We've come so far! Now we are at OnPlayerText
    // There is a simple math under here
    // tickcount - pChatTick[ playerid ]
    // [tickcount -> server time in ms] and [pChatTick is old server time in ms + CHAT_DELAY]
    // We will check, if the tick is larger or smaller than CHAT_DELAY
    // If it's smaller, then the player is spamming
    // If it's bigger, then the player is not spamming.
   
    if ( ( tickcount( ) - pChatTick[ playerid ] ) > CHAT_DELAY ) // This check is explained above, please read the comment above.
    {
        pChatTick[ playerid ] = tickcount( ); // Update pChatTick to the current tickcount (server time in ms)
    }
   
    else // Backwards check of the top function, so it checks if the player spams (tickcount - pChatTick is lower than CHAT_DELAY)
    {
        ++ pChatWarns[ playerid ]; // Increase player's warnings
       
        if ( pChatWarns[ playerid ] < MAX_WARNS ) //  Player still has not reached MAX_WARNS, send a warning
        {
            // Warn the player by a client message.
            SendClientMessage( playerid, -1, "{FF3333}[ANTI-SPAM]: {FFFFFF}Please wait before each message!" );
            // Update pChatTick to current tickcount (server time in ms). This avoids another spam being made.
            pChatTick[ playerid ] = tickcount( );
            return 0; // Don't send message.
        }
       
        else // Player has reached MAX_WARNS, then kick the player
        {
            // Send kick message to player before kicking the spammer.
            SendClientMessage( playerid, -1, "{FF3333}[ANTI-SPAM]: {FFFFFF}You have been kicked from the server because you didn't stop spamming." );
            // A delay to "Kick" function so you can SendClientMessage before kicking the player.
           
            SetTimerEx( "_Kick", 200, false, "i", playerid ); // Tell the server to create a timer that kicks the player in 200ms.
            // Q: What's the difference? SetTimerEx --> SetTimer
            // A: SetTimerEx allows you putting parameters (i, d, s, x, etc.) at the called function.
            // Q: What is 200, false, and "i"
            // A: 200 is the delay before calling the function (in ms)
            //    false means the timer doesn't play back after it's called
            //    "i" is the parameter, it means integer (as playerid is a number/integer)
           
            return 0; // Don't send message.
        }
    }
   
    return 1; // Passed the check, send the message!
}

// Now, making a timer
// The function "forward" below tells the compiler that a callback has been registered to the script.
forward _Kick( playerid );
// When the callback calls
public _Kick( playerid )
    return Kick( playerid ); // We kick the player.
Reply
#2

I am sorry for bumping, but any feedbacks, please?
Reply
#3

Good Job
but dont kick the player if u do this they will be mad

Becouse u tryed to help and it was nice explaned +REP
Reply


Forum Jump:


Users browsing this thread: 1 Guest(s)