mirror of
https://github.com/UberGames/GtkRadiant.git
synced 2024-11-10 06:31:41 +00:00
synapse: when using '*' for the minor, work extra hard to match with a single, already active provider. this fixes the problems related to having pk3 vfs and qlpk3 vfs both loaded for instance
This commit is contained in:
parent
2061e40028
commit
def29cb7b4
7 changed files with 111 additions and 20 deletions
|
@ -387,7 +387,7 @@ extern "C" CSynapseClient * SYNAPSE_DLL_EXPORT Synapse_EnumerateInterfaces( cons
|
|||
|
||||
g_SynapseClient.AddAPI( PLUGIN_MAJOR, "HydraToolz", sizeof( _QERPluginTable ) );
|
||||
g_SynapseClient.AddAPI( RADIANT_MAJOR, NULL, sizeof( g_FuncTable ), SYN_REQUIRE, &g_FuncTable );
|
||||
g_SynapseClient.AddAPI( VFS_MAJOR, "wad", sizeof( g_FileSystemTable ), SYN_REQUIRE, &g_FileSystemTable );
|
||||
g_SynapseClient.AddAPI( VFS_MAJOR, "*", sizeof( g_FileSystemTable ), SYN_REQUIRE, &g_FileSystemTable ); // wad, typically
|
||||
g_SynapseClient.AddAPI( ENTITY_MAJOR, NULL, sizeof( g_EntityTable ), SYN_REQUIRE, &g_EntityTable );
|
||||
return &g_SynapseClient;
|
||||
}
|
||||
|
|
|
@ -404,6 +404,11 @@ virtual bool OnActivate() { return true; }
|
|||
\return wether all APIs given were successfully found in the config
|
||||
*/
|
||||
bool ConfigXML( CSynapseServer *pServer, const char *client_name, const XMLConfigEntry_t entries[] );
|
||||
|
||||
/*!
|
||||
search for a SYN_PROVIDE with that major in this client, return the index, or -1 if fail
|
||||
*/
|
||||
APIDescriptor_t * FindProvidesMajor( const char * major ) const;
|
||||
};
|
||||
|
||||
/*!
|
||||
|
@ -607,8 +612,13 @@ virtual PFN_SYN_PRINTF_VA Get_Syn_Printf();
|
|||
the minors have to be both NULL, or equal, or one the minors be '*'
|
||||
NOTE: the '*' minor should ONLY be used on an API that will be unique. It is hackish and kinda dangerous
|
||||
*/
|
||||
static bool MatchAPI( APIDescriptor_t *p1, APIDescriptor_t *p2 );
|
||||
static bool MatchAPI( const char* major1, const char* minor1, const char* major2, const char* minor2 );
|
||||
bool MatchAPI( APIDescriptor_t *p1, APIDescriptor_t *p2 );
|
||||
/*!
|
||||
\return 0: not matching
|
||||
\return 1: matching
|
||||
\return 2: do extended checks for a minor of "*"
|
||||
*/
|
||||
static int MatchAPI( const char* major1, const char* minor1, const char* major2, const char* minor2 );
|
||||
|
||||
#if defined( _WIN32 )
|
||||
/*!
|
||||
|
@ -655,6 +665,15 @@ bool GetConfigForAPI( const char *api, char **minor );
|
|||
returns the filename of the module that the passed on client exists in
|
||||
*/
|
||||
const char *GetModuleFilename( CSynapseClient *pClient );
|
||||
|
||||
/*!
|
||||
look for a client that is active, and provides a specific major
|
||||
\return 0: not found
|
||||
\return 1: single found
|
||||
\return 2: multiple found
|
||||
*/
|
||||
int FindActiveMajorClient( const char * major, APIDescriptor_t ** ret ) const;
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -424,23 +424,83 @@ void CSynapseServer::PushRequired( CSynapseClient *pClient ){
|
|||
}
|
||||
}
|
||||
|
||||
bool CSynapseServer::MatchAPI( APIDescriptor_t *p1, APIDescriptor_t *p2 ){
|
||||
return MatchAPI( p1->major_name, p1->minor_name, p2->major_name, p2->minor_name );
|
||||
int CSynapseServer::FindActiveMajorClient( const char * major, APIDescriptor_t ** ret ) const {
|
||||
Syn_Printf( "checking if we have a single active client for major \"%s\"\n", major );
|
||||
*ret = NULL;
|
||||
list<CSynapseClientSlot>::const_iterator iClient;
|
||||
for ( iClient = mClients.begin(); iClient != mClients.end(); iClient++ ) {
|
||||
CSynapseClient *pClient = ( *iClient ).mpClient;
|
||||
if ( !pClient->IsActive() ) {
|
||||
continue;
|
||||
}
|
||||
APIDescriptor_t * found = pClient->FindProvidesMajor( major );
|
||||
if ( found == NULL ) {
|
||||
continue;
|
||||
}
|
||||
Syn_Printf( " found in %s\n", pClient->GetInfo() );
|
||||
if ( *ret != NULL ) {
|
||||
return 2;
|
||||
}
|
||||
*ret = found;
|
||||
}
|
||||
if ( *ret == NULL ) {
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
bool CSynapseServer::MatchAPI( const char* major1, const char* minor1, const char* major2, const char* minor2 ){
|
||||
if ( strcmp( major1, major2 ) ) {
|
||||
bool CSynapseServer::MatchAPI( APIDescriptor_t *p1, APIDescriptor_t *p2 ){
|
||||
int ret = MatchAPI( p1->major_name, p1->minor_name, p2->major_name, p2->minor_name );
|
||||
if ( ret == 2 ) {
|
||||
// find out if we can resolve the minor "*" situation
|
||||
APIDescriptor_t * any_minor_descriptor;
|
||||
APIDescriptor_t * provider_descriptor;
|
||||
if ( strcmp( p1->minor_name, "*" ) == 0 ) {
|
||||
any_minor_descriptor = p1;
|
||||
provider_descriptor = p2;
|
||||
} else {
|
||||
assert( strcmp( p2->minor_name, "*" ) == 0 );
|
||||
any_minor_descriptor = p2;
|
||||
provider_descriptor = p1;
|
||||
}
|
||||
assert( any_minor_descriptor->mType == SYN_REQUIRE );
|
||||
assert( provider_descriptor->mType == SYN_PROVIDE );
|
||||
APIDescriptor_t * search_major;
|
||||
int search_ret = FindActiveMajorClient( provider_descriptor->major_name, &search_major );
|
||||
if ( search_ret == 2 ) {
|
||||
// FIXME: ERROR
|
||||
Syn_Printf( "ERROR: Multiple modules active for major \"%s\": cannot resolve \"*\" for it\n", provider_descriptor->major_name );
|
||||
return false;
|
||||
}
|
||||
if ( search_ret == 0 ) {
|
||||
// can't resolve yet
|
||||
return false;
|
||||
}
|
||||
if ( search_major != provider_descriptor ) {
|
||||
// the provider_descriptor we were passed is likely not active yet, so just ignore
|
||||
return false;
|
||||
}
|
||||
return true; // this is a go, we have a unique match!
|
||||
}
|
||||
return ( ret != 0 );
|
||||
}
|
||||
|
||||
int CSynapseServer::MatchAPI( const char* major1, const char* minor1, const char* major2, const char* minor2 ){
|
||||
if ( strcmp( major1, major2 ) != 0 ) {
|
||||
return 0;
|
||||
}
|
||||
// either no minor at all for this API, or matching
|
||||
if ( ( minor1 && minor2 ) && !strcmp( minor1, minor2 ) ) {
|
||||
return true;
|
||||
if ( ( minor1 != NULL && minor2 != NULL ) && strcmp( minor1, minor2 ) == 0 ) {
|
||||
return 1;
|
||||
}
|
||||
// or one of the minors says "*" (knowing that the majors match already)
|
||||
if ( ( minor1 && !strcmp( minor1, "*" ) ) || ( minor2 && !strcmp( minor2, "*" ) ) ) {
|
||||
return true;
|
||||
if ( ( minor1 != NULL && strcmp( minor1, "*" ) == 0 ) || ( minor2 != NULL && strcmp( minor2, "*" ) == 0 ) ) {
|
||||
// one of the minors is "*", and the majors are matching
|
||||
// there may be multiple SYN_PROVIDE for this major though, and we can't decide which with only this information
|
||||
// e.g. "*" means "the one", not "any" (counter-intuitive, yeah)
|
||||
// so let the caller know, maybe he'll figure it out
|
||||
return 2;
|
||||
}
|
||||
return false;
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool CSynapseServer::ResolveAPI( APIDescriptor_t* pAPI ){
|
||||
|
@ -469,9 +529,9 @@ bool CSynapseServer::ResolveAPI( APIDescriptor_t* pAPI ){
|
|||
continue;
|
||||
}
|
||||
// this is an active client, we can request
|
||||
#ifdef SYNAPSE_VERBOSE
|
||||
#ifdef SYNAPSE_VERBOSE
|
||||
Syn_Printf( "RequestAPI '%s' '%s' from '%s' for API %p\n", pAPI->major_name, pAPI->minor_name, pScanClient->GetInfo(), pAPI );
|
||||
#endif
|
||||
#endif
|
||||
if ( !pScanClient->RequestAPI( pAPI ) ) {
|
||||
// this should never happen, means we think this module provides the API, but it answers that it doesn't
|
||||
Syn_Printf( "ERROR: RequestAPI failed\n" );
|
||||
|
@ -911,6 +971,18 @@ void CSynapseClient::AddManager( CSynapseAPIManager *pManager ){
|
|||
}
|
||||
}
|
||||
|
||||
APIDescriptor_t * CSynapseClient::FindProvidesMajor( const char * major ) const {
|
||||
int i,max = GetAPICount();
|
||||
for ( i = 0; i < max; i++ )
|
||||
{
|
||||
APIDescriptor_t *pAPI = GetAPIDescriptor( i );
|
||||
if ( pAPI->mType == SYN_PROVIDE && strcmp( pAPI->major_name, major ) == 0 ) {
|
||||
return pAPI;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
CSynapseAPIManager::~CSynapseAPIManager(){
|
||||
vector<APIDescriptor_t *>::iterator iAPI;
|
||||
for ( iAPI = mAPIs.begin(); iAPI != mAPIs.end(); iAPI++ )
|
||||
|
|
|
@ -155,7 +155,7 @@ extern "C" CSynapseClient * SYNAPSE_DLL_EXPORT Synapse_EnumerateInterfaces( cons
|
|||
g_SynapseClient.AddAPI( ECLASSMANAGER_MAJOR, NULL, sizeof( g_EClassManagerTable ), SYN_REQUIRE, &g_EClassManagerTable );
|
||||
|
||||
// Needs a 'default' option for this minor because we certainly don't load anything from wad files :)
|
||||
g_SynapseClient.AddAPI( VFS_MAJOR, "wad", sizeof( g_FileSystemTable ), SYN_REQUIRE, &g_FileSystemTable );
|
||||
g_SynapseClient.AddAPI( VFS_MAJOR, "*", sizeof( g_FileSystemTable ), SYN_REQUIRE, &g_FileSystemTable ); // wad, typically
|
||||
|
||||
return &g_SynapseClient;
|
||||
}
|
||||
|
|
|
@ -75,7 +75,7 @@ extern "C" CSynapseClient * SYNAPSE_DLL_EXPORT Synapse_EnumerateInterfaces( cons
|
|||
g_SynapseClient.AddAPI( IMAGE_MAJOR, "spr", sizeof( _QERPlugImageTable ) );
|
||||
#endif
|
||||
// this "wad" needs to be "*" for the VFS, we don't care what VFS we have, as long as we have one.
|
||||
g_SynapseClient.AddAPI( VFS_MAJOR, "wad", sizeof( _QERFileSystemTable ), SYN_REQUIRE, &g_FileSystemTable );
|
||||
g_SynapseClient.AddAPI( VFS_MAJOR, "*", sizeof( _QERFileSystemTable ), SYN_REQUIRE, &g_FileSystemTable ); // wad, typically
|
||||
g_SynapseClient.AddAPI( RADIANT_MAJOR, NULL, sizeof( _QERFuncTable_1 ), SYN_REQUIRE, &g_FuncTable );
|
||||
|
||||
return &g_SynapseClient;
|
||||
|
|
|
@ -63,7 +63,7 @@ extern "C" CSynapseClient * SYNAPSE_DLL_EXPORT Synapse_EnumerateInterfaces( cons
|
|||
|
||||
g_SynapseClient.AddAPI( IMAGE_MAJOR, "png", sizeof( _QERPlugImageTable ) );
|
||||
g_SynapseClient.AddAPI( RADIANT_MAJOR, NULL, sizeof( _QERFuncTable_1 ), SYN_REQUIRE, &g_FuncTable );
|
||||
g_SynapseClient.AddAPI( VFS_MAJOR, "pk3", sizeof( _QERFileSystemTable ), SYN_REQUIRE, &g_FileSystemTable );
|
||||
g_SynapseClient.AddAPI( VFS_MAJOR, "*", sizeof( _QERFileSystemTable ), SYN_REQUIRE, &g_FileSystemTable );
|
||||
|
||||
return &g_SynapseClient;
|
||||
}
|
||||
|
|
|
@ -62,7 +62,7 @@ void CSynapseBuiltinClientDef::EnumerateInterfaces( CSynapseServer *server ){
|
|||
AddAPI( RADIANT_MAJOR, NULL, sizeof( g_FuncTable ), SYN_REQUIRE, &g_FuncTable );
|
||||
AddAPI( ECLASSMANAGER_MAJOR, NULL, sizeof( g_EClassManagerTable ), SYN_REQUIRE, &g_EClassManagerTable );
|
||||
// hardcode the minor for now, we can still add it to the synapse.config at some point
|
||||
AddAPI( VFS_MAJOR, "pk3", sizeof( g_FileSystemTable_def ), SYN_REQUIRE, &g_FileSystemTable_def );
|
||||
AddAPI( VFS_MAJOR, "*", sizeof( g_FileSystemTable_def ), SYN_REQUIRE, &g_FileSystemTable_def );
|
||||
|
||||
AddAPI( ECLASS_MAJOR, "def", sizeof( _EClassTable ) );
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue