184 lines
7.1 KiB
C#
184 lines
7.1 KiB
C#
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using NitroxClient.GameLogic.Spawning.Abstract;
|
|
using NitroxClient.GameLogic.Spawning.Metadata;
|
|
using NitroxClient.GameLogic.Spawning.WorldEntities;
|
|
using NitroxClient.MonoBehaviours;
|
|
using NitroxClient.Unity.Helper;
|
|
using NitroxModel.DataStructures;
|
|
using NitroxModel.DataStructures.GameLogic;
|
|
using NitroxModel.DataStructures.GameLogic.Entities;
|
|
using NitroxModel.DataStructures.GameLogic.Entities.Bases;
|
|
using NitroxModel.DataStructures.Util;
|
|
using NitroxModel_Subnautica.DataStructures;
|
|
using UnityEngine;
|
|
|
|
namespace NitroxClient.GameLogic.Spawning.Bases;
|
|
|
|
public class InteriorPieceEntitySpawner : EntitySpawner<InteriorPieceEntity>
|
|
{
|
|
private readonly Entities entities;
|
|
private readonly EntityMetadataManager entityMetadataManager;
|
|
|
|
public InteriorPieceEntitySpawner(Entities entities, EntityMetadataManager entityMetadataManager)
|
|
{
|
|
this.entities = entities;
|
|
this.entityMetadataManager = entityMetadataManager;
|
|
}
|
|
|
|
protected override IEnumerator SpawnAsync(InteriorPieceEntity entity, TaskResult<Optional<GameObject>> result)
|
|
{
|
|
if (entity.ParentId == null || !NitroxEntity.TryGetComponentFrom(entity.ParentId, out Base @base))
|
|
{
|
|
Log.Error($"Couldn't find a Base component on the parent object of InteriorPieceEntity {entity.Id}");
|
|
yield break;
|
|
}
|
|
yield return RestoreInteriorPiece(entity, @base, result);
|
|
if (!result.Get().HasValue)
|
|
{
|
|
Log.Error($"Restoring interior piece failed: {entity}");
|
|
yield break;
|
|
}
|
|
bool isWaterPark = entity.IsWaterPark;
|
|
|
|
List<Entity> batch = new();
|
|
foreach (Entity childEntity in entity.ChildEntities)
|
|
{
|
|
switch(childEntity)
|
|
{
|
|
case InventoryItemEntity:
|
|
case InstalledModuleEntity:
|
|
batch.Add(childEntity);
|
|
break;
|
|
|
|
case PlanterEntity:
|
|
foreach (InventoryItemEntity childItemEntity in childEntity.ChildEntities.OfType<InventoryItemEntity>())
|
|
{
|
|
batch.Add(childItemEntity);
|
|
}
|
|
break;
|
|
|
|
case WorldEntity:
|
|
if (isWaterPark)
|
|
{
|
|
batch.Add(childEntity);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (isWaterPark)
|
|
{
|
|
// Must happen before child plant spawning
|
|
foreach (Planter planter in result.Get().Value.GetComponentsInChildren<Planter>(true))
|
|
{
|
|
yield return planter.DeserializeAsync();
|
|
}
|
|
}
|
|
|
|
yield return entities.SpawnBatchAsync(batch, true);
|
|
|
|
if (result.Get().Value.TryGetComponent(out PowerSource powerSource))
|
|
{
|
|
// TODO: Have synced/restored power
|
|
powerSource.SetPower(powerSource.maxPower);
|
|
}
|
|
}
|
|
|
|
protected override bool SpawnsOwnChildren(InteriorPieceEntity entity) => true;
|
|
|
|
public IEnumerator RestoreInteriorPiece(InteriorPieceEntity interiorPiece, Base @base, TaskResult<Optional<GameObject>> result = null)
|
|
{
|
|
if (!DefaultWorldEntitySpawner.TryGetCachedPrefab(out GameObject prefab, classId: interiorPiece.ClassId))
|
|
{
|
|
TaskResult<GameObject> prefabResult = new();
|
|
yield return DefaultWorldEntitySpawner.RequestPrefab(interiorPiece.ClassId, prefabResult);
|
|
if (!prefabResult.Get())
|
|
{
|
|
Log.Error($"Couldn't find a prefab for interior piece of ClassId {interiorPiece.ClassId}");
|
|
yield break;
|
|
}
|
|
prefab = prefabResult.Get();
|
|
}
|
|
|
|
Base.Face face = interiorPiece.BaseFace.ToUnity();
|
|
face.cell += @base.GetAnchor();
|
|
GameObject moduleObject = @base.SpawnModule(prefab, face);
|
|
if (moduleObject)
|
|
{
|
|
NitroxEntity.SetNewId(moduleObject, interiorPiece.Id);
|
|
yield return BuildingPostSpawner.ApplyPostSpawner(moduleObject, interiorPiece.Id);
|
|
entityMetadataManager.ApplyMetadata(moduleObject, interiorPiece.Metadata);
|
|
result.Set(moduleObject);
|
|
}
|
|
}
|
|
|
|
public static InteriorPieceEntity From(IBaseModule module, EntityMetadataManager entityMetadataManager)
|
|
{
|
|
InteriorPieceEntity interiorPiece = InteriorPieceEntity.MakeEmpty();
|
|
GameObject gameObject = (module as Component).gameObject;
|
|
if (gameObject && gameObject.TryGetComponent(out PrefabIdentifier identifier))
|
|
{
|
|
interiorPiece.ClassId = identifier.ClassId;
|
|
}
|
|
else
|
|
{
|
|
Log.Warn($"Couldn't find an identifier for the interior piece {module.GetType()}");
|
|
}
|
|
|
|
if (gameObject.TryGetIdOrWarn(out NitroxId entityId))
|
|
{
|
|
interiorPiece.Id = entityId;
|
|
}
|
|
|
|
if (gameObject.TryGetComponentInParent(out Base parentBase, true) &&
|
|
parentBase.TryGetNitroxId(out NitroxId parentId))
|
|
{
|
|
interiorPiece.ParentId = parentId;
|
|
}
|
|
|
|
switch (module)
|
|
{
|
|
case LargeRoomWaterPark:
|
|
PlanterEntity leftPlanter = new(interiorPiece.Id.Increment(), interiorPiece.Id);
|
|
PlanterEntity rightPlanter = new(leftPlanter.Id.Increment(), interiorPiece.Id);
|
|
interiorPiece.ChildEntities.Add(leftPlanter);
|
|
interiorPiece.ChildEntities.Add(rightPlanter);
|
|
break;
|
|
// When you deconstruct (not entirely) then construct back those pieces, they keep their inventories
|
|
case BaseNuclearReactor baseNuclearReactor:
|
|
interiorPiece.ChildEntities.AddRange(Items.GetEquipmentModuleEntities(baseNuclearReactor.equipment, entityId, entityMetadataManager));
|
|
break;
|
|
case BaseBioReactor baseBioReactor:
|
|
foreach (ItemsContainer.ItemGroup itemGroup in baseBioReactor.container._items.Values)
|
|
{
|
|
foreach (InventoryItem item in itemGroup.items)
|
|
{
|
|
interiorPiece.ChildEntities.Add(Items.ConvertToInventoryItemEntity(item.item.gameObject, interiorPiece.Id, entityMetadataManager));
|
|
}
|
|
}
|
|
break;
|
|
case WaterPark:
|
|
PlanterEntity planter = new(interiorPiece.Id.Increment(), interiorPiece.Id);
|
|
interiorPiece.ChildEntities.Add(planter);
|
|
break;
|
|
}
|
|
|
|
interiorPiece.BaseFace = module.moduleFace.ToDto();
|
|
|
|
return interiorPiece;
|
|
}
|
|
|
|
public static IEnumerator RestoreMapRoom(Base @base, MapRoomEntity mapRoomEntity)
|
|
{
|
|
MapRoomFunctionality mapRoomFunctionality = @base.GetMapRoomFunctionalityForCell(mapRoomEntity.Cell.ToUnity());
|
|
if (!mapRoomFunctionality)
|
|
{
|
|
Log.Error($"Couldn't find MapRoomFunctionality in base for cell {mapRoomEntity.Cell}");
|
|
yield break;
|
|
}
|
|
NitroxEntity.SetNewId(mapRoomFunctionality.gameObject, mapRoomEntity.Id);
|
|
}
|
|
}
|