fix(runtime): close Campaign LA7b review findings
This commit is contained in:
parent
0e82cbf700
commit
1b9e7e41f9
11 changed files with 700 additions and 28 deletions
|
|
@ -1125,11 +1125,12 @@ public sealed class WorldSession : IDisposable
|
|||
{
|
||||
var opcodes = new List<uint>();
|
||||
ProcessDatagram(datagram.Memory, opcodes);
|
||||
SweepTransport();
|
||||
return opcodes.Contains(0xF7DFu)
|
||||
|| _lastCharacterSelectionError is not null;
|
||||
},
|
||||
ReturnInboundDatagram);
|
||||
ReturnInboundDatagram,
|
||||
SweepTransport,
|
||||
TimeSpan.FromMilliseconds(25));
|
||||
}
|
||||
if (_lastCharacterSelectionError is { } selectionError)
|
||||
{
|
||||
|
|
@ -1817,6 +1818,12 @@ public sealed class WorldSession : IDisposable
|
|||
{
|
||||
continue;
|
||||
}
|
||||
// CharacterError::NumErrors is the enum-count sentinel, not
|
||||
// a server rejection. Retail never presents it, and treating
|
||||
// it as an EnterWorld failure would abort either handshake
|
||||
// pump before a valid ServerReady later in the same packet.
|
||||
if (parsed.AsCode == CharacterError.Code.NumErrors)
|
||||
continue;
|
||||
_lastCharacterSelectionError = parsed;
|
||||
CharacterErrorReceived?.Invoke(parsed);
|
||||
}
|
||||
|
|
@ -3339,10 +3346,15 @@ public sealed class WorldSession : IDisposable
|
|||
ChannelReader<T> reader,
|
||||
TimeSpan timeout,
|
||||
Func<T, bool> processAndCheckConfirmation,
|
||||
Action<T>? release = null)
|
||||
Action<T>? release = null,
|
||||
Action? periodicWork = null,
|
||||
TimeSpan? periodicInterval = null)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(reader);
|
||||
ArgumentNullException.ThrowIfNull(processAndCheckConfirmation);
|
||||
TimeSpan cadence = periodicInterval ?? TimeSpan.FromMilliseconds(25);
|
||||
if (periodicWork is not null && cadence <= TimeSpan.Zero)
|
||||
throw new ArgumentOutOfRangeException(nameof(periodicInterval));
|
||||
using var timeoutSource = new CancellationTokenSource(timeout);
|
||||
|
||||
// The deadline is also read straight off the monotonic clock, not only
|
||||
|
|
@ -3382,10 +3394,52 @@ public sealed class WorldSession : IDisposable
|
|||
return true;
|
||||
}
|
||||
|
||||
bool canRead = reader.WaitToReadAsync(timeoutSource.Token)
|
||||
.AsTask()
|
||||
.GetAwaiter()
|
||||
.GetResult();
|
||||
periodicWork?.Invoke();
|
||||
if (timeoutSource.IsCancellationRequested || Expired())
|
||||
return false;
|
||||
|
||||
bool canRead;
|
||||
if (periodicWork is null)
|
||||
{
|
||||
canRead = reader.WaitToReadAsync(timeoutSource.Token)
|
||||
.AsTask()
|
||||
.GetAwaiter()
|
||||
.GetResult();
|
||||
}
|
||||
else
|
||||
{
|
||||
TimeSpan wait = cadence;
|
||||
if (bounded)
|
||||
{
|
||||
TimeSpan remaining = timeout
|
||||
- Stopwatch.GetElapsedTime(started);
|
||||
if (remaining <= TimeSpan.Zero)
|
||||
return false;
|
||||
if (remaining < wait)
|
||||
wait = remaining;
|
||||
}
|
||||
|
||||
using var sliceSource =
|
||||
CancellationTokenSource.CreateLinkedTokenSource(
|
||||
timeoutSource.Token);
|
||||
sliceSource.CancelAfter(wait);
|
||||
try
|
||||
{
|
||||
canRead = reader.WaitToReadAsync(sliceSource.Token)
|
||||
.AsTask()
|
||||
.GetAwaiter()
|
||||
.GetResult();
|
||||
}
|
||||
catch (OperationCanceledException)
|
||||
when (!timeoutSource.IsCancellationRequested
|
||||
&& !Expired())
|
||||
{
|
||||
// This cadence is the paused selector's frame edge:
|
||||
// keep reliable transport work moving even when no
|
||||
// datagram arrives to wake the inbound queue.
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (!canRead)
|
||||
return false;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue