服务器命令
如上所述,服务器命令是通过服务器控制台触发的,无论是远程的、本地的还是通过 Source 引擎。没有与服务器命令关联的客户端索引。
服务器命令通过console.inc中定义的RegServerCmd()函数注册。注册服务器命令时,您可能正在挂钩一个已经存在的命令,因此返回值很重要。
- Plugin_Continue - 原始服务器命令将被处理,如果有的话。如果服务器命令是由插件创建的,则无效。
- Plugin_Handled - 不会处理原始服务器命令,如果有的话。如果服务器命令是由插件创建的,则无效。
- Plugin_Stop - 原始服务器命令将不会被处理,如果有的话。此外,在再次触发该命令之前,不会再调用任何钩子。
控制台命令
与服务器命令不同,控制台命令可以由服务器或客户端触发,因此回调函数接收客户端索引以及参数计数。如果服务器触发该命令,则客户端索引将为 0。
从回调中返回Action时,会发生以下效果:
- Plugin_Continue:命令的原始功能(如果有)仍将被处理。如果没有原始功能,客户端将在其控制台中收到“未知命令”。
- Plugin_Handled:命令的原始功能(如果有)将被阻止。如果最初没有功能,这会阻止客户端在其控制台中看到“未知命令”。
- Plugin_Stop :与Plugin_Handled相同,除了这将是最后一个调用的钩子。
- Plugin_Changed:输入或输出已被新值覆盖。
挂钩命令
一个常见的例子是挂钩 say 命令。假设我们想告诉玩家在游戏中说“/ff”时是否启用了FF。
简而言之:当我们Hook 默认的控制台命令say的时候,如果return Plugin_Continue,则代表say的文字会被正常显示给对应的人(team或者all);如果return Plugin_Handled,那么say的原始功能将丧失(显示消息),取而代之的是我们Hook的时候自定义的动作。下面举例:
ConVar g_cvarFF = null;
public void OnPluginStart()
{
g_cvarFF = FindConVar("mp_friendlyfire");
}
public Action OnClientSayCommand(int client, const char[] command, const char[] sArgs)
{
if (strcmp(sArgs, "ff", false) == 0)
{
if (g_cvarFF != null)
{
if (g_cvarFF.BoolValue)
{
PrintToChat(client, "Friendly fire is enabled.");
}
else
{
PrintToChat(client, "Friendly fire is disabled.");
}
/* Block the client's messsage from broadcasting */
return Plugin_Handled;
}
}
/* Let say continue normally */
return Plugin_Continue;
}
这里我们使用 OnClientSayCommand 来Hook say或者say_team动作的forward(可以使用RegConsoleCmd 或者AddCommandListener 来hook)
参考: