Editor/Server/EditorHostLifetime.cs
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Editor;
using Sandbox;
namespace HumanoidMocapHost;
/// <summary>Connects a host session to public editor events. Hotload stops the old
/// listener; a replacement must wait for its GPU work to drain before restarting.</summary>
internal sealed class EditorHostLifetime : IHotloadManaged
{
HostSession session;
GpuAdmission admission;
Task shutdown;
DateTime sampled;
internal bool IsRunning => shutdown is null && session is not null && !session.IsStopping;
internal EditorHostLifetime(HostSession session, GpuAdmission admission)
{
this.session = session; this.admission = admission;
EditorEvent.Register(this); SampleMemory();
}
[EditorEvent.Frame]
void SampleMemory()
{
if (!IsRunning || DateTime.UtcNow - sampled < TimeSpan.FromSeconds(1)) return;
sampled = DateTime.UtcNow;
admission.Update(Graphics.VideoMemoryBudget, Graphics.VideoMemoryUsed, Sandbox.Engine.SystemInfo.GpuMemory);
}
internal Task StopAsync()
{
if (shutdown is not null) return shutdown;
EditorEvent.Unregister(this);
return shutdown = session?.StopAsync() ?? Task.CompletedTask;
}
public void Destroyed(Dictionary<string, object> state) => state["shutdown"] = StopAsync();
public void Created(IReadOnlyDictionary<string, object> state)
{
session = null; admission = null;
shutdown = state.TryGetValue("shutdown", out var task) ? (Task)task : Task.CompletedTask;
}
public void Failed() => _ = StopAsync();
}