mirror of
https://github.com/space-wizards/RobustToolbox.git
synced 2026-09-01 17:47:24 +02:00
9cd8401cfb
Co-authored-by: deltanedas <@deltanedas:goida.zip> Co-authored-by: metalgearsloth <comedian_vs_clown@hotmail.com>
135 lines
4.9 KiB
C#
135 lines
4.9 KiB
C#
using System.Diagnostics.CodeAnalysis;
|
|
using Robust.Shared.Containers;
|
|
using Robust.Shared.GameObjects;
|
|
using Robust.Shared.GameStates;
|
|
using Robust.Shared.IoC;
|
|
|
|
namespace Robust.Server.GameObjects;
|
|
|
|
public sealed partial class PointLightSystem : SharedPointLightSystem
|
|
{
|
|
[Dependency] private readonly SharedContainerSystem _container = default!;
|
|
[Dependency] private MetaDataSystem _metadata = default!;
|
|
|
|
public override void Initialize()
|
|
{
|
|
base.Initialize();
|
|
SubscribeLocalEvent<PointLightComponent, ComponentGetState>(OnLightGetState);
|
|
//SubscribeLocalEvent<PointLightComponent, EntInsertedIntoContainerMessage>(OnInserted);
|
|
SubscribeLocalEvent<PointLightComponent, EntGotInsertedIntoContainerMessage>(OnInserted);
|
|
SubscribeLocalEvent<PointLightComponent, EntGotRemovedFromContainerMessage>(OnRemoved);
|
|
SubscribeLocalEvent<PointLightComponent, ComponentStartup>(OnLightStartup);
|
|
SubscribeLocalEvent<PointLightComponent, ComponentShutdown>(OnLightShutdown);
|
|
SubscribeLocalEvent<PointLightComponent, MetaFlagRemoveAttemptEvent>(OnFlagRemoveAttempt);
|
|
}
|
|
|
|
private void OnLightStartup(Entity<PointLightComponent> ent, ref ComponentStartup args)
|
|
{
|
|
UpdatePriority(ent.Owner, ent.Comp, MetaData(ent.Owner));
|
|
SetContainerOccluded(ent.Owner, IsCurrentContainerOrParentOccluder(ent.Owner), ent.Comp);
|
|
_lightTree.QueueTreeUpdate(ent.Owner, ent.Comp);
|
|
}
|
|
|
|
private void OnLightShutdown(Entity<PointLightComponent> ent, ref ComponentShutdown args)
|
|
{
|
|
UpdatePriority(ent.Owner, ent.Comp, MetaData(ent.Owner));
|
|
_lightTree.QueueTreeUpdate(ent.Owner, ent.Comp);
|
|
}
|
|
|
|
private void OnFlagRemoveAttempt(Entity<PointLightComponent> ent, ref MetaFlagRemoveAttemptEvent args)
|
|
{
|
|
if (IsHighPriority(ent.Comp))
|
|
args.ToRemove &= ~MetaDataFlags.PvsPriority;
|
|
}
|
|
|
|
|
|
private bool IsHighPriority(SharedPointLightComponent comp)
|
|
{
|
|
return comp is { Enabled: true, CastShadows: true, Radius: > 7, LifeStage: <= ComponentLifeStage.Running };
|
|
}
|
|
|
|
private void OnInserted(EntityUid uid, PointLightComponent component, EntGotInsertedIntoContainerMessage args)
|
|
{
|
|
SetContainerOccluded(uid, IsContainerOrParentOccluder(args.Container), component);
|
|
}
|
|
|
|
private void OnRemoved(EntityUid uid, PointLightComponent component, EntGotRemovedFromContainerMessage args)
|
|
{
|
|
SetContainerOccluded(uid, IsCurrentContainerOrParentOccluder(uid), component);
|
|
}
|
|
|
|
private void OnLightGetState(EntityUid uid, PointLightComponent component, ref ComponentGetState args)
|
|
{
|
|
args.State = new PointLightComponentState()
|
|
{
|
|
Color = component.Color,
|
|
Enabled = component.Enabled,
|
|
Energy = component.Energy,
|
|
Offset = component.Offset,
|
|
Radius = component.Radius,
|
|
Softness = component.Softness,
|
|
Falloff = component.Falloff,
|
|
CurveFactor = component.CurveFactor,
|
|
CastShadows = component.CastShadows,
|
|
ContainerOccluded = component.ContainerOccluded,
|
|
};
|
|
}
|
|
protected override void UpdatePriority(EntityUid uid, SharedPointLightComponent comp, MetaDataComponent meta)
|
|
{
|
|
_metadata.SetFlag((uid, meta), MetaDataFlags.PvsPriority, IsHighPriority(comp));
|
|
}
|
|
|
|
public override SharedPointLightComponent EnsureLight(EntityUid uid)
|
|
{
|
|
return EnsureComp<PointLightComponent>(uid);
|
|
}
|
|
|
|
public override bool ResolveLight(EntityUid uid, [NotNullWhen(true)] ref SharedPointLightComponent? component)
|
|
{
|
|
if (component is not null)
|
|
return true;
|
|
|
|
TryComp<PointLightComponent>(uid, out var comp);
|
|
component = comp;
|
|
return component != null;
|
|
}
|
|
|
|
public override bool TryGetLight(EntityUid uid, [NotNullWhen(true)] out SharedPointLightComponent? component)
|
|
{
|
|
if (TryComp<PointLightComponent>(uid, out var comp))
|
|
{
|
|
component = comp;
|
|
return true;
|
|
}
|
|
|
|
component = null;
|
|
return false;
|
|
}
|
|
|
|
public override bool RemoveLightDeferred(EntityUid uid)
|
|
{
|
|
return RemCompDeferred<PointLightComponent>(uid);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Recursively check if a container or any parent container occludes light.
|
|
/// This is probably a terribly unoptimized way to get the occlusion right
|
|
/// </summary>
|
|
/// <returns>True if any container should block light.</returns>
|
|
private bool IsContainerOrParentOccluder(BaseContainer container)
|
|
{
|
|
if (container.OccludesLight)
|
|
return true;
|
|
|
|
if (!_container.TryGetContainingContainer(container.Owner, out var nextContainer))
|
|
return false;
|
|
|
|
return IsContainerOrParentOccluder(nextContainer);
|
|
}
|
|
|
|
private bool IsCurrentContainerOrParentOccluder(EntityUid uid)
|
|
{
|
|
return _container.TryGetContainingContainer(uid, out var container) && IsContainerOrParentOccluder(container);
|
|
}
|
|
}
|