diff --git a/Content.Client/CharacterInfo/Components/CharacterInfoComponent.cs b/Content.Client/CharacterInfo/Components/CharacterInfoComponent.cs index 992e3f4daf..37d0420341 100644 --- a/Content.Client/CharacterInfo/Components/CharacterInfoComponent.cs +++ b/Content.Client/CharacterInfo/Components/CharacterInfoComponent.cs @@ -1,67 +1,31 @@ -using System; using Content.Client.CharacterInterface; using Content.Client.HUD.UI; using Content.Client.Stylesheets; -using Content.Shared.CharacterInfo; -using Robust.Client.GameObjects; -using Robust.Client.ResourceManagement; using Robust.Client.UserInterface; using Robust.Client.UserInterface.Controls; -using Robust.Client.Utility; using Robust.Shared.GameObjects; using Robust.Shared.IoC; using Robust.Shared.Localization; using Robust.Shared.Maths; -using Robust.Shared.Network; -using Robust.Shared.Players; namespace Content.Client.CharacterInfo.Components { [RegisterComponent] - public sealed class CharacterInfoComponent : SharedCharacterInfoComponent, ICharacterUI + public sealed class CharacterInfoComponent : Component, ICharacterUI { - [Dependency] private readonly IResourceCache _resourceCache = default!; + public override string Name => "CharacterInfo"; - private CharacterInfoControl _control = default!; + public CharacterInfoControl Control = default!; - public Control Scene { get; private set; } = default!; + public Control Scene { get; set; } = default!; public UIPriority Priority => UIPriority.Info; - protected override void OnAdd() - { - base.OnAdd(); - - Scene = _control = new CharacterInfoControl(_resourceCache); - } - public void Opened() { -#pragma warning disable 618 - SendNetworkMessage(new RequestCharacterInfoMessage()); -#pragma warning restore 618 + EntitySystem.Get().RequestCharacterInfo(Owner); } - [Obsolete("Component Messages are deprecated, use Entity Events instead.")] - public override void HandleNetworkMessage(ComponentMessage message, INetChannel netChannel, ICommonSession? session = null) - { - base.HandleNetworkMessage(message, netChannel, session); - - switch (message) - { - case CharacterInfoMessage characterInfoMessage: - _control.UpdateUI(characterInfoMessage); - var entityManager = IoCManager.Resolve(); - if (entityManager.TryGetComponent(Owner, out ISpriteComponent? spriteComponent)) - { - _control.SpriteView.Sprite = spriteComponent; - } - - _control.NameLabel.Text = entityManager.GetComponent(Owner).EntityName; - break; - } - } - - private sealed class CharacterInfoControl : BoxContainer + public sealed class CharacterInfoControl : BoxContainer { public SpriteView SpriteView { get; } public Label NameLabel { get; } @@ -69,7 +33,7 @@ namespace Content.Client.CharacterInfo.Components public BoxContainer ObjectivesContainer { get; } - public CharacterInfoControl(IResourceCache resourceCache) + public CharacterInfoControl() { IoCManager.InjectDependencies(this); @@ -91,7 +55,7 @@ namespace Content.Client.CharacterInfo.Components (SubText = new Label { VerticalAlignment = VAlignment.Top, - StyleClasses = {StyleNano.StyleClassLabelSubText}, + StyleClasses = {StyleBase.StyleClassLabelSubText}, }) } @@ -115,57 +79,6 @@ namespace Content.Client.CharacterInfo.Components PlaceholderText = Loc.GetString("character-info-roles-antagonist-text") }); } - - public void UpdateUI(CharacterInfoMessage characterInfoMessage) - { - SubText.Text = characterInfoMessage.JobTitle; - - ObjectivesContainer.RemoveAllChildren(); - foreach (var (groupId, objectiveConditions) in characterInfoMessage.Objectives) - { - var vbox = new BoxContainer - { - Orientation = LayoutOrientation.Vertical, - Modulate = Color.Gray - }; - - vbox.AddChild(new Label - { - Text = groupId, - Modulate = Color.LightSkyBlue - }); - - foreach (var objectiveCondition in objectiveConditions) - { - var hbox = new BoxContainer - { - Orientation = LayoutOrientation.Horizontal - }; - hbox.AddChild(new ProgressTextureRect - { - Texture = objectiveCondition.SpriteSpecifier.Frame0(), - Progress = objectiveCondition.Progress, - VerticalAlignment = VAlignment.Center - }); - hbox.AddChild(new Control - { - MinSize = (10,0) - }); - hbox.AddChild(new BoxContainer - { - Orientation = LayoutOrientation.Vertical, - Children = - { - new Label{Text = objectiveCondition.Title}, - new Label{Text = objectiveCondition.Description} - } - } - ); - vbox.AddChild(hbox); - } - ObjectivesContainer.AddChild(vbox); - } - } } } } diff --git a/Content.Client/CharacterInfo/Components/CharacterInfoSystem.cs b/Content.Client/CharacterInfo/Components/CharacterInfoSystem.cs new file mode 100644 index 0000000000..b1f6b8c98b --- /dev/null +++ b/Content.Client/CharacterInfo/Components/CharacterInfoSystem.cs @@ -0,0 +1,99 @@ +using System.Collections.Generic; +using Content.Shared.CharacterInfo; +using Content.Shared.Objectives; +using Robust.Client.GameObjects; +using Robust.Client.UserInterface; +using Robust.Client.UserInterface.Controls; +using Robust.Client.Utility; +using Robust.Shared.GameObjects; +using Robust.Shared.Maths; + +namespace Content.Client.CharacterInfo.Components; + +public class CharacterInfoSystem : EntitySystem +{ + public override void Initialize() + { + base.Initialize(); + + SubscribeNetworkEvent(OnCharacterInfoEvent); + SubscribeLocalEvent(OnComponentAdd); + } + + private void OnComponentAdd(EntityUid uid, CharacterInfoComponent component, ComponentAdd args) + { + component.Scene = component.Control = new CharacterInfoComponent.CharacterInfoControl(); + } + + public void RequestCharacterInfo(EntityUid entityUid) + { + RaiseNetworkEvent(new RequestCharacterInfoEvent(entityUid)); + } + + private void OnCharacterInfoEvent(CharacterInfoEvent msg, EntitySessionEventArgs args) + { + if (!EntityManager.TryGetComponent(msg.EntityUid, out CharacterInfoComponent characterInfoComponent)) + return; + + UpdateUI(characterInfoComponent, msg.JobTitle, msg.Objectives); + if (EntityManager.TryGetComponent(msg.EntityUid, out ISpriteComponent? spriteComponent)) + { + characterInfoComponent.Control.SpriteView.Sprite = spriteComponent; + } + + if (!EntityManager.TryGetComponent(msg.EntityUid, out MetaDataComponent metadata)) + return; + characterInfoComponent.Control.NameLabel.Text = metadata.EntityName; + } + + private void UpdateUI(CharacterInfoComponent comp, string jobTitle, Dictionary> objectives) + { + comp.Control.SubText.Text = jobTitle; + + comp.Control.ObjectivesContainer.RemoveAllChildren(); + foreach (var (groupId, objectiveConditions) in objectives) + { + var vbox = new BoxContainer + { + Orientation = BoxContainer.LayoutOrientation.Vertical, + Modulate = Color.Gray + }; + + vbox.AddChild(new Label + { + Text = groupId, + Modulate = Color.LightSkyBlue + }); + + foreach (var objectiveCondition in objectiveConditions) + { + var hbox = new BoxContainer + { + Orientation = BoxContainer.LayoutOrientation.Horizontal + }; + hbox.AddChild(new ProgressTextureRect + { + Texture = objectiveCondition.SpriteSpecifier.Frame0(), + Progress = objectiveCondition.Progress, + VerticalAlignment = Control.VAlignment.Center + }); + hbox.AddChild(new Control + { + MinSize = (10,0) + }); + hbox.AddChild(new BoxContainer + { + Orientation = BoxContainer.LayoutOrientation.Vertical, + Children = + { + new Label{Text = objectiveCondition.Title}, + new Label{Text = objectiveCondition.Description} + } + } + ); + vbox.AddChild(hbox); + } + comp.Control.ObjectivesContainer.AddChild(vbox); + } + } +} diff --git a/Content.Client/CharacterInterface/CharacterInterfaceComponent.cs b/Content.Client/CharacterInterface/CharacterInterfaceComponent.cs index ee944c0224..5c433b2123 100644 --- a/Content.Client/CharacterInterface/CharacterInterfaceComponent.cs +++ b/Content.Client/CharacterInterface/CharacterInterfaceComponent.cs @@ -1,14 +1,8 @@ using System.Collections.Generic; -using System.Linq; using Content.Client.CharacterInfo.Components; -using Content.Client.HUD; -using Content.Shared.Input; -using Robust.Client.GameObjects; -using Robust.Client.Input; using Robust.Client.UserInterface.Controls; using Robust.Client.UserInterface.CustomControls; using Robust.Shared.GameObjects; -using Robust.Shared.IoC; using static Robust.Client.UserInterface.Controls.BoxContainer; namespace Content.Client.CharacterInterface @@ -20,8 +14,6 @@ namespace Content.Client.CharacterInterface [RegisterComponent] public class CharacterInterfaceComponent : Component { - [Dependency] private readonly IGameHud _gameHud = default!; - public override string Name => "Character Interface Component"; /// @@ -30,104 +22,31 @@ namespace Content.Client.CharacterInterface /// /// Null if it would otherwise be empty. /// - public CharacterWindow? Window { get; private set; } + public CharacterWindow? Window { get; set; } - private List? _uiComponents; - - /// - /// Create the window with all character UIs and bind it to a keypress - /// - protected override void Initialize() - { - base.Initialize(); - - //Use all the character ui interfaced components to create the character window - _uiComponents = IoCManager.Resolve().GetComponents(Owner).ToList(); - if (_uiComponents.Count == 0) - { - return; - } - - Window = new CharacterWindow(_uiComponents); - Window.OnClose += () => _gameHud.CharacterButtonDown = false; - } - - /// - /// Dispose of window and the keypress binding - /// - protected override void OnRemove() - { - base.OnRemove(); - - if (_uiComponents != null) - { - foreach (var component in _uiComponents) - { - // Make sure these don't get deleted when the window is disposed. - component.Scene.Orphan(); - } - } - - _uiComponents = null; - - Window?.Close(); - Window = null; - - var inputMgr = IoCManager.Resolve(); - inputMgr.SetInputCommand(ContentKeyFunctions.OpenCharacterMenu, null); - } - - public void PlayerDetached() - { - if (Window != null) - { - _gameHud.CharacterButtonVisible = false; - Window.Close(); - } - } - - public void PlayerAttached() - { - if (Window != null) - { - _gameHud.CharacterButtonVisible = true; - - _gameHud.CharacterButtonToggled = b => - { - if (b) - { - Window.OpenCentered(); - } - else - { - Window.Close(); - } - }; - } - } + public List? UIComponents; /// /// A window that collects and shows all the individual character user interfaces /// public class CharacterWindow : SS14Window { - private readonly BoxContainer _contentsVBox; private readonly List _windowComponents; public CharacterWindow(List windowComponents) { Title = "Character"; - _contentsVBox = new BoxContainer + var contentsVBox = new BoxContainer { Orientation = LayoutOrientation.Vertical }; - Contents.AddChild(_contentsVBox); + Contents.AddChild(contentsVBox); windowComponents.Sort((a, b) => ((int) a.Priority).CompareTo((int) b.Priority)); foreach (var element in windowComponents) { - _contentsVBox.AddChild(element.Scene); + contentsVBox.AddChild(element.Scene); } _windowComponents = windowComponents; diff --git a/Content.Client/CharacterInterface/CharacterInterfaceSystem.cs b/Content.Client/CharacterInterface/CharacterInterfaceSystem.cs index fdc533ed56..b92a2c15fa 100644 --- a/Content.Client/CharacterInterface/CharacterInterfaceSystem.cs +++ b/Content.Client/CharacterInterface/CharacterInterfaceSystem.cs @@ -1,7 +1,10 @@ +using System.Linq; +using Content.Client.CharacterInfo.Components; using Content.Client.HUD; using Content.Shared.Input; using JetBrains.Annotations; using Robust.Client.GameObjects; +using Robust.Client.Input; using Robust.Client.Player; using Robust.Client.UserInterface.CustomControls; using Robust.Shared.GameObjects; @@ -15,6 +18,7 @@ namespace Content.Client.CharacterInterface { [Dependency] private readonly IGameHud _gameHud = default!; [Dependency] private readonly IPlayerManager _playerManager = default!; + [Dependency] private readonly IInputManager _inputManager = default!; public override void Initialize() { @@ -22,11 +26,13 @@ namespace Content.Client.CharacterInterface CommandBinds.Builder .Bind(ContentKeyFunctions.OpenCharacterMenu, - InputCmdHandler.FromDelegate(s => HandleOpenCharacterMenu())) + InputCmdHandler.FromDelegate(_ => HandleOpenCharacterMenu())) .Register(); - SubscribeLocalEvent((_, component, _) => component.PlayerAttached()); - SubscribeLocalEvent((_, component, _) => component.PlayerDetached()); + SubscribeLocalEvent(OnComponentInit); + SubscribeLocalEvent(OnComponentRemove); + SubscribeLocalEvent(OnPlayerAttached); + SubscribeLocalEvent(OnPlayerDetached); } public override void Shutdown() @@ -35,30 +41,76 @@ namespace Content.Client.CharacterInterface base.Shutdown(); } + private void OnComponentInit(EntityUid uid, CharacterInterfaceComponent comp, ComponentInit args) + { + //Use all the character ui interfaced components to create the character window + comp.UIComponents = EntityManager.GetComponents(uid).ToList(); + if (comp.UIComponents.Count == 0) + return; + + comp.Window = new CharacterInterfaceComponent.CharacterWindow(comp.UIComponents); + comp.Window.OnClose += () => _gameHud.CharacterButtonDown = false; + } + + private void OnComponentRemove(EntityUid uid, CharacterInterfaceComponent comp, ComponentRemove args) + { + if (comp.UIComponents != null) + { + foreach (var component in comp.UIComponents) + { + // Make sure these don't get deleted when the window is disposed. + component.Scene.Orphan(); + } + } + + comp.UIComponents = null; + + comp.Window?.Close(); + comp.Window = null; + + _inputManager.SetInputCommand(ContentKeyFunctions.OpenCharacterMenu, null); + } + + private void OnPlayerAttached(EntityUid uid, CharacterInterfaceComponent comp, PlayerAttachedEvent args) + { + if (comp.Window == null) + return; + + _gameHud.CharacterButtonVisible = true; + _gameHud.CharacterButtonToggled = b => + { + if (b) + comp.Window.OpenCentered(); + else + comp.Window.Close(); + }; + } + + private void OnPlayerDetached(EntityUid uid, CharacterInterfaceComponent comp, PlayerDetachedEvent args) + { + if (comp.Window == null) + return; + + _gameHud.CharacterButtonVisible = false; + comp.Window.Close(); + } + private void HandleOpenCharacterMenu() { - if (!EntityManager.TryGetComponent(_playerManager.LocalPlayer?.ControlledEntity, out CharacterInterfaceComponent? characterInterface)) - { + if (_playerManager.LocalPlayer?.ControlledEntity == null + || !EntityManager.TryGetComponent(_playerManager.LocalPlayer.ControlledEntity, out CharacterInterfaceComponent? characterInterface)) return; - } var menu = characterInterface.Window; - if (menu == null) - { return; - } if (menu.IsOpen) { if (menu.IsAtFront()) - { _setOpenValue(menu, false); - } else - { menu.MoveToFront(); - } } else { @@ -68,16 +120,11 @@ namespace Content.Client.CharacterInterface private void _setOpenValue(SS14Window menu, bool value) { + _gameHud.CharacterButtonDown = value; if (value) - { - _gameHud.CharacterButtonDown = true; menu.OpenCentered(); - } else - { - _gameHud.CharacterButtonDown = false; menu.Close(); - } } } } diff --git a/Content.Server/CharacterInfo/CharacterInfoComponent.cs b/Content.Server/CharacterInfo/CharacterInfoComponent.cs deleted file mode 100644 index 160724ab99..0000000000 --- a/Content.Server/CharacterInfo/CharacterInfoComponent.cs +++ /dev/null @@ -1,63 +0,0 @@ -using System; -using System.Collections.Generic; -using Content.Server.Mind.Components; -using Content.Server.Roles; -using Content.Shared.CharacterInfo; -using Content.Shared.Objectives; -using Robust.Shared.GameObjects; -using Robust.Shared.IoC; -using Robust.Shared.Network; -using Robust.Shared.Players; - -namespace Content.Server.CharacterInfo -{ - [RegisterComponent] - public class CharacterInfoComponent : SharedCharacterInfoComponent - { - [Obsolete("Component Messages are deprecated, use Entity Events instead.")] - public override void HandleNetworkMessage(ComponentMessage message, INetChannel netChannel, ICommonSession? session = null) - { - if(session?.AttachedEntity != Owner) return; - - switch (message) - { - case RequestCharacterInfoMessage _: - var conditions = new Dictionary>(); - var jobTitle = "No Profession"; - if (IoCManager.Resolve().TryGetComponent(Owner, out MindComponent? mindComponent)) - { - var mind = mindComponent.Mind; - - if (mind != null) - { - // getting conditions - foreach (var objective in mind.AllObjectives) - { - if (!conditions.ContainsKey(objective.Prototype.Issuer)) - conditions[objective.Prototype.Issuer] = new List(); - foreach (var condition in objective.Conditions) - { - conditions[objective.Prototype.Issuer].Add(new ConditionInfo(condition.Title, - condition.Description, condition.Icon, condition.Progress)); - } - } - - // getting jobtitle - foreach (var role in mind.AllRoles) - { - if (role.GetType() == typeof(Job)) - { - jobTitle = role.Name; - break; - } - } - } - } -#pragma warning disable 618 - SendNetworkMessage(new CharacterInfoMessage(jobTitle, conditions)); -#pragma warning restore 618 - break; - } - } - } -} diff --git a/Content.Server/CharacterInfo/CharacterInfoSystem.cs b/Content.Server/CharacterInfo/CharacterInfoSystem.cs new file mode 100644 index 0000000000..a8047d8792 --- /dev/null +++ b/Content.Server/CharacterInfo/CharacterInfoSystem.cs @@ -0,0 +1,59 @@ +using System.Collections.Generic; +using Content.Server.Mind.Components; +using Content.Server.Roles; +using Content.Shared.CharacterInfo; +using Content.Shared.Objectives; +using Robust.Shared.GameObjects; +using Robust.Shared.Player; + +namespace Content.Server.CharacterInfo; + +public class CharacterInfoSystem : EntitySystem +{ + public override void Initialize() + { + base.Initialize(); + + SubscribeNetworkEvent(OnRequestCharacterInfoEvent); + } + + private void OnRequestCharacterInfoEvent(RequestCharacterInfoEvent msg, EntitySessionEventArgs args) + { + if (!args.SenderSession.AttachedEntity.HasValue + || args.SenderSession.AttachedEntity != msg.EntityUid) + return; + + var entity = args.SenderSession.AttachedEntity.Value; + + var conditions = new Dictionary>(); + var jobTitle = "No Profession"; + if (EntityManager.TryGetComponent(entity, out MindComponent? mindComponent) && mindComponent.Mind != null) + { + var mind = mindComponent.Mind; + + // Get objectives + foreach (var objective in mind.AllObjectives) + { + if (!conditions.ContainsKey(objective.Prototype.Issuer)) + conditions[objective.Prototype.Issuer] = new List(); + foreach (var condition in objective.Conditions) + { + conditions[objective.Prototype.Issuer].Add(new ConditionInfo(condition.Title, + condition.Description, condition.Icon, condition.Progress)); + } + } + + // Get job title + foreach (var role in mind.AllRoles) + { + if (role.GetType() != typeof(Job)) continue; + + jobTitle = role.Name; + break; + } + } + + RaiseNetworkEvent(new CharacterInfoEvent(entity, jobTitle, conditions), + Filter.SinglePlayer(args.SenderSession)); + } +} diff --git a/Content.Server/Entry/IgnoredComponents.cs b/Content.Server/Entry/IgnoredComponents.cs index 0670b50806..7ed312385c 100644 --- a/Content.Server/Entry/IgnoredComponents.cs +++ b/Content.Server/Entry/IgnoredComponents.cs @@ -17,7 +17,8 @@ namespace Content.Server.Entry "RadiatingLight", "Icon", "ClientEntitySpawner", - "ToySingularity" + "ToySingularity", + "CharacterInfo" }; } } diff --git a/Content.Shared/CharacterInfo/SharedCharacterInfoComponent.cs b/Content.Shared/CharacterInfo/SharedCharacterInfoComponent.cs deleted file mode 100644 index d896245178..0000000000 --- a/Content.Shared/CharacterInfo/SharedCharacterInfoComponent.cs +++ /dev/null @@ -1,42 +0,0 @@ -using System; -using System.Collections.Generic; -using Content.Shared.Objectives; -using Robust.Shared.GameObjects; -using Robust.Shared.GameStates; -using Robust.Shared.Serialization; - -namespace Content.Shared.CharacterInfo -{ - [NetworkedComponent()] - public class SharedCharacterInfoComponent : Component - { - public override string Name => "CharacterInfo"; - - [Serializable, NetSerializable] -#pragma warning disable 618 - protected class RequestCharacterInfoMessage : ComponentMessage -#pragma warning restore 618 - { - public RequestCharacterInfoMessage() - { - Directed = true; - } - } - - [Serializable, NetSerializable] -#pragma warning disable 618 - protected class CharacterInfoMessage : ComponentMessage -#pragma warning restore 618 - { - public readonly Dictionary> Objectives; - public readonly string JobTitle; - - public CharacterInfoMessage(string jobTitle, Dictionary> objectives) - { - Directed = true; - JobTitle = jobTitle; - Objectives = objectives; - } - } - } -} diff --git a/Content.Shared/CharacterInfo/SharedCharacterInfoSystem.cs b/Content.Shared/CharacterInfo/SharedCharacterInfoSystem.cs new file mode 100644 index 0000000000..d887c6ac22 --- /dev/null +++ b/Content.Shared/CharacterInfo/SharedCharacterInfoSystem.cs @@ -0,0 +1,33 @@ +using System; +using System.Collections.Generic; +using Content.Shared.Objectives; +using Robust.Shared.GameObjects; +using Robust.Shared.Serialization; + +namespace Content.Shared.CharacterInfo; + +[Serializable, NetSerializable] +public class RequestCharacterInfoEvent : EntityEventArgs +{ + public readonly EntityUid EntityUid; + + public RequestCharacterInfoEvent(EntityUid entityUid) + { + EntityUid = entityUid; + } +} + +[Serializable, NetSerializable] +public class CharacterInfoEvent : EntityEventArgs +{ + public readonly EntityUid EntityUid; + public readonly string JobTitle; + public readonly Dictionary> Objectives; + + public CharacterInfoEvent(EntityUid entityUid, string jobTitle, Dictionary> objectives) + { + EntityUid = entityUid; + JobTitle = jobTitle; + Objectives = objectives; + } +}