Files
GTASource/game/streaming/streaming.cpp
expvintl 419f2e4752 init
2025-02-23 17:40:52 +08:00

1222 lines
38 KiB
C++

//
// streaming/streaming.cpp
//
// Copyright (C) 1999-2012 Rockstar Games. All Rights Reserved.
//
#include "streaming/streaming_channel.h"
STREAMING_OPTIMISATIONS()
#include "streaming.h"
// Rage headers
#include "file/asset.h"
#include "file/diskcache.h"
#include "file/packfile.h"
#include "profile/timebars.h"
#include "system/timer.h"
#include "system/memory.h"
#include "fragment/type.h"
#include "fragment/tune.h"
#include "rmcore/drawable.h"
// Framework headers
#include "grcore/debugdraw.h"
#include "fwrenderer/renderthread.h"
#include "fwscene/lod/LodTypes.h"
#include "fwscene/mapdata/mapdatadebug.h"
#include "fwscene/scan/VisibilityFlags.h"
#include "fwscene/stores/boxstreamersearch.h"
#include "fwscene/stores/drawablestore.h"
#include "fwscene/stores/fragmentstore.h"
#include "fwscene/stores/txdstore.h"
#include "fwscene/stores/mapdatastore.h"
#include "fwscene/stores/maptypesstore.h"
#include "fwsys/metadatastore.h"
#include "fwsys/timer.h"
#include "streaming/defragmentation.h"
#include "streaming/packfilemanager.h"
#include "streaming/streamingvisualize.h"
#include "streaming/zonedassetmanager.h"
// Game headers
#include "camera/caminterface.h"
#include "camera/viewports/viewportmanager.h"
#include "control/gamelogic.h"
#include "core/game.h"
#include "frontend/loadingscreens.h"
#include "frontend/PauseMenu.h"
#include "game/config.h"
#include "objects/dummyobject.h"
#include "pathserver/ExportCollision.h"
#include "pathserver/navgenparam.h"
#include "peds/ped.h"
#include "performance/clearinghouse.h"
#include "physics/physics.h"
#include "renderer/gtadrawable.h"
#include "scene/ContinuityMgr.h"
#include "scene/datafilemgr.h"
#include "scene/datafilemgr.h"
#include "scene/Entity.h"
#include "scene/focusentity.h"
#include "scene/InstancePriority.h"
#include "scene/ipl/iplcullbox.h"
#include "scene/loader/ManagedImapGroup.h"
#include "scene/loader/maptypes.h"
#include "scene/loader/mapFileMgr.h"
#include "scene/scene.h"
#include "scene/streamer/scenestreamermgr.h"
#include "scene/world/gameworld.h"
#include "scene/ExtraContent.h"
#include "script/script.h"
#include "streaming/cacheloader.h"
#include "streaming/requestrecorder.h"
#include "streaming/streamingdebug.h"
#include "streaming/streamingengine.h"
#include "streaming/streamingloader.h"
#include "streaming/streamingmodule.h"
#include "streaming/streamingrequestlist.h"
#include "system/controlmgr.h"
#include "system/keyboard.h"
#include "text/text.h"
#include "vehicleai/pathfind.h"
#include "streaming/populationstreaming.h"
#include "Network/Events/NetworkEventTypes.h"
#include "streaming/streamingdebuggraphextensions.h"
#include "control/replay/Replay.h"
#include "control/replay/ReplayIPLManager.h"
#include "control/replay/Misc/InteriorPacket.h"
#if __PPU
#include <sys/memory.h>
#endif // __PPU
CStreamingCleanup CStreaming::ms_cleanup;
bool CStreaming::ms_FirstInitComplete;
char CStreaming::ms_streamingFilePath[RAGE_MAX_PATH]={0};
#if !__FINAL
CStreamingDebug CStreaming::ms_debug;
bool CStreaming::ms_pauseStreaming = false;
#endif
bool CStreaming::ms_enableSceneStreaming = true;
bool CStreaming::ms_scriptSuppressingHdImaps = false;
bool CStreaming::ms_isPlayerPositioned = false;
bool CStreaming::ms_bRequestRenderThreadFlush = false;
#if RSG_PC
bool CStreaming::ms_bForceEnableHdImaps = false;
#endif
Vector3 CStreaming::ms_oldFocusPosn;
#if __BANK
XPARAM(askBeforeRestart);
#endif // __BANK
XPARAM(PartialDynArch);
PARAM(previewfolder, "Enable streaming from the preview folder");
PARAM(previewcoords, "Where to put the preview tag (=x,y)");
PARAM(recordstartuprequests, "Record all requests during startup and save them to a file");
PARAM(reloadpackfilesonrestart, "[streaming] Reload all packfiles when restarting the game");
#define STARTUP_REQ_FILE "%s/startupreq"
//#define TEXTURES_FOLDER "platform:/textures/"
//////////////////////////////////////////////////////////////////////////
class CGtaStreamingInterface: public strStreamingInterface
{
public:
CGtaStreamingInterface(size_t virtualSize, size_t physicalSize, int archiveCount) :
strStreamingInterface(virtualSize, physicalSize, archiveCount) {}
// CStreaming
virtual void LoadAllRequestedObjects(bool bPriorityRequestsOnly = false) { CStreaming::LoadAllRequestedObjects(bPriorityRequestsOnly); }
// CStreamingCleanup entry points:
virtual void RequestFlush(bool flag) { CStreaming::GetCleanup().RequestFlush(flag); }
virtual bool MakeSpaceForResourceFile(const char* filename, const char* ext, s32 version) {
return CStreaming::GetCleanup().MakeSpaceForResourceFile(filename, ext, version);
}
virtual bool MakeSpaceForMap(datResourceMap& map, strIndex index, bool keepMemory) {
return CStreaming::GetCleanup().MakeSpaceForMap(map, index, keepMemory);
}
virtual bool WasLastAllocationAborted() const {
return CStreaming::GetCleanup().WasLastAllocationAborted();
}
virtual bool WasLastAllocationFragmented() const {
return CStreaming::GetCleanup().WasLastAllocationFragmented();
}
#if __BANK
virtual void PrintMemoryDistribution(const sysMemDistribution& distribution, char* header, char* usedMemory, char* freeMemory) {
CStreamingDebug::PrintMemoryDistribution(distribution, header, usedMemory, freeMemory);
}
#endif // __BANK
#if __BANK
virtual void LogStreaming(strIndex index) { CStreamingDebug::LogStreaming(index); }
#else
virtual void LogStreaming(strIndex) { }
#endif
virtual void DisplayModuleMemory(bool) { CStreamingDebug::DisplayModuleMemory(true, false, false); }
// CStreamingRequestList:
#if !__FINAL
virtual void RecordRequest(strIndex index) { gStreamingRequestList.RecordRequest(index); }
#else
virtual void RecordRequest(strIndex) { }
#endif
// strStreamingEngine PS3 install stuff:
virtual void InstallFailure() { Quitf(ERR_DEFAULT,"Install failure. TODO: Flesh this out!"); } // HACK HACK HACK
virtual void PostLoadRpf(int index) { CStreaming::PostLoadRpf(index); }
#if !__NO_OUTPUT
virtual void DumpStreamingInterests() { g_SceneStreamerMgr.DumpStreamingInterests(); }
#if !__FINAL
virtual void FullMemoryReport() { CStreamingDebug::FullMemoryDump(); }
#endif // !__FINAL
#endif // !__NO_OUTPUT
#if __BANK
virtual void AddFailedStreamingAllocation(strIndex index, bool bFragmented, datResourceMap& map) { CStreaming::GetDebug().AddFailedStreamingAllocation(index, bFragmented, map);}
#endif
virtual void AddResidentObject(strIndex index ) { gPopStreaming.AddResidentObject(index); }
virtual void RemoveResidentObject(strIndex index) { gPopStreaming.RemoveResidentObject(index);}
};
#if STREAMING_VISUALIZE
//////////////////////////////////////////////////////////////////////////
const char *CStreaming::GetStreamingContext()
{
return CTheScripts::GetCurrentScriptName();
}
//////////////////////////////////////////////////////////////////////////
int CStreaming::EntityGuidGetter(const fwEntity *entity)
{
u32 guid;
if (((CEntity *) entity)->GetGuid(guid))
{
return (int) guid;
}
return 0;
}
//////////////////////////////////////////////////////////////////////////
float CStreaming::EntityBoundSphereGetter(const fwEntity *entity, Vector3 &outVector)
{
return static_cast<const CEntity *>(entity)->GetBoundCentreAndRadius(outVector);
}
//////////////////////////////////////////////////////////////////////////
void CStreaming::AddStackContext()
{
const char *scriptName = CTheScripts::GetCurrentScriptName();
if (scriptName && scriptName[0])
{
char markerContext[128];
formatf(markerContext, "From script %s", scriptName);
strStreamingVisualize::GetInstance().SetMarkerText(markerContext);
}
strStreamingVisualize::GetInstance().AddCallstackToMarker();
}
#endif // STREAMING_VISUALIZE
//////////////////////////////////////////////////////////////////////////
void CStreaming::InitLevelWithMapUnloaded()
{
USE_MEMBUCKET(MEMBUCKET_STREAMING);
if (PARAM_PartialDynArch.Get()){
CMapFileMgr::GetInstance().Reset();
strStreamingEngine::InitLevelWithMapUnloaded();
CMapFileMgr::GetInstance().SetMapFileDependencies();
} else {
strStreamingEngine::InitLevelWithMapUnloaded();
}
// disable title update patching for test levels etc
// #if !__FINAL
// XPARAM(level);
// bool bEnableTitleUpdate = true;
// const char* levelName = NULL;
// if (PARAM_level.Get(levelName))
// {
// bEnableTitleUpdate = (atHashString(levelName) == atHashString("gta5", 0x6D2855E0));
// }
// if (bEnableTitleUpdate)
// #endif
{
EXTRACONTENT.ExecuteTitleUpdateDataPatchGroup((u32)CCS_GROUP_UPDATE_STREAMING, true);
EXTRACONTENT.ExecuteTitleUpdateDataPatch(CCS_TITLE_UPDATE_STREAMING, true);
}
BANK_ONLY(strStreamingEngine::GetInfo().PrintPackfileRelationships();)
BANK_ONLY(strStreamingEngine::GetInfo().ValidateRelationships();)
}
void CStreaming::InitStreamingVisualize()
{
#if STREAMING_VISUALIZE
strStreamingVisualize::InitClass();
if (strStreamingVisualize::IsInstantiated())
{
strStreamingVisualize::GetInstance().SetStreamingContextCb(GetStreamingContext);
strStreamingVisualize::GetInstance().SetEntityGuidGetterCb(EntityGuidGetter);
strStreamingVisualize::GetInstance().SetEntityBoundSphereGetterCb(EntityBoundSphereGetter);
strStreamingVisualize::GetInstance().SetAddStackContextCb(AddStackContext);
STREAMINGVIS.StartNetworkWorker();
STRVIS_REGISTER_DEVICE(pgStreamer::OPTICAL, "Optical");
STRVIS_REGISTER_DEVICE(pgStreamer::HARDDRIVE, "Hard Drive");
}
#endif // STREAMING_VISUALIZE
}
void CStreaming::InitStreamingEngine()
{
USE_MEMBUCKET(MEMBUCKET_STREAMING);
const CConfigStreamingEngine& cfg = CGameConfig::Get().GetConfigStreamingEngine();
// Old Consoles in KB / PC next gen in MB
size_t virtualSize = (size_t)cfg.m_VirtualStreamingBuffer << (size_t)((__XENON || __PS3) ? 10 : 20);
size_t physicalSize = (size_t)cfg.m_PhysicalStreamingBuffer << (size_t)((__XENON || __PS3) ? 10 : 20);
#if __BANK
gStreamingLoaderPreCallback = &CStreamGraphAllocationsToResGameVirt::PreChange;
gStreamingLoaderPostCallback = &CStreamGraphAllocationsToResGameVirt::PostChange;
#endif
strStreamingEngine::InitClass(rage_new CGtaStreamingInterface(
virtualSize,
physicalSize,
cfg.m_ArchiveCount));
strStreamingEngine::Init();
CStreamingDebug::InitDebugSystems();
STRVIS_REGISTER_ENTITY_TYPE(ENTITY_TYPE_NOTHING, "Nothing", 0x0000ff, false);
STRVIS_REGISTER_ENTITY_TYPE(ENTITY_TYPE_BUILDING, "Building", 0xffffff, true);
STRVIS_REGISTER_ENTITY_TYPE(ENTITY_TYPE_ANIMATED_BUILDING, "Animated Building", 0xff8888, true);
STRVIS_REGISTER_ENTITY_TYPE(ENTITY_TYPE_VEHICLE, "Vehicle", 0x00ffff, true);
STRVIS_REGISTER_ENTITY_TYPE(ENTITY_TYPE_PED, "Ped", 0xff88ff, true);
STRVIS_REGISTER_ENTITY_TYPE(ENTITY_TYPE_OBJECT, "Object", 0xff00ff, true);
STRVIS_REGISTER_ENTITY_TYPE(ENTITY_TYPE_DUMMY_OBJECT, "Dummy", 0x0000ff, false);
STRVIS_REGISTER_ENTITY_TYPE(ENTITY_TYPE_PORTAL, "Portal", 0x0000ff, false);
STRVIS_REGISTER_ENTITY_TYPE(ENTITY_TYPE_MLO, "MLO", 0x0000ff, false);
STRVIS_REGISTER_ENTITY_TYPE(ENTITY_TYPE_NOTINPOOLS, "For Audio", 0x0000ff, false);
STRVIS_REGISTER_ENTITY_TYPE(ENTITY_TYPE_PARTICLESYSTEM, "Particle System", 0x0000ff, false);
STRVIS_REGISTER_ENTITY_TYPE(ENTITY_TYPE_LIGHT, "Light", 0x0000ff, false);
STRVIS_REGISTER_ENTITY_TYPE(ENTITY_TYPE_COMPOSITE, "Composite", 0x0000ff, false);
STRVIS_REGISTER_ENTITY_TYPE(ENTITY_TYPE_INSTANCE_LIST, "Instance List", 0x0000ff, false);
STRVIS_REGISTER_ENTITY_TYPE(ENTITY_TYPE_GRASS_INSTANCE_LIST, "Grass Instance List", 0x0000ff, false);
#if STREAMING_VISUALIZE
fwBoxStreamerSearch::RegisterSearchTypesWithSV();
for (int x=0; x<LODTYPES_DEPTH_TOTAL; x++)
{
#if !__FINAL
STRVIS_REGISTER_LOD_TYPE(x, fwLodData::ms_apszLevelNames[x]);
#else // !__FINAL
char dummyLod[64];
formatf(dummyLod, "LOD Level %d", x);
STRVIS_REGISTER_LOD_TYPE(x, dummyLod);
#endif // !__FINAL
}
#endif // STREAMING_VISUALIZE
}
#if !__FINAL
void CStreaming::BeginRecordingStartupSequence()
{
if (PARAM_recordstartuprequests.Get())
{
REQUESTRECORDER.BeginRecording(true, false);
}
}
void CStreaming::EndRecordingStartupSequence()
{
if (PARAM_recordstartuprequests.Get())
{
char fileBuffer[RAGE_MAX_PATH];
REQUESTRECORDER.EndRecording();
REQUESTRECORDER.SaveRecording(GetStarupSequenceRecordingName(fileBuffer, sizeof(fileBuffer)));
}
}
#endif // !__FINAL
const char *CStreaming::GetStarupSequenceRecordingName(char *outBuffer, size_t bufferSize)
{
char levelName[RAGE_MAX_PATH];
ASSET.RemoveNameFromPath(levelName, sizeof(levelName), CScene::GetLevelsData().GetFilename(CGameLogic::GetRequestedLevelIndex()));
formatf(outBuffer, bufferSize, STARTUP_REQ_FILE, levelName);
return outBuffer;
}
void CStreaming::ReplayStartupSequenceRecording()
{
#if !__FINAL
if (!PARAM_recordstartuprequests.Get())
#endif // !__FINAL
{
char fileBuffer[RAGE_MAX_PATH];
REQUESTRECORDER.LoadRecording(GetStarupSequenceRecordingName(fileBuffer, sizeof(fileBuffer)));
REQUESTRECORDER.ExecuteRecording();
}
}
void CStreaming::SetStreamingFile(const char* streamingFile)
{
memset(ms_streamingFilePath,0,RAGE_MAX_PATH);
strcpy(ms_streamingFilePath,streamingFile);
}
void CStreaming::Init(unsigned initMode)
{
if(initMode == INIT_CORE)
{
USE_MEMBUCKET(MEMBUCKET_STREAMING);
strStreamingEngine::GetInfo().AllocateStreamingInfoArray();
SetStreamingFile("platformcrc:/data/streaming");
#if LIVE_STREAMING
static bool init = true;
if (init && PARAM_previewfolder.Get())
{
strStreamingEngine::GetLive().SetEnabled(PARAM_previewfolder.Get());
init = false;
}
#endif // LIVE_STREAMING
fwPlaceFunctor placeDrawable;
placeDrawable.Reset<&CStreaming::PlaceDrawable>();
g_DrawableStore.SetPlaceFunctor(placeDrawable);
fwDefragmentFunctor defragmentDrawable;
defragmentDrawable.Reset<&CStreaming::DefragmentDrawable>();
g_DrawableStore.SetDefragmentFunctor(defragmentDrawable);
fwPlaceFunctor placeFragType;
placeFragType.Reset<&CStreaming::PlaceFragType>();
g_FragmentStore.SetPlaceFunctor(placeFragType);
fwDefragmentFunctor defragmentFragType;
defragmentFragType.Reset<&CStreaming::DefragmentFragType>();
g_FragmentStore.SetDefragmentFunctor(defragmentFragType);
fwPlaceFunctor placeDwd;
placeDwd.Reset<&CStreaming::PlaceDwd>();
g_DwdStore.SetPlaceFunctor(placeDwd);
fwDefragmentFunctor defragmentDwd;
defragmentDwd.Reset<&CStreaming::DefragmentDwd>();
g_DwdStore.SetDefragmentFunctor(defragmentDwd);
g_SceneStreamerMgr.Init();
GetCleanup().Init();
}
else if(initMode == INIT_SESSION)
{
ms_enableSceneStreaming = true;
CMapFileMgr::GetInstance().Reset();
strStreamingEngine::InitLevelWithMapLoaded();
if (ShouldLoadStaticData())
{
strStreamingEngine::InitPackfiles();
}
CMapFileMgr::GetInstance().SetMapFileDependencies();
CMapFileMgr::GetInstance().Cleanup();
CZonedAssetManager::Init();
CIslandHopper::GetInstance().Init();
}
}
void CStreaming::Shutdown(unsigned shutdownMode)
{
if(shutdownMode == SHUTDOWN_CORE)
{
ms_cleanup.Shutdown();
g_SceneStreamerMgr.Shutdown();
strStreamingEngine::ShutdownPackfiles();
strStreamingEngine::Shutdown();
}
else if(shutdownMode == SHUTDOWN_WITH_MAP_LOADED)
{
strStreamingEngine::ShutdownLevelWithMapUnloaded();
}
else if(shutdownMode == SHUTDOWN_SESSION)
{
// strStreamingEngine::ShutdownLevelWithMapLoaded(); used to be called here. It'll probably still need to be called
// when shutting down the map
strStreamingEngine::ShutdownSession();
if (GetReloadPackfilesOnRestart())
{
strStreamingEngine::ShutdownPackfiles();
}
}
}
#if !__FINAL
bool CStreaming::GetReloadPackfilesOnRestart()
{
#if __BANK
if (PARAM_askBeforeRestart.Get())
{
return true;
}
#endif // __BANK
return PARAM_reloadpackfilesonrestart.Get();
}
#endif // !__FINAL
bool CStreaming::ShouldLoadStaticData()
{
return !ms_FirstInitComplete || GetReloadPackfilesOnRestart();
}
#if __PS3
#define PLATFORM_STREAMING_FILES CDataFileMgr::STREAMING_FILE_PLATFORM_PS3
#elif __XENON
#define PLATFORM_STREAMING_FILES CDataFileMgr::STREAMING_FILE_PLATFORM_XENON
#else
#define PLATFORM_STREAMING_FILES CDataFileMgr::STREAMING_FILE_PLATFORM_OTHER
#endif
void CStreaming::LoadStreamingMetaFile()
{
// streaming.meta specifies a list of streaming files to be registered with the packfile manager
DATAFILEMGR.Load(ms_streamingFilePath, true);
}
void CStreaming::RegisterStreamingFiles()
{
const CDataFileMgr::DataFileType streamTypes[] = { CDataFileMgr::STREAMING_FILE, PLATFORM_STREAMING_FILES };
u32 uType = 0;
char relativePathBuffer[256];
// First iteration registers platform agnostic files, the second deals with platform specific ones.
do
{
const CDataFileMgr::DataFile* pData = DATAFILEMGR.GetFirstFile(streamTypes[uType]);
while(DATAFILEMGR.IsValid(pData))
{
char FilenameWithoutExtension[RAGE_MAX_PATH];
char PlatformFilename[RAGE_MAX_PATH];
const char *ext = ASSET.FindExtensionInPath( pData->m_filename );
streamAssert(ext!=NULL);
ASSET.RemoveExtensionFromPath( FilenameWithoutExtension, sizeof( FilenameWithoutExtension ), pData->m_filename );
// All of the file paths include a wildcard # token in the extension which
// pgRscBuilder::ConstructName can patch to create a platform specific path for us to register.
pgRscBuilder::ConstructName(PlatformFilename, sizeof( PlatformFilename ), FilenameWithoutExtension, &ext[1]);
const char *relativePath = NULL;
const char *srcRelativePath = pData->m_registerAs.c_str();
// The parser likes to create empty strings, we don't want that.
if (srcRelativePath && *srcRelativePath)
{
safecpy(relativePathBuffer, srcRelativePath);
// Append the extension, which might be platform-specific.
const char *extPtr = strrchr(PlatformFilename, '.');
if (extPtr)
{
safecat(relativePathBuffer, extPtr);
}
relativePath = relativePathBuffer;
}
strPackfileManager::RegisterIndividualFile(PlatformFilename, true, relativePath);
pData = DATAFILEMGR.GetNextFile(pData);
}
} while (++uType < COUNTOF(streamTypes));
}
void CStreaming::PostLoadRpf(int index)
{
strStreamingFile* file = strPackfileManager::GetImageFile(index);
fiPackfile* pack = static_cast<fiPackfile*>(file->m_packfile);
// streamAssert(pack->GetEntries()); // this is okay now when we have the cache file active
streamVerify( pack->MountAs( "localPack:/" ) );
CMapFileMgr::GetInstance().LoadPackFileMetaData(pack, file->m_name.GetCStr());
streamVerify( fiDevice::Unmount("localPack:/"));
}
void CStreaming::SetKeepAliveCallback(void (*callback)(), u32 intervalInMS)
{
strStreamingEngine::GetLoader().SetKeepAliveCallback(callback, intervalInMS);
}
void CStreaming::Update()
{
USE_MEMBUCKET(MEMBUCKET_STREAMING);
CIslandHopper::GetInstance().Update();
#if GTA_REPLAY
ReplayIPLManager::DoOnExit();
ReplayIPLManager::DoProcess();
CPacketInteriorEntitySet::ProcessDeferredEntitySetUpdates();
#endif //GTA_REPLAY
// notify load monitor of num streaming requsets
strStreamingEngine::SetBurstMode(camInterface::IsFadedOut() || CPauseMenu::GetPauseRenderPhasesStatus() || !gRenderThreadInterface.IsUsingDefaultRenderFunction());
PF_START_TIMEBAR_DETAIL("Cleanup");
ms_cleanup.Update();
#if USE_DEFRAGMENTATION
strStreamingEngine::GetDefragmentation()->Frack(CTheScripts::IsFracked());
#endif
#if RSG_PC
static bool bHackProcessed = false;
if(NetworkInterface::IsGameInProgress() && !bHackProcessed && CTheScripts::IsFracked())
{
CReportMyselfEvent::Trigger(NetworkRemoteCheaterDetector::CODE_TAMPERING);
bHackProcessed = true;
}
#endif // RSG_PC
#if LIVE_STREAMING
strStreamingEngine::GetLive().UpdateUnlinkedFiles();
#endif // LIVE_STREAMING
#if !__FINAL
PF_START_TIMEBAR_DETAIL("Debug");
GetDebug().Update();
if (CControlMgr::GetKeyboard().GetKeyJustDown(KEY_SCROLL, KEYBOARD_MODE_DEBUG, "{Pause Streaming"))
ms_pauseStreaming = !ms_pauseStreaming;
if(ms_pauseStreaming)
{
DEBUG_DRAW_ONLY(grcDebugDraw::AddDebugOutput("Streaming locked"));
#if __BANK
COMMERCE_CONTAINER_ONLY(if (!CLiveManager::GetCommerceMgr().ContainerIsStoreMode()))
{
strStreamingEngine::DebugDraw();
}
#endif // __BANK
return;
}
#endif // /!__FINAL
if(strStreamingEngine::IsStreamingDisabled())
{
return;
}
CTheScripts::UnFrack();
gStreamingRequestList.ComputeSearchesAndFocus();
strStreamingEngine::PreLoadedUpdate();
PF_PUSH_TIMEBAR_BUDGETED("Synchronous resource placement", 1.0f);
strStreamingEngine::GetLoader().ProcessAsyncFiles();
PF_POP_TIMEBAR();
PF_START_TIMEBAR_DETAIL("Text");
TheText.ProcessStreamingAdditionalText();
#if NAVMESH_EXPORT
if(CNavMeshDataExporter::WillExportCollision())
ms_isPlayerPositioned = true;
#endif
if (ms_isPlayerPositioned COMMERCE_CONTAINER_ONLY(&& !CLiveManager::GetCommerceMgr().ContainerIsStoreMode()))
{
Vector3 playerPosn = CFocusEntityMgr::GetMgr().GetPos();
// a >300m shift in focus can generate a big .ityp overlap : if we are faded out, then we can do something to avoid that...
if ( ms_oldFocusPosn.Dist(playerPosn) > 300.0f)
{
ms_bRequestRenderThreadFlush = true;
}
PF_PUSH_TIMEBAR_BUDGETED("IMAP streaming", 1.0f);
{
CInstancePriority::Update();
//////////////////////////////////////////////////////////////////////////
// is the player in an aircraft and moving quickly? if so disable hd imap streaming
#if RSG_PC
const bool bFastMovement = ( (g_ContinuityMgr.HighSpeedFlying() || g_ContinuityMgr.HighSpeedFalling()) && !ms_bForceEnableHdImaps) || ms_scriptSuppressingHdImaps;
#else
const bool bFastMovement = ( g_ContinuityMgr.HighSpeedFlying() || g_ContinuityMgr.HighSpeedFalling() ) || ms_scriptSuppressingHdImaps;
#endif
const bool bAllowHdStreaming = !( bFastMovement && CFocusEntityMgr::GetMgr().IsPlayerPed() ) BANK_ONLY(|| !fwMapDataDebug::SuppressHdWhenFlyingFast());
INSTANCE_STORE.SetHdStreaming( bAllowHdStreaming );
ms_scriptSuppressingHdImaps = false;
//////////////////////////////////////////////////////////////////////////
PF_START_TIMEBAR_DETAIL("IMAP cull boxes");
// load IPLs (model instance info)
CIplCullBox::Update(playerPosn);
PF_START_TIMEBAR_DETAIL("Zoned assets");
CZonedAssetManager::Update(VECTOR3_TO_VEC3V(playerPosn));
PF_START_TIMEBAR_DETAIL("Managed IMAP groups");
CManagedImapGroupMgr::Update(RCC_VEC3V(playerPosn));
PF_START_TIMEBAR_DETAIL("RequestAboutPos");
INSTANCE_STORE.GetBoxStreamer().RequestAboutPos(RCC_VEC3V(playerPosn), (camInterface::IsFadedOut()) ? STRFLAG_PRIORITY_LOAD : 0);
PF_START_TIMEBAR_DETAIL("Update");
INSTANCE_STORE.Update();
const bool bGameIsNotRendering = (camInterface::IsFadedOut() || CLoadingScreens::AreActive() || CPauseMenu::GetPauseRenderPhasesStatus() BANK_ONLY(|| gStreamingRequestList.IsRecording()));
if(ms_bRequestRenderThreadFlush && bGameIsNotRendering)
{
gRenderThreadInterface.Flush();
}
ms_bRequestRenderThreadFlush = false;
g_MapTypesStore.Update();
// PF_START_TIMEBAR_DETAIL("EnsureLoadedAboutPos");
// if (CTheScripts::GetAllowGameToPauseForStreaming())
// {
// INSTANCE_STORE.GetBoxStreamer().EnsureLoadedAboutPos(RCC_VEC3V(playerPosn));
// }
}
PF_POP_TIMEBAR();
#if GTA_REPLAY
PF_PUSH_TIMEBAR("Replay export wait for mapdata");
{
if (CReplayMgr::IsExporting())
{
CStreaming::LoadAllRequestedObjects();
}
}
PF_POP_TIMEBAR();
#endif //GTA_REPLAY
PF_PUSH_TIMEBAR_BUDGETED("MetaData streaming", 1.0f);
{
PF_START_TIMEBAR_DETAIL("RequestAboutPos");
// Use the population position for this, so we stream in scenario regions around the point where we want to spawn.
const Vec3V popPosV = VECTOR3_TO_VEC3V(CFocusEntityMgr::GetMgr().GetPopPos());
Vec3V offset(ScalarV(0.1f));//0.1f is the default sphere size used if you just pass in a position to RequestAboutPos
Vec3V min = popPosV - offset;
Vec3V max = popPosV + offset;
//Want to stretch the bounds in the Z direction if the entity is in a heli or is in the air(falling, parachuting)
// - probably shouldn't do this if we have an override position.
if(!CFocusEntityMgr::GetMgr().HasOverridenPop())
{
const CEntity* ntt = CFocusEntityMgr::GetMgr().GetEntity();
if (ntt && ntt->GetIsTypePed())
{
const CPed* ped = (const CPed*)ntt;
CVehicle* veh = ped->GetVehiclePedInside();
if ( ped->GetPedConfigFlag(CPED_CONFIG_FLAG_IsInTheAir) ||
(veh && (veh->InheritsFromHeli() || veh->GetHoverMode()))
)
{
ScalarV extraZ(100.0f);
min.SetZ(min.GetZ() - extraZ);
max.SetZ(max.GetZ() + extraZ);
}
}
}
spdAABB mySearchBox(min, max);
fwBoxStreamerSearch primarySearch(mySearchBox, fwBoxStreamerSearch::TYPE_PRIMARY, fwBoxStreamerAsset::FLAG_METADATA);
g_fwMetaDataStore.GetBoxStreamer().RequestAboutPos(primarySearch);
PF_START_TIMEBAR_DETAIL("Update");
g_fwMetaDataStore.Update();
}
PF_POP_TIMEBAR();
PF_START_TIMEBAR_DETAIL("physics streaming");
CPhysics::UpdateStreaming();
PF_START_TIMEBAR_DETAIL("path streaming");
ThePaths.UpdateStreaming();
PF_START_TIMEBAR_DETAIL("scene streaming");
ms_oldFocusPosn = playerPosn;
}
gStreamingRequestList.Update();
// If we have no more open requests, we can re-enable HD vehicles.
// This is fucking voodoo, and sucks. I'm open for suggestions for a better approach.
if (strStreamingEngine::GetInfo().GetNumberObjectsRequested() == 0)
{
CVehicle::SetDisableHDVehicles(false);
}
strStreamingEngine::Update();
#if STREAMING_VISUALIZE
STREAM_TICKER_ONLY(StrTicker::StepPut());
STREAM_TICKER_ONLY(StrTicker::StepGet());
#endif
#if __BANK
COMMERCE_CONTAINER_ONLY(if (!CLiveManager::GetCommerceMgr().ContainerIsStoreMode()))
{
strStreamingEngine::DebugDraw();
}
#endif // __BANK
perfClearingHouse::SetValue(perfClearingHouse::NORMAL_PRIORITY_STREAMING_REQUESTS, strStreamingEngine::GetInfo().GetNumberObjectsRequested() - strStreamingEngine::GetInfo().GetNumberPriorityObjectsRequested());
perfClearingHouse::SetValue(perfClearingHouse::HIGH_PRIORITY_STREAMING_REQUESTS, strStreamingEngine::GetInfo().GetNumberPriorityObjectsRequested());
}
// bank_bool g_RequestNearbyObjects = true;
//
// void CStreaming::RequestNearbyObjects()
// {
// if (!g_RequestNearbyObjects)
// return;
//
// const Vector3 playerPosn = CGameWorld::FindLocalPlayerCoors();
// #if NAVMESH_EXPORT
// if(CNavMeshDataExporter::IsExportingCollision())
// ms_scene.AddObjectsToRequestListForNavMeshExport(playerPosn);
// else
// #endif
// if(strStreamingEngine::GetIsLoadingPriorityObjects() == false && gStreamingRequestList.IsActive() == false && ms_enableSceneStreaming)
// {
// const Vector3& camPosn = camInterface::GetPos();
// bool bCanSeeExterior = true;
// CInteriorInst* pInterior = CPortalVisTracker::m_pPrimaryIntInst;
// s32 roomIdx = CPortalVisTracker::m_primaryRoomIdx;
//
// // If there are no exit portals in current room then set bCanSeeExterior to false
// if(pInterior && roomIdx > 0){
// if ((pInterior->GetNumExitPortals() == 0) || (pInterior->GetNumExitPortalsInRoom(roomIdx) == 0)){
// bCanSeeExterior = false;
// }
// }
// if(camPosn.z < 50.0f)
// ms_scene.AddObjectsToRequestList(camPosn, bCanSeeExterior);
// if(bCanSeeExterior)
// ms_scene.AddLodsToRequestList(camPosn);
// }
// }
void CStreaming::PurgeRequestList(u32 ignoreFlags)
{
strStreamingEngine::GetInfo().PurgeRequestList(ignoreFlags);
}
// #if USE_DUALLAYER
// static bool gbForceLayerRead = false;
// static s32 gLayerToRead = 0;
// void CStreaming::ForceLayerToRead(s32 layer)
// {
// gbForceLayerRead = true;
// gLayerToRead = layer;
// }
// #endif
void CStreaming::SetObjectIsDeletable(strLocalIndex objIndex, s32 module)
{
strIndex index = strStreamingEngine::GetInfo().GetModuleMgr().GetModule(module)->GetStreamingIndex(objIndex);
strStreamingEngine::GetInfo().SetObjectIsDeletable(index);
}
void CStreaming::SetObjectIsNotDeletable(strLocalIndex objIndex, s32 module)
{
strIndex index = strStreamingEngine::GetInfo().GetModuleMgr().GetModule(module)->GetStreamingIndex(objIndex);
strStreamingEngine::GetInfo().SetObjectIsNotDeletable(index);
}
bool CStreaming::GetObjectIsDeletable(strLocalIndex objIndex, s32 module)
{
strIndex index = strStreamingEngine::GetInfo().GetModuleMgr().GetModule(module)->GetStreamingIndex(objIndex);
return strStreamingEngine::GetInfo().IsObjectDeletable(index);
}
void CStreaming::SetMissionDoesntRequireObject(strLocalIndex objIndex, s32 module)
{
strIndex index = strStreamingEngine::GetInfo().GetModuleMgr().GetModule(module)->GetStreamingIndex(objIndex);
strStreamingEngine::GetInfo().SetMissionDoesntRequireObject(index);
}
void CStreaming::SetInteriorDoesntRequireObject(strLocalIndex objIndex, s32 module)
{
strIndex index = strStreamingEngine::GetInfo().GetModuleMgr().GetModule(module)->GetStreamingIndex(objIndex);
strStreamingEngine::GetInfo().SetInteriorDoesntRequireObject(index);
}
void CStreaming::SetCutsceneDoesntRequireObject(strLocalIndex objIndex, s32 module)
{
strIndex index = strStreamingEngine::GetInfo().GetModuleMgr().GetModule(module)->GetStreamingIndex(objIndex);
strStreamingEngine::GetInfo().SetCutsceneDoesntRequireObject(index);
}
void CStreaming::SetDoNotDefrag(strLocalIndex objIndex, s32 module)
{
strIndex index = strStreamingEngine::GetInfo().GetModuleMgr().GetModule(module)->GetStreamingIndex(objIndex);
strStreamingEngine::GetInfo().SetDoNotDefrag(index);
}
u64 CStreaming::GetImageTime(strLocalIndex index)
{
return strPackfileManager::GetImageTime(index.Get());
}
const char* CStreaming::GetImageFilename(strLocalIndex index)
{
return strPackfileManager::GetImageFile(index.Get())->m_name.GetCStr();
}
void CStreaming::SetImageIsNew(strLocalIndex index)
{
strPackfileManager::GetImageFile(index.Get())->m_bNew = true;
}
bool CStreaming::GetImageIsNew(strLocalIndex index)
{
return strPackfileManager::GetImageFile(index.Get())->m_bNew;
}
void CStreaming::LoadAllRequestedObjects(bool bPriorityRequestsOnly)
{
#if STREAMING_VISUALIZE
const char *origin = CTheScripts::GetCurrentScriptNameAndProgramCounter();
if (!origin || !origin[0])
{
origin = "Code";
}
STRVIS_SET_MARKER_TEXT("Block: Load all, from %s", origin);
#endif // STREAMING_VISUALIZE
USE_MEMBUCKET(MEMBUCKET_STREAMING);
strStreamingEngine::GetLoader().LoadAllRequestedObjects(bPriorityRequestsOnly); // @todo
}
#if GTA_REPLAY
void CStreaming::LoadAllRequestedObjectsWithTimeout(bool bPriorityRequestsOnly, u32 timeoutMS)
{
#if STREAMING_VISUALIZE
const char *origin = CTheScripts::GetCurrentScriptNameAndProgramCounter();
if (!origin || !origin[0])
{
origin = "Replay";
}
STRVIS_SET_MARKER_TEXT("Block: Load all, from %s", origin);
#endif // STREAMING_VISUALIZE
USE_MEMBUCKET(MEMBUCKET_STREAMING);
strStreamingEngine::GetLoader().LoadAllRequestedObjectsWithTimeout(bPriorityRequestsOnly, timeoutMS);
}
#endif
void CStreaming::Flush()
{
strStreamingEngine::Flush();
}
bool CStreaming::RequestObject(strLocalIndex objIndex, s32 module, s32 flags)
{
streamAssert(objIndex.Get() >= 0);
strIndex index = strStreamingEngine::GetInfo().GetModuleMgr().GetModule(module)->GetStreamingIndex(objIndex);
return strStreamingEngine::GetInfo().RequestObject(index, flags);
}
void CStreaming::ClearRequiredFlag(strLocalIndex objIndex, s32 module, s32 flags)
{
streamAssert(objIndex.Get() >= 0);
strIndex index = strStreamingEngine::GetInfo().GetModuleMgr().GetModule(module)->GetStreamingIndex(objIndex);
strStreamingEngine::GetInfo().ClearRequiredFlag(index, flags);
}
void CStreaming::RemoveObject(strLocalIndex objIndex, s32 module)
{
streamAssert(objIndex.Get() >= 0);
strIndex index = strStreamingEngine::GetInfo().GetModuleMgr().GetModule(module)->GetStreamingIndex(objIndex);
strStreamingEngine::GetInfo().RemoveObject(index);
}
u32 CStreaming::GetObjectFlags(strLocalIndex objIndex, s32 module)
{
strIndex index = strStreamingEngine::GetInfo().GetModuleMgr().GetModule(module)->GetStreamingIndex(objIndex);
return strStreamingEngine::GetInfo().GetObjectFlags(index);
}
u32 CStreaming::GetObjectVirtualSize(strLocalIndex objIndex, s32 module)
{
strIndex index = strStreamingEngine::GetInfo().GetModuleMgr().GetModule(module)->GetStreamingIndex(objIndex);
return strStreamingEngine::GetInfo().GetObjectVirtualSize(index);
}
u32 CStreaming::GetObjectPhysicalSize(strLocalIndex objIndex, s32 module)
{
strIndex index = strStreamingEngine::GetInfo().GetModuleMgr().GetModule(module)->GetStreamingIndex(objIndex);
return strStreamingEngine::GetInfo().GetObjectPhysicalSize(index);
}
void CStreaming::GetObjectAndDependenciesSizes(strLocalIndex objIndex, s32 module, u32& virtualSize, u32& physicalSize, const strIndex* ignoreList, s32 numIgnores, bool mayFail)
{
strIndex index = strStreamingEngine::GetInfo().GetModuleMgr().GetModule(module)->GetStreamingIndex(objIndex);
virtualSize = 0;
physicalSize = 0;
strStreamingEngine::GetInfo().GetObjectAndDependenciesSizes(index, virtualSize, physicalSize, ignoreList, numIgnores, mayFail);
}
void CStreaming::GetObjectAndDependencies(strLocalIndex objIndex, s32 module, atArray<strIndex>& allDeps, const strIndex* ignoreList, s32 numIgnores)
{
strStreamingModule *pModule = strStreamingEngine::GetInfo().GetModuleMgr().GetModule(module);
strIndex index = pModule->GetStreamingIndex(objIndex);
pModule->GetObjectAndDependencies(index, allDeps, ignoreList, numIgnores);
}
bool CStreaming::HasObjectLoaded(strLocalIndex objIndex, s32 module)
{
strIndex index = strStreamingEngine::GetInfo().GetModuleMgr().GetModule(module)->GetStreamingIndex(objIndex);
return (strStreamingEngine::GetInfo().GetStreamingInfo(index)->GetStatus() == STRINFO_LOADED);
}
bool CStreaming::IsObjectRequested(strLocalIndex objIndex, s32 module)
{
strIndex index = strStreamingEngine::GetInfo().GetModuleMgr().GetModule(module)->GetStreamingIndex(objIndex);
return (strStreamingEngine::GetInfo().GetStreamingInfo(index)->GetStatus() == STRINFO_LOADREQUESTED);
}
bool CStreaming::IsObjectLoading(strLocalIndex objIndex, s32 module)
{
strIndex index = strStreamingEngine::GetInfo().GetModuleMgr().GetModule(module)->GetStreamingIndex(objIndex);
return (strStreamingEngine::GetInfo().GetStreamingInfo(index)->GetStatus() == STRINFO_LOADING);
}
bool CStreaming::IsObjectInImage(strLocalIndex objIndex, s32 module)
{
strIndex index = strStreamingEngine::GetInfo().GetModuleMgr().GetModule(module)->GetStreamingIndex(objIndex);
return strStreamingEngine::GetInfo().IsObjectInImage(index);
}
bool CStreaming::IsObjectNew(strLocalIndex objIndex, s32 module)
{
strIndex index = strStreamingEngine::GetInfo().GetModuleMgr().GetModule(module)->GetStreamingIndex(objIndex);
return strStreamingEngine::GetInfo().IsObjectNew(index);
}
s32 CStreaming::GetNumberObjectsRequested()
{
return strStreamingEngine::GetInfo().GetNumberObjectsRequested();
}
strIndex CStreaming::RegisterDummyObject(const char* name, strLocalIndex objectIndex, s32 module)
{
return strStreamingEngine::GetInfo().RegisterDummyObject(name, objectIndex, module);
}
bool CStreaming::LoadObject(strLocalIndex objIndex, s32 module, bool bCanBeDefragged, bool bCanBeDeleted)
{
s32 flags = STRFLAG_FORCE_LOAD|STRFLAG_DONTDELETE;
if(!strStreamingEngine::GetInfo().GetModuleMgr().GetModule(module)->StreamingBlockingLoad(objIndex, flags))
{
return false;
}
strIndex index = strStreamingEngine::GetInfo().GetModuleMgr().GetModule(module)->GetStreamingIndex(objIndex);
if(bCanBeDeleted)
{
strStreamingEngine::GetInfo().ClearRequiredFlag(index, STRFLAG_DONTDELETE);
}
if(!bCanBeDefragged && (!(strStreamingEngine::GetInfo().GetStreamingInfoRef(index).GetFlags() & STRFLAG_INTERNAL_DUMMY)))
{
CStreaming::SetDoNotDefrag( objIndex, module );
}
return true;
}
void CStreaming::ClearFlagForAll(u32 flag)
{
strStreamingEngine::GetInfo().ClearFlagForAll(flag);
}
void CStreaming::DisableStreaming()
{
strStreamingEngine::DisableStreaming();
}
void CStreaming::EnableStreaming()
{
strStreamingEngine::EnableStreaming();
}
bool CStreaming::IsStreamingDisabled()
{
return strStreamingEngine::IsStreamingDisabled();
}
#if ENABLE_DEFRAG_CALLBACK
bool CStreaming::IsObjectReadyToDelete(void* ptr)
{
sysMemAllocator* pAllocator = strStreamingEngine::GetAllocator().GetPointerOwner(ptr);
Assert(pAllocator);
void* pBlock = pAllocator->GetCanonicalBlockPtr(ptr);
streamAssert(pBlock);
const strIndex index = strStreamingInfoManager::GetStreamingIndexFromMemBlock(pBlock);
return index.IsValid() && strStreamingEngine::GetInfo().IsObjectReadyToDelete(index, STRFLAG_NONE);
}
#endif
#if __BANK
void CStreaming::InitWidgets()
{
GetDebug().InitWidgets();
}
#endif
//////////////////////////////////////////////////////////////////////////
// fwTxd Defragmentation Support
#include "streaming/defragmentation.h"
#include "cutscene/cutscenemanagernew.h"
#include "fwscene/stores/drawablestore.h"
#include "fwscene/stores/dwdstore.h"
#include "fwscene/stores/fragmentstore.h"
#include "ModelInfo/ModelInfo.h"
#include "ModelInfo/ModelInfo_Factories.h"
#include "modelinfo/pedmodelinfo.h"
#include "modelinfo/timemodelinfo.h"
#include "renderer/drawlists/drawlist.h"
#include "scene/entity.h"
#include "shaders/customshadereffectped.h"
#include "shaders/customshadereffectvehicle.h"
#include "vehicles/vehicle.h"
namespace rage {
extern grcEffect* g_DefaultEffect;
}
pgBase* CStreaming::PlaceDrawable(datResourceInfo& info, datResourceMap &map, const char *debugName, bool isDefrag)
{
gtaDrawable* t = NULL;
pgRscBuilder::PlaceStream(t, info, map, debugName, isDefrag);
return t;
}
pgBase* CStreaming::PlaceFragType(datResourceInfo& info, datResourceMap &map, const char *debugName, bool isDefrag)
{
gtaFragType* t = NULL;
pgRscBuilder::PlaceStream(t, info, map, debugName, isDefrag);
return t;
}
pgBase* CStreaming::PlaceDwd(datResourceInfo& info, datResourceMap &map, const char *debugName, bool isDefrag)
{
pgDictionary<gtaDrawable>* t = NULL;
pgRscBuilder::PlaceStream(t, info, map, debugName, isDefrag);
return t;
}
pgBase* CStreaming::DefragmentDrawable(datResourceMap &map)
{
gtaDrawable* object = static_cast<gtaDrawable*>(map.GetVirtualBase());
datResource rsc(map,"defrag",true);
gtaDrawable::Place(object, rsc);
return object;
}
pgBase* CStreaming::DefragmentFragType(datResourceMap& map)
{
gtaFragType* object = static_cast<gtaFragType*>(map.GetVirtualBase());
datResource rsc(map,"defrag",true);
gtaFragType::Place(object, rsc);
return object;
}
pgBase* CStreaming::DefragmentDwd(datResourceMap& map)
{
pgDictionary<gtaDrawable>* object = static_cast<pgDictionary<gtaDrawable>*>(map.GetVirtualBase());
datResource rsc(map,"defrag",true);
pgDictionary<gtaDrawable>::Place(object, rsc);
return object;
}