alliedmodders / sourcemod

SourceMod - Source Engine Scripting and Administration
http://www.sourcemod.net/
986 stars 423 forks source link

a newbie question #630

Closed jellyr closed 7 years ago

jellyr commented 7 years ago

hi: I want to ask an question about how an function is implement. In sourcemod/plugins/include/clients.inc , there is an function called KickClient, but I can not find where this function is implemented. I just want to call KickClient in my dll(windows dynamic library), but I can not figure how it was implemented. please help, thank you!

jellyr commented 7 years ago

oh, my bad, I found it in /core/logic/smn_players.cpp .

Kenzzer commented 7 years ago

https://github.com/alliedmodders/sourcemod/search?utf8=%E2%9C%93&q=KickClient&type=

https://github.com/alliedmodders/sourcemod/blob/16d7e39b579da93d1974f94d040dfe97a3968c48/core/logic/smn_players.cpp#L1334#L1367

in my dll(windows dynamic library) You are making an extension?

Because you can "remake" the function into your extension, and if I'm not mistaken, IGamePlayer IGameHelpers are exposed to extensions, so it should be good. Unless sourcemod exposes a kick function to extension as well.

Edit: Well you posted right before me, see it took you 2 minutes to find your answer, use the search bar next time.

jellyr commented 7 years ago

Thank you !!! I am writing an plugin completely by myself, a minimal csgo plugin without any other third party. What I am trying to do is kick an player with a custom message window. (csgo game) . If i use kickid (engine->ServerCommand(buffer) ) , I will get the same window without custom message. So I do a reserch, how sm_kick was implemented. It seems like :


void CPlayer::Kick(const char *str)
{
        MarkAsBeingKicked();
        IClient *pClient = GetIClient();
    if (pClient == nullptr)
    {
        int userid = GetUserId();
        if (userid > 0)
        {
            char buffer[255];
            ke::SafeSprintf(buffer, sizeof(buffer), "kickid %d %s\n", userid, str);
            engine->ServerCommand(buffer);
        }
    }
    else
    {
#if SOURCE_ENGINE == SE_CSGO
        pClient->Disconnect(str);
#else
        pClient->Disconnect("%s", str);
#endif
    }
}

it call IClient *pClient = GetIClient(); and

if SOURCE_ENGINE == SE_CSGO

    pClient->Disconnect(str);

this line of code is exact what I want.

let's dig in:

IClient *CPlayer::GetIClient() const
{
    return m_pIClient;
}

and dig in again m_pIClient = engine->GetIServer()->GetClient(m_iIndex - 1);

and dig in again
I can call engine->GetIServer() , because i can call this vitual function by caculate it's virtual table index (virtual IServer *GetIServer() = 0;) . list in
https://github.com/L-EARN/SourceSdk-ServerPlugin/blob/2a5bfa71c07e8a9987aa5eb169f2c840429c9798/Interfaces/IVEngineServer/IVEngineServer023.h . then I got an IServer object. then I can call GetClient by caculate it's virtual table index list in https://github.com/alliedmodders/hl2sdk/blob/98fe5b5a34b3721fe4d60ec7ba3a28ade3512560/public/iserver.h and then i can call pClient->Disconnect("%s", str); the disconnect virtual table addr can calculate by https://github.com/alliedmodders/hl2sdk/blob/98fe5b5a34b3721fe4d60ec7ba3a28ade3512560/public/iclient.h.

may be i will success , not try yet!!!

asherkin commented 7 years ago

Please use the forum for stuff like this in the future.