first commit

This commit is contained in:
2025-07-06 00:23:46 +02:00
commit 38f50c8819
1788 changed files with 112878 additions and 0 deletions

View File

@@ -0,0 +1,183 @@
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);
}
}