using System; using System.Collections; using System.Collections.Generic; using NitroxClient.GameLogic.PlayerLogic.PlayerModel.Abstract; using NitroxClient.GameLogic.Spawning.Abstract; using NitroxClient.GameLogic.Spawning.Metadata; using NitroxClient.GameLogic.Spawning.WorldEntities; using NitroxClient.MonoBehaviours; using NitroxModel.DataStructures.GameLogic.Entities; using NitroxModel.DataStructures.Util; using NitroxModel.Helper; using NitroxModel_Subnautica.DataStructures; using UnityEngine; namespace NitroxClient.GameLogic.Spawning; public class WorldEntitySpawner : SyncEntitySpawner { private readonly WorldEntitySpawnerResolver worldEntitySpawnResolver; private readonly Dictionary batchCellsById; public WorldEntitySpawner(EntityMetadataManager entityMetadataManager, PlayerManager playerManager, LocalPlayer localPlayer, Entities entities, SimulationOwnership simulationOwnership) { worldEntitySpawnResolver = new WorldEntitySpawnerResolver(entityMetadataManager, playerManager, localPlayer, entities, simulationOwnership); if (NitroxEnvironment.IsNormal) { batchCellsById = (Dictionary)LargeWorldStreamer.main.cellManager.batch2cells; } } protected override IEnumerator SpawnAsync(WorldEntity entity, TaskResult> result) { EntityCell cellRoot = EnsureCell(entity); if (cellRoot == null) { // Error logging is done in EnsureCell return null; } Optional parent = (entity.ParentId != null) ? NitroxEntity.GetObjectFrom(entity.ParentId) : Optional.Empty; IWorldEntitySpawner entitySpawner = worldEntitySpawnResolver.ResolveEntitySpawner(entity); if (entitySpawner is IWorldEntitySyncSpawner syncSpawner && syncSpawner.SpawnSync(entity, parent, cellRoot, result)) { return null; } return entitySpawner.SpawnAsync(entity, parent, cellRoot, result); } protected override bool SpawnsOwnChildren(WorldEntity entity) { IWorldEntitySpawner entitySpawner = worldEntitySpawnResolver.ResolveEntitySpawner(entity); return entitySpawner.SpawnsOwnChildren(); } protected override bool SpawnSync(WorldEntity entity, TaskResult> result) { EntityCell cellRoot = EnsureCell(entity); if (cellRoot == null) { // Error logging is done in EnsureCell return true; } Optional parent = (entity.ParentId != null) ? NitroxEntity.GetObjectFrom(entity.ParentId) : Optional.Empty; IWorldEntitySpawner entitySpawner = worldEntitySpawnResolver.ResolveEntitySpawner(entity); return entitySpawner is IWorldEntitySyncSpawner syncSpawner && syncSpawner.SpawnSync(entity, parent, cellRoot, result); } public EntityCell EnsureCell(WorldEntity entity) { EntityCell entityCell; Int3 batchId = entity.AbsoluteEntityCell.BatchId.ToUnity(); Int3 cellId = entity.AbsoluteEntityCell.CellId.ToUnity(); if (!batchCellsById.TryGetValue(batchId, out BatchCells batchCells)) { batchCells = LargeWorldStreamer.main.cellManager.InitializeBatchCells(batchId); } try { entityCell = batchCells.EnsureCell(cellId, entity.Level); } catch (Exception) { // Error logging is done in BatchCells.EnsureCell return null; } entityCell.EnsureRoot(); return entityCell; } }