first commit
This commit is contained in:
159
NitroxClient/GameLogic/Spawning/Bases/ModuleEntitySpawner.cs
Normal file
159
NitroxClient/GameLogic/Spawning/Bases/ModuleEntitySpawner.cs
Normal file
@@ -0,0 +1,159 @@
|
||||
using System.Collections;
|
||||
using System.Linq;
|
||||
using NitroxClient.GameLogic.Bases;
|
||||
using NitroxClient.GameLogic.Helper;
|
||||
using NitroxClient.GameLogic.Spawning.Abstract;
|
||||
using NitroxClient.GameLogic.Spawning.WorldEntities;
|
||||
using NitroxClient.MonoBehaviours;
|
||||
using NitroxClient.MonoBehaviours.Cyclops;
|
||||
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 ModuleEntitySpawner : EntitySpawner<ModuleEntity>
|
||||
{
|
||||
private readonly Entities entities;
|
||||
|
||||
public ModuleEntitySpawner(Entities entities)
|
||||
{
|
||||
this.entities = entities;
|
||||
}
|
||||
|
||||
protected override IEnumerator SpawnAsync(ModuleEntity entity, TaskResult<Optional<GameObject>> result)
|
||||
{
|
||||
if (NitroxEntity.TryGetObjectFrom(entity.Id, out GameObject gameObject) && gameObject)
|
||||
{
|
||||
Log.Error("Trying to respawn an already spawned module without a proper resync process.");
|
||||
yield break;
|
||||
}
|
||||
Transform parent = BuildingHandler.GetParentOrGlobalRoot(entity.ParentId);
|
||||
|
||||
yield return RestoreModule(parent, entity, result);
|
||||
|
||||
if (!result.Get().HasValue)
|
||||
{
|
||||
Log.Error($"Module couldn't be spawned {entity}");
|
||||
yield break;
|
||||
}
|
||||
GameObject moduleObject = result.Get().Value;
|
||||
|
||||
Optional<ItemsContainer> opContainer = InventoryContainerHelper.TryGetContainerByOwner(moduleObject);
|
||||
if (opContainer.HasValue)
|
||||
{
|
||||
yield return entities.SpawnBatchAsync(entity.ChildEntities.OfType<InventoryItemEntity>().ToList<Entity>(), true);
|
||||
}
|
||||
|
||||
Optional<Equipment> opEquipment = EquipmentHelper.FindEquipmentComponent(moduleObject);
|
||||
if (opEquipment.HasValue)
|
||||
{
|
||||
yield return entities.SpawnBatchAsync(entity.ChildEntities.OfType<InstalledModuleEntity>().ToList<Entity>(), true);
|
||||
}
|
||||
|
||||
if (moduleObject.TryGetComponent(out PowerSource powerSource))
|
||||
{
|
||||
// TODO: Have synced/restored power
|
||||
powerSource.SetPower(powerSource.maxPower);
|
||||
}
|
||||
}
|
||||
|
||||
protected override bool SpawnsOwnChildren(ModuleEntity entity) => true;
|
||||
|
||||
public static IEnumerator RestoreModule(Transform parent, ModuleEntity moduleEntity, TaskResult<Optional<GameObject>> result = null)
|
||||
{
|
||||
if (!DefaultWorldEntitySpawner.TryGetCachedPrefab(out GameObject prefab, classId: moduleEntity.ClassId))
|
||||
{
|
||||
TaskResult<GameObject> prefabResult = new();
|
||||
yield return DefaultWorldEntitySpawner.RequestPrefab(moduleEntity.ClassId, prefabResult);
|
||||
if (!prefabResult.Get())
|
||||
{
|
||||
Log.Error($"Couldn't find a prefab for module of ClassId {moduleEntity.ClassId}");
|
||||
yield break;
|
||||
}
|
||||
prefab = prefabResult.Get();
|
||||
}
|
||||
|
||||
GameObject moduleObject = UnityEngine.Object.Instantiate(prefab);
|
||||
Transform moduleTransform = moduleObject.transform;
|
||||
moduleTransform.parent = parent;
|
||||
moduleTransform.localPosition = moduleEntity.Transform.LocalPosition.ToUnity();
|
||||
moduleTransform.localRotation = moduleEntity.Transform.LocalRotation.ToUnity();
|
||||
moduleTransform.localScale = moduleEntity.Transform.LocalScale.ToUnity();
|
||||
ApplyModuleData(moduleEntity, moduleObject, result);
|
||||
MoveToGlobalRoot(moduleObject);
|
||||
|
||||
if (parent && parent.TryGetComponent(out NitroxCyclops nitroxCyclops) && nitroxCyclops.Virtual)
|
||||
{
|
||||
nitroxCyclops.Virtual.ReplicateConstructable(moduleObject.GetComponent<Constructable>());
|
||||
}
|
||||
|
||||
yield return BuildingPostSpawner.ApplyPostSpawner(moduleObject, moduleEntity.Id);
|
||||
}
|
||||
|
||||
public static void ApplyModuleData(ModuleEntity moduleEntity, GameObject moduleObject, TaskResult<Optional<GameObject>> result = null)
|
||||
{
|
||||
Constructable constructable = moduleObject.GetComponent<Constructable>();
|
||||
constructable.SetIsInside(moduleEntity.IsInside);
|
||||
if (moduleEntity.IsInside)
|
||||
{
|
||||
SkyEnvironmentChanged.Send(moduleObject, moduleObject.GetComponentInParent<SubRoot>(true));
|
||||
}
|
||||
else
|
||||
{
|
||||
SkyEnvironmentChanged.Send(moduleObject, (Component)null);
|
||||
}
|
||||
constructable.constructedAmount = moduleEntity.ConstructedAmount;
|
||||
constructable.SetState(moduleEntity.ConstructedAmount >= 1f, false);
|
||||
constructable.UpdateMaterial();
|
||||
NitroxEntity.SetNewId(moduleObject, moduleEntity.Id);
|
||||
|
||||
result?.Set(moduleObject);
|
||||
}
|
||||
|
||||
public static void FillObject(ModuleEntity moduleEntity, Constructable constructable)
|
||||
{
|
||||
moduleEntity.ClassId = constructable.GetComponent<PrefabIdentifier>().ClassId;
|
||||
|
||||
if (constructable.TryGetNitroxId(out NitroxId entityId))
|
||||
{
|
||||
moduleEntity.Id = entityId;
|
||||
}
|
||||
if (constructable.TryGetComponentInParent(out Base parentBase, true) &&
|
||||
parentBase.TryGetNitroxId(out NitroxId parentId))
|
||||
{
|
||||
moduleEntity.ParentId = parentId;
|
||||
}
|
||||
moduleEntity.Transform = constructable.transform.ToLocalDto();
|
||||
moduleEntity.TechType = constructable.techType.ToDto();
|
||||
moduleEntity.ConstructedAmount = constructable.constructedAmount;
|
||||
moduleEntity.IsInside = constructable.isInside;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// We don't want constructables to be put in CellRoots but in GlobalRoot, because when a player has simulation ownership over a base,
|
||||
/// they also need to keep loaded everything which could be related to the said base (e.g. power relays)
|
||||
/// </summary>
|
||||
public static void MoveToGlobalRoot(GameObject gameObject)
|
||||
{
|
||||
if (!gameObject.TryGetComponent(out LargeWorldEntity largeWorldEntity))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
largeWorldEntity.cellLevel = LargeWorldEntity.CellLevel.Global;
|
||||
largeWorldEntity.Start();
|
||||
}
|
||||
|
||||
public static ModuleEntity From(Constructable constructable)
|
||||
{
|
||||
ModuleEntity module = ModuleEntity.MakeEmpty();
|
||||
FillObject(module, constructable);
|
||||
return module;
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user