refactor(net): cut GameWindow over to session owner
This commit is contained in:
parent
783ef1d6db
commit
6a5d9e2e6a
5 changed files with 363 additions and 268 deletions
|
|
@ -216,7 +216,6 @@ public sealed class LiveSessionController : IDisposable
|
|||
private SessionScope? _retiredScope;
|
||||
private ILiveSessionLifecycleHost? _pendingInitialResetHost;
|
||||
private PendingOperation? _pendingOperation;
|
||||
private WorldSession? _legacySession;
|
||||
private int _operationDepth;
|
||||
private bool _inWorld;
|
||||
private bool _disposeRequested;
|
||||
|
|
@ -236,12 +235,9 @@ public sealed class LiveSessionController : IDisposable
|
|||
|
||||
public WorldSession? CurrentSession
|
||||
{
|
||||
get { lock (_gate) return _scope?.Session ?? _legacySession; }
|
||||
get { lock (_gate) return _scope?.Session; }
|
||||
}
|
||||
|
||||
/// <summary>Temporary Slice-3 compatibility alias; removed at GameWindow cutover.</summary>
|
||||
public WorldSession? Session => CurrentSession;
|
||||
|
||||
public ICommandBus Commands
|
||||
{
|
||||
get
|
||||
|
|
@ -319,11 +315,6 @@ public sealed class LiveSessionController : IDisposable
|
|||
{
|
||||
if (_disposed)
|
||||
return;
|
||||
if (_legacySession is not null && _scope is null)
|
||||
{
|
||||
_legacySession.Tick();
|
||||
return;
|
||||
}
|
||||
if (!_inWorld || _scope is null || _operationDepth != 0)
|
||||
return;
|
||||
|
||||
|
|
@ -629,11 +620,6 @@ public sealed class LiveSessionController : IDisposable
|
|||
private void DisposeCore()
|
||||
{
|
||||
StopCore();
|
||||
if (_legacySession is { } legacy)
|
||||
{
|
||||
_operations.DisposeSession(legacy);
|
||||
_legacySession = null;
|
||||
}
|
||||
_disposed = true;
|
||||
}
|
||||
|
||||
|
|
@ -649,40 +635,4 @@ public sealed class LiveSessionController : IDisposable
|
|||
throw new ObjectDisposedException(nameof(LiveSessionController));
|
||||
}
|
||||
|
||||
// Temporary compatibility surface for Slice 3 Commit E. The complete
|
||||
// controller above is exercised independently before GameWindow cuts over.
|
||||
public WorldSession? CreateAndWire(RuntimeOptions options, Action<WorldSession> wireEvents)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(options);
|
||||
ArgumentNullException.ThrowIfNull(wireEvents);
|
||||
lock (_gate)
|
||||
{
|
||||
ThrowIfDisposing();
|
||||
if (!options.LiveMode)
|
||||
return null;
|
||||
if (string.IsNullOrEmpty(options.LiveUser) || string.IsNullOrEmpty(options.LivePass))
|
||||
{
|
||||
Console.WriteLine(
|
||||
"live: ACDREAM_LIVE set but TEST_USER/TEST_PASS missing; skipping");
|
||||
return null;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
IPEndPoint endpoint = _operations.ResolveEndpoint(options.LiveHost, options.LivePort);
|
||||
Console.WriteLine($"live: connecting to {endpoint} as {options.LiveUser}");
|
||||
_legacySession = _operations.CreateSession(endpoint);
|
||||
wireEvents(_legacySession);
|
||||
return _legacySession;
|
||||
}
|
||||
catch (Exception error)
|
||||
{
|
||||
Console.WriteLine($"live: session setup failed: {error.Message}");
|
||||
if (_legacySession is not null)
|
||||
_operations.DisposeSession(_legacySession);
|
||||
_legacySession = null;
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
65
src/AcDream.App/Net/LiveSessionLifecycleHost.cs
Normal file
65
src/AcDream.App/Net/LiveSessionLifecycleHost.cs
Normal file
|
|
@ -0,0 +1,65 @@
|
|||
using AcDream.Core.Net;
|
||||
|
||||
namespace AcDream.App.Net;
|
||||
|
||||
internal sealed record LiveSessionLifecycleBindings(
|
||||
Func<WorldSession, LiveSessionBinding> Bind,
|
||||
Action Reset,
|
||||
Action<string, int, string> Connecting,
|
||||
Action Connected,
|
||||
Action<LiveSessionCharacterSelection> Selected,
|
||||
Action<LiveSessionCharacterSelection> Entered);
|
||||
|
||||
/// <summary>
|
||||
/// Focused adapter between the session lifetime owner and App composition.
|
||||
/// It tracks only the exact borrowed session attached to the host; domain and
|
||||
/// presentation state remain behind the supplied lifecycle callbacks.
|
||||
/// </summary>
|
||||
internal sealed class LiveSessionLifecycleHost : ILiveSessionLifecycleHost
|
||||
{
|
||||
private readonly LiveSessionLifecycleBindings _bindings;
|
||||
private WorldSession? _boundSession;
|
||||
|
||||
public LiveSessionLifecycleHost(LiveSessionLifecycleBindings bindings)
|
||||
{
|
||||
_bindings = bindings ?? throw new ArgumentNullException(nameof(bindings));
|
||||
ArgumentNullException.ThrowIfNull(bindings.Bind);
|
||||
ArgumentNullException.ThrowIfNull(bindings.Reset);
|
||||
ArgumentNullException.ThrowIfNull(bindings.Connecting);
|
||||
ArgumentNullException.ThrowIfNull(bindings.Connected);
|
||||
ArgumentNullException.ThrowIfNull(bindings.Selected);
|
||||
ArgumentNullException.ThrowIfNull(bindings.Entered);
|
||||
}
|
||||
|
||||
public LiveSessionBinding BindSession(WorldSession session)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(session);
|
||||
if (_boundSession is not null)
|
||||
throw new InvalidOperationException("A live session is already attached to this host.");
|
||||
|
||||
LiveSessionBinding binding = _bindings.Bind(session);
|
||||
_boundSession = session;
|
||||
return binding;
|
||||
}
|
||||
|
||||
public void ResetSessionState() => _bindings.Reset();
|
||||
|
||||
public void ReportConnecting(string host, int port, string user) =>
|
||||
_bindings.Connecting(host, port, user);
|
||||
|
||||
public void ReportConnected() => _bindings.Connected();
|
||||
|
||||
public void ApplySelectedCharacter(LiveSessionCharacterSelection selection) =>
|
||||
_bindings.Selected(selection);
|
||||
|
||||
public void ApplyEnteredWorld(LiveSessionCharacterSelection selection) =>
|
||||
_bindings.Entered(selection);
|
||||
|
||||
public void DetachSession(WorldSession session)
|
||||
{
|
||||
if (!ReferenceEquals(_boundSession, session))
|
||||
throw new InvalidOperationException(
|
||||
"The live-session controller attempted to detach a session that is not bound.");
|
||||
_boundSession = null;
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue