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

Languages #2226

Draft
wants to merge 4 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 3 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
10 changes: 10 additions & 0 deletions Content.Client/SS220/Language/LanguageSystem.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
using Content.Shared.SS220.Language;
using Content.Shared.Verbs;
using Robust.Client.Console;
using Robust.Shared.Player;
using Robust.Shared.Utility;
Jopaglazik marked this conversation as resolved.
Show resolved Hide resolved


namespace Content.Client.SS220.Language;
public sealed class LanguageSystem : SharedLanguageSystem;

133 changes: 133 additions & 0 deletions Content.Server/Administration/Commands/LanguageCommands.cs
Jopaglazik marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
// © SS220, An EULA/CLA with a hosting restriction, full text: https://raw.githubusercontent.com/SerbiaStrong-220/space-station-14/master/CLA.txt
using Content.Shared.Administration;
using Robust.Shared.Console;
using Content.Shared.SS220.Language;
using Robust.Shared.Prototypes;

namespace Content.Server.Administration.Commands;

[AdminCommand(AdminFlags.Admin)]
public sealed class AddLanguageCommand : IConsoleCommand
{
[Dependency] private readonly IEntityManager _entities = default!;
[Dependency] private readonly IPrototypeManager _proto = default!;

public string Command => "addlanguage";
public string Description => Loc.GetString("cmd-language-add-desc");
public string Help => "addlanguage <entityId> <languageId>";

public void Execute(IConsoleShell shell, string argStr, string[] args)
{
if (args.Length != 2)
{
shell.WriteError("addlanguage <entityId> <languageId>");
return;
}

if (!EntityUid.TryParse(args[0], out var entityId))
{
shell.WriteError(Loc.GetString("cmd-language-invalid-id"));
return;
}

var languageId = args[1];

if (!_proto.TryIndex<LanguagesPrototype>(languageId, out var languageProto))
{
shell.WriteError(Loc.GetString("cmd-language-proto-miss"));
return;
}

if (!_entities.TryGetComponent<LanguageComponent>(entityId, out var languageComp))
{
shell.WriteError(Loc.GetString("cmd-language-comp-miss"));
return;
}

if (!languageComp.LearnedLanguages.Contains(languageId))
{
languageComp.LearnedLanguages.Add(languageId);
shell.WriteLine(Loc.GetString("cmd-language-success-add"));
}
else
{
shell.WriteLine(Loc.GetString("cmd-language-already-have"));
}
}
}

[AdminCommand(AdminFlags.Admin)]
public sealed class RemoveLanguageCommand : IConsoleCommand
{
[Dependency] private readonly IEntityManager _entities = default!;

public string Command => "removelanguage";
public string Description => Loc.GetString("cmd-language-remove-desc");
public string Help => "removelanguage <entityId> <languageId>";

public void Execute(IConsoleShell shell, string argStr, string[] args)
{
if (args.Length != 2)
{
shell.WriteError("removelanguage <entityId> <languageId>");
return;
}

if (!EntityUid.TryParse(args[0], out var entityId))
{
shell.WriteError(Loc.GetString("cmd-language-invalid-id"));
return;
}

var languageId = args[1];

if (!_entities.TryGetComponent<LanguageComponent>(entityId, out var languageComp))
{
shell.WriteError(Loc.GetString("cmd-language-comp-miss"));
return;
}

if (languageComp.LearnedLanguages.Remove(languageId))
{
shell.WriteLine(Loc.GetString("cmd-language-succes-remove"));
}
else
{
shell.WriteLine(Loc.GetString("cmd-language-fail-remove"));
}
}
}

[AdminCommand(AdminFlags.Admin)]
public sealed class ClearLanguagesCommand : IConsoleCommand
{
[Dependency] private readonly IEntityManager _entities = default!;

public string Command => "clearlanguages";
public string Description => Loc.GetString("cmd-language-clear-desc");
public string Help => "clearlanguages <entityId>";

public void Execute(IConsoleShell shell, string argStr, string[] args)
{
if (args.Length != 1)
{
shell.WriteError("clearlanguages <entityId>");
return;
}

if (!EntityUid.TryParse(args[0], out var entityId))
{
shell.WriteError(Loc.GetString("cmd-language-invalid-id"));
return;
}

if (!_entities.TryGetComponent<LanguageComponent>(entityId, out var languageComp))
{
shell.WriteError(Loc.GetString("cmd-language-comp-miss"));
return;
}

languageComp.LearnedLanguages.Clear();
shell.WriteLine(Loc.GetString("cmd-language-clear"));
}
}
20 changes: 10 additions & 10 deletions Content.Server/Chat/Managers/ChatSanitizationManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -175,16 +175,16 @@ public bool TrySanitizeEmoteShorthands(string message,
}

// SS220 no English begin
var ntAllowed = sanitized.Replace("NanoTrasen", string.Empty, StringComparison.OrdinalIgnoreCase);
ntAllowed = ntAllowed.Replace("nt", string.Empty, StringComparison.OrdinalIgnoreCase);

// Remember, no English
if (Regex.Matches(ntAllowed, @"[a-zA-Z]").Any())
{
sanitized = string.Empty;
emote = "кашляет";
return true;
}
//var ntAllowed = sanitized.Replace("NanoTrasen", string.Empty, StringComparison.OrdinalIgnoreCase);
Jopaglazik marked this conversation as resolved.
Show resolved Hide resolved
//ntAllowed = ntAllowed.Replace("nt", string.Empty, StringComparison.OrdinalIgnoreCase);

//// Remember, no English
//if (Regex.Matches(ntAllowed, @"[a-zA-Z]").Any())
//{
// sanitized = string.Empty;
// emote = "кашляет";
// return true;
//}
// SS220 no English end

sanitized = message.Trim();
Expand Down
104 changes: 83 additions & 21 deletions Content.Server/Chat/Systems/ChatSystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@
using Robust.Shared.Replays;
using Robust.Shared.Utility;
using Robust.Shared.Timing;
using Content.Shared.SS220.Language; // SS220-Add-Languages-begin
using Content.Server.SS220.Language; // SS220-Add-Languages-end

namespace Content.Server.Chat.Systems;

Expand Down Expand Up @@ -63,6 +65,7 @@ public sealed partial class ChatSystem : SharedChatSystem
[Dependency] private readonly ReplacementAccentSystem _wordreplacement = default!;
[Dependency] private readonly EntityWhitelistSystem _whitelistSystem = default!;
[Dependency] private readonly ExamineSystemShared _examineSystem = default!;
[Dependency] private readonly LanguageSystem _languageSystem = default!; // SS220-Add-Languages

public const int VoiceRange = 10; // how far voice goes in world units
public const int WhisperClearRange = 2; // how far whisper goes while still being understandable, in world units
Expand Down Expand Up @@ -162,9 +165,13 @@ public void TrySendInGameICMessage(
IConsoleShell? shell = null,
ICommonSession? player = null, string? nameOverride = null,
bool checkRadioPrefix = true,
bool ignoreActionBlocker = false)
bool ignoreActionBlocker = false,
LanguagesPrototype? languageProto = null) // SS220-Add-Languages
{
TrySendInGameICMessage(source, message, desiredType, hideChat ? ChatTransmitRange.HideChat : ChatTransmitRange.Normal, hideLog, shell, player, nameOverride, checkRadioPrefix, ignoreActionBlocker);
TrySendInGameICMessage(source, message, desiredType,
hideChat ? ChatTransmitRange.HideChat : ChatTransmitRange.Normal,
hideLog, shell, player, nameOverride, checkRadioPrefix,
ignoreActionBlocker, languageProto: languageProto); // SS220-Add-Languages
}

/// <summary>
Expand All @@ -188,8 +195,8 @@ public void TrySendInGameICMessage(
ICommonSession? player = null,
string? nameOverride = null,
bool checkRadioPrefix = true,
bool ignoreActionBlocker = false
)
bool ignoreActionBlocker = false,
LanguagesPrototype? languageProto = null) // SS220-Add-Languages
{
if (HasComp<GhostComponent>(source))
{
Expand Down Expand Up @@ -285,7 +292,7 @@ public void TrySendInGameICMessage(
SendEntitySpeak(source, message, range, nameOverride, hideLog, ignoreActionBlocker);
break;
case InGameICChatType.Whisper:
SendEntityWhisper(source, message, range, null, nameOverride, hideLog, ignoreActionBlocker);
SendEntityWhisper(source, message, range, null, nameOverride, hideLog, ignoreActionBlocker, languageProto); // SS220-Add-Languages
break;
case InGameICChatType.Emote:
SendEntityEmote(source, message, range, nameOverride, hideLog: hideLog, ignoreActionBlocker: ignoreActionBlocker);
Expand Down Expand Up @@ -496,15 +503,36 @@ private void SendEntitySpeak(
}

name = FormattedMessage.EscapeText(name);
// SS220-Add-Languages begin
foreach (var (session, data) in GetRecipients(source, VoiceRange))
{
if (session.AttachedEntity is not { Valid: true } playerEntity)
continue;

var wrappedMessage = Loc.GetString(speech.Bold ? "chat-manager-entity-say-bold-wrap-message" : "chat-manager-entity-say-wrap-message",
("entityName", name),
("verb", Loc.GetString(_random.Pick(speech.SpeechVerbStrings))),
("fontType", speech.FontId),
("fontSize", speech.FontSize),
("message", FormattedMessage.EscapeText(message)));
var listener = session.AttachedEntity.Value;
var languageProto = _languageSystem.GetProto(source);

if (languageProto == null)
return;

var canUnderstand = _languageSystem.CheckLanguage(listener, languageProto);

var currentMessage = canUnderstand ? message : _languageSystem.ScrambleText(source, originalMessage, languageProto);
if (languageProto?.Color != null)
{
currentMessage = _languageSystem.SetColor(currentMessage, languageProto);
}
// SS220-Add-Languages end

var wrappedMessage = Loc.GetString(speech.Bold ? "chat-manager-entity-say-bold-wrap-message" : "chat-manager-entity-say-wrap-message",
("entityName", name),
("verb", Loc.GetString(_random.Pick(speech.SpeechVerbStrings))),
("fontType", speech.FontId),
("fontSize", speech.FontSize),
("message", currentMessage /*SS220-Add-Languages*/));

SendInVoiceRange(ChatChannel.Local, message, wrappedMessage, source, range);
Jopaglazik marked this conversation as resolved.
Show resolved Hide resolved
_chatManager.ChatMessageToOne(ChatChannel.Local, currentMessage, wrappedMessage, source, false, session.Channel); //SS220-Add-Languages
}

var ev = new EntitySpokeEvent(source, message, originalMessage, null, null);
RaiseLocalEvent(source, ev, true);
Expand Down Expand Up @@ -539,8 +567,8 @@ private void SendEntityWhisper(
RadioChannelPrototype? channel,
string? nameOverride,
bool hideLog = false,
bool ignoreActionBlocker = false
)
bool ignoreActionBlocker = false,
LanguagesPrototype? languageProto = null) // SS220-Add-Languages
{
if (!_actionBlocker.CanSpeak(source) && !ignoreActionBlocker)
return;
Expand All @@ -566,9 +594,18 @@ private void SendEntityWhisper(
name = nameEv.VoiceName;
}
name = FormattedMessage.EscapeText(name);
// SS220-Add-Languages begin
if (languageProto == null)
languageProto = _languageSystem.GetProto(source);
Jopaglazik marked this conversation as resolved.
Show resolved Hide resolved

if (languageProto?.Color != null)
{
message = _languageSystem.SetColor(message, languageProto);
}
// SS220-Add-Languages end

var wrappedMessage = Loc.GetString("chat-manager-entity-whisper-wrap-message",
("entityName", name), ("message", FormattedMessage.EscapeText(message)));
("entityName", name), ("message", message /*SS220-Add-Languages*/));

var wrappedobfuscatedMessage = Loc.GetString("chat-manager-entity-whisper-wrap-message",
("entityName", nameIdentity), ("message", FormattedMessage.EscapeText(obfuscatedMessage)));
Expand All @@ -579,23 +616,48 @@ private void SendEntityWhisper(

foreach (var (session, data) in GetRecipients(source, WhisperMuffledRange))
{
EntityUid listener;

Jopaglazik marked this conversation as resolved.
Show resolved Hide resolved
if (session.AttachedEntity is not { Valid: true } playerEntity)
continue;
listener = session.AttachedEntity.Value;
// SS220-Add-Languages begin

var listener = session.AttachedEntity.Value;

var scrambledMessage = message;
var obfuscatedScrambledMessage = obfuscatedMessage;
var wrappedScrambledMessage = wrappedMessage;
var wrappedObfuscatedScrambledMessage = wrappedobfuscatedMessage;
var wrappedUnknownScrambledMessage = wrappedUnknownMessage;

if (!_languageSystem.CheckLanguage(listener, languageProto) && languageProto != null)
{
scrambledMessage = _languageSystem.ScrambleText(source, message, languageProto);
obfuscatedScrambledMessage = ObfuscateMessageReadability(scrambledMessage, 0.2f);

if (languageProto.Color != null)
{
scrambledMessage = _languageSystem.SetColor(scrambledMessage, languageProto);
}

wrappedScrambledMessage = Loc.GetString("chat-manager-entity-whisper-wrap-message",
("entityName", name), ("message", scrambledMessage));
wrappedObfuscatedScrambledMessage = Loc.GetString("chat-manager-entity-whisper-wrap-message",
("entityName", nameIdentity), ("message", FormattedMessage.EscapeText(obfuscatedScrambledMessage)));
wrappedUnknownScrambledMessage = Loc.GetString("chat-manager-entity-whisper-unknown-wrap-message",
("message", FormattedMessage.EscapeText(obfuscatedScrambledMessage)));
}
// SS220-Add-Languages end

if (MessageRangeCheck(session, data, range) != MessageRangeCheckResult.Full)
continue; // Won't get logged to chat, and ghosts are too far away to see the pop-up, so we just won't send it to them.

if (data.Range <= WhisperClearRange || data.Observer /* SS220 Observer-Hearing */)
_chatManager.ChatMessageToOne(ChatChannel.Whisper, message, wrappedMessage, source, false, session.Channel);
_chatManager.ChatMessageToOne(ChatChannel.Whisper, scrambledMessage, wrappedScrambledMessage /*SS220-Add-Languages*/, source, false, session.Channel);
//If listener is too far, they only hear fragments of the message
else if (_examineSystem.InRangeUnOccluded(source, listener, WhisperMuffledRange))
_chatManager.ChatMessageToOne(ChatChannel.Whisper, obfuscatedMessage, wrappedobfuscatedMessage, source, false, session.Channel);
_chatManager.ChatMessageToOne(ChatChannel.Whisper, obfuscatedScrambledMessage, wrappedObfuscatedScrambledMessage /*SS220-Add-Languages*/, source, false, session.Channel);
//If listener is too far and has no line of sight, they can't identify the whisperer's identity
else
_chatManager.ChatMessageToOne(ChatChannel.Whisper, obfuscatedMessage, wrappedUnknownMessage, source, false, session.Channel);
_chatManager.ChatMessageToOne(ChatChannel.Whisper, obfuscatedScrambledMessage, wrappedUnknownScrambledMessage /*SS220-Add-Languages*/, source, false, session.Channel);
}

_replay.RecordServerMessage(new ChatMessage(ChatChannel.Whisper, message, wrappedMessage, GetNetEntity(source), null, MessageRangeHideChatForReplay(range)));
Expand Down
10 changes: 10 additions & 0 deletions Content.Server/EntityEffects/Effects/MakeSentient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using Content.Server.Speech.Components;
using Content.Shared.EntityEffects;
using Content.Shared.Mind.Components;
using Content.Shared.SS220.Language; // SS220-Add-Languages
using Robust.Shared.Prototypes;

namespace Content.Server.EntityEffects.Effects;
Expand All @@ -22,6 +23,15 @@ public override void Effect(EntityEffectBaseArgs args)
entityManager.RemoveComponent<ReplacementAccentComponent>(uid);
entityManager.RemoveComponent<MonkeyAccentComponent>(uid);

// SS220-Add-Languages begin
if (!entityManager.HasComponent<LanguageComponent>(uid))
{
var language = entityManager.AddComponent<LanguageComponent>(uid);
language.LearnedLanguages.Add("Galactic");
Jopaglazik marked this conversation as resolved.
Show resolved Hide resolved
language.CurrentLanguage = language.LearnedLanguages[0];
}
// SS220-Add-Languages end

// Stops from adding a ghost role to things like people who already have a mind
if (entityManager.TryGetComponent<MindContainerComponent>(uid, out var mindContainer) && mindContainer.HasMind)
{
Expand Down
Loading
Loading