Files
Nitrox/NitroxClient/GameLogic/Spawning/Metadata/EntityMetadataManager.cs
2025-07-06 00:23:46 +02:00

101 lines
3.4 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using NitroxClient.GameLogic.Spawning.Metadata.Extractor.Abstract;
using NitroxClient.GameLogic.Spawning.Metadata.Processor.Abstract;
using NitroxModel.DataStructures;
using NitroxModel.DataStructures.GameLogic.Entities.Metadata;
using NitroxModel.DataStructures.Util;
using UnityEngine;
namespace NitroxClient.GameLogic.Spawning.Metadata;
public class EntityMetadataManager
{
private readonly Dictionary<Type, IEntityMetadataExtractor> extractors;
private readonly Dictionary<Type, IEntityMetadataProcessor> processors;
/// <summary>
/// As it takes some time spawning lots of entities, it can happen that we receive metadata updates for those which are still in the queue.
/// Therefore we list the updates which happened while we didn't have the said objects loaded
/// </summary>
private readonly Dictionary<NitroxId, EntityMetadata> newerMetadataById = new();
public EntityMetadataManager(IEnumerable<IEntityMetadataExtractor> extractors, IEnumerable<IEntityMetadataProcessor> processors)
{
this.extractors = extractors.ToDictionary(p => p.GetType().BaseType.GetGenericArguments()[0]);
this.processors = processors.ToDictionary(p => p.GetType().BaseType.GetGenericArguments()[0]);
}
public Optional<EntityMetadata> Extract(object o)
{
if (extractors.TryGetValue(o.GetType(), out IEntityMetadataExtractor extractor))
{
return extractor.From(o);
}
return Optional.Empty;
}
public Optional<EntityMetadata> Extract(GameObject o)
{
foreach (Component component in o.GetComponents<Component>())
{
if (extractors.TryGetValue(component.GetType(), out IEntityMetadataExtractor extractor))
{
Optional<EntityMetadata> metadata = extractor.From(component);
if (metadata.HasValue)
{
return metadata;
}
}
}
return Optional.Empty;
}
public bool TryExtract(object o, out EntityMetadata metadata)
{
Optional<EntityMetadata> opMetadata = Extract(o);
metadata = opMetadata.Value;
return opMetadata.HasValue;
}
public Optional<IEntityMetadataProcessor> FromMetaData(EntityMetadata metadata)
{
if (metadata != null && processors.TryGetValue(metadata.GetType(), out IEntityMetadataProcessor processor))
{
return Optional.Of(processor);
}
return Optional.Empty;
}
public void ApplyMetadata(GameObject gameObject, EntityMetadata metadata)
{
// In case a metadata update was received while this entity was in the spawn queue
if (gameObject.TryGetNitroxId(out NitroxId objectId) &&
newerMetadataById.TryGetValue(objectId, out EntityMetadata newMetadata))
{
metadata = newMetadata;
newerMetadataById.Remove(objectId);
}
Optional<IEntityMetadataProcessor> metadataProcessor = FromMetaData(metadata);
if (metadataProcessor.HasValue)
{
metadataProcessor.Value.ProcessMetadata(gameObject, metadata);
}
}
public void RegisterNewerMetadata(NitroxId entityId, EntityMetadata metadata)
{
newerMetadataById[entityId] = metadata;
}
public void ClearNewerMetadata()
{
newerMetadataById.Clear();
}
}