#include "ZMMOJobsSubsystem.h" #include "AssetRegistry/AssetRegistryModule.h" #include "Modules/ModuleManager.h" #include "ZMMOJobDataAsset.h" DEFINE_LOG_CATEGORY_STATIC(LogZMMOJobs, Log, All); void UZMMOJobsSubsystem::Initialize(FSubsystemCollectionBase& Collection) { Super::Initialize(Collection); LoadJobsFromAssetRegistry(); UE_LOG(LogZMMOJobs, Log, TEXT("[ZMMOJobsSubsystem] Initialize: %d job(s) carregados"), CachedJobs.Num()); } void UZMMOJobsSubsystem::Deinitialize() { CachedJobs.Empty(); Super::Deinitialize(); } void UZMMOJobsSubsystem::LoadJobsFromAssetRegistry() { FAssetRegistryModule& AssetRegistryModule = FModuleManager::LoadModuleChecked("AssetRegistry"); IAssetRegistry& AR = AssetRegistryModule.Get(); // Editor pode chamar antes de scan inicial. Standalone/PIE scan ja' rodou. // SearchAllAssets(false) = nao-blocking; assume cache populado em runtime. #if WITH_EDITOR AR.SearchAllAssets(true); // bloqueia editor; ok em Initialize #endif TArray Assets; const FTopLevelAssetPath ClassPath(UZMMOJobDataAsset::StaticClass()->GetClassPathName()); AR.GetAssetsByClass(ClassPath, Assets, /*bSearchSubClasses*/ true); for (const FAssetData& AssetData : Assets) { UZMMOJobDataAsset* Job = Cast(AssetData.GetAsset()); if (Job == nullptr) { continue; } if (CachedJobs.Contains(Job->ClassId)) { UE_LOG(LogZMMOJobs, Warning, TEXT("[ZMMOJobsSubsystem] Duplicate ClassId=%d (existing=%s, new=%s) — ignorando segundo"), Job->ClassId, *CachedJobs[Job->ClassId]->GetName(), *Job->GetName()); continue; } CachedJobs.Add(Job->ClassId, Job); UE_LOG(LogZMMOJobs, Verbose, TEXT("[ZMMOJobsSubsystem] Cached classId=%d name=%s display=%s"), Job->ClassId, *Job->TechnicalName, *Job->DisplayName.ToString()); } } UZMMOJobDataAsset* UZMMOJobsSubsystem::GetJobData(int32 ClassId) const { if (const TObjectPtr* Found = CachedJobs.Find(ClassId)) { return Found->Get(); } return nullptr; }