Add base CommandIterator implementation (#819)
* Add base CommandIterator implementation * Add check for invalid pos & finalize pr
This commit is contained in:
parent
aaac0b9eb2
commit
28f1ea82b6
@ -342,9 +342,10 @@ bool ConCmdManager::AddAdminCommand(IPluginFunction *pFunction,
|
||||
const char *group,
|
||||
int adminflags,
|
||||
const char *description,
|
||||
int flags)
|
||||
int flags,
|
||||
IPlugin *pPlugin)
|
||||
{
|
||||
ConCmdInfo *pInfo = AddOrFindCommand(name, description, flags);
|
||||
ConCmdInfo *pInfo = AddOrFindCommand(name, description, flags, pPlugin);
|
||||
|
||||
if (!pInfo)
|
||||
return false;
|
||||
@ -388,10 +389,11 @@ bool ConCmdManager::AddAdminCommand(IPluginFunction *pFunction,
|
||||
bool ConCmdManager::AddServerCommand(IPluginFunction *pFunction,
|
||||
const char *name,
|
||||
const char *description,
|
||||
int flags)
|
||||
int flags,
|
||||
IPlugin *pPlugin)
|
||||
|
||||
{
|
||||
ConCmdInfo *pInfo = AddOrFindCommand(name, description, flags);
|
||||
ConCmdInfo *pInfo = AddOrFindCommand(name, description, flags, pPlugin);
|
||||
|
||||
if (!pInfo)
|
||||
return false;
|
||||
@ -555,7 +557,7 @@ bool ConCmdManager::LookForCommandAdminFlags(const char *cmd, FlagBits *pFlags)
|
||||
return true;
|
||||
}
|
||||
|
||||
ConCmdInfo *ConCmdManager::AddOrFindCommand(const char *name, const char *description, int flags)
|
||||
ConCmdInfo *ConCmdManager::AddOrFindCommand(const char *name, const char *description, int flags, IPlugin *pPlugin)
|
||||
{
|
||||
ConCmdInfo *pInfo;
|
||||
if (!m_Cmds.retrieve(name, &pInfo))
|
||||
@ -580,6 +582,7 @@ ConCmdInfo *ConCmdManager::AddOrFindCommand(const char *name, const char *descri
|
||||
char *new_name = sm_strdup(name);
|
||||
char *new_help = sm_strdup(description);
|
||||
pCmd = new ConCommand(new_name, CommandCallback, new_help, flags);
|
||||
pInfo->pPlugin = pPlugin;
|
||||
pInfo->sourceMod = true;
|
||||
}
|
||||
else
|
||||
|
@ -99,8 +99,9 @@ struct ConCmdInfo
|
||||
{
|
||||
ConCmdInfo()
|
||||
{
|
||||
pPlugin = nullptr;
|
||||
sourceMod = false;
|
||||
pCmd = NULL;
|
||||
pCmd = nullptr;
|
||||
eflags = 0;
|
||||
}
|
||||
bool sourceMod; /**< Determines whether or not concmd was created by a SourceMod plugin */
|
||||
@ -108,6 +109,7 @@ struct ConCmdInfo
|
||||
CmdHookList hooks; /**< Hook list */
|
||||
FlagBits eflags; /**< Effective admin flags */
|
||||
ke::RefPtr<CommandHook> sh_hook; /**< SourceHook hook, if any. */
|
||||
IPlugin *pPlugin; /**< Owning plugin handle. */
|
||||
};
|
||||
|
||||
typedef List<ConCmdInfo *> ConCmdList;
|
||||
@ -132,13 +134,14 @@ public: //IRootConsoleCommand
|
||||
public: //IConCommandTracker
|
||||
void OnUnlinkConCommandBase(ConCommandBase *pBase, const char *name) override;
|
||||
public:
|
||||
bool AddServerCommand(IPluginFunction *pFunction, const char *name, const char *description, int flags);
|
||||
bool AddServerCommand(IPluginFunction *pFunction, const char *name, const char *description, int flags, IPlugin *pPlugin);
|
||||
bool AddAdminCommand(IPluginFunction *pFunction,
|
||||
const char *name,
|
||||
const char *group,
|
||||
int adminflags,
|
||||
const char *description,
|
||||
int flags);
|
||||
int flags,
|
||||
IPlugin *pPlugin);
|
||||
ResultType DispatchClientCommand(int client, const char *cmd, int args, ResultType type);
|
||||
void UpdateAdminCmdFlags(const char *cmd, OverrideType type, FlagBits bits, bool remove);
|
||||
bool LookForSourceModCommand(const char *cmd);
|
||||
@ -146,7 +149,7 @@ public:
|
||||
private:
|
||||
bool InternalDispatch(int client, const ICommandArgs *args);
|
||||
ResultType RunAdminCommand(ConCmdInfo *pInfo, int client, int args);
|
||||
ConCmdInfo *AddOrFindCommand(const char *name, const char *description, int flags);
|
||||
ConCmdInfo *AddOrFindCommand(const char *name, const char *description, int flags, IPlugin *pPlugin);
|
||||
void AddToCmdList(ConCmdInfo *info);
|
||||
void RemoveConCmd(ConCmdInfo *info, const char *cmd, bool untrack);
|
||||
bool CheckAccess(int client, const char *cmd, AdminCmdInfo *pAdmin);
|
||||
|
@ -712,7 +712,8 @@ static cell_t sm_RegServerCmd(IPluginContext *pContext, const cell_t *params)
|
||||
return pContext->ThrowNativeError("Invalid function id (%X)", params[2]);
|
||||
}
|
||||
|
||||
if (!g_ConCmds.AddServerCommand(pFunction, name, help, params[4]))
|
||||
IPlugin *pPlugin = scripts->FindPluginByContext(pContext->GetContext());
|
||||
if (!g_ConCmds.AddServerCommand(pFunction, name, help, params[4], pPlugin))
|
||||
{
|
||||
return pContext->ThrowNativeError("Command \"%s\" could not be created. A convar with the same name already exists.", name);
|
||||
}
|
||||
@ -742,7 +743,7 @@ static cell_t sm_RegConsoleCmd(IPluginContext *pContext, const cell_t *params)
|
||||
|
||||
IPlugin *pPlugin = scripts->FindPluginByContext(pContext->GetContext());
|
||||
const char *group = pPlugin->GetFilename();
|
||||
if (!g_ConCmds.AddAdminCommand(pFunction, name, group, 0, help, params[4]))
|
||||
if (!g_ConCmds.AddAdminCommand(pFunction, name, group, 0, help, params[4], pPlugin))
|
||||
{
|
||||
return pContext->ThrowNativeError("Command \"%s\" could not be created. A convar with the same name already exists.", name);
|
||||
}
|
||||
@ -769,9 +770,9 @@ static cell_t sm_RegAdminCmd(IPluginContext *pContext, const cell_t *params)
|
||||
pContext->LocalToString(params[5], (char **)&group);
|
||||
pFunction = pContext->GetFunctionById(params[2]);
|
||||
|
||||
IPlugin *pPlugin = scripts->FindPluginByContext(pContext->GetContext());
|
||||
if (group[0] == '\0')
|
||||
{
|
||||
IPlugin *pPlugin = scripts->FindPluginByContext(pContext->GetContext());
|
||||
group = pPlugin->GetFilename();
|
||||
}
|
||||
|
||||
@ -780,7 +781,7 @@ static cell_t sm_RegAdminCmd(IPluginContext *pContext, const cell_t *params)
|
||||
return pContext->ThrowNativeError("Invalid function id (%X)", params[2]);
|
||||
}
|
||||
|
||||
if (!g_ConCmds.AddAdminCommand(pFunction, name, group, flags, help, cmdflags))
|
||||
if (!g_ConCmds.AddAdminCommand(pFunction, name, group, flags, help, cmdflags, pPlugin))
|
||||
{
|
||||
return pContext->ThrowNativeError("Command \"%s\" could not be created. A convar with the same name already exists.", name);
|
||||
}
|
||||
@ -1307,6 +1308,141 @@ static cell_t FakeClientCommandKeyValues(IPluginContext *pContext, const cell_t
|
||||
#endif
|
||||
}
|
||||
|
||||
static cell_t sm_CommandIterator(IPluginContext *pContext, const cell_t *params)
|
||||
{
|
||||
GlobCmdIter *iter = new GlobCmdIter;
|
||||
iter->started = false;
|
||||
|
||||
Handle_t hndl = handlesys->CreateHandle(hCmdIterType, iter, pContext->GetIdentity(), g_pCoreIdent, NULL);
|
||||
if (hndl == BAD_HANDLE)
|
||||
{
|
||||
delete iter;
|
||||
}
|
||||
|
||||
return hndl;
|
||||
}
|
||||
|
||||
static cell_t sm_CommandIteratorNext(IPluginContext *pContext, const cell_t *params)
|
||||
{
|
||||
GlobCmdIter *iter;
|
||||
HandleError err;
|
||||
HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent);
|
||||
|
||||
if ((err = handlesys->ReadHandle(params[1], hCmdIterType, &sec, (void **)&iter))
|
||||
!= HandleError_None)
|
||||
{
|
||||
return pContext->ThrowNativeError("Invalid CommandIterator Handle %x", params[1]);
|
||||
}
|
||||
|
||||
const List<ConCmdInfo *> &cmds = g_ConCmds.GetCommandList();
|
||||
|
||||
if (!iter->started)
|
||||
{
|
||||
iter->iter = cmds.begin();
|
||||
iter->started = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
iter->iter++;
|
||||
}
|
||||
|
||||
// iterate further, skip non-sourcemod cmds
|
||||
while (iter->iter != cmds.end() && !(*(iter->iter))->sourceMod)
|
||||
{
|
||||
iter->iter++;
|
||||
}
|
||||
|
||||
return iter->iter != cmds.end();
|
||||
}
|
||||
|
||||
static cell_t sm_CommandIteratorFlags(IPluginContext *pContext, const cell_t *params)
|
||||
{
|
||||
GlobCmdIter *iter;
|
||||
HandleError err;
|
||||
HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent);
|
||||
|
||||
if ((err = handlesys->ReadHandle(params[1], hCmdIterType, &sec, (void **)&iter))
|
||||
!= HandleError_None)
|
||||
{
|
||||
return pContext->ThrowNativeError("Invalid CommandIterator Handle %x", params[1]);
|
||||
}
|
||||
const List<ConCmdInfo *> &cmds = g_ConCmds.GetCommandList();
|
||||
if (!iter->started || iter->iter == cmds.end())
|
||||
{
|
||||
return pContext->ThrowNativeError("Invalid CommandIterator position");
|
||||
}
|
||||
|
||||
ConCmdInfo *pInfo = (*(iter->iter));
|
||||
return pInfo->eflags;
|
||||
}
|
||||
|
||||
static cell_t sm_CommandIteratorGetDesc(IPluginContext *pContext, const cell_t *params)
|
||||
{
|
||||
GlobCmdIter *iter;
|
||||
HandleError err;
|
||||
HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent);
|
||||
|
||||
if ((err = handlesys->ReadHandle(params[1], hCmdIterType, &sec, (void **)&iter))
|
||||
!= HandleError_None)
|
||||
{
|
||||
return pContext->ThrowNativeError("Invalid CommandIterator Handle %x", params[1]);
|
||||
}
|
||||
const List<ConCmdInfo *> &cmds = g_ConCmds.GetCommandList();
|
||||
if (!iter->started || iter->iter == cmds.end())
|
||||
{
|
||||
return pContext->ThrowNativeError("Invalid CommandIterator position");
|
||||
}
|
||||
|
||||
ConCmdInfo *pInfo = (*(iter->iter));
|
||||
pContext->StringToLocalUTF8(params[2], params[3], pInfo->pCmd->GetHelpText(), NULL);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static cell_t sm_CommandIteratorGetName(IPluginContext *pContext, const cell_t *params)
|
||||
{
|
||||
GlobCmdIter *iter;
|
||||
HandleError err;
|
||||
HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent);
|
||||
|
||||
if ((err = handlesys->ReadHandle(params[1], hCmdIterType, &sec, (void **)&iter))
|
||||
!= HandleError_None)
|
||||
{
|
||||
return pContext->ThrowNativeError("Invalid CommandIterator Handle %x", params[1]);
|
||||
}
|
||||
const List<ConCmdInfo *> &cmds = g_ConCmds.GetCommandList();
|
||||
if (!iter->started || iter->iter == cmds.end())
|
||||
{
|
||||
return pContext->ThrowNativeError("Invalid CommandIterator position");
|
||||
}
|
||||
|
||||
ConCmdInfo *pInfo = (*(iter->iter));
|
||||
pContext->StringToLocalUTF8(params[2], params[3], pInfo->pCmd->GetName(), NULL);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static cell_t sm_CommandIteratorPlugin(IPluginContext *pContext, const cell_t *params)
|
||||
{
|
||||
GlobCmdIter *iter;
|
||||
HandleError err;
|
||||
HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent);
|
||||
|
||||
if ((err = handlesys->ReadHandle(params[1], hCmdIterType, &sec, (void **)&iter))
|
||||
!= HandleError_None)
|
||||
{
|
||||
return pContext->ThrowNativeError("Invalid CommandIterator Handle %x", params[1]);
|
||||
}
|
||||
const List<ConCmdInfo *> &cmds = g_ConCmds.GetCommandList();
|
||||
if (!iter->started || iter->iter == cmds.end())
|
||||
{
|
||||
return pContext->ThrowNativeError("Invalid CommandIterator position");
|
||||
}
|
||||
|
||||
ConCmdInfo *pInfo = (*(iter->iter));
|
||||
return pInfo->pPlugin->GetMyHandle();
|
||||
}
|
||||
|
||||
REGISTER_NATIVES(consoleNatives)
|
||||
{
|
||||
{"CreateConVar", sm_CreateConVar},
|
||||
@ -1372,5 +1508,12 @@ REGISTER_NATIVES(consoleNatives)
|
||||
{"ConVar.AddChangeHook", sm_HookConVarChange},
|
||||
{"ConVar.RemoveChangeHook", sm_UnhookConVarChange},
|
||||
|
||||
{"CommandIterator.CommandIterator", sm_CommandIterator},
|
||||
{"CommandIterator.Next", sm_CommandIteratorNext},
|
||||
{"CommandIterator.GetDescription", sm_CommandIteratorGetDesc},
|
||||
{"CommandIterator.GetName", sm_CommandIteratorGetName},
|
||||
{"CommandIterator.Flags.get", sm_CommandIteratorFlags},
|
||||
{"CommandIterator.Plugin.get", sm_CommandIteratorPlugin},
|
||||
|
||||
{NULL, NULL}
|
||||
};
|
||||
|
@ -433,6 +433,52 @@ native int GetCmdArg(int argnum, char[] buffer, int maxlength);
|
||||
*/
|
||||
native int GetCmdArgString(char[] buffer, int maxlength);
|
||||
|
||||
methodmap CommandIterator < Handle {
|
||||
// Creates a new CommandIterator. Must be freed with delete or
|
||||
// CloseHandle().
|
||||
//
|
||||
// The CommandIterator can be used to iterate commands created by
|
||||
// SourceMod plugins and allows inspection of properties associated
|
||||
// with the command.
|
||||
//
|
||||
// @return New CommandIterator Handle.
|
||||
public native CommandIterator();
|
||||
|
||||
// Determines if there is a next command. If one is found, the
|
||||
// iterator is advanced to it.
|
||||
//
|
||||
// @return true if found and iterator is advanced.
|
||||
public native bool Next();
|
||||
|
||||
// Retrieves the command's description.
|
||||
//
|
||||
// @param buffer Buffer to copy to.
|
||||
// @param maxlen Maximum size of the buffer.
|
||||
// @error Invalid iterator position.
|
||||
public native void GetDescription(char[] buffer, int maxlen);
|
||||
|
||||
// Retrieves the command's name.
|
||||
//
|
||||
// @param buffer Buffer to copy to.
|
||||
// @param maxlen Maximum size of the buffer.
|
||||
// @error Invalid iterator position.
|
||||
public native void GetName(char[] buffer, int maxlen);
|
||||
|
||||
// Retrieves the plugin handle of the command's creator
|
||||
//
|
||||
// @error Invalid iterator position.
|
||||
property Handle Plugin {
|
||||
public native get();
|
||||
}
|
||||
|
||||
// Retrieves the command's default flags
|
||||
//
|
||||
// @error Invalid iterator position.
|
||||
property int Flags {
|
||||
public native get();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a command iterator. Must be freed with CloseHandle().
|
||||
*
|
||||
|
Loading…
Reference in New Issue
Block a user