Skip to content

Commit

Permalink
Merge branch 'Simple-Station:master' into descchange
Browse files Browse the repository at this point in the history
  • Loading branch information
SleepyScarecrow authored Aug 2, 2024
2 parents 8b06254 + 49c944d commit f127315
Show file tree
Hide file tree
Showing 276 changed files with 4,926 additions and 1,606 deletions.
21 changes: 7 additions & 14 deletions Content.Client/Administration/Systems/AdminSystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,9 @@ public sealed partial class AdminSystem : EntitySystem
{
public event Action<List<PlayerInfo>>? PlayerListChanged;

private Dictionary<NetUserId, PlayerInfo>? _playerList;
public IReadOnlyList<PlayerInfo> PlayerList
{
get
{
if (_playerList != null) return _playerList.Values.ToList();

return new List<PlayerInfo>();
}
}
public Dictionary<NetUserId, PlayerInfo> PlayerInfos = new();
public IReadOnlyList<PlayerInfo> PlayerList =>
PlayerInfos != null ? PlayerInfos.Values.ToList() : new List<PlayerInfo>();

public override void Initialize()
{
Expand All @@ -40,15 +33,15 @@ private void OnPlayerInfoChanged(PlayerInfoChangedEvent ev)
{
if(ev.PlayerInfo == null) return;

if (_playerList == null) _playerList = new();
if (PlayerInfos == null) PlayerInfos = new();

_playerList[ev.PlayerInfo.SessionId] = ev.PlayerInfo;
PlayerListChanged?.Invoke(_playerList.Values.ToList());
PlayerInfos[ev.PlayerInfo.SessionId] = ev.PlayerInfo;
PlayerListChanged?.Invoke(PlayerInfos.Values.ToList());
}

private void OnPlayerListChanged(FullPlayerListEvent msg)
{
_playerList = msg.PlayersInfo.ToDictionary(x => x.SessionId, x => x);
PlayerInfos = msg.PlayersInfo.ToDictionary(x => x.SessionId, x => x);
PlayerListChanged?.Invoke(msg.PlayersInfo);
}
}
Expand Down
11 changes: 9 additions & 2 deletions Content.Client/Administration/Systems/BwoinkSystem.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
#nullable enable
using Content.Client.UserInterface.Systems.Bwoink;
using Content.Shared.Administration;
using JetBrains.Annotations;
using Robust.Client.Audio;
using Robust.Shared.Network;
using Robust.Shared.Player;
using Robust.Shared.Timing;

namespace Content.Client.Administration.Systems
Expand All @@ -10,6 +13,8 @@ namespace Content.Client.Administration.Systems
public sealed class BwoinkSystem : SharedBwoinkSystem
{
[Dependency] private readonly IGameTiming _timing = default!;
[Dependency] private readonly AudioSystem _audio = default!;
[Dependency] private readonly AdminSystem _adminSystem = default!;

public event EventHandler<BwoinkTextMessage>? OnBwoinkTextMessageRecieved;
private (TimeSpan Timestamp, bool Typing) _lastTypingUpdateSent;
Expand All @@ -21,6 +26,10 @@ protected override void OnBwoinkTextMessage(BwoinkTextMessage message, EntitySes

public void Send(NetUserId channelId, string text, bool playSound)
{
var info = _adminSystem.PlayerInfos.GetValueOrDefault(channelId)?.Connected ?? true;
_audio.PlayGlobal(info ? AHelpUIController.AHelpSendSound : AHelpUIController.AHelpErrorSound,
Filter.Local(), false);

// Reuse the channel ID as the 'true sender'.
// Server will ignore this and if someone makes it not ignore this (which is bad, allows impersonation!!!), that will help.
RaiseNetworkEvent(new BwoinkTextMessage(channelId, channelId, text, playSound: playSound));
Expand All @@ -31,9 +40,7 @@ public void SendInputTextUpdated(NetUserId channel, bool typing)
{
if (_lastTypingUpdateSent.Typing == typing &&
_lastTypingUpdateSent.Timestamp + TimeSpan.FromSeconds(1) > _timing.RealTime)
{
return;
}

_lastTypingUpdateSent = (_timing.RealTime, typing);
RaiseNetworkEvent(new BwoinkClientTypingUpdated(channel, typing));
Expand Down
24 changes: 21 additions & 3 deletions Content.Client/LateJoin/LateJoinGui.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,13 @@
using Content.Client.GameTicking.Managers;
using Content.Client.UserInterface.Controls;
using Content.Client.Players.PlayTimeTracking;
using Content.Client.Preferences;
using Content.Shared.CCVar;
using Content.Shared.Customization.Systems;
using Content.Shared.Preferences;
using Content.Shared.Roles;
using Content.Shared.StatusIcon;
using Microsoft.Win32.SafeHandles;
using Robust.Client.Console;
using Robust.Client.GameObjects;
using Robust.Client.UserInterface;
Expand All @@ -26,12 +30,15 @@ public sealed class LateJoinGui : DefaultWindow
[Dependency] private readonly IConfigurationManager _configManager = default!;
[Dependency] private readonly IEntitySystemManager _entitySystem = default!;
[Dependency] private readonly JobRequirementsManager _jobRequirements = default!;
[Dependency] private readonly IEntityManager _entityManager = default!;
[Dependency] private readonly IClientPreferencesManager _prefs = default!;

public event Action<(NetEntity, string)> SelectedId;

private readonly ClientGameTicker _gameTicker;
private readonly SpriteSystem _sprites;
private readonly CrewManifestSystem _crewManifest;
private readonly CharacterRequirementsSystem _characterRequirements;

private readonly Dictionary<NetEntity, Dictionary<string, List<JobButton>>> _jobButtons = new();
private readonly Dictionary<NetEntity, Dictionary<string, BoxContainer>> _jobCategories = new();
Expand All @@ -46,6 +53,7 @@ public LateJoinGui()
_sprites = _entitySystem.GetEntitySystem<SpriteSystem>();
_crewManifest = _entitySystem.GetEntitySystem<CrewManifestSystem>();
_gameTicker = _entitySystem.GetEntitySystem<ClientGameTicker>();
_characterRequirements = _entitySystem.GetEntitySystem<CharacterRequirementsSystem>();

Title = Loc.GetString("late-join-gui-title");

Expand Down Expand Up @@ -254,14 +262,24 @@ private void RebuildUI()

jobButton.OnPressed += _ => SelectedId.Invoke((id, jobButton.JobId));

if (!_jobRequirements.IsAllowed(prototype, out var reason))
if (!_characterRequirements.CheckRequirementsValid(
prototype.Requirements ?? new(),
prototype,
(HumanoidCharacterProfile) (_prefs.Preferences?.SelectedCharacter
?? HumanoidCharacterProfile.DefaultWithSpecies()),
_jobRequirements.GetRawPlayTimeTrackers(),
_jobRequirements.IsWhitelisted(),
_entityManager,
_prototypeManager,
_configManager,
out var reasons))
{
jobButton.Disabled = true;

if (!reason.IsEmpty)
if (reasons.Count > 0)
{
var tooltip = new Tooltip();
tooltip.SetMessage(reason);
tooltip.SetMessage(_characterRequirements.GetRequirementsText(reasons));
jobButton.TooltipSupplier = _ => tooltip;
}

Expand Down
12 changes: 5 additions & 7 deletions Content.Client/Lobby/LobbyUIController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using Content.Client.Humanoid;
using Content.Client.Inventory;
using Content.Client.Lobby.UI;
using Content.Client.Players.PlayTimeTracking;
using Content.Client.Preferences;
using Content.Client.Preferences.UI;
using Content.Shared.Clothing.Loadouts.Systems;
Expand All @@ -23,6 +24,7 @@ public sealed class LobbyUIController : UIController, IOnStateEntered<LobbyState
[Dependency] private readonly IClientPreferencesManager _preferencesManager = default!;
[Dependency] private readonly IStateManager _stateManager = default!;
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
[Dependency] private readonly JobRequirementsManager _jobRequirements = default!;
[UISystemDependency] private readonly HumanoidAppearanceSystem _humanoid = default!;
[UISystemDependency] private readonly ClientInventorySystem _inventory = default!;
[UISystemDependency] private readonly LoadoutSystem _loadouts = default!;
Expand Down Expand Up @@ -123,7 +125,8 @@ public void UpdateCharacterUI()
if (ShowClothes)
GiveDummyJobClothes(_previewDummy.Value, GetPreferredJob(maybeProfile), maybeProfile);
if (ShowLoadouts)
GiveDummyLoadouts(_previewDummy.Value, GetPreferredJob(maybeProfile), maybeProfile);
_loadouts.ApplyCharacterLoadout(_previewDummy.Value, GetPreferredJob(maybeProfile), maybeProfile,
_jobRequirements.GetRawPlayTimeTrackers(), _jobRequirements.IsWhitelisted());
UpdateClothes = false;
}

Expand Down Expand Up @@ -170,12 +173,7 @@ public void GiveDummyJobClothesLoadout(EntityUid dummy, HumanoidCharacterProfile
{
var job = GetPreferredJob(profile);
GiveDummyJobClothes(dummy, job, profile);
GiveDummyLoadouts(dummy, job, profile);
}

public void GiveDummyLoadouts(EntityUid dummy, JobPrototype job, HumanoidCharacterProfile profile)
{
_loadouts.ApplyCharacterLoadout(dummy, job, profile);
_loadouts.ApplyCharacterLoadout(dummy, job, profile, _jobRequirements.GetRawPlayTimeTrackers(), _jobRequirements.IsWhitelisted());
}

/// <summary>
Expand Down
52 changes: 7 additions & 45 deletions Content.Client/Players/PlayTimeTracking/JobRequirementsManager.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System.Diagnostics.CodeAnalysis;
using Content.Shared.CCVar;
using Content.Shared.Customization.Systems;
using Content.Shared.Players;
using Content.Shared.Players.PlayTimeTracking;
using Content.Shared.Roles;
Expand All @@ -17,9 +18,6 @@ public sealed partial class JobRequirementsManager : ISharedPlaytimeManager
{
[Dependency] private readonly IBaseClient _client = default!;
[Dependency] private readonly IClientNetManager _net = default!;
[Dependency] private readonly IConfigurationManager _cfg = default!;
[Dependency] private readonly IEntityManager _entManager = default!;
[Dependency] private readonly IPlayerManager _playerManager = default!;
[Dependency] private readonly IPrototypeManager _prototypes = default!;

private readonly Dictionary<string, TimeSpan> _roles = new();
Expand Down Expand Up @@ -80,43 +78,6 @@ private void RxPlayTime(MsgPlayTime message)
Updated?.Invoke();
}

public bool IsAllowed(JobPrototype job, [NotNullWhen(false)] out FormattedMessage? reason)
{
reason = null;

if (_roleBans.Contains($"Job:{job.ID}"))
{
reason = FormattedMessage.FromUnformatted(Loc.GetString("role-ban"));
return false;
}

var player = _playerManager.LocalSession;
if (player == null)
return true;

return CheckRoleTime(job.Requirements, out reason);
}

public bool CheckRoleTime(HashSet<JobRequirement>? requirements, [NotNullWhen(false)] out FormattedMessage? reason, string? localePrefix = "role-timer-")
{
reason = null;

if (requirements == null || !_cfg.GetCVar(CCVars.GameRoleTimers))
return true;

var reasons = new List<string>();
foreach (var requirement in requirements)
{
if (JobRequirements.TryRequirementMet(requirement, _roles, out var jobReason, _entManager, _prototypes, _whitelisted, localePrefix))
continue;

reasons.Add(jobReason.ToMarkup());
}

reason = reasons.Count == 0 ? null : FormattedMessage.FromMarkup(string.Join('\n', reasons));
return reason == null;
}

public TimeSpan FetchOverallPlaytime()
{
return _roles.TryGetValue("Overall", out var overallPlaytime) ? overallPlaytime : TimeSpan.Zero;
Expand All @@ -137,12 +98,13 @@ public Dictionary<string, TimeSpan> FetchPlaytimeByRoles()

public Dictionary<string, TimeSpan> GetPlayTimes()
{
var dict = new Dictionary<string, TimeSpan>();

var dict = FetchPlaytimeByRoles();
dict.Add(PlayTimeTrackingShared.TrackerOverall, FetchOverallPlaytime());
foreach (var role in FetchPlaytimeByRoles())
dict.Add(role.Key, role.Value);

return dict;
}

public Dictionary<string, TimeSpan> GetRawPlayTimeTrackers()
{
return _roles;
}
}
26 changes: 23 additions & 3 deletions Content.Client/Preferences/UI/AntagPreferenceSelector.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
using Content.Client.Players.PlayTimeTracking;
using Content.Shared.Customization.Systems;
using Content.Shared.Preferences;
using Content.Shared.Roles;
using Robust.Shared.Configuration;
using Robust.Shared.Prototypes;

namespace Content.Client.Preferences.UI;

Expand All @@ -14,7 +18,7 @@ public bool Preference

public event Action<bool>? PreferenceChanged;

public AntagPreferenceSelector(AntagPrototype proto) : base(proto)
public AntagPreferenceSelector(AntagPrototype proto, JobPrototype highJob) : base(proto, highJob)
{
Options.OnItemSelected += _ => PreferenceChanged?.Invoke(Preference);

Expand All @@ -30,7 +34,23 @@ public AntagPreferenceSelector(AntagPrototype proto) : base(proto)
// Immediately lock requirements if they aren't met.
// Another function checks Disabled after creating the selector so this has to be done now
var requirements = IoCManager.Resolve<JobRequirementsManager>();
if (proto.Requirements != null && !requirements.CheckRoleTime(proto.Requirements, out var reason))
LockRequirements(reason);
var prefs = IoCManager.Resolve<IClientPreferencesManager>();
var entMan = IoCManager.Resolve<IEntityManager>();
var characterReqs = entMan.System<CharacterRequirementsSystem>();
var protoMan = IoCManager.Resolve<IPrototypeManager>();
var configMan = IoCManager.Resolve<IConfigurationManager>();

if (proto.Requirements != null
&& !characterReqs.CheckRequirementsValid(
proto.Requirements,
highJob,
(HumanoidCharacterProfile) (prefs.Preferences?.SelectedCharacter ?? HumanoidCharacterProfile.DefaultWithSpecies()),
requirements.GetRawPlayTimeTrackers(),
requirements.IsWhitelisted(),
entMan,
protoMan,
configMan,
out var reasons))
LockRequirements(characterReqs.GetRequirementsText(reasons));
}
}
Loading

0 comments on commit f127315

Please sign in to comment.