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; namespace Content.Server.NewPlayer; /// /// Used to set "new player" icons, and to manage the components to only have them visible to players with . /// public sealed partial class NewPlayerSystem : EntitySystem { [Dependency] private IConfigurationManager _config = default!; [Dependency] private PlayTimeTrackingManager _playtimeManager = default!; [Dependency] private WhitelistManager _whitelistManager = default!; [Dependency] private EntityQuery _showPlayerIconQuery = default!; private TimeSpan _newPlayerTimeTotal; /// public override void Initialize() { base.Initialize(); Subs.CVar(_config, CCVars.NewPlayerTimeTotalMinutes, v => _newPlayerTimeTotal = TimeSpan.FromMinutes(v), true); } [SubscribeLocalEvent] private void OnNewPlayerGetStateAttempt(Entity entity, ref ComponentGetStateAttemptEvent args) { args.Cancelled = !(args.Player?.AttachedEntity is not { } uid || _showPlayerIconQuery.HasComp(uid)); } /// /// 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. /// [SubscribeLocalEvent] private void OnComponentStartup(Entity entity, ref ComponentStartup args) { var newPlayerQuery = AllEntityQuery(); 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(ev.Mob); // Give the players who should have it try { var totalTime = _playtimeManager.GetOverallPlaytime(ev.Player); if (totalTime < _newPlayerTimeTotal) EnsureComp(ev.Mob); } catch (Exception e) { Log.Error($"Error getting new player playtime:\n{e}"); } } [SubscribeLocalEvent] private void OnPlayerAttachedEvent(Entity ent, ref PlayerAttachedEvent ev) { if (_whitelistManager.IsConnectedWhitelisted(ev.Player)) EnsureComp(ev.Entity); } }