using System.Collections; using NitroxClient.GameLogic.Helper; using NitroxClient.GameLogic.Spawning.Abstract; using NitroxClient.GameLogic.Spawning.WorldEntities; using NitroxClient.MonoBehaviours; using NitroxClient.Unity.Helper; using NitroxModel.DataStructures.GameLogic.Entities; using NitroxModel.DataStructures.Util; using NitroxModel_Subnautica.DataStructures; using UnityEngine; namespace NitroxClient.GameLogic.Spawning; public class InstalledModuleEntitySpawner : SyncEntitySpawner { protected override IEnumerator SpawnAsync(InstalledModuleEntity entity, TaskResult> result) { if (!CanSpawn(entity, out GameObject parentObject, out Equipment equipment, out string errorLog)) { Log.Info(errorLog); result.Set(Optional.Empty); yield break; } TaskResult gameObjectResult = new(); yield return DefaultWorldEntitySpawner.CreateGameObject(entity.TechType.ToUnity(), entity.ClassId, entity.Id, gameObjectResult); GameObject gameObject = gameObjectResult.Get(); SetupObject(entity, gameObject, parentObject, equipment); result.Set(Optional.Of(gameObject)); } protected override bool SpawnSync(InstalledModuleEntity entity, TaskResult> result) { if (!DefaultWorldEntitySpawner.TryGetCachedPrefab(out GameObject prefab, entity.TechType.ToUnity(), entity.ClassId)) { return false; } if (!CanSpawn(entity, out GameObject parentObject, out Equipment equipment, out string errorLog)) { Log.Error(errorLog); return true; } GameObject gameObject = GameObjectHelper.SpawnFromPrefab(prefab, entity.Id); SetupObject(entity, gameObject, parentObject, equipment); result.Set(gameObject); return true; } protected override bool SpawnsOwnChildren(InstalledModuleEntity entity) => false; private bool CanSpawn(InstalledModuleEntity entity, out GameObject parentObject, out Equipment equipment, out string errorLog) { if (!NitroxEntity.TryGetObjectFrom(entity.ParentId, out parentObject)) { equipment = null; errorLog = $"Unable to find inventory container with id {entity.Id} for {entity}"; return false; } // The game considers modules as vehicle equipment. Get the container and install it into the required slot. Optional opEquipment = EquipmentHelper.FindEquipmentComponent(parentObject); if (!opEquipment.HasValue) { equipment = null; errorLog = $"Unable to find equipment container inside {parentObject}"; return false; } equipment = opEquipment.Value; errorLog = null; return true; } private void SetupObject(InstalledModuleEntity entity, GameObject gameObject, GameObject parentObject, Equipment equipment) { Pickupable pickupable = gameObject.RequireComponent(); pickupable.Initialize(); InventoryItem inventoryItem = new(pickupable) { container = equipment }; inventoryItem.item.Reparent(equipment.tr); equipment.equipment[entity.Slot] = inventoryItem; equipment.UpdateCount(pickupable.GetTechType(), true); Equipment.SendEquipmentEvent(pickupable, 0, parentObject, entity.Slot); equipment.NotifyEquip(entity.Slot, inventoryItem); } }