using Content.Server.Administration.Logs; using Content.Server.Mind; using Content.Server.Roles.Jobs; using Content.Shared.Database; using Content.Shared.Roles; using Robust.Shared.Prototypes; namespace Content.Server.Roles; public sealed class RoleSystem : EntitySystem { [Dependency] private readonly IAdminLogManager _adminLogger = default!; [Dependency] private readonly IPrototypeManager _prototypes = default!; [Dependency] private readonly MindSystem _minds = default!; // TODO please lord make role entities private readonly HashSet _antagTypes = new(); public override void Initialize() { // TODO make roles entities SubscribeLocalEvent(OnJobGetAllRoles); SubscribeAntagEvents(); SubscribeAntagEvents(); SubscribeAntagEvents(); SubscribeAntagEvents(); } private void OnJobGetAllRoles(EntityUid uid, JobComponent component, ref MindGetAllRolesEvent args) { var name = "game-ticker-unknown-role"; string? playTimeTracker = null; if (component.PrototypeId != null && _prototypes.TryIndex(component.PrototypeId, out JobPrototype? job)) { name = job.Name; playTimeTracker = job.PlayTimeTracker; } name = Loc.GetString(name); args.Roles.Add(new RoleInfo(component, name, false, playTimeTracker)); } private void SubscribeAntagEvents() where T : AntagonistRoleComponent { SubscribeLocalEvent((EntityUid _, T component, ref MindGetAllRolesEvent args) => { var name = "game-ticker-unknown-role"; if (component.PrototypeId != null && _prototypes.TryIndex(component.PrototypeId, out AntagPrototype? antag)) { name = antag.Name; } name = Loc.GetString(name); args.Roles.Add(new RoleInfo(component, name, true, null)); }); SubscribeLocalEvent((EntityUid _, T _, ref MindIsAntagonistEvent args) => args.IsAntagonist = true); _antagTypes.Add(typeof(T)); } /// /// Gives this mind a new role. /// /// The mind to add the role to. /// The role instance to add. /// The role type to add. /// Whether or not the role should be added silently /// The instance of the role. /// /// Thrown if we already have a role with this type. /// public void MindAddRole(EntityUid mindId, T component, MindComponent? mind = null, bool silent = false) where T : Component, new() { if (!Resolve(mindId, ref mind)) return; if (HasComp(mindId)) { throw new ArgumentException($"We already have this role: {typeof(T)}"); } AddComp(mindId, component); var antagonist = IsAntagonistRole(); var mindEv = new MindRoleAddedEvent(); RaiseLocalEvent(mindId, ref mindEv); var message = new RoleAddedEvent(mindId, mind, antagonist, silent); if (mind.OwnedEntity != null) { RaiseLocalEvent(mind.OwnedEntity.Value, message, true); } _adminLogger.Add(LogType.Mind, LogImpact.Low, $"'Role {typeof(T).Name}' added to mind of {_minds.MindOwnerLoggingString(mind)}"); } /// /// Removes a role from this mind. /// /// The mind to remove the role from. /// The type of the role to remove. /// /// Thrown if we do not have this role. /// public void MindRemoveRole(EntityUid mindId) where T : Component { if (!RemComp(mindId)) { throw new ArgumentException($"We do not have this role: {typeof(T)}"); } var mind = Comp(mindId); var antagonist = IsAntagonistRole(); var message = new RoleRemovedEvent(mindId, mind, antagonist); if (mind.OwnedEntity != null) { RaiseLocalEvent(mind.OwnedEntity.Value, message, true); } _adminLogger.Add(LogType.Mind, LogImpact.Low, $"'Role {typeof(T).Name}' removed from mind of {_minds.MindOwnerLoggingString(mind)}"); } public bool MindTryRemoveRole(EntityUid mindId) where T : Component { if (!MindHasRole(mindId)) return false; MindRemoveRole(mindId); return true; } public bool MindHasRole(EntityUid mindId) where T : Component { return HasComp(mindId); } public List MindGetAllRoles(EntityUid mindId) { var ev = new MindGetAllRolesEvent(new List()); RaiseLocalEvent(mindId, ref ev); return ev.Roles; } public bool MindIsAntagonist(EntityUid? mindId) { if (mindId == null) return false; var ev = new MindIsAntagonistEvent(); RaiseLocalEvent(mindId.Value, ref ev); return ev.IsAntagonist; } public string? MindGetBriefing(EntityUid? mindId) { // TODO this should be an event return CompOrNull(mindId)?.Briefing; } public bool IsAntagonistRole() { return _antagTypes.Contains(typeof(T)); } }