mirror of
https://foundry.openuru.org/gitblit/r/CWE-ou-minkata.git
synced 2025-07-14 10:37:41 -04:00
Fix line endings and tabs
This commit is contained in:
@ -1,455 +1,455 @@
|
||||
/*==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/>.
|
||||
|
||||
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 "plAgeLoader.h"
|
||||
#include "hsStream.h"
|
||||
#include "plgDispatch.h"
|
||||
#include "hsResMgr.h"
|
||||
//#include "hsTimer.h"
|
||||
#include "plResPatcher.h"
|
||||
#include "plBackgroundDownloader.h"
|
||||
#include "process.h" // for getpid()
|
||||
|
||||
#include "pnProduct/pnProduct.h"
|
||||
|
||||
#include "pnKeyedObject/plKey.h"
|
||||
#include "pnKeyedObject/plFixedKey.h"
|
||||
#include "pnSceneObject/plSceneObject.h"
|
||||
#include "pnMessage/plClientMsg.h"
|
||||
#include "pnNetCommon/plNetApp.h"
|
||||
|
||||
#include "plScene/plRelevanceMgr.h"
|
||||
#include "plResMgr/plKeyFinder.h"
|
||||
#include "plAgeDescription/plAgeDescription.h"
|
||||
#include "plSDL/plSDL.h"
|
||||
#include "plNetClient/plNetClientMgr.h"
|
||||
#include "plResMgr/plRegistryHelpers.h"
|
||||
#include "plResMgr/plRegistryNode.h"
|
||||
#include "plResMgr/plResManager.h"
|
||||
#include "plFile/plEncryptedStream.h"
|
||||
|
||||
/// TEMP HACK TO LOAD CONSOLE INIT FILES ON AGE LOAD
|
||||
#include "plMessage/plConsoleMsg.h"
|
||||
#include "plMessage/plLoadAvatarMsg.h"
|
||||
#include "plMessage/plAgeLoadedMsg.h"
|
||||
|
||||
|
||||
extern hsBool gDataServerLocal;
|
||||
extern hsBool gUseBackgroundDownloader;
|
||||
|
||||
// static
|
||||
plAgeLoader* plAgeLoader::fInstance=nil;
|
||||
|
||||
//
|
||||
// CONSTRUCT
|
||||
//
|
||||
plAgeLoader::plAgeLoader() :
|
||||
fInitialAgeState(nil),
|
||||
fFlags(0)
|
||||
{
|
||||
}
|
||||
|
||||
//
|
||||
// DESTRUCT
|
||||
//
|
||||
plAgeLoader::~plAgeLoader()
|
||||
{
|
||||
delete fInitialAgeState;
|
||||
fInitialAgeState=nil;
|
||||
|
||||
if ( PendingAgeFniFiles().size() )
|
||||
plNetClientApp::StaticErrorMsg( "~plAgeLoader(): %d pending age fni files", PendingAgeFniFiles().size() );
|
||||
if ( PendingPageOuts().size() )
|
||||
plNetClientApp::StaticErrorMsg( "~plAgeLoader(): %d pending page outs", PendingPageOuts().size() );
|
||||
|
||||
ClearPageExcludeList(); // Clear our debugging exclude list, just to be tidy
|
||||
|
||||
if (fInstance==this)
|
||||
SetInstance(nil);
|
||||
}
|
||||
|
||||
void plAgeLoader::Shutdown()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void plAgeLoader::Init()
|
||||
{
|
||||
RegisterAs( kAgeLoader_KEY );
|
||||
plgDispatch::Dispatch()->RegisterForExactType(plInitialAgeStateLoadedMsg::Index(), GetKey());
|
||||
plgDispatch::Dispatch()->RegisterForExactType(plClientMsg::Index(), GetKey());
|
||||
|
||||
if (!gDataServerLocal && gUseBackgroundDownloader)
|
||||
plBackgroundDownloader::StartThread();
|
||||
}
|
||||
|
||||
//
|
||||
// STATIC
|
||||
//
|
||||
plAgeLoader* plAgeLoader::GetInstance()
|
||||
{
|
||||
return fInstance;
|
||||
}
|
||||
|
||||
//
|
||||
// STATIC
|
||||
//
|
||||
void plAgeLoader::SetInstance(plAgeLoader* inst)
|
||||
{
|
||||
fInstance=inst;
|
||||
}
|
||||
|
||||
//
|
||||
// Plasma Msg Handler
|
||||
//
|
||||
hsBool plAgeLoader::MsgReceive(plMessage* msg)
|
||||
{
|
||||
plInitialAgeStateLoadedMsg *stateMsg = plInitialAgeStateLoadedMsg::ConvertNoRef( msg );
|
||||
if( stateMsg != nil )
|
||||
{
|
||||
// done receiving the initial state of the age from the server
|
||||
return true;
|
||||
}
|
||||
|
||||
plClientMsg* clientMsg = plClientMsg::ConvertNoRef(msg);
|
||||
if (clientMsg && clientMsg->GetClientMsgFlag()==plClientMsg::kInitComplete)
|
||||
{
|
||||
ExecPendingAgeFniFiles(); // exec age-specific fni files
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
return plReceiver::MsgReceive(msg);
|
||||
}
|
||||
|
||||
//
|
||||
// read in the age desc file and page in/out the rooms belonging to the specified age.
|
||||
// return false on error
|
||||
//
|
||||
//============================================================================
|
||||
bool plAgeLoader::LoadAge(const char ageName[])
|
||||
{
|
||||
return ILoadAge(ageName);
|
||||
}
|
||||
|
||||
//============================================================================
|
||||
bool plAgeLoader::UpdateAge(const char ageName[])
|
||||
{
|
||||
bool result = true;
|
||||
|
||||
if (!gDataServerLocal)
|
||||
{
|
||||
plResPatcher myPatcher(ageName);
|
||||
result = myPatcher.Update();
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
//============================================================================
|
||||
void plAgeLoader::NotifyAgeLoaded( bool loaded )
|
||||
{
|
||||
if ( loaded )
|
||||
fFlags &= ~kLoadingAge;
|
||||
else
|
||||
fFlags &= ~kUnLoadingAge;
|
||||
|
||||
plAgeLoadedMsg * msg = TRACKED_NEW plAgeLoadedMsg;
|
||||
msg->fLoaded = loaded;
|
||||
msg->Send();
|
||||
}
|
||||
|
||||
|
||||
//// ILoadAge ////////////////////////////////////////////////////////////////
|
||||
// Does the loading-specific stuff for queueing an age to load
|
||||
|
||||
bool plAgeLoader::ILoadAge(const char ageName[])
|
||||
{
|
||||
plNetClientApp* nc = plNetClientApp::GetInstance();
|
||||
ASSERT(!nc->GetFlagsBit(plNetClientApp::kPlayingGame));
|
||||
|
||||
StrCopy(fAgeName, ageName, arrsize(fAgeName));
|
||||
|
||||
nc->DebugMsg( "Net: Loading age %s", fAgeName);
|
||||
|
||||
if ((fFlags & kLoadMask) != 0)
|
||||
ErrorFatal(__LINE__, __FILE__, "Fatal Error:\nAlready loading or unloading an age.\n%S will now exit.", ProductShortName());
|
||||
|
||||
fFlags |= kLoadingAge;
|
||||
|
||||
plAgeBeginLoadingMsg* ageBeginLoading = TRACKED_NEW plAgeBeginLoadingMsg();
|
||||
ageBeginLoading->Send();
|
||||
|
||||
///////////////////////////////////////////////////////
|
||||
|
||||
|
||||
/// Step 1: Update all of the dat files for this age
|
||||
/*
|
||||
UpdateAge(fAgeName);
|
||||
*/
|
||||
|
||||
/// Step 2: Load the keys for this age, so we can find sceneNodes for them
|
||||
// exec age .fni file when data is done loading
|
||||
char consoleIniName[ 256 ];
|
||||
sprintf( consoleIniName, "dat\\%s.fni", fAgeName);
|
||||
fPendingAgeFniFiles.push_back( consoleIniName );
|
||||
|
||||
char csvName[256];
|
||||
sprintf(csvName, "dat\\%s.csv", fAgeName);
|
||||
fPendingAgeCsvFiles.push_back(csvName);
|
||||
|
||||
plSynchEnabler p( false ); // turn off dirty tracking while in this function
|
||||
|
||||
hsStream* stream=GetAgeDescFileStream(fAgeName);
|
||||
if (!stream)
|
||||
{
|
||||
nc->ErrorMsg("Failed loading age. Age desc file %s has nil stream", fAgeName);
|
||||
fFlags &= ~kLoadingAge;
|
||||
return false;
|
||||
}
|
||||
|
||||
plAgeDescription ad;
|
||||
ad.Read(stream);
|
||||
ad.SetAgeName(fAgeName);
|
||||
stream->Close();
|
||||
delete stream;
|
||||
ad.SeekFirstPage();
|
||||
|
||||
plAgePage *page;
|
||||
plKey clientKey = hsgResMgr::ResMgr()->FindKey( kClient_KEY );
|
||||
|
||||
// Copy, exclude pages we want excluded, and collect our scene nodes
|
||||
fCurAgeDescription.CopyFrom(ad);
|
||||
while( ( page = ad.GetNextPage() ) != nil )
|
||||
{
|
||||
if( IsPageExcluded( page, fAgeName) )
|
||||
continue;
|
||||
|
||||
plKey roomKey = plKeyFinder::Instance().FindSceneNodeKey( fAgeName, page->GetName() );
|
||||
if( roomKey != nil )
|
||||
AddPendingPageInRoomKey( roomKey );
|
||||
}
|
||||
ad.SeekFirstPage();
|
||||
|
||||
|
||||
// Tell the client to load-and-hold all the keys for this age, to make the loading process work better
|
||||
plClientMsg *loadAgeKeysMsg = TRACKED_NEW plClientMsg( plClientMsg::kLoadAgeKeys );
|
||||
loadAgeKeysMsg->SetAgeName( fAgeName);
|
||||
loadAgeKeysMsg->Send( clientKey );
|
||||
|
||||
//
|
||||
// Load the Age's SDL Hook object (and it's python modifier)
|
||||
//
|
||||
plUoid oid=nc->GetAgeSDLObjectUoid(fAgeName);
|
||||
plKey ageSDLObjectKey = hsgResMgr::ResMgr()->FindKey(oid);
|
||||
if (ageSDLObjectKey)
|
||||
hsgResMgr::ResMgr()->AddViaNotify(ageSDLObjectKey, TRACKED_NEW plGenRefMsg(nc->GetKey(), plRefMsg::kOnCreate, -1,
|
||||
plNetClientMgr::kAgeSDLHook), plRefFlags::kActiveRef);
|
||||
|
||||
int nPages = 0;
|
||||
|
||||
plClientMsg* pMsg1 = TRACKED_NEW plClientMsg(plClientMsg::kLoadRoom);
|
||||
pMsg1->SetAgeName(fAgeName);
|
||||
|
||||
// Loop and ref!
|
||||
while( ( page = ad.GetNextPage() ) != nil )
|
||||
{
|
||||
if( IsPageExcluded( page, fAgeName) )
|
||||
{
|
||||
nc->DebugMsg( "\tExcluding page %s\n", page->GetName() );
|
||||
continue;
|
||||
}
|
||||
|
||||
nPages++;
|
||||
|
||||
pMsg1->AddRoomLoc(ad.CalcPageLocation(page->GetName()));
|
||||
nc->DebugMsg("\tPaging in room %s\n", page->GetName());
|
||||
}
|
||||
|
||||
pMsg1->Send(clientKey);
|
||||
|
||||
// Send the client a message to let go of the extra keys it was holding on to
|
||||
plClientMsg *dumpAgeKeys = TRACKED_NEW plClientMsg( plClientMsg::kReleaseAgeKeys );
|
||||
dumpAgeKeys->SetAgeName( fAgeName);
|
||||
dumpAgeKeys->Send( clientKey );
|
||||
|
||||
if ( nPages==0 )
|
||||
{
|
||||
// age is done loading because it has no pages?
|
||||
fFlags &= ~kLoadingAge;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//// plUnloadAgeCollector ////////////////////////////////////////////////////
|
||||
// Registry page iterator to collect all the loaded pages of a given age
|
||||
// Note: we have to do an IterateAllPages(), since we want to also catch
|
||||
// pages that are partially loaded, which are skipped in the vanilla
|
||||
// IteratePages() call.
|
||||
|
||||
class plUnloadAgeCollector : public plRegistryPageIterator
|
||||
{
|
||||
public:
|
||||
hsTArray<plRegistryPageNode *> fPages;
|
||||
const char *fAge;
|
||||
|
||||
plUnloadAgeCollector( const char *a ) : fAge( a ) {}
|
||||
|
||||
virtual hsBool EatPage( plRegistryPageNode *page )
|
||||
{
|
||||
if( fAge && stricmp( page->GetPageInfo().GetAge(), fAge ) == 0 )
|
||||
{
|
||||
fPages.Append( page );
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
//// IUnloadAge //////////////////////////////////////////////////////////////
|
||||
// Does the UNloading-specific stuff for queueing an age to unload.
|
||||
// Far simpler that ILoadAge :)
|
||||
|
||||
bool plAgeLoader::IUnloadAge()
|
||||
{
|
||||
plNetClientApp* nc = plNetClientApp::GetInstance();
|
||||
nc->DebugMsg( "Net: Unloading age %s", fAgeName);
|
||||
|
||||
hsAssert( (fFlags & kLoadMask)==0, "already loading or unloading an age?");
|
||||
fFlags |= kUnLoadingAge;
|
||||
|
||||
plAgeBeginLoadingMsg* msg = TRACKED_NEW plAgeBeginLoadingMsg();
|
||||
msg->fLoading = false;
|
||||
msg->Send();
|
||||
|
||||
// Note: instead of going from the .age file, we just want a list of what
|
||||
// is REALLY paged in for this age. So ask the resMgr!
|
||||
plUnloadAgeCollector collector( fAgeName);
|
||||
// WARNING: unsafe cast here, but it's ok, until somebody is mean and makes a non-plResManager resMgr
|
||||
( (plResManager *)hsgResMgr::ResMgr() )->IterateAllPages( &collector );
|
||||
|
||||
// Dat was easy...
|
||||
plKey clientKey = hsgResMgr::ResMgr()->FindKey( kClient_KEY );
|
||||
|
||||
// Build up a list of all the rooms we're going to page out
|
||||
plKeyVec newPageOuts;
|
||||
|
||||
int i;
|
||||
for( i = 0; i < collector.fPages.GetCount(); i++ )
|
||||
{
|
||||
plRegistryPageNode *page = collector.fPages[ i ];
|
||||
|
||||
plKey roomKey = plKeyFinder::Instance().FindSceneNodeKey( page->GetPageInfo().GetLocation() );
|
||||
if( roomKey != nil && roomKey->ObjectIsLoaded() )
|
||||
{
|
||||
nc->DebugMsg( "\tPaging out room %s\n", page->GetPageInfo().GetPage() );
|
||||
newPageOuts.push_back(roomKey);
|
||||
}
|
||||
}
|
||||
|
||||
// Put them in our pending page outs
|
||||
for( i = 0; i < newPageOuts.size(); i++ )
|
||||
fPendingPageOuts.push_back(newPageOuts[i]);
|
||||
|
||||
// ...then send the unload messages. That way we ensure the list is complete
|
||||
// before any messages get processed
|
||||
for( i = 0; i < newPageOuts.size(); i++ )
|
||||
{
|
||||
plClientMsg *pMsg1 = TRACKED_NEW plClientMsg( plClientMsg::kUnloadRoom );
|
||||
pMsg1->AddRoomLoc(newPageOuts[i]->GetUoid().GetLocation());
|
||||
pMsg1->Send( clientKey );
|
||||
}
|
||||
|
||||
if ( newPageOuts.size()==0 )
|
||||
{
|
||||
// age is done unloading because it has no pages?
|
||||
NotifyAgeLoaded( false );
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void plAgeLoader::ExecPendingAgeFniFiles()
|
||||
{
|
||||
int i;
|
||||
for (i=0;i<PendingAgeFniFiles().size(); i++)
|
||||
{
|
||||
plConsoleMsg *cMsg = TRACKED_NEW plConsoleMsg( plConsoleMsg::kExecuteFile, fPendingAgeFniFiles[i].c_str() );
|
||||
plgDispatch::MsgSend( cMsg );
|
||||
}
|
||||
fPendingAgeFniFiles.clear();
|
||||
}
|
||||
|
||||
void plAgeLoader::ExecPendingAgeCsvFiles()
|
||||
{
|
||||
int i;
|
||||
for (i=0;i<PendingAgeCsvFiles().size(); i++)
|
||||
{
|
||||
hsStream* stream = plEncryptedStream::OpenEncryptedFile(fPendingAgeCsvFiles[i].c_str());
|
||||
if (stream)
|
||||
{
|
||||
plRelevanceMgr::Instance()->ParseCsvInput(stream);
|
||||
stream->Close();
|
||||
delete stream;
|
||||
}
|
||||
}
|
||||
fPendingAgeCsvFiles.clear();
|
||||
}
|
||||
|
||||
//
|
||||
// return alloced stream or nil
|
||||
// static
|
||||
//
|
||||
hsStream* plAgeLoader::GetAgeDescFileStream(const char* ageName)
|
||||
{
|
||||
if (!ageName)
|
||||
return nil;
|
||||
|
||||
char ageDescFileName[256];
|
||||
sprintf(ageDescFileName, "dat\\%s.age", ageName);
|
||||
|
||||
hsStream* stream = plEncryptedStream::OpenEncryptedFile(ageDescFileName);
|
||||
if (!stream)
|
||||
{
|
||||
char str[256];
|
||||
sprintf(str, "Can't find age desc file %s", ageDescFileName);
|
||||
hsAssert(false, str);
|
||||
return nil;
|
||||
}
|
||||
|
||||
return stream;
|
||||
}
|
||||
|
||||
//
|
||||
// sent from server with joinAck
|
||||
//
|
||||
void plAgeLoader::ISetInitialAgeState(plStateDataRecord* s)
|
||||
{
|
||||
hsAssert(fInitialAgeState != s, "duplicate initial age state");
|
||||
delete fInitialAgeState;
|
||||
fInitialAgeState=s;
|
||||
}
|
||||
/*==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/>.
|
||||
|
||||
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 "plAgeLoader.h"
|
||||
#include "hsStream.h"
|
||||
#include "plgDispatch.h"
|
||||
#include "hsResMgr.h"
|
||||
//#include "hsTimer.h"
|
||||
#include "plResPatcher.h"
|
||||
#include "plBackgroundDownloader.h"
|
||||
#include "process.h" // for getpid()
|
||||
|
||||
#include "pnProduct/pnProduct.h"
|
||||
|
||||
#include "pnKeyedObject/plKey.h"
|
||||
#include "pnKeyedObject/plFixedKey.h"
|
||||
#include "pnSceneObject/plSceneObject.h"
|
||||
#include "pnMessage/plClientMsg.h"
|
||||
#include "pnNetCommon/plNetApp.h"
|
||||
|
||||
#include "plScene/plRelevanceMgr.h"
|
||||
#include "plResMgr/plKeyFinder.h"
|
||||
#include "plAgeDescription/plAgeDescription.h"
|
||||
#include "plSDL/plSDL.h"
|
||||
#include "plNetClient/plNetClientMgr.h"
|
||||
#include "plResMgr/plRegistryHelpers.h"
|
||||
#include "plResMgr/plRegistryNode.h"
|
||||
#include "plResMgr/plResManager.h"
|
||||
#include "plFile/plEncryptedStream.h"
|
||||
|
||||
/// TEMP HACK TO LOAD CONSOLE INIT FILES ON AGE LOAD
|
||||
#include "plMessage/plConsoleMsg.h"
|
||||
#include "plMessage/plLoadAvatarMsg.h"
|
||||
#include "plMessage/plAgeLoadedMsg.h"
|
||||
|
||||
|
||||
extern hsBool gDataServerLocal;
|
||||
extern hsBool gUseBackgroundDownloader;
|
||||
|
||||
// static
|
||||
plAgeLoader* plAgeLoader::fInstance=nil;
|
||||
|
||||
//
|
||||
// CONSTRUCT
|
||||
//
|
||||
plAgeLoader::plAgeLoader() :
|
||||
fInitialAgeState(nil),
|
||||
fFlags(0)
|
||||
{
|
||||
}
|
||||
|
||||
//
|
||||
// DESTRUCT
|
||||
//
|
||||
plAgeLoader::~plAgeLoader()
|
||||
{
|
||||
delete fInitialAgeState;
|
||||
fInitialAgeState=nil;
|
||||
|
||||
if ( PendingAgeFniFiles().size() )
|
||||
plNetClientApp::StaticErrorMsg( "~plAgeLoader(): %d pending age fni files", PendingAgeFniFiles().size() );
|
||||
if ( PendingPageOuts().size() )
|
||||
plNetClientApp::StaticErrorMsg( "~plAgeLoader(): %d pending page outs", PendingPageOuts().size() );
|
||||
|
||||
ClearPageExcludeList(); // Clear our debugging exclude list, just to be tidy
|
||||
|
||||
if (fInstance==this)
|
||||
SetInstance(nil);
|
||||
}
|
||||
|
||||
void plAgeLoader::Shutdown()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void plAgeLoader::Init()
|
||||
{
|
||||
RegisterAs( kAgeLoader_KEY );
|
||||
plgDispatch::Dispatch()->RegisterForExactType(plInitialAgeStateLoadedMsg::Index(), GetKey());
|
||||
plgDispatch::Dispatch()->RegisterForExactType(plClientMsg::Index(), GetKey());
|
||||
|
||||
if (!gDataServerLocal && gUseBackgroundDownloader)
|
||||
plBackgroundDownloader::StartThread();
|
||||
}
|
||||
|
||||
//
|
||||
// STATIC
|
||||
//
|
||||
plAgeLoader* plAgeLoader::GetInstance()
|
||||
{
|
||||
return fInstance;
|
||||
}
|
||||
|
||||
//
|
||||
// STATIC
|
||||
//
|
||||
void plAgeLoader::SetInstance(plAgeLoader* inst)
|
||||
{
|
||||
fInstance=inst;
|
||||
}
|
||||
|
||||
//
|
||||
// Plasma Msg Handler
|
||||
//
|
||||
hsBool plAgeLoader::MsgReceive(plMessage* msg)
|
||||
{
|
||||
plInitialAgeStateLoadedMsg *stateMsg = plInitialAgeStateLoadedMsg::ConvertNoRef( msg );
|
||||
if( stateMsg != nil )
|
||||
{
|
||||
// done receiving the initial state of the age from the server
|
||||
return true;
|
||||
}
|
||||
|
||||
plClientMsg* clientMsg = plClientMsg::ConvertNoRef(msg);
|
||||
if (clientMsg && clientMsg->GetClientMsgFlag()==plClientMsg::kInitComplete)
|
||||
{
|
||||
ExecPendingAgeFniFiles(); // exec age-specific fni files
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
return plReceiver::MsgReceive(msg);
|
||||
}
|
||||
|
||||
//
|
||||
// read in the age desc file and page in/out the rooms belonging to the specified age.
|
||||
// return false on error
|
||||
//
|
||||
//============================================================================
|
||||
bool plAgeLoader::LoadAge(const char ageName[])
|
||||
{
|
||||
return ILoadAge(ageName);
|
||||
}
|
||||
|
||||
//============================================================================
|
||||
bool plAgeLoader::UpdateAge(const char ageName[])
|
||||
{
|
||||
bool result = true;
|
||||
|
||||
if (!gDataServerLocal)
|
||||
{
|
||||
plResPatcher myPatcher(ageName);
|
||||
result = myPatcher.Update();
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
//============================================================================
|
||||
void plAgeLoader::NotifyAgeLoaded( bool loaded )
|
||||
{
|
||||
if ( loaded )
|
||||
fFlags &= ~kLoadingAge;
|
||||
else
|
||||
fFlags &= ~kUnLoadingAge;
|
||||
|
||||
plAgeLoadedMsg * msg = TRACKED_NEW plAgeLoadedMsg;
|
||||
msg->fLoaded = loaded;
|
||||
msg->Send();
|
||||
}
|
||||
|
||||
|
||||
//// ILoadAge ////////////////////////////////////////////////////////////////
|
||||
// Does the loading-specific stuff for queueing an age to load
|
||||
|
||||
bool plAgeLoader::ILoadAge(const char ageName[])
|
||||
{
|
||||
plNetClientApp* nc = plNetClientApp::GetInstance();
|
||||
ASSERT(!nc->GetFlagsBit(plNetClientApp::kPlayingGame));
|
||||
|
||||
StrCopy(fAgeName, ageName, arrsize(fAgeName));
|
||||
|
||||
nc->DebugMsg( "Net: Loading age %s", fAgeName);
|
||||
|
||||
if ((fFlags & kLoadMask) != 0)
|
||||
ErrorFatal(__LINE__, __FILE__, "Fatal Error:\nAlready loading or unloading an age.\n%S will now exit.", ProductShortName());
|
||||
|
||||
fFlags |= kLoadingAge;
|
||||
|
||||
plAgeBeginLoadingMsg* ageBeginLoading = TRACKED_NEW plAgeBeginLoadingMsg();
|
||||
ageBeginLoading->Send();
|
||||
|
||||
///////////////////////////////////////////////////////
|
||||
|
||||
|
||||
/// Step 1: Update all of the dat files for this age
|
||||
/*
|
||||
UpdateAge(fAgeName);
|
||||
*/
|
||||
|
||||
/// Step 2: Load the keys for this age, so we can find sceneNodes for them
|
||||
// exec age .fni file when data is done loading
|
||||
char consoleIniName[ 256 ];
|
||||
sprintf( consoleIniName, "dat\\%s.fni", fAgeName);
|
||||
fPendingAgeFniFiles.push_back( consoleIniName );
|
||||
|
||||
char csvName[256];
|
||||
sprintf(csvName, "dat\\%s.csv", fAgeName);
|
||||
fPendingAgeCsvFiles.push_back(csvName);
|
||||
|
||||
plSynchEnabler p( false ); // turn off dirty tracking while in this function
|
||||
|
||||
hsStream* stream=GetAgeDescFileStream(fAgeName);
|
||||
if (!stream)
|
||||
{
|
||||
nc->ErrorMsg("Failed loading age. Age desc file %s has nil stream", fAgeName);
|
||||
fFlags &= ~kLoadingAge;
|
||||
return false;
|
||||
}
|
||||
|
||||
plAgeDescription ad;
|
||||
ad.Read(stream);
|
||||
ad.SetAgeName(fAgeName);
|
||||
stream->Close();
|
||||
delete stream;
|
||||
ad.SeekFirstPage();
|
||||
|
||||
plAgePage *page;
|
||||
plKey clientKey = hsgResMgr::ResMgr()->FindKey( kClient_KEY );
|
||||
|
||||
// Copy, exclude pages we want excluded, and collect our scene nodes
|
||||
fCurAgeDescription.CopyFrom(ad);
|
||||
while( ( page = ad.GetNextPage() ) != nil )
|
||||
{
|
||||
if( IsPageExcluded( page, fAgeName) )
|
||||
continue;
|
||||
|
||||
plKey roomKey = plKeyFinder::Instance().FindSceneNodeKey( fAgeName, page->GetName() );
|
||||
if( roomKey != nil )
|
||||
AddPendingPageInRoomKey( roomKey );
|
||||
}
|
||||
ad.SeekFirstPage();
|
||||
|
||||
|
||||
// Tell the client to load-and-hold all the keys for this age, to make the loading process work better
|
||||
plClientMsg *loadAgeKeysMsg = TRACKED_NEW plClientMsg( plClientMsg::kLoadAgeKeys );
|
||||
loadAgeKeysMsg->SetAgeName( fAgeName);
|
||||
loadAgeKeysMsg->Send( clientKey );
|
||||
|
||||
//
|
||||
// Load the Age's SDL Hook object (and it's python modifier)
|
||||
//
|
||||
plUoid oid=nc->GetAgeSDLObjectUoid(fAgeName);
|
||||
plKey ageSDLObjectKey = hsgResMgr::ResMgr()->FindKey(oid);
|
||||
if (ageSDLObjectKey)
|
||||
hsgResMgr::ResMgr()->AddViaNotify(ageSDLObjectKey, TRACKED_NEW plGenRefMsg(nc->GetKey(), plRefMsg::kOnCreate, -1,
|
||||
plNetClientMgr::kAgeSDLHook), plRefFlags::kActiveRef);
|
||||
|
||||
int nPages = 0;
|
||||
|
||||
plClientMsg* pMsg1 = TRACKED_NEW plClientMsg(plClientMsg::kLoadRoom);
|
||||
pMsg1->SetAgeName(fAgeName);
|
||||
|
||||
// Loop and ref!
|
||||
while( ( page = ad.GetNextPage() ) != nil )
|
||||
{
|
||||
if( IsPageExcluded( page, fAgeName) )
|
||||
{
|
||||
nc->DebugMsg( "\tExcluding page %s\n", page->GetName() );
|
||||
continue;
|
||||
}
|
||||
|
||||
nPages++;
|
||||
|
||||
pMsg1->AddRoomLoc(ad.CalcPageLocation(page->GetName()));
|
||||
nc->DebugMsg("\tPaging in room %s\n", page->GetName());
|
||||
}
|
||||
|
||||
pMsg1->Send(clientKey);
|
||||
|
||||
// Send the client a message to let go of the extra keys it was holding on to
|
||||
plClientMsg *dumpAgeKeys = TRACKED_NEW plClientMsg( plClientMsg::kReleaseAgeKeys );
|
||||
dumpAgeKeys->SetAgeName( fAgeName);
|
||||
dumpAgeKeys->Send( clientKey );
|
||||
|
||||
if ( nPages==0 )
|
||||
{
|
||||
// age is done loading because it has no pages?
|
||||
fFlags &= ~kLoadingAge;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//// plUnloadAgeCollector ////////////////////////////////////////////////////
|
||||
// Registry page iterator to collect all the loaded pages of a given age
|
||||
// Note: we have to do an IterateAllPages(), since we want to also catch
|
||||
// pages that are partially loaded, which are skipped in the vanilla
|
||||
// IteratePages() call.
|
||||
|
||||
class plUnloadAgeCollector : public plRegistryPageIterator
|
||||
{
|
||||
public:
|
||||
hsTArray<plRegistryPageNode *> fPages;
|
||||
const char *fAge;
|
||||
|
||||
plUnloadAgeCollector( const char *a ) : fAge( a ) {}
|
||||
|
||||
virtual hsBool EatPage( plRegistryPageNode *page )
|
||||
{
|
||||
if( fAge && stricmp( page->GetPageInfo().GetAge(), fAge ) == 0 )
|
||||
{
|
||||
fPages.Append( page );
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
//// IUnloadAge //////////////////////////////////////////////////////////////
|
||||
// Does the UNloading-specific stuff for queueing an age to unload.
|
||||
// Far simpler that ILoadAge :)
|
||||
|
||||
bool plAgeLoader::IUnloadAge()
|
||||
{
|
||||
plNetClientApp* nc = plNetClientApp::GetInstance();
|
||||
nc->DebugMsg( "Net: Unloading age %s", fAgeName);
|
||||
|
||||
hsAssert( (fFlags & kLoadMask)==0, "already loading or unloading an age?");
|
||||
fFlags |= kUnLoadingAge;
|
||||
|
||||
plAgeBeginLoadingMsg* msg = TRACKED_NEW plAgeBeginLoadingMsg();
|
||||
msg->fLoading = false;
|
||||
msg->Send();
|
||||
|
||||
// Note: instead of going from the .age file, we just want a list of what
|
||||
// is REALLY paged in for this age. So ask the resMgr!
|
||||
plUnloadAgeCollector collector( fAgeName);
|
||||
// WARNING: unsafe cast here, but it's ok, until somebody is mean and makes a non-plResManager resMgr
|
||||
( (plResManager *)hsgResMgr::ResMgr() )->IterateAllPages( &collector );
|
||||
|
||||
// Dat was easy...
|
||||
plKey clientKey = hsgResMgr::ResMgr()->FindKey( kClient_KEY );
|
||||
|
||||
// Build up a list of all the rooms we're going to page out
|
||||
plKeyVec newPageOuts;
|
||||
|
||||
int i;
|
||||
for( i = 0; i < collector.fPages.GetCount(); i++ )
|
||||
{
|
||||
plRegistryPageNode *page = collector.fPages[ i ];
|
||||
|
||||
plKey roomKey = plKeyFinder::Instance().FindSceneNodeKey( page->GetPageInfo().GetLocation() );
|
||||
if( roomKey != nil && roomKey->ObjectIsLoaded() )
|
||||
{
|
||||
nc->DebugMsg( "\tPaging out room %s\n", page->GetPageInfo().GetPage() );
|
||||
newPageOuts.push_back(roomKey);
|
||||
}
|
||||
}
|
||||
|
||||
// Put them in our pending page outs
|
||||
for( i = 0; i < newPageOuts.size(); i++ )
|
||||
fPendingPageOuts.push_back(newPageOuts[i]);
|
||||
|
||||
// ...then send the unload messages. That way we ensure the list is complete
|
||||
// before any messages get processed
|
||||
for( i = 0; i < newPageOuts.size(); i++ )
|
||||
{
|
||||
plClientMsg *pMsg1 = TRACKED_NEW plClientMsg( plClientMsg::kUnloadRoom );
|
||||
pMsg1->AddRoomLoc(newPageOuts[i]->GetUoid().GetLocation());
|
||||
pMsg1->Send( clientKey );
|
||||
}
|
||||
|
||||
if ( newPageOuts.size()==0 )
|
||||
{
|
||||
// age is done unloading because it has no pages?
|
||||
NotifyAgeLoaded( false );
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void plAgeLoader::ExecPendingAgeFniFiles()
|
||||
{
|
||||
int i;
|
||||
for (i=0;i<PendingAgeFniFiles().size(); i++)
|
||||
{
|
||||
plConsoleMsg *cMsg = TRACKED_NEW plConsoleMsg( plConsoleMsg::kExecuteFile, fPendingAgeFniFiles[i].c_str() );
|
||||
plgDispatch::MsgSend( cMsg );
|
||||
}
|
||||
fPendingAgeFniFiles.clear();
|
||||
}
|
||||
|
||||
void plAgeLoader::ExecPendingAgeCsvFiles()
|
||||
{
|
||||
int i;
|
||||
for (i=0;i<PendingAgeCsvFiles().size(); i++)
|
||||
{
|
||||
hsStream* stream = plEncryptedStream::OpenEncryptedFile(fPendingAgeCsvFiles[i].c_str());
|
||||
if (stream)
|
||||
{
|
||||
plRelevanceMgr::Instance()->ParseCsvInput(stream);
|
||||
stream->Close();
|
||||
delete stream;
|
||||
}
|
||||
}
|
||||
fPendingAgeCsvFiles.clear();
|
||||
}
|
||||
|
||||
//
|
||||
// return alloced stream or nil
|
||||
// static
|
||||
//
|
||||
hsStream* plAgeLoader::GetAgeDescFileStream(const char* ageName)
|
||||
{
|
||||
if (!ageName)
|
||||
return nil;
|
||||
|
||||
char ageDescFileName[256];
|
||||
sprintf(ageDescFileName, "dat\\%s.age", ageName);
|
||||
|
||||
hsStream* stream = plEncryptedStream::OpenEncryptedFile(ageDescFileName);
|
||||
if (!stream)
|
||||
{
|
||||
char str[256];
|
||||
sprintf(str, "Can't find age desc file %s", ageDescFileName);
|
||||
hsAssert(false, str);
|
||||
return nil;
|
||||
}
|
||||
|
||||
return stream;
|
||||
}
|
||||
|
||||
//
|
||||
// sent from server with joinAck
|
||||
//
|
||||
void plAgeLoader::ISetInitialAgeState(plStateDataRecord* s)
|
||||
{
|
||||
hsAssert(fInitialAgeState != s, "duplicate initial age state");
|
||||
delete fInitialAgeState;
|
||||
fInitialAgeState=s;
|
||||
}
|
||||
|
Reference in New Issue
Block a user