fixed amb1808 - KickClient() is delayed and does not crash -- KickClientEx() is the old functionality
--HG-- extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/trunk%402363
This commit is contained in:
parent
3d96f8f127
commit
0e1ae4d85b
@ -511,3 +511,31 @@ const char *CHalfLife2::CurrentCommandName()
|
|||||||
return m_CommandStack.front().cmd;
|
return m_CommandStack.front().cmd;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CHalfLife2::AddDelayedKick(int client, int userid, const char *msg)
|
||||||
|
{
|
||||||
|
DelayedKickInfo kick;
|
||||||
|
|
||||||
|
kick.client = client;
|
||||||
|
kick.userid = userid;
|
||||||
|
UTIL_Format(kick.buffer, sizeof(kick.buffer), "%s", msg);
|
||||||
|
|
||||||
|
m_DelayedKicks.push(kick);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CHalfLife2::ProcessDelayedKicks()
|
||||||
|
{
|
||||||
|
while (!m_DelayedKicks.empty())
|
||||||
|
{
|
||||||
|
DelayedKickInfo info = m_DelayedKicks.first();
|
||||||
|
m_DelayedKicks.pop();
|
||||||
|
|
||||||
|
CPlayer *player = g_Players.GetPlayerByIndex(info.client);
|
||||||
|
if (player == NULL || player->GetUserId() != info.userid)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
player->Kick(info.buffer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -79,6 +79,13 @@ struct CachedCommandInfo
|
|||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct DelayedKickInfo
|
||||||
|
{
|
||||||
|
int userid;
|
||||||
|
int client;
|
||||||
|
char buffer[384];
|
||||||
|
};
|
||||||
|
|
||||||
class CHalfLife2 :
|
class CHalfLife2 :
|
||||||
public SMGlobalClass,
|
public SMGlobalClass,
|
||||||
public IGameHelpers
|
public IGameHelpers
|
||||||
@ -110,6 +117,8 @@ public:
|
|||||||
void PopCommandStack();
|
void PopCommandStack();
|
||||||
const CCommand *PeekCommandStack();
|
const CCommand *PeekCommandStack();
|
||||||
const char *CurrentCommandName();
|
const char *CurrentCommandName();
|
||||||
|
void AddDelayedKick(int client, int userid, const char *msg);
|
||||||
|
void ProcessDelayedKicks();
|
||||||
#if !defined METAMOD_PLAPI_VERSION
|
#if !defined METAMOD_PLAPI_VERSION
|
||||||
bool IsOriginalEngine();
|
bool IsOriginalEngine();
|
||||||
#endif
|
#endif
|
||||||
@ -125,6 +134,7 @@ private:
|
|||||||
Queue<DelayedFakeCliCmd *> m_CmdQueue;
|
Queue<DelayedFakeCliCmd *> m_CmdQueue;
|
||||||
CStack<DelayedFakeCliCmd *> m_FreeCmds;
|
CStack<DelayedFakeCliCmd *> m_FreeCmds;
|
||||||
CStack<CachedCommandInfo> m_CommandStack;
|
CStack<CachedCommandInfo> m_CommandStack;
|
||||||
|
Queue<DelayedKickInfo> m_DelayedKicks;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern CHalfLife2 g_HL2;
|
extern CHalfLife2 g_HL2;
|
||||||
|
@ -44,6 +44,7 @@ void RunFrameHooks(bool simulating)
|
|||||||
/* Frame based hooks */
|
/* Frame based hooks */
|
||||||
g_DBMan.RunFrame();
|
g_DBMan.RunFrame();
|
||||||
g_HL2.ProcessFakeCliCmdQueue();
|
g_HL2.ProcessFakeCliCmdQueue();
|
||||||
|
g_HL2.ProcessDelayedKicks();
|
||||||
g_SourceMod.ProcessGameFrameHooks(simulating);
|
g_SourceMod.ProcessGameFrameHooks(simulating);
|
||||||
|
|
||||||
float curtime = *g_pUniversalTime;
|
float curtime = *g_pUniversalTime;
|
||||||
|
@ -1258,10 +1258,64 @@ static cell_t KickClient(IPluginContext *pContext, const cell_t *params)
|
|||||||
if (!pPlayer)
|
if (!pPlayer)
|
||||||
{
|
{
|
||||||
return pContext->ThrowNativeError("Client index %d is invalid", client);
|
return pContext->ThrowNativeError("Client index %d is invalid", client);
|
||||||
} else if (!pPlayer->IsConnected()) {
|
}
|
||||||
|
else if (!pPlayer->IsConnected())
|
||||||
|
{
|
||||||
return pContext->ThrowNativeError("Client %d is not connected", client);
|
return pContext->ThrowNativeError("Client %d is not connected", client);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Ignore duplicate kicks */
|
||||||
|
if (pPlayer->IsInKickQueue())
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
pPlayer->MarkAsBeingKicked();
|
||||||
|
|
||||||
|
if (pPlayer->IsFakeClient())
|
||||||
|
{
|
||||||
|
char kickcmd[40];
|
||||||
|
UTIL_Format(kickcmd, sizeof(kickcmd), "kick %s\n", pPlayer->GetName());
|
||||||
|
|
||||||
|
engine->ServerCommand(kickcmd);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_SourceMod.SetGlobalTarget(client);
|
||||||
|
|
||||||
|
char buffer[256];
|
||||||
|
g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, 2);
|
||||||
|
|
||||||
|
if (pContext->GetContext()->n_err != SP_ERROR_NONE)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_HL2.AddDelayedKick(client, pPlayer->GetUserId(), buffer);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static cell_t KickClientEx(IPluginContext *pContext, const cell_t *params)
|
||||||
|
{
|
||||||
|
int client = params[1];
|
||||||
|
|
||||||
|
CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
|
||||||
|
if (!pPlayer)
|
||||||
|
{
|
||||||
|
return pContext->ThrowNativeError("Client index %d is invalid", client);
|
||||||
|
}
|
||||||
|
else if (!pPlayer->IsConnected())
|
||||||
|
{
|
||||||
|
return pContext->ThrowNativeError("Client %d is not connected", client);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Ignore duplicate kicks */
|
||||||
|
if (pPlayer->IsInKickQueue())
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
pPlayer->MarkAsBeingKicked();
|
pPlayer->MarkAsBeingKicked();
|
||||||
|
|
||||||
if (pPlayer->IsFakeClient())
|
if (pPlayer->IsFakeClient())
|
||||||
@ -1460,6 +1514,7 @@ REGISTER_NATIVES(playernatives)
|
|||||||
{"ShowActivityEx", ShowActivityEx},
|
{"ShowActivityEx", ShowActivityEx},
|
||||||
{"ShowActivity2", ShowActivity2},
|
{"ShowActivity2", ShowActivity2},
|
||||||
{"KickClient", KickClient},
|
{"KickClient", KickClient},
|
||||||
|
{"KickClientEx", KickClientEx},
|
||||||
{"RunAdminCacheChecks", RunAdminCacheChecks},
|
{"RunAdminCacheChecks", RunAdminCacheChecks},
|
||||||
{"NotifyPostAdminCheck", NotifyPostAdminCheck},
|
{"NotifyPostAdminCheck", NotifyPostAdminCheck},
|
||||||
{"IsClientInKickQueue", IsClientInKickQueue},
|
{"IsClientInKickQueue", IsClientInKickQueue},
|
||||||
|
@ -634,7 +634,28 @@ native Float:GetClientAvgPackets(client, NetFlow:flow);
|
|||||||
native GetClientOfUserId(userid);
|
native GetClientOfUserId(userid);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Disconnects a client from the server.
|
* Disconnects a client from the server as soon as the next frame starts.
|
||||||
|
*
|
||||||
|
* Note: Originally, KickClient() was immediate. The delay was introduced
|
||||||
|
* because despite warnings, plugins were using it in ways that would crash.
|
||||||
|
* The new safe version can break cases that rely on immediate disconnects,
|
||||||
|
* but ensures that plugins do not accidentally cause crashes.
|
||||||
|
*
|
||||||
|
* If you need immediate disconnects, use KickClientEx().
|
||||||
|
*
|
||||||
|
* Note: IsClientInKickQueue() will return true before the kick occurs.
|
||||||
|
*
|
||||||
|
* @param client Client index.
|
||||||
|
* @param format Optional formatting rules for disconnect reason.
|
||||||
|
* Note that a period is automatically appended to the string by the engine.
|
||||||
|
* @param ... Variable number of format parameters.
|
||||||
|
* @noreturn
|
||||||
|
* @error Invalid client index, or client not connected.
|
||||||
|
*/
|
||||||
|
native KickClient(client, const String:format[]="", any:...);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Immediately disconnects a client from the server.
|
||||||
*
|
*
|
||||||
* Kicking clients from certain events or callbacks may cause crashes. If in
|
* Kicking clients from certain events or callbacks may cause crashes. If in
|
||||||
* doubt, create a short (0.1 second) timer to kick the client in the next
|
* doubt, create a short (0.1 second) timer to kick the client in the next
|
||||||
@ -647,7 +668,7 @@ native GetClientOfUserId(userid);
|
|||||||
* @noreturn
|
* @noreturn
|
||||||
* @error Invalid client index, or client not connected.
|
* @error Invalid client index, or client not connected.
|
||||||
*/
|
*/
|
||||||
native KickClient(client, const String:format[]="", any:...);
|
native KickClientEx(client, const String:format[]="", any:...);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Changes a client's team through the mod's generic team changing function.
|
* Changes a client's team through the mod's generic team changing function.
|
||||||
|
Loading…
Reference in New Issue
Block a user