From eb02f01f4366f881233056271a6b34ed5ff650b7 Mon Sep 17 00:00:00 2001 From: tornac1234 <24827220+tornac1234@users.noreply.github.com> Date: Wed, 8 Jan 2025 17:02:34 +0100 Subject: [PATCH] Small corrections and fix map full loading percentage --- .../Parsers/PrefabPlaceholderGroupsParser.cs | 50 +++++++++++-------- .../Resources/ResourceAssets.cs | 4 +- .../GameLogic/Bases/BuildingManager.cs | 6 ++- .../GameLogic/Entities/WorldEntityManager.cs | 9 ++-- 4 files changed, 39 insertions(+), 30 deletions(-) diff --git a/NitroxServer-Subnautica/Resources/Parsers/PrefabPlaceholderGroupsParser.cs b/NitroxServer-Subnautica/Resources/Parsers/PrefabPlaceholderGroupsParser.cs index 72782fa552..f102e3b960 100644 --- a/NitroxServer-Subnautica/Resources/Parsers/PrefabPlaceholderGroupsParser.cs +++ b/NitroxServer-Subnautica/Resources/Parsers/PrefabPlaceholderGroupsParser.cs @@ -10,6 +10,7 @@ using AssetsTools.NET.Extra; using Newtonsoft.Json; using NitroxModel.DataStructures.Unity; +using NitroxModel.Helper; using NitroxServer.GameLogic.Entities; using NitroxServer.Resources; using NitroxServer_Subnautica.Resources.Parsers.Helper; @@ -59,11 +60,8 @@ public Dictionary ParseFile() // Loading all prefabs by their classId and file paths (first the path to the prefab then the dependencies) LoadAddressableCatalog(prefabDatabase); - string nitroxCachePath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "Nitrox", "Cache"); - if (!Directory.Exists(nitroxCachePath)) - { - Directory.CreateDirectory(nitroxCachePath); - } + string nitroxCachePath = Path.Combine(NitroxUser.AppDataPath, "Cache"); + Directory.CreateDirectory(nitroxCachePath); Dictionary prefabPlaceholdersGroupPaths = null; string prefabPlaceholdersGroupAssetCachePath = Path.Combine(nitroxCachePath, "PrefabPlaceholdersGroupAssetsCache.json"); @@ -93,24 +91,25 @@ public Dictionary ParseFile() return prefabPlaceholdersGroupPaths; } - private Dictionary MakeAndSerializeCache(string path) + private Dictionary MakeAndSerializeCache(string filePath) { ConcurrentDictionary prefabPlaceholdersGroupPaths = GetAllPrefabPlaceholdersGroupsFast(); Dictionary prefabPlaceholdersGroupAssets = new(GetPrefabPlaceholderGroupAssetsByGroupClassId(prefabPlaceholdersGroupPaths)); - using StreamWriter stream = File.CreateText(path); + using StreamWriter stream = File.CreateText(filePath); serializer.Serialize(stream, new Cache(prefabPlaceholdersGroupAssets, RandomPossibilitiesByClassId)); return prefabPlaceholdersGroupAssets; } - private Cache? DeserializeCache(string path) + private Cache? DeserializeCache(string filePath) { try { - using StreamReader reader = File.OpenText(path); + using StreamReader reader = File.OpenText(filePath); return (Cache)serializer.Deserialize(reader, typeof(Cache)); - } catch (Exception exception) + } + catch (Exception exception) { Log.Error(exception, "An error occurred while deserializing the game Cache. Re-creating it."); } @@ -143,7 +142,7 @@ private void LoadAddressableCatalog(Dictionary prefabDatabase) { ContentCatalogData ccd = AddressablesJsonParser.FromString(File.ReadAllText(Path.Combine(aaRootPath, "catalog.json"))); Dictionary classIdByPath = prefabDatabase.ToDictionary(m => m.Value, m => m.Key); - + foreach (KeyValuePair> entry in ccd.Resources) { if (entry.Key is string primaryKey && primaryKey.Length == 32 && @@ -230,19 +229,25 @@ private ConcurrentDictionary GetAllPrefabPlaceholdersGroupsFas AssetsBundleManager bundleManagerInst = am.Clone(); AssetsFileInstance assetFileInstance = bundleManagerInst.LoadBundleWithDependencies(assetPaths); - if (assetFileInstance.file.Metadata.TypeTreeTypes.Any(typeTree => typeTree.TypeId == (int)AssetClassID.MonoBehaviour && typeTree.TypeHash.data.SequenceEqual(prefabPlaceholdersGroupHash))) + foreach (TypeTreeType typeTreeType in assetFileInstance.file.Metadata.TypeTreeTypes) { - prefabPlaceholdersGroupPaths.TryAdd(keyValuePair.Key, keyValuePair.Value); - } - else if (assetFileInstance.file.Metadata.TypeTreeTypes.Any(typeTree => typeTree.TypeId == (int)AssetClassID.MonoBehaviour && typeTree.TypeHash.data.SequenceEqual(spawnRandomHash))) - { - AssetsFileInstance assetFileInst = am.LoadBundleWithDependencies(assetPaths); - - GetPrefabGameObjectInfoFromBundle(am, assetFileInst, out AssetFileInfo prefabGameObjectInfo); + if (typeTreeType.TypeId != (int)AssetClassID.MonoBehaviour) + { + continue; + } - AssetFileInfo spawnRandomInfo = am.GetMonoBehaviourFromGameObject(assetFileInst, prefabGameObjectInfo, "SpawnRandom"); - if (spawnRandomInfo != null) + if (typeTreeType.TypeHash.data.SequenceEqual(prefabPlaceholdersGroupHash)) + { + prefabPlaceholdersGroupPaths.TryAdd(keyValuePair.Key, keyValuePair.Value); + break; + } + else if (typeTreeType.TypeHash.data.SequenceEqual(spawnRandomHash)) { + AssetsFileInstance assetFileInst = am.LoadBundleWithDependencies(assetPaths); + + GetPrefabGameObjectInfoFromBundle(am, assetFileInst, out AssetFileInfo prefabGameObjectInfo); + + AssetFileInfo spawnRandomInfo = am.GetMonoBehaviourFromGameObject(assetFileInst, prefabGameObjectInfo, "SpawnRandom"); // See SpawnRandom.Start AssetTypeValueField spawnRandom = am.GetBaseField(assetFileInst, spawnRandomInfo); List classIds = []; @@ -252,6 +257,7 @@ private ConcurrentDictionary GetAllPrefabPlaceholdersGroupsFas } RandomPossibilitiesByClassId.TryAdd(keyValuePair.Key, [.. classIds]); + break; } } @@ -380,7 +386,7 @@ private IPrefabAsset GetAndCacheAsset(AssetsBundleManager amInst, string classId { classIds.Add(classIdByRuntimeKey[assetReference["m_AssetGUID"].AsString]); } - + return new PrefabPlaceholderRandomAsset(classIds); } diff --git a/NitroxServer-Subnautica/Resources/ResourceAssets.cs b/NitroxServer-Subnautica/Resources/ResourceAssets.cs index c6dc6555e9..f33e5c4138 100644 --- a/NitroxServer-Subnautica/Resources/ResourceAssets.cs +++ b/NitroxServer-Subnautica/Resources/ResourceAssets.cs @@ -11,8 +11,8 @@ public class ResourceAssets public Dictionary WorldEntitiesByClassId { get; init; } = new(); public string LootDistributionsJson { get; init; } = ""; public Dictionary PrefabPlaceholdersGroupsByGroupClassId { get; init; } = new(); - public RandomStartGenerator NitroxRandom { get; init; } public Dictionary RandomPossibilitiesByClassId { get; init; } + public RandomStartGenerator NitroxRandom { get; init; } public static void ValidateMembers(ResourceAssets resourceAssets) { @@ -20,7 +20,7 @@ public static void ValidateMembers(ResourceAssets resourceAssets) Validate.IsTrue(resourceAssets.WorldEntitiesByClassId.Count > 0); Validate.IsTrue(resourceAssets.LootDistributionsJson != ""); Validate.IsTrue(resourceAssets.PrefabPlaceholdersGroupsByGroupClassId.Count > 0); - Validate.NotNull(resourceAssets.NitroxRandom); Validate.IsTrue(resourceAssets.RandomPossibilitiesByClassId.Count > 0); + Validate.NotNull(resourceAssets.NitroxRandom); } } diff --git a/NitroxServer/GameLogic/Bases/BuildingManager.cs b/NitroxServer/GameLogic/Bases/BuildingManager.cs index b7b538dba6..9cb807a651 100644 --- a/NitroxServer/GameLogic/Bases/BuildingManager.cs +++ b/NitroxServer/GameLogic/Bases/BuildingManager.cs @@ -102,7 +102,9 @@ public bool ModifyConstructedAmount(ModifyConstructedAmount modifyConstructedAmo Log.Error($"Trying to modify the constructed amount of a non-registered object (GhostId: {modifyConstructedAmount.GhostId})"); return false; } - // Certain entities are just "regular" WorldEntities and for simplicity we'll just ignore the + + // Certain entities with a Constructable are just "regular" WorldEntities (e.g. starship boxes) and for simplicity we'll just not persist their progress + // since their only use is to be deconstructed to give materials to players if (entity is not GhostEntity && entity is not ModuleEntity) { // In case the entity was fully deconstructed @@ -275,7 +277,7 @@ public bool ReplacePieceByGhost(Player player, PieceDeconstructed pieceDeconstru removedEntity = worldEntityManager.RemoveGlobalRootEntity(pieceDeconstructed.PieceId).Value; GhostEntity ghostEntity = pieceDeconstructed.ReplacerGhost; - + worldEntityManager.AddOrUpdateGlobalRootEntity(ghostEntity); buildEntity.BaseData = pieceDeconstructed.BaseData; buildEntity.OperationId++; diff --git a/NitroxServer/GameLogic/Entities/WorldEntityManager.cs b/NitroxServer/GameLogic/Entities/WorldEntityManager.cs index 86080cd3c4..f877ccd5b8 100644 --- a/NitroxServer/GameLogic/Entities/WorldEntityManager.cs +++ b/NitroxServer/GameLogic/Entities/WorldEntityManager.cs @@ -217,7 +217,8 @@ public void LoadAllUnspawnedEntities(System.Threading.CancellationToken token) { IMap map = NitroxServiceLocator.LocateService(); - int totalEntites = 0; + int totalBatches = map.DimensionsInBatches.X * map.DimensionsInBatches.Y * map.DimensionsInBatches.Z; + int batchesLoaded = 0; for (int x = 0; x < map.DimensionsInBatches.X; x++) { @@ -230,13 +231,13 @@ public void LoadAllUnspawnedEntities(System.Threading.CancellationToken token) Log.Debug($"Loaded {spawned} entities from batch ({x}, {y}, {z})"); - totalEntites += spawned; + batchesLoaded++; } } - if (totalEntites > 0) + if (batchesLoaded > 0) { - Log.Info($"Loading : {(int)((totalEntites/ 709531) * 100)}%"); + Log.Info($"Loading : {(int)(100f * batchesLoaded / totalBatches)}%"); } } }