Merge branch 'master' into ed-25-08-2025-upstream-sync

This commit is contained in:
Ed
2025-09-08 11:31:28 +03:00
177 changed files with 2400 additions and 896 deletions

View File

@@ -1,6 +1,7 @@
using System.Globalization;
using System.Linq;
using System.Numerics;
using Content.Client._CP14.IdentityRecognition;
using Content.Client.Administration.Managers;
using Content.Client.Chat;
using Content.Client.Chat.Managers;
@@ -820,6 +821,21 @@ public sealed partial class ChatUIController : UIController
public void ProcessChatMessage(ChatMessage msg, bool speechBubble = true)
{
//CP14 transform message on clientside
if (_player.LocalEntity is not null && msg.SenderEntity.IsValid())
{
var ev = new CP14ClientTransformNameEvent(msg.SenderEntity);
_ent.EventBus.RaiseLocalEvent(_player.LocalEntity.Value, ev);
if (ev.Handled)
{
var oldName = SharedChatSystem.GetStringInsideTag(msg, "Name");
var newName = ev.Name;
msg.WrappedMessage = msg.WrappedMessage.Replace($"[Name]{oldName}[/Name]", $"[Name]{newName}[/Name]");
}
}
//CP14 end
// color the name unless it's something like "the old man"
if ((msg.Channel == ChatChannel.Local || msg.Channel == ChatChannel.Whisper) && _chatNameColorsEnabled)
{

View File

@@ -0,0 +1,7 @@
using Content.Shared._CP14.Actions;
namespace Content.Client._CP14.Actions;
public sealed partial class CP14ClientActionSystem : CP14SharedActionSystem
{
}

View File

@@ -0,0 +1,54 @@
using Content.Shared._CP14.IdentityRecognition;
using Content.Shared.IdentityManagement;
using Content.Shared.Mind;
using Content.Shared.Mind.Components;
namespace Content.Client._CP14.IdentityRecognition;
public sealed partial class CP14ClientIdentityRecognitionSystem : CP14SharedIdentityRecognitionSystem
{
[Dependency] private readonly SharedMindSystem _mind = default!;
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<MindContainerComponent, CP14ClientTransformNameEvent>(OnTransformSpeakerName);
}
private void OnTransformSpeakerName(Entity<MindContainerComponent> ent, ref CP14ClientTransformNameEvent args)
{
if (args.Handled)
return;
var mindEntity = ent.Comp.Mind;
if (mindEntity is null)
return;
TryComp<CP14RememberedNamesComponent>(mindEntity.Value, out var knownNames);
var speaker = GetEntity(args.Speaker);
if (speaker == ent.Owner)
return;
if (knownNames is not null && knownNames.Names.TryGetValue(args.Speaker.Id, out var name))
{
args.Name = name;
}
else
{
args.Name = Identity.Name(speaker, EntityManager, ent);
}
args.Handled = true;
}
}
public sealed class CP14ClientTransformNameEvent(NetEntity speaker) : EntityEventArgs
{
public NetEntity Speaker = speaker;
public string Name = string.Empty;
public bool Handled { get; set; }
}

View File

@@ -0,0 +1,97 @@
using Content.Shared._CP14.IdentityRecognition;
using Content.Shared.Labels.Components;
using Content.Shared.Mind.Components;
using Robust.Client.Player;
using Robust.Client.UserInterface;
namespace Content.Client._CP14.IdentityRecognition;
public sealed class CP14IdentityRecognitionBoundUserInterface : BoundUserInterface
{
[Dependency] private readonly IEntityManager _entManager = default!;
[Dependency] private readonly IPlayerManager _player = default!;
[ViewVariables]
private CP14RememberNameWindow? _window;
private NetEntity? _rememberedTarget;
public CP14IdentityRecognitionBoundUserInterface(EntityUid owner, Enum uiKey) : base(owner, uiKey)
{
IoCManager.InjectDependencies(this);
}
protected override void Open()
{
base.Open();
_window = this.CreateWindow<CP14RememberNameWindow>();
if (_entManager.TryGetComponent(Owner, out HandLabelerComponent? labeler))
{
_window.SetMaxLabelLength(labeler!.MaxLabelChars);
}
_window.OnRememberedNameChanged += OnLabelChanged;
Reload();
}
private void OnLabelChanged(string newLabel)
{
if (_rememberedTarget is null)
return;
// Focus moment
var currentName = CurrentName();
if (currentName is not null && currentName.Equals(newLabel))
return;
SendPredictedMessage(new CP14RememberedNameChangedMessage(newLabel, _rememberedTarget.Value));
}
public void Reload()
{
if (_window is null)
return;
var currentName = CurrentName();
if (currentName is null)
return;
_window.SetCurrentLabel(currentName);
}
private string? CurrentName()
{
if (_rememberedTarget is null)
return null;
if (!_entManager.TryGetComponent<MindContainerComponent>(_player.LocalEntity, out var mindContainer))
return null;
if (!_entManager.TryGetComponent<CP14RememberedNamesComponent>(mindContainer.Mind, out var knownNames))
return null;
var netId = _rememberedTarget.Value.Id;
return knownNames.Names.GetValueOrDefault(netId);
}
protected override void UpdateState(BoundUserInterfaceState state)
{
base.UpdateState(state);
if (_window is null)
return;
switch (state)
{
case CP14RememberNameUiState rememberNameUiState:
_rememberedTarget = rememberNameUiState.Target;
var currentName = CurrentName();
if (currentName is not null)
_window.SetCurrentLabel(currentName);
break;
}
}
}

View File

@@ -0,0 +1,8 @@
<DefaultWindow xmlns="https://spacestation14.io"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="{Loc 'cp14-remember-name-verb'}">
<BoxContainer Orientation="Vertical" SeparationOverride="4" MinWidth="180">
<Label Name="CurrentTextLabel" Text="{Loc 'cp14-remember-name-name'}" />
<LineEdit Name="LabelLineEdit" />
</BoxContainer>
</DefaultWindow>

View File

@@ -0,0 +1,61 @@
using Robust.Client.AutoGenerated;
using Robust.Client.UserInterface.CustomControls;
using Robust.Client.UserInterface.XAML;
namespace Content.Client._CP14.IdentityRecognition;
[GenerateTypedNameReferences]
public sealed partial class CP14RememberNameWindow : DefaultWindow
{
public event Action<string>? OnRememberedNameChanged;
/// <summary>
/// Is the user currently entering text into the control?
/// </summary>
private bool _focused;
// TODO LineEdit Make this a bool on the LineEdit control
private string _label = string.Empty;
public CP14RememberNameWindow()
{
RobustXamlLoader.Load(this);
LabelLineEdit.OnTextChanged += e =>
{
_label = e.Text;
OnRememberedNameChanged?.Invoke(_label);
};
LabelLineEdit.OnFocusEnter += _ => _focused = true;
LabelLineEdit.OnFocusExit += _ =>
{
_focused = false;
LabelLineEdit.Text = _label;
};
}
protected override void Opened()
{
base.Opened();
// Give the editor keyboard focus, since that's the only
// thing the user will want to be doing with this UI
LabelLineEdit.GrabKeyboardFocus();
}
public void SetCurrentLabel(string label)
{
if (label == _label)
return;
_label = label;
if (!_focused)
LabelLineEdit.Text = label;
}
public void SetMaxLabelLength(int maxLength)
{
LabelLineEdit.IsValid = s => s.Length <= maxLength;
}
}

View File

@@ -2,4 +2,4 @@ using Content.Shared._CP14.MagicEnergy;
namespace Content.Client._CP14.MagicEnergy;
public sealed class CP14MagicEnergySystem : SharedCP14MagicEnergySystem;
public sealed class CP14MagicEnergySystem : CP14SharedMagicEnergySystem;