Add a PluginIterator methodmap (#1779)

* Add a PluginIterator methodmap

* Follow convention

* Update sourcemod.inc

* Turn method ReadPlugin into property Plugin

* Requested change

* Update sourcemod.inc

* Curse you VSC

* Follow behavior of other iterators instead of the natives

* Fix a stray space

* Implement a hacked CPluginIterator

* Oops

Copy paste go brr

* Revert a change made before the custom impl
This commit is contained in:
Deathreus 2022-06-24 02:46:03 -07:00 committed by GitHub
parent 28a5d4b342
commit 37c2a83523
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 149 additions and 2 deletions

View File

@ -32,6 +32,7 @@
#include <time.h>
#include <string.h>
#include <stdlib.h>
#include <list>
#include "common_logic.h"
#include "Logger.h"
@ -56,6 +57,7 @@
#include <bridge/include/CoreProvider.h>
#include <bridge/include/IScriptManager.h>
#include <bridge/include/IExtensionBridge.h>
#include <sh_vector.h>
using namespace SourceMod;
using namespace SourcePawn;
@ -114,6 +116,71 @@ public:
}
} g_CoreNativeHelpers;
/**
* @brief Nearly identical to the standard core plugin iterator
* with one key difference. Next doesn't increment the counter
* the first time it is ran. This is a hack for the methodmap..
*/
class CMMPluginIterator
: public IPluginIterator,
public IPluginsListener
{
public:
CMMPluginIterator(const CVector<SMPlugin *> *list)
: m_hasStarted(false)
{
for(auto iter = list->begin(); iter != list->end(); ++iter) {
m_list.push_back(*iter);
}
scripts->FreePluginList(list);
m_current = m_list.begin();
scripts->AddPluginsListener(this);
}
virtual ~CMMPluginIterator()
{
scripts->RemovePluginsListener(this);
}
virtual bool MorePlugins() override
{
return (m_current != m_list.end());
}
virtual IPlugin *GetPlugin() override
{
return *m_current;
}
virtual void NextPlugin() override
{
if(!m_hasStarted)
{
m_hasStarted = true;
return;
}
m_current++;
}
virtual void Release() override
{
delete this;
}
public:
virtual void OnPluginDestroyed(IPlugin *plugin) override
{
if (*m_current == plugin)
m_current = m_list.erase(m_current);
else
m_list.remove(static_cast<SMPlugin *>(plugin));
}
private:
std::list<SMPlugin *> m_list;
std::list<SMPlugin *>::iterator m_current;
bool m_hasStarted;
};
void LogAction(Handle_t hndl, int type, int client, int target, const char *message)
{
if (g_OnLogAction->GetFunctionCount())
@ -146,7 +213,7 @@ void LogAction(Handle_t hndl, int type, int client, int target, const char *mess
g_Logger.LogMessage("[%s] %s", logtag, message);
}
static cell_t ThrowError(IPluginContext *pContext, const cell_t *params)
static cell_t ThrowError(IPluginContext *pContext, const cell_t *params)
{
char buffer[512];
@ -264,6 +331,60 @@ static cell_t ReadPlugin(IPluginContext *pContext, const cell_t *params)
return pPlugin->GetMyHandle();
}
static cell_t PluginIterator_Create(IPluginContext *pContext, const cell_t *params)
{
IPluginIterator *iter = new CMMPluginIterator(scripts->ListPlugins());
Handle_t hndl = handlesys->CreateHandle(g_PlIter, iter, pContext->GetIdentity(), g_pCoreIdent, NULL);
if (hndl == BAD_HANDLE)
{
iter->Release();
}
return hndl;
}
static cell_t PluginIterator_Next(IPluginContext *pContext, const cell_t *params)
{
Handle_t hndl = (Handle_t)params[1];
HandleSecurity sec{pContext->GetIdentity(), g_pCoreIdent};
HandleError err{};
IPluginIterator *pIter = nullptr;
if ((err=handlesys->ReadHandle(hndl, g_PlIter, &sec, (void **)&pIter)) != HandleError_None)
{
return pContext->ThrowNativeError("Could not read Handle %x (error %d)", hndl, err);
}
if(!pIter->MorePlugins())
return 0;
pIter->NextPlugin();
return 1;
}
static cell_t PluginIterator_Plugin_get(IPluginContext *pContext, const cell_t *params)
{
Handle_t hndl = (Handle_t)params[1];
HandleSecurity sec{pContext->GetIdentity(), g_pCoreIdent};
HandleError err{};
IPluginIterator *pIter = nullptr;
if ((err=handlesys->ReadHandle(hndl, g_PlIter, &sec, (void **)&pIter)) != HandleError_None)
{
return pContext->ThrowNativeError("Could not read Handle %x (error %d)", hndl, err);
}
IPlugin *pPlugin = pIter->GetPlugin();
if (!pPlugin)
{
return BAD_HANDLE;
}
return pPlugin->GetMyHandle();
}
IPlugin *GetPluginFromHandle(IPluginContext *pContext, Handle_t hndl)
{
if (hndl == BAD_HANDLE)
@ -969,7 +1090,7 @@ REGISTER_NATIVES(coreNatives)
{"FormatTime", FormatTime},
{"GetPluginIterator", GetPluginIterator},
{"MorePlugins", MorePlugins},
{"ReadPlugin", ReadPlugin},
{"ReadPlugin", ReadPlugin},
{"GetPluginStatus", GetPluginStatus},
{"GetPluginFilename", GetPluginFilename},
{"IsPluginDebugging", IsPluginDebugging},
@ -1000,5 +1121,9 @@ REGISTER_NATIVES(coreNatives)
{"FrameIterator.LineNumber.get", FrameIterator_LineNumber},
{"FrameIterator.GetFunctionName", FrameIterator_GetFunctionName},
{"FrameIterator.GetFilePath", FrameIterator_GetFilePath},
{"PluginIterator.PluginIterator", PluginIterator_Create},
{"PluginIterator.Next", PluginIterator_Next},
{"PluginIterator.Plugin.get", PluginIterator_Plugin_get},
{NULL, NULL},
};

View File

@ -243,6 +243,28 @@ forward void OnAllPluginsLoaded();
*/
native Handle GetMyHandle();
methodmap PluginIterator < Handle
{
// Returns an iterator that can be used to search through plugins.
//
// @return A new Handle to a PluginIterator.
public native PluginIterator();
// Advances the iterator. Returns whether there are more plugins available in the iterator.
//
// @return True on more plugins, false otherwise.
// @error Invalid Handle.
public native bool Next();
// Returns the current plugin in the iterator.
//
// @return Current plugin the iterator is at
// @error Invalid Handle.
property Handle Plugin {
public native get();
}
}
/**
* Returns an iterator that can be used to search through plugins.
*