using System; using System.Collections; using System.Collections.Generic; using System.Linq; using HG; using HG.Coroutines; using RoR2.EntitlementManagement; using RoR2.ExpansionManagement; using RoR2.Skills; using UnityEngine; namespace RoR2.ContentManagement; public static class ContentManager { private class ContentPackLoader { private delegate IEnumerator PerContentPackAction(ref ContentPackLoadInfo contentPackLoadInfo, ReadOnlyArray readOnlyPeers, IProgress progressReceiver); private ContentPackLoadInfo[] contentPackLoadInfos; public List output = new List(); public ContentPackLoader(List contentPackProviders) { contentPackLoadInfos = new ContentPackLoadInfo[contentPackProviders.Count]; for (int i = 0; i < contentPackProviders.Count; i++) { string identifier = contentPackProviders[i].identifier; contentPackLoadInfos[i] = new ContentPackLoadInfo { index = i, contentPackProviderIdentifier = identifier, contentPackProvider = contentPackProviders[i], previousContentPack = new ContentPack { identifier = identifier }, retries = 0 }; } } private IEnumerator DoPerContentPackProviderCoroutine(IProgress progressReceiver, PerContentPackAction action) { ReadOnlyArray readOnlyPeers = ArrayUtils.Clone(contentPackLoadInfos); ParallelProgressCoroutine parallelProgressCoroutine = new ParallelProgressCoroutine(progressReceiver); for (int i = 0; i < contentPackLoadInfos.Length; i++) { ReadableProgress readableProgress = new ReadableProgress(); IEnumerator coroutine = action(ref contentPackLoadInfos[i], readOnlyPeers, readableProgress); parallelProgressCoroutine.Add(coroutine, readableProgress); } return parallelProgressCoroutine; } public IEnumerator InitialLoad(IProgress progressReceiver) { yield return DoPerContentPackProviderCoroutine(progressReceiver, StartLoadCoroutine); static IEnumerator StartLoadCoroutine(ref ContentPackLoadInfo loadInfo, ReadOnlyArray readOnlyPeers, IProgress providedProgressReceiver) { LoadStaticContentAsyncArgs args = new LoadStaticContentAsyncArgs(providedProgressReceiver, readOnlyPeers); return loadInfo.contentPackProvider.LoadStaticContentAsync(args); } } public IEnumerator StepGenerateContentPacks(IProgress progressReceiver, IProgress completionReceiver, int retriesRemaining) { ContentPack[] newContentPacks = new ContentPack[contentPackLoadInfos.Length]; for (int i = 0; i < newContentPacks.Length; i++) { newContentPacks[i] = new ContentPack { identifier = contentPackLoadInfos[i].contentPackProviderIdentifier }; } yield return DoPerContentPackProviderCoroutine(progressReceiver, StartGeneratorCoroutine); bool flag = true; for (int j = 0; j < contentPackLoadInfos.Length; j++) { ContentPack contentPack = newContentPacks[j]; contentPack.identifier = contentPackLoadInfos[j].contentPackProviderIdentifier; if (!contentPackLoadInfos[j].previousContentPack.Equals(contentPack)) { flag = false; contentPackLoadInfos[j].retries++; contentPackLoadInfos[j].previousContentPack = contentPack; } } if (flag) { completionReceiver.Report(value: true); } IEnumerator StartGeneratorCoroutine(ref ContentPackLoadInfo loadInfo, ReadOnlyArray readOnlyPeers, IProgress providedProgressReceiver) { ContentPack contentPack2 = newContentPacks[loadInfo.index]; GetContentPackAsyncArgs args = new GetContentPackAsyncArgs(providedProgressReceiver, contentPack2, readOnlyPeers, retriesRemaining); return loadInfo.contentPackProvider.GenerateContentPackAsync(args); } } public IEnumerator LoadContentPacks(IProgress progressReceiver) { int maxRetries = 10; bool complete = false; ReadableProgress completionReceiver = new ReadableProgress(delegate(bool result) { complete = result; }); int i = 0; while (i < maxRetries) { yield return StepGenerateContentPacks(progressReceiver, completionReceiver, maxRetries - i - 1); if (complete) { break; } int num = i + 1; i = num; } for (int j = 0; j < contentPackLoadInfos.Length; j++) { output.Add(contentPackLoadInfos[j].previousContentPack); } } public IEnumerator RunCleanup(IProgress progressReceiver) { yield return DoPerContentPackProviderCoroutine(progressReceiver, StartFinalizeCoroutine); IEnumerator StartFinalizeCoroutine(ref ContentPackLoadInfo loadInfo, ReadOnlyArray readOnlyPeers, IProgress providedProgressReceiver) { FinalizeAsyncArgs args = new FinalizeAsyncArgs(providedProgressReceiver, readOnlyPeers, contentPackLoadInfos[loadInfo.index].previousContentPack); return loadInfo.contentPackProvider.FinalizeAsync(args); } } } public delegate void AddContentPackProviderDelegate(IContentPackProvider contentPackProvider); public delegate void CollectContentPackProvidersDelegate(AddContentPackProviderDelegate addContentPackProvider); private static ContentPack[] contentPacks; public static ItemDef[] _itemDefs; public static ItemTierDef[] _itemTierDefs; private static ItemRelationshipProvider[] _itemRelationshipProviders; private static ItemRelationshipType[] _itemRelationshipTypes; public static EquipmentDef[] _equipmentDefs; public static BuffDef[] _buffDefs; public static EliteDef[] _eliteDefs; public static UnlockableDef[] _unlockableDefs; public static SurvivorDef[] _survivorDefs; public static GameObject[] _bodyPrefabs; public static GameObject[] _masterPrefabs; public static ArtifactDef[] _artifactDefs; public static EffectDef[] _effectDefs; public static SkillDef[] _skillDefs; public static SkillFamily[] _skillFamilies; public static SurfaceDef[] _surfaceDefs; public static SceneDef[] _sceneDefs; public static GameObject[] _projectilePrefabs; public static NetworkSoundEventDef[] _networkSoundEventDefs; public static MusicTrackDef[] _musicTrackDefs; public static GameObject[] _networkedObjectPrefabs; public static GameObject[] _gameModePrefabs; public static GameEndingDef[] _gameEndingDefs; public static EntityStateConfiguration[] _entityStateConfigurations; public static Type[] _entityStateTypes; public static ExpansionDef[] _expansionDefs; public static EntitlementDef[] _entitlementDefs; private static MiscPickupDef[] _miscPickupDefs; public static ItemDef[] itemDefs => _itemDefs; public static ItemTierDef[] itemTierDefs => _itemTierDefs; public static ItemRelationshipProvider[] itemRelationshipProviders => _itemRelationshipProviders; public static ItemRelationshipType[] itemRelationshipTypes => _itemRelationshipTypes; public static EquipmentDef[] equipmentDefs => _equipmentDefs; public static BuffDef[] buffDefs => _buffDefs; public static EliteDef[] eliteDefs => _eliteDefs; public static UnlockableDef[] unlockableDefs => _unlockableDefs; public static SurvivorDef[] survivorDefs => _survivorDefs; public static GameObject[] bodyPrefabs => _bodyPrefabs; public static GameObject[] masterPrefabs => _masterPrefabs; public static ArtifactDef[] artifactDefs => _artifactDefs; public static EffectDef[] effectDefs => _effectDefs; public static SkillDef[] skillDefs => _skillDefs; public static SkillFamily[] skillFamilies => _skillFamilies; public static SurfaceDef[] surfaceDefs => _surfaceDefs; public static SceneDef[] sceneDefs => _sceneDefs; public static GameObject[] projectilePrefabs => _projectilePrefabs; public static NetworkSoundEventDef[] networkSoundEventDefs => _networkSoundEventDefs; public static MusicTrackDef[] musicTrackDefs => _musicTrackDefs; public static GameObject[] networkedObjectPrefabs => _networkedObjectPrefabs; public static GameObject[] gameModePrefabs => _gameModePrefabs; public static GameEndingDef[] gameEndingDefs => _gameEndingDefs; public static EntityStateConfiguration[] entityStateConfigurations => _entityStateConfigurations; public static Type[] entityStateTypes => _entityStateTypes; public static ExpansionDef[] expansionDefs => _expansionDefs; public static EntitlementDef[] entitlementDefs => _entitlementDefs; public static MiscPickupDef[] miscPickupDefs => _miscPickupDefs; public static ReadOnlyArray allLoadedContentPacks { get; private set; } = Array.Empty(); public static event CollectContentPackProvidersDelegate collectContentPackProviders; public static event Action> onContentPacksAssigned; public static IEnumerator LoadContentPacks(IProgress progressReceiver) { List contentPackProviders = new List(); ContentManager.collectContentPackProviders?.Invoke(AddContentPackProvider); ContentManager.collectContentPackProviders = null; ContentPackLoader loader = new ContentPackLoader(contentPackProviders); yield return loader.InitialLoad(new ReadableProgress(delegate(float newValue) { progressReceiver.Report(Util.Remap(newValue, 0f, 1f, 0f, 0.8f)); })); yield return loader.LoadContentPacks(new ReadableProgress(delegate(float newValue) { progressReceiver.Report(Util.Remap(newValue, 0f, 1f, 0.8f, 0.95f)); })); yield return loader.RunCleanup(new ReadableProgress(delegate(float newValue) { progressReceiver.Report(Util.Remap(newValue, 0f, 1f, 0.95f, 1f)); })); yield return SetContentPacks(loader.output); void AddContentPackProvider(IContentPackProvider contentPackProvider) { contentPackProviders.Add(contentPackProvider); } } private static IEnumerator SetContentPacks(List newContentPacks) { allLoadedContentPacks = newContentPacks.ToArray(); SetAssets(ref _itemDefs, (ReadOnlyContentPack contentPack) => contentPack.itemDefs); SetAssets(ref _itemTierDefs, (ReadOnlyContentPack contentPack) => contentPack.itemTierDefs); SetAssets(ref _itemRelationshipProviders, (ReadOnlyContentPack contentPack) => contentPack.itemRelationshipProviders); SetAssets(ref _itemRelationshipTypes, (ReadOnlyContentPack contentPack) => contentPack.itemRelationshipTypes); SetAssets(ref _equipmentDefs, (ReadOnlyContentPack contentPack) => contentPack.equipmentDefs); SetAssets(ref _buffDefs, (ReadOnlyContentPack contentPack) => contentPack.buffDefs); SetAssets(ref _eliteDefs, (ReadOnlyContentPack contentPack) => contentPack.eliteDefs); SetAssets(ref _unlockableDefs, (ReadOnlyContentPack contentPack) => contentPack.unlockableDefs); yield return 0; SetAssets(ref _survivorDefs, (ReadOnlyContentPack contentPack) => contentPack.survivorDefs); SetAssets(ref _bodyPrefabs, (ReadOnlyContentPack contentPack) => contentPack.bodyPrefabs); SetAssets(ref _masterPrefabs, (ReadOnlyContentPack contentPack) => contentPack.masterPrefabs); SetAssets(ref _artifactDefs, (ReadOnlyContentPack contentPack) => contentPack.artifactDefs); yield return 0; SetAssets(ref _effectDefs, (ReadOnlyContentPack contentPack) => contentPack.effectDefs); SetAssets(ref _skillDefs, (ReadOnlyContentPack contentPack) => contentPack.skillDefs); SetAssets(ref _skillFamilies, (ReadOnlyContentPack contentPack) => contentPack.skillFamilies); SetAssets(ref _surfaceDefs, (ReadOnlyContentPack contentPack) => contentPack.surfaceDefs); SetAssets(ref _sceneDefs, (ReadOnlyContentPack contentPack) => contentPack.sceneDefs); SetAssets(ref _projectilePrefabs, (ReadOnlyContentPack contentPack) => contentPack.projectilePrefabs); yield return 0; SetAssets(ref _networkSoundEventDefs, (ReadOnlyContentPack contentPack) => contentPack.networkSoundEventDefs); SetAssets(ref _musicTrackDefs, (ReadOnlyContentPack contentPack) => contentPack.musicTrackDefs); SetAssets(ref _networkedObjectPrefabs, (ReadOnlyContentPack contentPack) => contentPack.networkedObjectPrefabs); SetAssets(ref _gameModePrefabs, (ReadOnlyContentPack contentPack) => contentPack.gameModePrefabs); SetAssets(ref _gameEndingDefs, (ReadOnlyContentPack contentPack) => contentPack.gameEndingDefs); SetAssets(ref _entityStateTypes, (ReadOnlyContentPack contentPack) => contentPack.entityStateTypes); yield return 0; SetAssets(ref _entityStateConfigurations, (ReadOnlyContentPack contentPack) => contentPack.entityStateConfigurations); SetAssets(ref _expansionDefs, (ReadOnlyContentPack contentPack) => contentPack.expansionDefs); SetAssets(ref _entitlementDefs, (ReadOnlyContentPack contentPack) => contentPack.entitlementDefs); SetAssets(ref _miscPickupDefs, (ReadOnlyContentPack contentPack) => contentPack.miscPickupDefs); yield return 0; ContentManager.onContentPacksAssigned?.Invoke(allLoadedContentPacks); void SetAssets(ref T[] field, Func> selector) { field = newContentPacks.SelectMany(selector).ToArray(); } } public static ReadOnlyContentPack? FindContentPack(string contentPackIdentifier) { int num = 0; while (true) { int num2 = num; ReadOnlyArray readOnlyArray = allLoadedContentPacks; if (num2 >= readOnlyArray.Length) { break; } readOnlyArray = allLoadedContentPacks; ref readonly ReadOnlyContentPack reference = ref readOnlyArray[num]; if (string.Equals(reference.identifier, contentPackIdentifier, StringComparison.Ordinal)) { return reference; } num++; } return null; } }