mirror of
https://foundry.openuru.org/gitblit/r/CWE-ou-minkata.git
synced 2025-07-21 04:39:45 +00:00
Hoist MOULOpenSourceClientPlugin/Plasma20/* to top level
to match H'uru layout and make patching/cherry-picking easier.
This commit is contained in:
514
Sources/Plasma/PubUtilLib/plResMgr/plKeyFinder.cpp
Normal file
514
Sources/Plasma/PubUtilLib/plResMgr/plKeyFinder.cpp
Normal file
@ -0,0 +1,514 @@
|
||||
/*==LICENSE==*
|
||||
|
||||
CyanWorlds.com Engine - MMOG client, server and tools
|
||||
Copyright (C) 2011 Cyan Worlds, Inc.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Additional permissions under GNU GPL version 3 section 7
|
||||
|
||||
If you modify this Program, or any covered work, by linking or
|
||||
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
|
||||
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
|
||||
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
|
||||
(or a modified version of those libraries),
|
||||
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
|
||||
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
|
||||
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
|
||||
licensors of this Program grant you additional
|
||||
permission to convey the resulting work. Corresponding Source for a
|
||||
non-source form of such a combination shall include the source code for
|
||||
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
|
||||
work.
|
||||
|
||||
You can contact Cyan Worlds, Inc. by email legal@cyan.com
|
||||
or by snail mail at:
|
||||
Cyan Worlds, Inc.
|
||||
14617 N Newport Hwy
|
||||
Mead, WA 99021
|
||||
|
||||
*==LICENSE==*/
|
||||
#include "plKeyFinder.h"
|
||||
|
||||
#include "hsTemplates.h"
|
||||
#include "hsStlUtils.h"
|
||||
|
||||
#include "hsResMgr.h"
|
||||
#include "plResManager.h"
|
||||
|
||||
#include "plRegistryHelpers.h"
|
||||
#include "plRegistryNode.h"
|
||||
#include "plRegistryKeyList.h"
|
||||
#include "plPageInfo.h"
|
||||
#include "../pnFactory/plFactory.h"
|
||||
#include "hsUtils.h"
|
||||
#include "plCreatableIndex.h"
|
||||
|
||||
plResManager* IGetResMgr() { return (plResManager*)hsgResMgr::ResMgr(); }
|
||||
|
||||
plKeyFinder& plKeyFinder::Instance()
|
||||
{
|
||||
static plKeyFinder theInstance;
|
||||
return theInstance;
|
||||
}
|
||||
|
||||
const char* plKeyFinder::GetLastErrorString() // For Console display
|
||||
{
|
||||
// For Console display
|
||||
static const char* KeyFinderErrors[] =
|
||||
{
|
||||
"Ok",
|
||||
"Age not found",
|
||||
"Page not found",
|
||||
"Invalid class",
|
||||
"None of those classes in this page",
|
||||
"Object not found"
|
||||
};
|
||||
return KeyFinderErrors[fLastError];
|
||||
}
|
||||
|
||||
//
|
||||
// Does name string compare with potentially mangled (ie. [1 0 0]foo) names
|
||||
//
|
||||
hsBool NameMatches(const char* obName, const char* pKName, hsBool subString)
|
||||
{
|
||||
if (!obName || !pKName)
|
||||
return false;
|
||||
|
||||
const char *o = obName;
|
||||
const char *p = pKName;
|
||||
|
||||
// If names are mangled, unmangle
|
||||
if (*o != '[' || *p != '[')
|
||||
{
|
||||
// skip past ']' in both names in case mangled
|
||||
while (*o && *o != ']')
|
||||
o++;
|
||||
o = (*o==']') ? o+1 : obName;
|
||||
|
||||
while (*p && *p != ']')
|
||||
p++;
|
||||
p = (*p==']') ? p+1 : pKName;
|
||||
}
|
||||
|
||||
if (!subString)
|
||||
{
|
||||
if (!_stricmp(o, p))
|
||||
return true; // FOUND IT!!!!!!!!!!!!!!!!!!!
|
||||
}
|
||||
else
|
||||
{
|
||||
char oCopy[256], pCopy[256];
|
||||
strcpy(oCopy, o);
|
||||
strcpy(pCopy, p);
|
||||
hsStrLower(oCopy);
|
||||
hsStrLower(pCopy);
|
||||
if (strstr(pCopy, oCopy))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
plKey plKeyFinder::StupidSearch(const char * age, const char * rm,
|
||||
const char *className, const char *obName, hsBool subString)
|
||||
{
|
||||
UInt16 ty = plFactory::FindClassIndex(className);
|
||||
return StupidSearch(age, rm, ty, obName, subString);
|
||||
}
|
||||
|
||||
class plKeyFinderIter : public plRegistryKeyIterator, public plRegistryPageIterator
|
||||
{
|
||||
protected:
|
||||
UInt16 fClassType;
|
||||
const char *fObjName;
|
||||
hsBool fSubstr;
|
||||
plKey fFoundKey;
|
||||
const char *fAgeName;
|
||||
|
||||
public:
|
||||
plKey GetFoundKey( void ) const { return fFoundKey; }
|
||||
|
||||
plKeyFinderIter( UInt16 classType, const char *obName, hsBool substr )
|
||||
: fFoundKey( nil ), fClassType( classType ), fObjName( obName ), fSubstr( substr ) { }
|
||||
|
||||
plKeyFinderIter( UInt16 classType, const char *obName, hsBool substr, const char *ageName )
|
||||
: fFoundKey( nil ), fClassType( classType ), fObjName( obName ), fSubstr( substr ),
|
||||
fAgeName( ageName ) {}
|
||||
|
||||
virtual hsBool EatKey( const plKey& key )
|
||||
{
|
||||
if( key->GetUoid().GetClassType() == fClassType &&
|
||||
NameMatches( fObjName, key->GetUoid().GetObjectName(), fSubstr ) )
|
||||
{
|
||||
fFoundKey = key;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual hsBool EatPage( plRegistryPageNode *pageNode )
|
||||
{
|
||||
#ifndef _DEBUG
|
||||
try
|
||||
{
|
||||
#endif
|
||||
if( stricmp( pageNode->GetPageInfo().GetAge(), fAgeName ) == 0 )
|
||||
{
|
||||
// Try loading and searching thru this page
|
||||
std::set<plKey> keyRefs;
|
||||
|
||||
IGetResMgr()->LoadPageKeys( pageNode );
|
||||
plKeyCollector coll( keyRefs );
|
||||
pageNode->IterateKeys( &coll );
|
||||
|
||||
if( !pageNode->IterateKeys( this ) )
|
||||
return false;
|
||||
}
|
||||
#ifndef _DEBUG
|
||||
} catch (...)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
plKey plKeyFinder::StupidSearch(const char * age, const char * rm,
|
||||
UInt16 classType, const char *obName, hsBool subString)
|
||||
{
|
||||
if (!obName)
|
||||
return nil;
|
||||
|
||||
plUoid newOid;
|
||||
|
||||
fLastError = kOk;
|
||||
|
||||
UInt16 maxClasses = plFactory::GetNumClasses();
|
||||
|
||||
UInt16 ty = classType;
|
||||
if (ty == maxClasses) // error
|
||||
{ fLastError = kInvalidClass;
|
||||
return nil;
|
||||
}
|
||||
|
||||
if( age != nil && rm != nil )
|
||||
{
|
||||
const plLocation &loc = IGetResMgr()->FindLocation( age, rm );
|
||||
if( !loc.IsValid() )
|
||||
{
|
||||
fLastError = kPageNotFound;
|
||||
return nil;
|
||||
}
|
||||
|
||||
plKeyFinderIter keyFinder( classType, obName, subString );
|
||||
|
||||
if( !IGetResMgr()->IterateKeys( &keyFinder, loc ) )
|
||||
// Return value of false means it stopped somewhere, i.e. found something
|
||||
return keyFinder.GetFoundKey();
|
||||
}
|
||||
else if( age != nil )
|
||||
{
|
||||
plKeyFinderIter keyFinder(classType, obName, subString, age);
|
||||
|
||||
if( !IGetResMgr()->IterateAllPages( &keyFinder ) )
|
||||
return keyFinder.GetFoundKey();
|
||||
}
|
||||
else
|
||||
{
|
||||
plKeyFinderIter keyFinder( classType, obName, subString );
|
||||
|
||||
if( !IGetResMgr()->IterateKeys( &keyFinder ) )
|
||||
// Return value of false means it stopped somewhere, i.e. found something
|
||||
return keyFinder.GetFoundKey();
|
||||
}
|
||||
|
||||
fLastError = kObjectNotFound;
|
||||
return nil;
|
||||
}
|
||||
|
||||
void plKeyFinder::ReallyStupidResponderSearch(const char *name, std::vector<plKey>& foundKeys, const plLocation &hintLocation )
|
||||
{
|
||||
ReallyStupidSubstringSearch(name, CLASS_INDEX_SCOPED(plResponderModifier), foundKeys, hintLocation);
|
||||
}
|
||||
|
||||
void plKeyFinder::ReallyStupidActivatorSearch(const char *name, std::vector<plKey>& foundKeys, const plLocation &hintLocation)
|
||||
{
|
||||
// use the createable macro so we don't have to pull in all of Python
|
||||
ReallyStupidSubstringSearch(name, CLASS_INDEX_SCOPED(plLogicModifier), foundKeys, hintLocation);
|
||||
ReallyStupidSubstringSearch(name, CLASS_INDEX_SCOPED(plPythonFileMod), foundKeys, hintLocation);
|
||||
ReallyStupidSubstringSearch(name, CLASS_INDEX_SCOPED(plSittingModifier), foundKeys, hintLocation);
|
||||
}
|
||||
|
||||
void plKeyFinder::IGetNames(std::vector<std::string>& names, const char* searchName, int index)
|
||||
{
|
||||
// Not really searching for any particular key, just need all the logic mods
|
||||
std::vector<plKey> keys;
|
||||
ReallyStupidSubstringSearch(searchName, index, keys);
|
||||
|
||||
for (int i = 0; i < keys.size(); i++)
|
||||
{
|
||||
// Only allow loaded ones to cut down on the crap
|
||||
plKey key = keys[i];
|
||||
if (key->ObjectIsLoaded())
|
||||
names.push_back(key->GetName());
|
||||
}
|
||||
}
|
||||
|
||||
void plKeyFinder::GetResponderNames(std::vector<std::string>& names)
|
||||
{
|
||||
IGetNames(names, "", CLASS_INDEX_SCOPED(plResponderModifier));
|
||||
}
|
||||
|
||||
void plKeyFinder::GetActivatorNames(std::vector<std::string>& names)
|
||||
{
|
||||
IGetNames(names, "", CLASS_INDEX_SCOPED(plLogicModifier));
|
||||
}
|
||||
|
||||
class plKeyFinderIterator : public plRegistryKeyIterator, public plRegistryPageIterator
|
||||
{
|
||||
protected:
|
||||
|
||||
UInt16 fClassType;
|
||||
const char *fObjName;
|
||||
|
||||
std::vector<plKey> &fFoundKeys;
|
||||
|
||||
public:
|
||||
|
||||
plKeyFinderIterator( UInt16 classType, const char *obName, std::vector<plKey>& foundKeys )
|
||||
: fClassType( classType ), fObjName( obName ), fFoundKeys( foundKeys ) { }
|
||||
|
||||
virtual hsBool EatKey( const plKey& key )
|
||||
{
|
||||
if( key->GetUoid().IsValid() && key->GetUoid().GetClassType() == fClassType &&
|
||||
strstr( key->GetUoid().GetObjectName(), fObjName ) )
|
||||
{
|
||||
fFoundKeys.push_back( key );
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual hsBool EatPage( plRegistryPageNode *page )
|
||||
{
|
||||
hsBool ret = page->IterateKeys( this );
|
||||
return ret;
|
||||
}
|
||||
};
|
||||
|
||||
void plKeyFinder::ReallyStupidSubstringSearch(const char *name, UInt16 objType, std::vector<plKey>& foundKeys, const plLocation &hintLocation )
|
||||
{
|
||||
if (!name)
|
||||
return;
|
||||
|
||||
plKeyFinderIterator collector( objType, name, foundKeys );
|
||||
if( hintLocation.IsValid() )
|
||||
{
|
||||
plRegistryPageNode *hintPage = IGetResMgr()->FindPage( hintLocation );
|
||||
if( hintPage != nil )
|
||||
{
|
||||
// Try all pages in the same age as that page
|
||||
IGetResMgr()->IteratePages( &collector, hintPage->GetPageInfo().GetAge() );
|
||||
}
|
||||
|
||||
if (foundKeys.size() > 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
//fpReg->IterateKeys( &collector );
|
||||
IGetResMgr()->IterateAllPages( &collector );
|
||||
}
|
||||
|
||||
//// Helper Class for FindSceneNodeKey ///////////////////////////////////////
|
||||
|
||||
class plPageFinder : public plRegistryPageIterator
|
||||
{
|
||||
protected:
|
||||
|
||||
plRegistryPageNode **fPagePtr;
|
||||
const char *fFindString, *fAgeString;
|
||||
|
||||
public:
|
||||
|
||||
plPageFinder( plRegistryPageNode **page, const char *find ) : fPagePtr( page ), fFindString( find ), fAgeString( nil )
|
||||
{ *fPagePtr = nil; }
|
||||
|
||||
plPageFinder( plRegistryPageNode **page, const char *ageS, const char *pageS ) : fPagePtr( page ), fFindString( pageS ), fAgeString( ageS )
|
||||
{ *fPagePtr = nil; }
|
||||
|
||||
virtual hsBool EatPage( plRegistryPageNode *node )
|
||||
{
|
||||
static char str[ 512 ];
|
||||
const plPageInfo &info = node->GetPageInfo();
|
||||
|
||||
// Are we searching by age/page?
|
||||
if( fAgeString != nil )
|
||||
{
|
||||
if( stricmp( info.GetAge(), fAgeString ) == 0 &&
|
||||
stricmp( info.GetPage(), fFindString ) == 0 )
|
||||
{
|
||||
*fPagePtr = node;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// Try for page only
|
||||
if( stricmp( info.GetPage(), fFindString ) == 0 )
|
||||
{
|
||||
*fPagePtr = node;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Try for full location
|
||||
sprintf( str, "%s_%s_%s", info.GetAge(), info.GetPage() );
|
||||
if( stricmp( str, fFindString ) == 0 )
|
||||
{
|
||||
*fPagePtr = node;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true; // Keep searching
|
||||
}
|
||||
};
|
||||
|
||||
//// FindSceneNodeKey ////////////////////////////////////////////////////////
|
||||
// Given a string for either a page name or a fully qualified location name,
|
||||
// finds the page and then returns the key for the sceneNode in that page.
|
||||
// Note: in our case, we want to force the page's keys to load if necessary,
|
||||
// since the only time we call this function will be to actually load
|
||||
// the darned thing.
|
||||
|
||||
plKey plKeyFinder::FindSceneNodeKey( const char *pageOrFullLocName ) const
|
||||
{
|
||||
plRegistryPageNode *pageNode;
|
||||
plPageFinder pageFinder( &pageNode, pageOrFullLocName );
|
||||
|
||||
|
||||
// Use our own page finder, since we want to do nifty things like partial
|
||||
// matches, etc.
|
||||
if( IGetResMgr()->IterateAllPages( &pageFinder ) || pageNode == nil )
|
||||
return nil;
|
||||
|
||||
return IFindSceneNodeKey( pageNode );
|
||||
}
|
||||
|
||||
//// FindSceneNodeKey ////////////////////////////////////////////////////////
|
||||
// Age/page pair version
|
||||
|
||||
plKey plKeyFinder::FindSceneNodeKey( const char *ageName, const char *pageName ) const
|
||||
{
|
||||
plRegistryPageNode *pageNode;
|
||||
plPageFinder pageFinder( &pageNode, ageName, pageName );
|
||||
|
||||
// Use our own page finder, since we want to do nifty things like partial
|
||||
// matches, etc.
|
||||
if (IGetResMgr()->IterateAllPages(&pageFinder) || pageNode == nil)
|
||||
return nil;
|
||||
|
||||
return IFindSceneNodeKey( pageNode );
|
||||
}
|
||||
|
||||
//// FindSceneNodeKey ////////////////////////////////////////////////////////
|
||||
// plLocation version
|
||||
|
||||
plKey plKeyFinder::FindSceneNodeKey(const plLocation& location) const
|
||||
{
|
||||
plRegistryPageNode* pageNode = IGetResMgr()->FindPage(location);
|
||||
if (pageNode == nil)
|
||||
return nil;
|
||||
|
||||
return IFindSceneNodeKey(pageNode);
|
||||
}
|
||||
|
||||
//// IFindSceneNodeKey ///////////////////////////////////////////////////////
|
||||
|
||||
|
||||
plKey plKeyFinder::IFindSceneNodeKey(plRegistryPageNode* page) const
|
||||
{
|
||||
// Got the pageNode, try a find before loading
|
||||
plRegistryKeyList* keyList = page->IGetKeyList(CLASS_INDEX_SCOPED(plSceneNode));
|
||||
if (keyList)
|
||||
{
|
||||
if (keyList->fStaticKeys.size() == 1)
|
||||
{
|
||||
return plKey::Make((plKeyData*)keyList->fStaticKeys[0]);
|
||||
}
|
||||
else if (keyList->fDynamicKeys.size() == 1) // happens during export
|
||||
{
|
||||
plRegistryKeyList::DynSet::const_iterator it = keyList->fDynamicKeys.begin();
|
||||
plKeyImp* keyImp = *it;
|
||||
return plKey::Make(keyImp);
|
||||
}
|
||||
}
|
||||
|
||||
// Try loading and see if that helps
|
||||
if (page->IsFullyLoaded())
|
||||
return nil;
|
||||
|
||||
IGetResMgr()->LoadPageKeys(page);
|
||||
|
||||
// Get the list of all sceneNodes
|
||||
plKey retVal(nil);
|
||||
keyList = page->IGetKeyList(CLASS_INDEX_SCOPED(plSceneNode));
|
||||
if (keyList && keyList->fStaticKeys.size() == 1)
|
||||
{
|
||||
retVal = plKey::Make((plKeyData*)keyList->fStaticKeys[0]);
|
||||
}
|
||||
// If we just loaded up all the keys for this page, then we
|
||||
// may have a bunch of keys with a refcount of 0. For any of
|
||||
// these keys that nothing else refs (yes, we have unused objects
|
||||
// in the data), they don't get deleted because the refcount never
|
||||
// rises above zero or falls back to zero. So we'll go ahead and
|
||||
// ref and unref all of them. The ones in use stay put, the ones
|
||||
// not being used go away. This is less than ideal.
|
||||
IGetResMgr()->DumpUnusedKeys(page);
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
//// FindLocation ////////////////////////////////////////////////////////////
|
||||
|
||||
const plLocation &plKeyFinder::FindLocation( const char *age, const char *page ) const
|
||||
{
|
||||
if (age == nil)
|
||||
{
|
||||
static plLocation invalidLoc;
|
||||
plRegistryPageNode *pageNode;
|
||||
plPageFinder pageFinder( &pageNode, page );
|
||||
|
||||
if( IGetResMgr()->IterateAllPages( &pageFinder ) || pageNode == nil )
|
||||
return invalidLoc;
|
||||
|
||||
return pageNode->GetPageInfo().GetLocation();
|
||||
}
|
||||
|
||||
return IGetResMgr()->FindLocation( age, page );
|
||||
}
|
||||
|
||||
//// GetLocationInfo /////////////////////////////////////////////////////////
|
||||
|
||||
const plPageInfo* plKeyFinder::GetLocationInfo( const plLocation &loc ) const
|
||||
{
|
||||
plRegistryPageNode *node = IGetResMgr()->FindPage( loc );
|
||||
if (node)
|
||||
return &node->GetPageInfo();
|
||||
else
|
||||
return nil;
|
||||
}
|
||||
|
Reference in New Issue
Block a user