Files
RobustToolbox/Robust.Client/Replays/Loading/ReplayLoadManager.Implicit.cs
2023-09-11 09:42:55 +10:00

84 lines
2.8 KiB
C#

using System;
using System.Collections.Generic;
using Robust.Client.GameStates;
using Robust.Shared;
using Robust.Shared.GameObjects;
using Robust.Shared.Timing;
using Robust.Shared.Utility;
using Robust.Shared.Map;
namespace Robust.Client.Replays.Loading;
// This partial class contains code for generating implicit component states.
public sealed partial class ReplayLoadManager
{
/// <summary>
/// Cached implicit entity states.
/// </summary>
private Dictionary<string, (List<ComponentChange>, HashSet<ushort>)> _implicitData = new();
private EntityState AddImplicitData(EntityState entState)
{
var prototype = GetPrototype(entState);
if (prototype == null)
return entState;
var (list, set) = GetImplicitData(prototype);
return MergeStates(entState, list, set);
}
private (List<ComponentChange>, HashSet<ushort>) GetImplicitData(string prototype)
{
if (_implicitData.TryGetValue(prototype, out var result))
return result;
var list = new List<ComponentChange>();
var set = new HashSet<ushort>();
_implicitData[prototype] = (list, set);
var entCount = _entMan.EntityCount;
var uid = _entMan.SpawnEntity(prototype, MapCoordinates.Nullspace);
foreach (var (netId, component) in _entMan.GetNetComponents(uid))
{
if (!component.NetSyncEnabled)
continue;
var state = _entMan.GetComponentState(_entMan.EventBus, component, null, GameTick.Zero);
DebugTools.Assert(state is not IComponentDeltaState delta || delta.FullState);
list.Add(new ComponentChange(netId, state, GameTick.Zero));
set.Add(netId);
}
_entMan.DeleteEntity(uid);
DebugTools.Assert(entCount == _entMan.EntityCount);
return (list, set);
}
private string? GetPrototype(EntityState entState)
{
foreach (var comp in entState.ComponentChanges.Span)
{
if (comp.NetID == _metaId)
{
var state = (MetaDataComponentState) comp.State;
return state.PrototypeId;
}
}
if (!entState.ComponentChanges.HasContents)
{
// This shouldn't be possible, yet it has happened?
// TODO this should probably also throw an exception.
_sawmill.Error($"Encountered blank entity state? Entity: {entState.NetEntity}. Last modified: {entState.EntityLastModified}. Attempting to continue.");
return null;
}
if (!_confMan.GetCVar(CVars.ReplayIgnoreErrors))
throw new MissingMetadataException(entState.NetEntity);
_sawmill.Error($"Missing metadata component. Entity: {entState.NetEntity}. Last modified: {entState.EntityLastModified}.");
return null;
}
}