Open bottiger1 opened 3 months ago
If you have optional natives coming from an extension, they stop working when you reload the extension.
If they come from a plugin instead, if you reload the plugin that provides the natives, they continue to work.
I've spent some time trying to see if it's an easy solution but it appears to be quite complex because "fake natives" which I assume are plugin natives, seem to have an entirely different implementation.
It's unfortunate that you deleted the template, as this has (binding) seen significant work since 1.5, 1.6, 1.7, 1.8, and I think 1.10.
What version of sourcemod are you running?
If you have optional natives coming from an extension, they stop working when you reload the extension. If they come from a plugin instead, if you reload the plugin that provides the natives, they continue to work. I've spent some time trying to see if it's an easy solution but it appears to be quite complex because "fake natives" which I assume are plugin natives, seem to have an entirely different implementation.
It's unfortunate that you deleted the template, as this has (binding) seen significant work since 1.5, 1.6, 1.7, 1.8, and I think 1.10.
What version of sourcemod are you running?
I'm using bleeding edge sourcemod and this has been a problem for as long as I can remember.
https://github.com/alliedmodders/sourcemod/commit/e07c120cab173a0d40cafa840537cd11c7bb6ee9
I wrote some untested pseudocode.
The logic is to go through all the plugins, find any unbound optional natives, and rebind them.
Do you know if this will work?
bool CPluginManager::RequireExtensions(CPlugin *pPlugin)
if(!ext.required)
{
pPlugin->optionalExtensions.add(ext.name); // std::set
}
////////////////////////////////////
void CExtension::MarkAllLoaded()
if (!bridge->IsMapLoading())
{
std::set<string> libs = m_libraries
for (PluginIter iter(g_PluginSys.m_plugins); !iter.done(); iter.next()) {
CPlugin *pPlugin = (*iter);
IPluginContext *pContext = pPlugin->GetBaseContext();
if(pPlugin->optionalExtensions.contains(GetAPI()->GetExtensionName()))
{
sharesys->BeginBindingFor(pPlugin); // maybe not needed?
uint32_t native_count = pContext->GetNativesNum();
auto rt = pPlugin->GetRuntime();
// find unbound optional natives
for (uint32_t i = 0; i < native_count; i++)
{
const sp_native_t *native = pContext->GetRuntime()->GetNative(i);
if (!native)
continue;
if ( (native->flags & SP_NTVFLAG_OPTIONAL) == 0 || native->func != nullptr)
continue;
auto extensionNative = sharesys->FindNative(native->name);
if(!extensionNative)
continue;
rt->UpdateNativeBinding(i, extensionNative->native->func, native->flags, nullptr);
}
}
}
}
If you have optional natives coming from an extension, they stop working when you reload the extension.
If they come from a plugin instead, if you reload the plugin that provides the natives, they continue to work.
I've spent some time trying to see if it's an easy solution but it appears to be quite complex because "fake natives" which I assume are plugin natives, seem to have an entirely different implementation.