Files
RobustToolbox/Robust.Server/GameStates/PvsSystem.Leave.cs
Leon Friedrich 665294bee8 Rethrow more exceptions when EXCEPTION_TOLERANCE is false (#6238)
* Rethrow more exceptions when EXCEPTION_TOLERANCE is false

* A

* update test

* Revert "update test"

This reverts commit 37f4da67fc.

* actually we probably want to know if Deleting an exception throwing entity throws another exception
2025-10-20 20:51:24 +02:00

97 lines
2.8 KiB
C#

using System;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Threading;
using Prometheus;
using Robust.Shared.Enums;
using Robust.Shared.Log;
using Robust.Shared.Network.Messages;
using Robust.Shared.Player;
using Robust.Shared.Threading;
using Robust.Shared.Utility;
namespace Robust.Server.GameStates;
// Partial class for handling entities leaving a player's pvs range.
internal sealed partial class PvsSystem
{
private WaitHandle? _leaveTask;
private void ProcessLeavePvs()
{
if (!CullingEnabled || _sessions.Length == 0)
return;
DebugTools.AssertNull(_leaveTask);
if (_async)
{
_leaveTask = _parallelMgr.Process(_leaveJob, _leaveJob.Count);
return;
}
using var _ = Histogram.WithLabels("Process Leave").NewTimer();
_parallelMgr.ProcessNow(_leaveJob, _leaveJob.Count);
}
/// <summary>
/// Figure out what entities are no longer visible to the client. These entities are sent reliably to the client
/// in a separate net message. This has to be called after EntityData.LastSent is updated.
/// </summary>
private void ProcessLeavePvs(PvsSession session)
{
if (session.DisableCulling || session.Session.Status != SessionStatus.InGame)
return;
if (session.LastSent == null)
return;
var (toTick, lastSent) = session.LastSent.Value;
foreach (var intPtr in CollectionsMarshal.AsSpan(lastSent))
{
ref var data = ref session.DataMemory.GetRef(intPtr.Index);
if (data.LastSeen == toTick)
continue;
session.LeftView.Add(IndexToNetEntity(intPtr));
data.LastLeftView = toTick;
}
if (session.LeftView.Count == 0)
return;
var pvsMessage = new MsgStateLeavePvs {Entities = session.LeftView, Tick = toTick};
// PVS benchmarks use dummy sessions.
// ReSharper disable once ConditionIsAlwaysTrueOrFalseAccordingToNullableAPIContract
if (session.Session.Status == SessionStatus.InGame && session.Channel != null)
_netMan.ServerSendMessage(pvsMessage, session.Channel);
session.LeftView.Clear();
}
private record struct PvsLeaveJob(PvsSystem _pvs) : IParallelRobustJob
{
public int BatchSize => 2;
private PvsSystem _pvs = _pvs;
public int Count => _pvs._sessions.Length;
public void Execute(int index)
{
try
{
_pvs.ProcessLeavePvs(_pvs._sessions[index]);
}
catch (Exception e)
{
_pvs.Log.Log(LogLevel.Error, e, $"Caught exception while processing pvs-leave messages.");
#if !EXCEPTION_TOLERANCE
throw;
#endif
}
}
}
}