CatStation/Content.Server/NewPlayer/NewPlayerSystem.cs
2026-09-30 14:30:21 +07:00

86 lines
3.4 KiB
C#

using Content.Server.Database;
using Content.Server.Players.PlayTimeTracking;
using Content.Server.Players.Whitelist;
using Content.Shared.CCVar;
using Content.Shared.NewPlayer;
using Content.Shared.GameTicking;
using Content.Shared.Ghost.Components;
using Robust.Shared.Configuration;
using Robust.Shared.GameStates;
using Robust.Shared.Player;
using Content.Server.Corvax.Ghost;
namespace Content.Server.NewPlayer;
/// <summary>
/// Used to set "new player" icons, and to manage the components to only have them visible to players with <see cref="ShowNewPlayerIconComponent"/>.
/// </summary>
public sealed partial class NewPlayerSystem : EntitySystem
{
[Dependency] private IConfigurationManager _config = default!;
[Dependency] private PlayTimeTrackingManager _playtimeManager = default!;
[Dependency] private WhitelistManager _whitelistManager = default!;
[Dependency] private GhostGoLobbySystem _ghostGoLobby = default!;//corvax
[Dependency] private EntityQuery<ShowNewPlayerIconComponent> _showPlayerIconQuery = default!;
private TimeSpan _newPlayerTimeTotal;
/// <inheritdoc />
public override void Initialize()
{
base.Initialize();
Subs.CVar(_config, CCVars.NewPlayerTimeTotalMinutes, v => _newPlayerTimeTotal = TimeSpan.FromMinutes(v), true);
}
[SubscribeLocalEvent]
private void OnNewPlayerGetStateAttempt(Entity<NewPlayerIconComponent> entity, ref ComponentGetStateAttemptEvent args)
{
args.Cancelled = !(args.Player?.AttachedEntity is not { } uid || _showPlayerIconQuery.HasComp(uid));
}
/// <summary>
/// This is a bit of a "hack" to ensure that the component states are properly updated in the event a component
/// is removed out of when the client isn't here to receive it. It's taken from how SharedRevolutionarySystem does it.
/// TODO: It's not ideal, and preferably we'd have a more solid way to handle specific session component handling.
/// </summary>
[SubscribeLocalEvent]
private void OnComponentStartup(Entity<ShowNewPlayerIconComponent> entity, ref ComponentStartup args)
{
var newPlayerQuery = AllEntityQuery<NewPlayerIconComponent>();
while (newPlayerQuery.MoveNext(out var uid, out var comp))
{
Dirty(uid, comp);
}
}
[SubscribeLocalEvent]
private void OnPlayerSpawnComplete(PlayerSpawnCompleteEvent ev)
{
// Give to players who should see
if (_whitelistManager.IsConnectedWhitelisted(ev.Player)) // TODO: This should use permissions from a Mentor group or similar, as this only checks manual whitelisting.
EnsureComp<ShowNewPlayerIconComponent>(ev.Mob);
// Give the players who should have it
try
{
var totalTime = _playtimeManager.GetOverallPlaytime(ev.Player);
if (totalTime < _newPlayerTimeTotal)
EnsureComp<NewPlayerIconComponent>(ev.Mob);
}
catch (Exception e)
{
Log.Error($"Error getting new player playtime:\n{e}");
}
}
[SubscribeLocalEvent]
private void OnPlayerAttachedEvent(Entity<GhostComponent> ent, ref PlayerAttachedEvent ev)
{
_ghostGoLobby.OnGhostAttached(ent, ev);// corvax - перенёс сюда ивент из GhostGoLobbySystem по причине дублирования подписки
if (_whitelistManager.IsConnectedWhitelisted(ev.Player))
EnsureComp<ShowNewPlayerIconComponent>(ev.Entity);
}
}