Make PvsSystem consider offset and zoom from EyeComponent (#5228)

* Make PvsSystem consider offset and zoom from EyeComponent

* Just use PvsScale float

* float.IsFinite

---------

Co-authored-by: geraeumig <alfenos@proton.me>
Co-authored-by: ElectroJr <leonsfriedrich@gmail.com>
This commit is contained in:
geraeumig
2024-06-28 06:24:22 +02:00
committed by GitHub
parent fe5cdf9e3c
commit c0ef976588
5 changed files with 51 additions and 9 deletions

View File

@@ -80,14 +80,17 @@ internal sealed partial class PvsSystem
// Update visibility masks & viewer positions
// TODO PVS do this before sending state.
// I,e, we already enumerate over all eyes when computing visible chunks.
Span<MapCoordinates> positions = stackalloc MapCoordinates[session.Viewers.Length];
Span<(MapCoordinates pos, float scale)> positions = stackalloc (MapCoordinates, float)[session.Viewers.Length];
int i = 0;
foreach (var viewer in session.Viewers)
{
if (viewer.Comp2 != null)
session.VisMask |= viewer.Comp2.VisibilityMask;
positions[i++] = _transform.GetMapCoordinates(viewer.Owner, viewer.Comp1);
var mapCoordinates = _transform.GetMapCoordinates(viewer.Owner, viewer.Comp1);
mapCoordinates = mapCoordinates.Offset(viewer.Comp2?.Offset ?? Vector2.Zero);
var scale = MathF.Max((viewer.Comp2?.PvsScale ?? 1), 0.1f);
positions[i++] = (mapCoordinates, scale);
}
if (!CullingEnabled || session.DisableCulling)
@@ -112,7 +115,7 @@ internal sealed partial class PvsSystem
DebugTools.Assert(!chunk.UpdateQueued);
DebugTools.Assert(!chunk.Dirty);
foreach (var pos in positions)
foreach (var (pos, scale) in positions)
{
if (pos.MapId != chunk.Position.MapId)
continue;
@@ -120,8 +123,9 @@ internal sealed partial class PvsSystem
dist = Math.Min(dist, (pos.Position - chunk.Position.Position).LengthSquared());
var relative = Vector2.Transform(pos.Position, chunk.InvWorldMatrix) - chunk.Centre;
relative = Vector2.Abs(relative);
chebDist = Math.Min(chebDist, Math.Max(relative.X, relative.Y));
chebDist = Math.Min(chebDist, Math.Max(relative.X, relative.Y) / scale);
}
distances.Add(dist);

View File

@@ -362,8 +362,19 @@ internal sealed partial class PvsSystem : EntitySystem
private (Vector2 worldPos, float range, EntityUid? map) CalcViewBounds(Entity<TransformComponent, EyeComponent?> eye)
{
var size = Math.Max(eye.Comp2?.PvsSize ?? _priorityViewSize, 1);
return (_transform.GetWorldPosition(eye.Comp1), size / 2f, eye.Comp1.MapUid);
var size = _priorityViewSize;
var worldPos = _transform.GetWorldPosition(eye.Comp1);
if (eye.Comp2 is not null)
{
// not using EyeComponent.Eye.Position, because it's updated only on the client's side
worldPos += eye.Comp2.Offset;
size *= eye.Comp2.PvsScale;
}
size = Math.Max(size, 1);
return (worldPos, size / 2f, eye.Comp1.MapUid);
}
private void CullDeletionHistoryUntil(GameTick tick)

View File

@@ -1,7 +1,6 @@
using System.Numerics;
using Robust.Shared.GameStates;
using Robust.Shared.Graphics;
using Robust.Shared.Map;
using Robust.Shared.Maths;
using Robust.Shared.Serialization.Manager.Attributes;
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom;
@@ -41,6 +40,9 @@ namespace Robust.Shared.GameObjects
[ViewVariables(VVAccess.ReadWrite), DataField("zoom")]
public Vector2 Zoom = Vector2.One;
/// <summary>
/// Eye offset, relative to the map, and not affected by <see cref="Rotation"/>
/// </summary>
[ViewVariables(VVAccess.ReadWrite), DataField("offset"), AutoNetworkedField]
public Vector2 Offset;
@@ -52,9 +54,13 @@ namespace Robust.Shared.GameObjects
public int VisibilityMask = DefaultVisibilityMask;
/// <summary>
/// Overrides the PVS view range of this eye, Effectively a per-eye <see cref="CVars.NetMaxUpdateRange"/> cvar.
/// Scaling factor for the PVS view range of this eye. This effectively allows the
/// <see cref="CVars.NetMaxUpdateRange"/> and <see cref="CVars.NetPvsPriorityRange"/> cvars to be configured per
/// eye.
/// </summary>
[DataField] public float? PvsSize;
[Access(typeof(SharedEyeSystem))]
[DataField]
public float PvsScale = 1;
}
/// <summary>

View File

@@ -1,3 +1,4 @@
using System;
using System.Numerics;
using Robust.Shared.IoC;
using Robust.Shared.Maths;
@@ -97,6 +98,23 @@ public abstract class SharedEyeSystem : EntitySystem
eyeComponent.Eye.Zoom = value;
}
public void SetPvsScale(Entity<EyeComponent?> eye, float scale)
{
if (!Resolve(eye.Owner, ref eye.Comp, false))
return;
// Prevent a admin or some other fuck-up from causing exception spam in PVS system due to divide-by-zero or
// other such issues
if (!float.IsFinite(scale))
{
Log.Error($"Attempted to set pvs scale to invalid value: {scale}. Eye: {ToPrettyString(eye)}");
SetPvsScale(eye, 1);
return;
}
eye.Comp.PvsScale = Math.Clamp(scale, 0.1f, 100f);
}
public void SetVisibilityMask(EntityUid uid, int value, EyeComponent? eyeComponent = null)
{
if (!Resolve(uid, ref eyeComponent))

View File

@@ -31,6 +31,9 @@ namespace Robust.Shared.Graphics
set => _coords = value;
}
/// <summary>
/// Eye offset, relative to the map, and not affected by <see cref="Rotation"/>
/// </summary>
[ViewVariables(VVAccess.ReadWrite)]
public Vector2 Offset { get; set; }