Files
wwdpublic/Content.Client/Language/Systems/LanguageSystem.cs
Mnemotechnican 82cbea2aef Language Refactor 3 (#937)
# Description
This significantly improves the quality of the language system by fixing
the mistakes I've made almost a year ago while developing it.

Mainly, this throws away the old half-broken way of networking in favor
of the component state system provided by RT. Language speaker comp is
now shared with SendOnlyToOwner = true, and its state is handled
manually.

In addition to that, this brings the following changes:
- UniversalLanguageSpeaker and LanguageKnowledge are now server-side
- DetermineLanguagesEvent and LanguagesUpdateEvent are now shared (so
that future systems can be built in shared, if needed)
- Everything now uses the ProtoId<LanguagePrototype> type instead of raw
strings (god, I hated those so much)
- The server-side language system now accepts Entity<T?> arguments
instead of EntityUid + T
- UniversalLanguageSpeaker is now based on DetermineEntityLanguagesEvent
and gets an Enabled field, which allows to turn it off. This may have
some use in the future.
- Some minor cleanup

<!--
TODO MEDIA

<details><summary><h1>Media</h1></summary>
<p>

![Example Media Embed](https://example.com/thisimageisntreal.png)

</p>
</details>

-->

# Changelog
No cl

---------

Co-authored-by: VMSolidus <evilexecutive@gmail.com>
2024-10-19 13:41:35 +07:00

62 lines
2.0 KiB
C#

using Content.Shared.Language;
using Content.Shared.Language.Components;
using Content.Shared.Language.Events;
using Content.Shared.Language.Systems;
using Robust.Client.Player;
using Robust.Shared.GameStates;
using Robust.Shared.Prototypes;
namespace Content.Client.Language.Systems;
public sealed class LanguageSystem : SharedLanguageSystem
{
[Dependency] private readonly IPlayerManager _playerManager = default!;
/// <summary>
/// Invoked when the languages of the local player entity change, for use in UI.
/// </summary>
public event Action? OnLanguagesChanged;
public override void Initialize()
{
_playerManager.LocalPlayerAttached += NotifyUpdate;
SubscribeLocalEvent<LanguageSpeakerComponent, ComponentHandleState>(OnHandleState);
}
private void OnHandleState(Entity<LanguageSpeakerComponent> ent, ref ComponentHandleState args)
{
if (args.Current is not LanguageSpeakerComponent.State state)
return;
ent.Comp.CurrentLanguage = state.CurrentLanguage;
ent.Comp.SpokenLanguages = state.SpokenLanguages;
ent.Comp.UnderstoodLanguages = state.UnderstoodLanguages;
if (ent.Owner == _playerManager.LocalEntity)
NotifyUpdate(ent);
}
/// <summary>
/// Returns the LanguageSpeakerComponent of the local player entity.
/// Will return null if the player does not have an entity, or if the client has not yet received the component state.
/// </summary>
public LanguageSpeakerComponent? GetLocalSpeaker()
{
return CompOrNull<LanguageSpeakerComponent>(_playerManager.LocalEntity);
}
public void RequestSetLanguage(ProtoId<LanguagePrototype> language)
{
if (GetLocalSpeaker()?.CurrentLanguage?.Equals(language) == true)
return;
RaiseNetworkEvent(new LanguagesSetMessage(language));
}
private void NotifyUpdate(EntityUid localPlayer)
{
RaiseLocalEvent(localPlayer, new LanguagesUpdateEvent(), broadcast: true);
OnLanguagesChanged?.Invoke();
}
}