[Include] OPRL.inc - OnPlayerRconLogin : Calls out when a player logs in as RCON, not an IP.
#1

OPRL - OnPlayerRconLogin
v1.3 update released! (RECOMMENDED)
So basically, most of them had been using "OnRconLoginAttempt" and IP tracing to detect RCON login and in case if there's any system like second RCON login. It's not completely efficient because it would return multiple users in case if they're playing with same IP addresses. This include is a simple one and it provides a callback called OnPlayerRconLogin which gets called to the certain player who has logged in as RCON.

I've actually released a snippet version of this on Useful Snippets earlier and here's the post. But here's an include version which can be used easily by the server coders.

The version 1.2 of this include has been released which uses the callback "OnRconLoginAttempt" callback but in a way that player ID is being returned according to the one who has logged in. It will work same as version 1, however I suggest everyone to use v1.2 as it don't add repeating timers or use OnPlayerUpdate. Thanks to Konstantinos for suggesting a new method in making this include better!

If you had been using previous version of OPRL (other than OPRL3.inc), please consider using the latest version of this include (OPRL3.inc) as it's mainly a security update. Changes done over this include can be found under change logs.

Hooked Callbacks

v1.3 (Latest)
pawn Код:
OnFilterScriptInit
OnGameModeInit
OnRconLoginAttempt
OnPlayerConnect
v1.2 (Outdated version)
pawn Код:
#if defined FILTERSCRIPT
OnFilterScriptInit
#else
OnGameModeInit();
#endif
OnRconLoginAttempt
v1.0 (Outdated version)
pawn Код:
#if defined FILTERSCRIPT
OnFilterScriptInit();
OnFilterScriptExit();
#else
OnGameModeInit();
OnGameModeExit();
#endif
#if !defined OPRL_USE_TIMER
OnPlayerUpdate(playerid);
#endif


Changelogs
Код:
v1.3 (RECOMMENDED)
(13-09-2014)

• Defining of FILTERSCRIPT constant is no longer required before including this include in case if it's used for filterscripts. Thanks to ****** for the tip.
• Removed useless timer call.
• Fixed player array values while connections.
• The include has been renamed from "OPRL2.inc" to "OPRL3.inc"

v1.2
(02-02-2014)

• Include has been optimized! Thanks to Konstantinos for showing a better method
  to callout "OnPlayerRconLogin"

v1.0
(01-02-2014)
• Initial Release
Examples

• A simple notification to everyone when a player logs in as RCON.

pawn Код:
#include <a_samp>
#include <OPRL3>

public OnPlayerRconLogin(playerid)
{
    new
        Lname[MAX_PLAYER_NAME],
        string[128];
    GetPlayerName(playerid, Lname, sizeof(Lname));
    format(string, sizeof(string), "<RCON LOGIN> : %s (ID:%d) has logged in as RCON Administrator!", Lname, playerid);
    SendClientMessageToAll(-1, string);
    printf(string); //Not actually required as it debugs itself, however just adding it as it's an example.
    return 1;
}
• Second RCON system. (FilterScript version)

This is not just an example but also created in a filterscript way which gives performs efficient than other Second RCON systems I've seen. As it uses OnPlayerRconLogin, it ensures that the second RCON login confirmation is sent only to the player who RCON logged in, not others who got the same IP address.

◘ Configurations
- Change SECOND_RCON_DIALOG to the Dialog ID of the second RCON.
- Change SECOND_RCON_PASS to your second RCON password. Default password is testing
- Change MAX_FALSE_2RCON_ATTEMPTS to maximum wrong second rcon login attempts. Default is set to 3.
- Change MAX_HOLD_SECONDS to the max seconds a player could stay online as RCON without logging into second RCON.

pawn Код:
/*______________________________________________________________________________

                        Lordz's Second RCON System!
                        Copyright© - 2014 "SecondRCON"
                        Author : Lordz™ AKA Lordzy

NOTE:
This script is created as a filterscript, mainly as an example for the include
"OPRL" AKA "OnPlayerRconLogin". This script ensures that the second RCON request
is only sent to the player who RCON logins, not to the players who got the same
IP address.

______________________________________________________________________________*/



#include <a_samp>
#include <OPRL3>

new
    bool:RCON2LoggedIn[MAX_PLAYERS],
    RCON2WrongLogins[MAX_PLAYERS];
   
#define SECOND_RCON_DIALOG  1126 //Dialog ID of the second RCON.
#define SECOND_RCON_PASS    "testing" //Second RCON password, you can change it but keep it in quotes.
#define MAX_FALSE_2RCON_ATTEMPTS    3 //Maximum number of second RCON fails.
#define MAX_HOLD_SECONDS    120 //Maximum seconds in which a player could stay as RCON without confirming second RCON.

public OnPlayerConnect(playerid)
{
    if(IsPlayerAdmin(playerid)) RCON2LoggedIn[playerid] = true;
    else RCON2LoggedIn[playerid] = false;
    RCON2WrongLogins[playerid] = 0;
    return 1;
}

public OnFilterScriptInit()
{
    for(new i; i< GetMaxPlayers(); i++)
    {
        if(!IsPlayerConnected(i)) continue;
        if(IsPlayerAdmin(i)) RCON2LoggedIn[i] = true;
        else RCON2LoggedIn[i] = false;
        RCON2WrongLogins[i] = 0;
    }
    printf("-------------------------------------------------");
    printf("    OnPlayerRconLogin - Second RCON system");
    printf("                    Loaded!");
    printf("-------------------------------------------------");
    return 1;
}

public OnPlayerRconLogin(playerid)
{
    if(RCON2LoggedIn[playerid] == false)
    {
        SendClientMessage(playerid, -1, "{FF0000}Server : {880088}Before playing as RCON Administrator, please login to the second RCON option too.");
        ShowPlayerDialog(playerid, SECOND_RCON_DIALOG, DIALOG_STYLE_INPUT, "Second RCON Login", "Hello,\nBefore accessing RCON, please login to the second RCON.", "Login", "");
        SetTimerEx("DetectSecondRconLogin", 1000*MAX_HOLD_SECONDS, false, "d", playerid);
    }
    return 1;
}

public OnDialogResponse(playerid, dialogid, response, listitem, inputtext[])
{
    if(dialogid == SECOND_RCON_DIALOG)
    {
        if(response)
        {
            if(!strlen(inputtext))
            {
                RCON2WrongLogins[playerid]++;
                new
                    string[128];
                if(RCON2WrongLogins[playerid] >= MAX_FALSE_2RCON_ATTEMPTS)
                {
                    new
                        Lname[MAX_PLAYER_NAME];
                    GetPlayerName(playerid, Lname, sizeof(Lname));
                    format(string, sizeof(string), "%s (ID:%d) has been automatically kicked from the server! (Reason : %d/%d)", Lname, playerid, RCON2WrongLogins[playerid], MAX_FALSE_2RCON_ATTEMPTS);
                    SendClientMessageToAll(0xFF0000FF, string);
                    return SetTimerEx("KickPlayer", 150, false, "d", playerid);
                }
                format(string, sizeof(string), "ERROR! The previous second RCON given was incorrect! (Warnings : %d/%d)", RCON2WrongLogins[playerid], MAX_FALSE_2RCON_ATTEMPTS);
                SendClientMessage(playerid, 0xFF0000FF, string);
                return ShowPlayerDialog(playerid, SECOND_RCON_DIALOG, DIALOG_STYLE_INPUT, "Second RCON Login", "Hello,\nBefore accessing RCON, please login to the second RCON.", "Login", "");
            }
            if(!strcmp(inputtext, SECOND_RCON_PASS, false))
            {
                GameTextForPlayer(playerid, "~G~ACCESS GRANTED!", 2000, 3);
                PlayerPlaySound(playerid, 1057, 0.0, 0.0, 0.0);
                RCON2LoggedIn[playerid] = true;
                return 1;
            }
            else if(strcmp(inputtext, SECOND_RCON_PASS, false))
            {
                RCON2WrongLogins[playerid]++;
                new
                    string[128];
                if(RCON2WrongLogins[playerid] >= MAX_FALSE_2RCON_ATTEMPTS)
                {
                    new
                        Lname[MAX_PLAYER_NAME];
                    GetPlayerName(playerid, Lname, sizeof(Lname));
                    format(string, sizeof(string), "%s (ID:%d) has been automatically kicked from the server! (Reason : Wrong RCON logins | %d/%d)", Lname, playerid, RCON2WrongLogins[playerid], MAX_FALSE_2RCON_ATTEMPTS);
                    SendClientMessageToAll(0xFF0000FF, string);
                    return SetTimerEx("KickPlayer", 150, false, "d", playerid);
                }
                format(string, sizeof(string), "ERROR! The previous second RCON given was incorrect! (Warnings : %d/%d)", RCON2WrongLogins[playerid], MAX_FALSE_2RCON_ATTEMPTS);
                SendClientMessage(playerid, 0xFF0000FF, string);
                return ShowPlayerDialog(playerid, SECOND_RCON_DIALOG, DIALOG_STYLE_INPUT, "Second RCON Login", "Hello,\nBefore accessing RCON, please login to the second RCON.", "Login", "");
            }
        }
        if(!response)
        {
            new
                string[128],
                Lname[MAX_PLAYER_NAME];
            format(string, sizeof(string), "%s (ID:%d) has been automatically kicked from the server! (Reason : Wrong RCON login)", Lname, playerid);
            SendClientMessageToAll(0xFF000FF, string);
            return SetTimerEx("KickPlayer", 150, false, "d", playerid);
        }
    }
    return 1;
}


forward KickPlayer(playerid);
forward DetectSecondRconLogin(playerid);


public DetectSecondRconLogin(playerid)
{
    if(IsPlayerAdmin(playerid))
    {
        if(RCON2LoggedIn[playerid] == false)
        {
            new
                Lname[MAX_PLAYER_NAME],
                string[128];
            GetPlayerName(playerid, Lname, sizeof(Lname));
            format(string, sizeof(string), "%s (ID:%d) has been automatically kicked from the server! (Reason : Delayed RCON confirmation)", Lname, playerid);
            SendClientMessageToAll(0xFF0000FF, string);
            return SetTimerEx("KickPlayer", 150, false, "d", playerid);
        }
    }
    return 1;
}

public KickPlayer(playerid) return Kick(playerid);

Tutorial

https://sampforum.blast.hk/showthread.php?tid=499455

It's found on the "PART 2" of that tutorial.

Notes

• You must define FILTERSCRIPT before including this one in case if it's a filterscript. It's because of the hooking methods used in the include.
• The reason why I've kept an extra define in toggling OnPlayerUpdate mode or Timer mode is because if the player is logged in but if OnPlayerUpdate isn't being called due to any glitches or cheats, a timer is always efficient.
• If there's any mistake, feel free to point out.
• If there's any suggestion to improve this include, feel free to point out.

Thanks to

Konstantinos for suggesting a better method for the OPRL call.
****** for suggesting a better hook method to handle both filterscripts and gamemodes easily.

Downloads

GitHub - Examples and Include (Complete Project)
PasteBin - Include Only


Regards,
Lordzy.
Reply
#2

Good work, but I've a question: Can this include be used to create an kinda of "seccond" rcon login?
Reply
#3

It can be done without the need of a continuing timer and an array. I wrote this:
pawn Код:
#include <a_samp>
#include <foreach>

main() {}

public OnRconLoginAttempt(ip[], password[], success)
{
    if (success) SetTimerEx("RetrieveRconPlayer", 1000, false, "s", ip);
    return 1;
}

forward OnPlayerRconLogin(playerid);
public OnPlayerRconLogin(playerid)
{
    printf("OnPlayerRconLogin -> playerid (%i) has been RCON logged in!", playerid);
    return 1;
}

forward RetrieveRconPlayer(ip[]);
public RetrieveRconPlayer(ip[])
{
    new
        ip2[16];

    foreach(new i : Player)
    {
        GetPlayerIp(i, ip2, 16);
        if (!strcmp(ip, ip2) && IsPlayerAdmin(i))
        {
            CallRemoteFunction("OnPlayerRconLogin", "i", i);
        }
    }
    return 1;
}
and it works very well.
Reply
#4

Quote:
Originally Posted by [WH]Marcos
Посмотреть сообщение
Good work, but I've a question: Can this include be used to create an kinda of "seccond" rcon login?
Yes, you can. I've added a second RCON example too.
pawn Код:
/*______________________________________________________________________________

                        Lordz's Second RCON System!
                        Copyright© - 2014 "SecondRCON"
                        Author : Lordz™ AKA Lordzy

NOTE:
This script is created as a filterscript, mainly as an example for the include
"OPRL" AKA "OnPlayerRconLogin". This script ensures that the second RCON request
is only sent to the player who RCON logins, not to the players who got the same
IP address.

______________________________________________________________________________*/


#define FILTERSCRIPT

#include <a_samp>
#include <OPRL>

new
    bool:RCON2LoggedIn[MAX_PLAYERS],
    RCON2WrongLogins[MAX_PLAYERS];
   
#define SECOND_RCON_DIALOG  1126 //Dialog ID of the second RCON.
#define SECOND_RCON_PASS    "testing" //Second RCON password, you can change it but keep it in quotes.
#define MAX_FALSE_2RCON_ATTEMPTS    3 //Maximum number of second RCON fails.
#define MAX_HOLD_SECONDS    120 //Maximum seconds in which a player could stay as RCON without confirming second RCON.

public OnPlayerConnect(playerid)
{
    if(IsPlayerAdmin(playerid)) RCON2LoggedIn[playerid] = true;
    else RCON2LoggedIn[playerid] = false;
    RCON2WrongLogins[playerid] = 0;
    return 1;
}

public OnFilterScriptInit()
{
    for(new i; i< GetMaxPlayers(); i++)
    {
        if(!IsPlayerConnected(i)) continue;
        if(IsPlayerAdmin(i)) RCON2LoggedIn[i] = true;
        else RCON2LoggedIn[i] = false;
        RCON2WrongLogins[i] = 0;
    }
    printf("-------------------------------------------------");
    printf("    OnPlayerRconLogin - Second RCON system");
    printf("                    Loaded!");
    printf("-------------------------------------------------");
    return 1;
}

public OnPlayerRconLogin(playerid)
{
    if(RCON2LoggedIn[playerid] == false)
    {
        SendClientMessage(playerid, -1, "{FF0000}Server : {880088}Before playing as RCON Administrator, please login to the second RCON option too.");
        ShowPlayerDialog(playerid, SECOND_RCON_DIALOG, DIALOG_STYLE_INPUT, "Second RCON Login", "Hello,\nBefore accessing RCON, please login to the second RCON.", "Login", "");
        SetTimerEx("DetectSecondRconLogin", 1000*MAX_HOLD_SECONDS, false, "d", playerid);
    }
    return 1;
}

public OnDialogResponse(playerid, dialogid, response, listitem, inputtext[])
{
    if(dialogid == SECOND_RCON_DIALOG)
    {
        if(response)
        {
            if(!strlen(inputtext))
            {
                RCON2WrongLogins[playerid]++;
                new
                    string[128];
                if(RCON2WrongLogins[playerid] >= MAX_FALSE_2RCON_ATTEMPTS)
                {
                    new
                        Lname[MAX_PLAYER_NAME];
                    GetPlayerName(playerid, Lname, sizeof(Lname));
                    format(string, sizeof(string), "%s (ID:%d) has been automatically kicked from the server! (Reason : %d/%d)", Lname, playerid, RCON2WrongLogins[playerid], MAX_FALSE_2RCON_ATTEMPTS);
                    SendClientMessageToAll(0xFF0000FF, string);
                    return SetTimerEx("KickPlayer", 150, false, "d", playerid);
                }
                format(string, sizeof(string), "ERROR! The previous second RCON given was incorrect! (Warnings : %d/%d)", RCON2WrongLogins[playerid], MAX_FALSE_2RCON_ATTEMPTS);
                SendClientMessage(playerid, 0xFF0000FF, string);
                return ShowPlayerDialog(playerid, SECOND_RCON_DIALOG, DIALOG_STYLE_INPUT, "Second RCON Login", "Hello,\nBefore accessing RCON, please login to the second RCON.", "Login", "");
            }
            if(!strcmp(inputtext, SECOND_RCON_PASS, false))
            {
                GameTextForPlayer(playerid, "~G~ACCESS GRANTED!", 2000, 3);
                PlayerPlaySound(playerid, 1057, 0.0, 0.0, 0.0);
                RCON2LoggedIn[playerid] = true;
                return 1;
            }
            else if(strcmp(inputtext, SECOND_RCON_PASS, false))
            {
                RCON2WrongLogins[playerid]++;
                new
                    string[128];
                if(RCON2WrongLogins[playerid] >= MAX_FALSE_2RCON_ATTEMPTS)
                {
                    new
                        Lname[MAX_PLAYER_NAME];
                    GetPlayerName(playerid, Lname, sizeof(Lname));
                    format(string, sizeof(string), "%s (ID:%d) has been automatically kicked from the server! (Reason : Wrong RCON logins | %d/%d)", Lname, playerid, RCON2WrongLogins[playerid], MAX_FALSE_2RCON_ATTEMPTS);
                    SendClientMessageToAll(0xFF0000FF, string);
                    return SetTimerEx("KickPlayer", 150, false, "d", playerid);
                }
                format(string, sizeof(string), "ERROR! The previous second RCON given was incorrect! (Warnings : %d/%d)", RCON2WrongLogins[playerid], MAX_FALSE_2RCON_ATTEMPTS);
                SendClientMessage(playerid, 0xFF0000FF, string);
                return ShowPlayerDialog(playerid, SECOND_RCON_DIALOG, DIALOG_STYLE_INPUT, "Second RCON Login", "Hello,\nBefore accessing RCON, please login to the second RCON.", "Login", "");
            }
        }
        if(!response)
        {
            new
                string[128],
                Lname[MAX_PLAYER_NAME];
            format(string, sizeof(string), "%s (ID:%d) has been automatically kicked from the server! (Reason : Wrong RCON login)", Lname, playerid);
            SendClientMessageToAll(0xFF000FF, string);
            return SetTimerEx("KickPlayer", 150, false, "d", playerid);
        }
    }
    return 1;
}


forward KickPlayer(playerid);
forward DetectSecondRconLogin(playerid);


public DetectSecondRconLogin(playerid)
{
    if(IsPlayerAdmin(playerid))
    {
        if(RCON2LoggedIn[playerid] == false)
        {
            new
                Lname[MAX_PLAYER_NAME],
                string[128];
            GetPlayerName(playerid, Lname, sizeof(Lname));
            format(string, sizeof(string), "%s (ID:%d) has been automatically kicked from the server! (Reason : Delayed RCON confirmation)", Lname, playerid);
            SendClientMessageToAll(0xFF0000FF, string);
            return SetTimerEx("KickPlayer", 150, false, "d", playerid);
        }
    }
    return 1;
}

public KickPlayer(playerid) return Kick(playerid);
Quote:
Originally Posted by Konstantinos
Посмотреть сообщение
It can be done without the need of a continuing timer and an array. I wrote this:
pawn Код:
#include <a_samp>
#include <foreach>

main() {}

public OnRconLoginAttempt(ip[], password[], success)
{
    if (success) SetTimerEx("RetrieveRconPlayer", 1000, false, "s", ip);
    return 1;
}

forward OnPlayerRconLogin(playerid);
public OnPlayerRconLogin(playerid)
{
    printf("OnPlayerRconLogin -> playerid (%i) has been RCON logged in!", playerid);
    return 1;
}

forward RetrieveRconPlayer(ip[]);
public RetrieveRconPlayer(ip[])
{
    new
        ip2[16];

    foreach(new i : Player)
    {
        GetPlayerIp(i, ip2, 16);
        if (!strcmp(ip, ip2) && IsPlayerAdmin(i))
        {
            CallRemoteFunction("OnPlayerRconLogin", "i", i);
        }
    }
    return 1;
}
and it works very well.
It may work, however not very well. What if there are members with same IP address who have already RCON logged in?

EDIT:
I've tested your code right now to confirm well and yes I was right. It don't work well in case if there's already admins logged in as RCON with same IP address.
Код:
[22:57:45] [join] yolo has joined the server (...)
[22:57:55] RCON (In-Game): Player #1 (yolo) has logged in.
[22:57:56] OnPlayerRconLogin -> playerid (1) has been RCON logged in!
[22:58:09] RCON (In-Game): Player #0 (blabla) has logged in.
[22:58:10] OnPlayerRconLogin -> playerid (0) has been RCON logged in!
[22:58:10] OnPlayerRconLogin -> playerid (1) has been RCON logged in!
Reply
#5

Quote:
Originally Posted by Lordz™
Посмотреть сообщение
It may work, however not very well. What if there are members with same IP address who have already RCON logged in?

EDIT:
I've tested your code right now to confirm well and yes I was right. It don't work well in case if there's already admins logged in as RCON with same IP address.
Код:
[22:57:45] [join] yolo has joined the server (...)
[22:57:55] RCON (In-Game): Player #1 (yolo) has logged in.
[22:57:56] OnPlayerRconLogin -> playerid (1) has been RCON logged in!
[22:58:09] RCON (In-Game): Player #0 (blabla) has logged in.
[22:58:10] OnPlayerRconLogin -> playerid (0) has been RCON logged in!
[22:58:10] OnPlayerRconLogin -> playerid (1) has been RCON logged in!
Good thought! The use of the array is needed then but the repeated timer is a bit bad idea. OnRconLoginAttempt is called and if it's success, after 1 second it sends the message in the console that the player has been logged in as RCON.

Here's a better version:
pawn Код:
#include <a_samp>
#include <foreach>

static
    bool: Player_Rcon[MAX_PLAYERS char];

main() {}

public OnPlayerConnect(playerid)
{
    Player_Rcon{playerid} = false;
    return 1;
}

public OnRconLoginAttempt(ip[], password[], success)
{
    if (success) SetTimerEx("RetrieveRconPlayer", 1000, false, "s", ip);
    return 1;
}

forward OnPlayerRconLogin(playerid);
public OnPlayerRconLogin(playerid)
{
    printf("OnPlayerRconLogin -> playerid (%i) has been RCON logged in!", playerid);
    return 1;
}

forward RetrieveRconPlayer(ip[]);
public RetrieveRconPlayer(ip[])
{
    new
        ip2[16];

    foreach(new i : Player)
    {
        GetPlayerIp(i, ip2, 16);
        if (!strcmp(ip, ip2) && !Player_Rcon{i} && IsPlayerAdmin(i))
        {
            Player_Rcon{i} = true;
            CallRemoteFunction("OnPlayerRconLogin", "i", i);
        }
    }
    return 1;
}
Can you test it like before with a player already logged in with the same ip? It should work now.

By the way, good idea for an include!
Reply
#6

Heyhey! http://pastebin.com/Px5SMVcc. (BY: ENZOMETLC ON JAN 23RD, 2014).

You stole the idea from me!


Nice work and include ^^.
Reply
#7

@Konstant... (Your name is hard) Dwayne for the win : Thanks, and yes it will be working.
EDIT : It does.
Quote:
Originally Posted by EnzoMetlc
Посмотреть сообщение
Heyhey! http://pastebin.com/Px5SMVcc. (BY: ENZOMETLC ON JAN 23RD, 2014).

You stole the idea from me!


Nice work and include ^^.
No, I haven't copied your ideas. Check the date of my post on Useful Snippets.
Here's the post link : http://forum.sa-mp.com/showpost.php?...postcount=1089 Also, mine is completely different from yours. And thanks for your compliment.
Reply
#8

Include has been updated to version 1.2!
Код:
• Include has been optimized! Thanks to Konstantinos for showing a better method
  to callout "OnPlayerRconLogin"
Thanks to Konstantinos for suggesting a better way in detecting RCON logins. It removes the use of a timer getting repeated all the time or OnPlayerUpdate being used.
Reply
#9

OPRL's tutorial, usage and some good methods which can be implemented has been posted. Take a look over there if you're using this include.

https://sampforum.blast.hk/showthread.php?tid=499455

PART #2 of that tutorial.

* Added a link towards OPRL's Tutorial on the topic!*
Reply
#10

A question, instead of :
pawn Код:
for(new i; i< GetMaxPlayers(); i++)
Why not? :
pawn Код:
for(new i, j = GetMaxPlayers(); i< j; i++)
Reply


Forum Jump:


Users browsing this thread: 1 Guest(s)