Skip to content

Commit

Permalink
Перенос механики языков, переводчиков языков, имплантеров языков. (#116)
Browse files Browse the repository at this point in the history
Как-то так

no cl
  • Loading branch information
Lonkuk authored Jul 11, 2024
1 parent 91e936e commit bc747b9
Show file tree
Hide file tree
Showing 58 changed files with 4,089 additions and 28 deletions.
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

0 comments on commit bc747b9

Please sign in to comment.