Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Перенос механики языков, переводчиков языков, имплантеров языков. #116

Merged
merged 3 commits into from
Jul 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 51 additions & 0 deletions Content.Client/ADT/Language/LanguageMenuUIController.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
using Content.Client.ADT.Language;
using Content.Client.Gameplay;
using Content.Shared.Language;
using Robust.Client.UserInterface.Controllers;
using Robust.Client.UserInterface.Controls;
using static Content.Shared.Language.Systems.SharedLanguageSystem;

namespace Content.Client.ADT.Language;

public sealed class LanguageMenuUIController : UIController, IOnStateEntered<GameplayState>, IOnStateExited<GameplayState>
{
public LanguageMenuWindow? _languageWindow;

public override void Initialize()
{
EntityManager.EventBus.SubscribeLocalEvent<LanguageSpeakerComponent, LanguageMenuActionEvent>(OnActionMenu);
EntityManager.EventBus.SubscribeEvent<LanguageMenuStateMessage>(EventSource.Network, this, OnStateUpdate);
}

private void OnStateUpdate(LanguageMenuStateMessage ev)
{
if (_languageWindow == null)
return;

_languageWindow.UpdateState(ev);
}

private void OnActionMenu(EntityUid uid, LanguageSpeakerComponent component, LanguageMenuActionEvent args)
{
if (_languageWindow == null)
return;

if (!_languageWindow.IsOpen)
{
_languageWindow.Open();
EntityManager.EntityNetManager?.SendSystemNetworkMessage(new RequestLanguageMenuStateMessage());
}
}

public void OnStateEntered(GameplayState state)
{
_languageWindow = UIManager.CreateWindow<LanguageMenuWindow>();
LayoutContainer.SetAnchorPreset(_languageWindow, LayoutContainer.LayoutPreset.Center);
}

public void OnStateExited(GameplayState state)
{
_languageWindow?.Dispose();
_languageWindow = null;
}
}
18 changes: 18 additions & 0 deletions Content.Client/ADT/Language/LanguageMenuWindow.xaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<DefaultWindow xmlns="https://spacestation14.io"
xmlns:ui="clr-namespace:Content.Client.UserInterface.Controls"
Title="a"
SetSize="300 200">
<BoxContainer Orientation="Vertical" SeparationOverride="4" MinWidth="150">
<PanelContainer Name="CurrentLanguageContainer" Access="Public" StyleClasses="PdaBorderRect">
<Label Name="CurrentLanguageLabel" Access="Public" Text="Current Language:" HorizontalExpand="True"></Label>
</PanelContainer>

<ui:HLine></ui:HLine>

<ScrollContainer HorizontalExpand="True" VerticalExpand="True" HScrollEnabled="False" VScrollEnabled="True" MinHeight="50">
<BoxContainer Name="OptionsList" Access="Public" HorizontalExpand="True" SeparationOverride="2" Orientation="Vertical">
<!-- The rest here is generated programmatically -->
</BoxContainer>
</ScrollContainer>
</BoxContainer>
</DefaultWindow>
124 changes: 124 additions & 0 deletions Content.Client/ADT/Language/LanguageMenuWindow.xaml.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
using Content.Client.Language.Systems;
using Content.Shared.Language;
using Content.Shared.Language.Systems;
using Robust.Client.AutoGenerated;
using Robust.Client.UserInterface.Controls;
using Robust.Client.UserInterface.CustomControls;
using Robust.Client.UserInterface.XAML;
using Robust.Shared.Console;
using Robust.Shared.Utility;
using static Content.Shared.Language.Systems.SharedLanguageSystem;

namespace Content.Client.ADT.Language; // This EXACT class must have the _NF part because of xaml linking

[GenerateTypedNameReferences]
public sealed partial class LanguageMenuWindow : DefaultWindow
{
[Dependency] private readonly IConsoleHost _consoleHost = default!;
private readonly LanguageSystem _language;

private readonly List<EntryState> _entries = new();

public LanguageMenuWindow()
{
RobustXamlLoader.Load(this);
IoCManager.InjectDependencies(this);
_language = IoCManager.Resolve<IEntitySystemManager>().GetEntitySystem<LanguageSystem>();

Title = Loc.GetString("language-menu-window-title");
}

public void UpdateState(LanguageMenuStateMessage state)
{
var clanguage = _language.GetLanguage(state.CurrentLanguage);
CurrentLanguageLabel.Text = Loc.GetString("language-menu-current-language", ("language", clanguage?.LocalizedName ?? "<error>"));

OptionsList.RemoveAllChildren();
_entries.Clear();

foreach (var language in state.Options)
{
AddLanguageEntry(language);
}

// Disable the button for the currently chosen language
foreach (var entry in _entries)
{
if (entry.button != null)
entry.button.Disabled = entry.language == state.CurrentLanguage;
}
}

private void AddLanguageEntry(string language)
{
var proto = _language.GetLanguage(language);
var state = new EntryState { language = language };

var container = new BoxContainer();
container.Orientation = BoxContainer.LayoutOrientation.Vertical;

// Create and add a header with the name and the button to select the language
{
var header = new BoxContainer();
header.Orientation = BoxContainer.LayoutOrientation.Horizontal;

header.Orientation = BoxContainer.LayoutOrientation.Horizontal;
header.HorizontalExpand = true;
header.SeparationOverride = 2;

var name = new Label();
name.Text = proto?.LocalizedName ?? "<error>";
name.MinWidth = 50;
name.HorizontalExpand = true;

var button = new Button();
button.Text = "Выбрать";
button.OnPressed += _ => OnLanguageChosen(language);
state.button = button;

header.AddChild(name);
header.AddChild(button);

container.AddChild(header);
}

// Create and add a collapsible description
{
var body = new CollapsibleBody();
body.HorizontalExpand = true;
body.Margin = new Thickness(4f, 4f);

var description = new RichTextLabel();
description.SetMessage(proto?.LocalizedDescription ?? "<error>");
description.HorizontalExpand = true;

body.AddChild(description);

var collapser = new Collapsible(Loc.GetString("language-menu-description-header"), body);
collapser.Orientation = BoxContainer.LayoutOrientation.Vertical;
collapser.HorizontalExpand = true;

container.AddChild(collapser);
}

// Before adding, wrap the new container in a PanelContainer to give it a distinct look
var wrapper = new PanelContainer();
wrapper.StyleClasses.Add("PdaBorderRect");

wrapper.AddChild(container);
OptionsList.AddChild(wrapper);

_entries.Add(state);
}

private void OnLanguageChosen(string id)
{
_consoleHost.ExecuteCommand("lsselectlang " + id);
}

private struct EntryState
{
public string language;
public Button? button;
}
}
8 changes: 8 additions & 0 deletions Content.Client/ADT/Language/Systems/LanguageSystem.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
using Content.Shared.Language.Systems;

namespace Content.Client.Language.Systems;

public sealed class LanguageSystem : SharedLanguageSystem
{

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
using Content.Shared.Language.Systems;

namespace Content.Client.Language.Systems;

public sealed class TranslatorImplanterSystem : SharedTranslatorImplanterSystem
{

}
39 changes: 39 additions & 0 deletions Content.Server/ADT/Language/Commands/ListLanguagesCommand.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
using System.Linq;
using Content.Shared.Administration;
using Robust.Shared.Console;
using Robust.Shared.Enums;

namespace Content.Server.Language.Commands;

[AnyCommand]
public sealed class ListLanguagesCommand : IConsoleCommand
{
public string Command => "lslangs";
public string Description => "List languages your current entity can speak at the current moment.";
public string Help => "lslangs";

public void Execute(IConsoleShell shell, string argStr, string[] args)
{
if (shell.Player is not { } player)
{
shell.WriteError("This command cannot be run from the server.");
return;
}

if (player.Status != SessionStatus.InGame)
return;

if (player.AttachedEntity is not { } playerEntity)
{
shell.WriteError("You don't have an entity!");
return;
}

var languages = IoCManager.Resolve<IEntitySystemManager>().GetEntitySystem<LanguageSystem>();

var (spokenLangs, knownLangs) = languages.GetAllLanguages(playerEntity);

shell.WriteLine("Spoken: " + string.Join(", ", spokenLangs));
shell.WriteLine("Understood: " + string.Join(", ", knownLangs));
}
}
53 changes: 53 additions & 0 deletions Content.Server/ADT/Language/Commands/SayLanguageCommand.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
using Content.Server.Chat.Systems;
using Content.Shared.Administration;
using Robust.Shared.Console;
using Robust.Shared.Enums;

namespace Content.Server.Language.Commands;

[AnyCommand]
public sealed class SayLanguageCommand : IConsoleCommand
{
public string Command => "lsay";
public string Description => "Send chat languages to the local channel or a specific chat channel, in a specific language.";
public string Help => "lsay <language id> <text>";

public void Execute(IConsoleShell shell, string argStr, string[] args)
{
if (shell.Player is not { } player)
{
shell.WriteError("This command cannot be run from the server.");
return;
}

if (player.Status != SessionStatus.InGame)
return;

if (player.AttachedEntity is not { } playerEntity)
{
shell.WriteError("You don't have an entity!");
return;
}

if (args.Length < 2)
return;

var languageId = args[0];
var message = string.Join(" ", args, startIndex: 1, count: args.Length - 1).Trim();

if (string.IsNullOrEmpty(message))
return;

var languages = IoCManager.Resolve<IEntitySystemManager>().GetEntitySystem<LanguageSystem>();
var chats = IoCManager.Resolve<IEntitySystemManager>().GetEntitySystem<ChatSystem>();

var language = languages.GetLanguage(languageId);
if (language == null || !languages.CanSpeak(playerEntity, language.ID))
{
shell.WriteError($"Language {languageId} is invalid or you cannot speak it!");
return;
}

chats.TrySendInGameICMessage(playerEntity, message, InGameICChatType.Speak, ChatTransmitRange.Normal, false, shell, player, languageOverride: language);
}
}
48 changes: 48 additions & 0 deletions Content.Server/ADT/Language/Commands/SelectLanguageCommand.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
using System.Linq;
using Content.Shared.Administration;
using Robust.Shared.Console;
using Robust.Shared.Enums;

namespace Content.Server.Language.Commands;

[AnyCommand]
public sealed class SelectLanguageCommand : IConsoleCommand
{
public string Command => "lsselectlang";
public string Description => "Open a menu to select a langauge to speak.";
public string Help => "lsselectlang";

public void Execute(IConsoleShell shell, string argStr, string[] args)
{
if (shell.Player is not { } player)
{
shell.WriteError("This command cannot be run from the server.");
return;
}

if (player.Status != SessionStatus.InGame)
return;

if (player.AttachedEntity is not { } playerEntity)
{
shell.WriteError("You don't have an entity!");
return;
}

if (args.Length < 1)
return;

var languageId = args[0];

var languages = IoCManager.Resolve<IEntitySystemManager>().GetEntitySystem<LanguageSystem>();

var language = languages.GetLanguage(languageId);
if (language == null || !languages.CanSpeak(playerEntity, language.ID))
{
shell.WriteError($"Language {languageId} is invalid or you cannot speak it!");
return;
}

languages.SetLanguage(playerEntity, language.ID);
}
}
40 changes: 40 additions & 0 deletions Content.Server/ADT/Language/LanguageSystem.Windows.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
using Content.Shared.Language;
using Robust.Server.GameObjects;
using Robust.Shared.Player;

namespace Content.Server.Language;

public sealed partial class LanguageSystem
{
[Dependency] private readonly UserInterfaceSystem _uiSystem = default!;

public void InitializeWindows()
{
SubscribeNetworkEvent<RequestLanguageMenuStateMessage>(OnLanguagesRequest);
SubscribeLocalEvent<LanguageSpeakerComponent, LanguagesUpdateEvent>(OnLanguageSwitch);
}

private void OnLanguagesRequest(RequestLanguageMenuStateMessage args, EntitySessionEventArgs session)
{
var uid = session.SenderSession.AttachedEntity;
if (uid == null)
return;

var langs = GetLanguages(uid.Value);
if (langs == null)
return;

var state = new LanguageMenuStateMessage(langs.CurrentLanguage, langs.SpokenLanguages);
RaiseNetworkEvent(state, uid.Value);
}

private void OnLanguageSwitch(EntityUid uid, LanguageSpeakerComponent component, LanguagesUpdateEvent args)
{
var langs = GetLanguages(uid);
if (langs == null)
return;

var state = new LanguageMenuStateMessage(langs.CurrentLanguage, langs.SpokenLanguages);
RaiseNetworkEvent(state, uid);
}
}
Loading
Loading