From d7ff965a0186f84ce728b0db31ba106410abb303 Mon Sep 17 00:00:00 2001 From: Jopaglazik Date: Tue, 12 Nov 2024 06:30:01 +0400 Subject: [PATCH 01/48] init --- .../SS220/Language/LanguageSystem.cs | 10 + .../Commands/LanguageCommands.cs | 133 +++++++++++++ .../Chat/Managers/ChatSanitizationManager.cs | 22 +-- Content.Server/Chat/Systems/ChatSystem.cs | 122 ++++++++---- .../EntityEffects/Effects/MakeSentient.cs | 10 + Content.Server/PAI/PAISystem.cs | 27 +++ .../Radio/EntitySystems/HeadsetSystem.cs | 9 +- .../Radio/EntitySystems/RadioDeviceSystem.cs | 15 +- .../Radio/EntitySystems/RadioSystem.cs | 44 ++++- Content.Server/Radio/RadioEvent.cs | 6 +- .../SS220/Language/LanguageSystem.cs | 152 +++++++++++++++ .../Language/Special/AddLanguageSpecial.cs | 23 +++ .../TapeRecorder/TapeRecorderSystem.cs | 5 +- Content.Server/Traits/TraitSystem.cs | 8 + .../Zombies/ZombieSystem.Transform.cs | 2 + .../SS220/Language/LanguageComponent.cs | 29 +++ .../SS220/Language/LanguageVerbs.cs | 96 ++++++++++ .../SS220/Language/LanguagesPrototype.cs | 41 ++++ .../SS220/Language/SharedLanguageSystem.cs | 121 ++++++++++++ Content.Shared/Traits/TraitPrototype.cs | 3 + Content.Shared/Verbs/VerbCategory.cs | 4 + .../ru-RU/ss220/language/language-cmd.ftl | 13 ++ .../ru-RU/ss220/language/language-desc.ftl | 21 +++ .../ru-RU/ss220/language/language-name.ftl | 19 ++ .../language/language-trait-category.ftl | 1 + .../ru-RU/ss220/taperecorder/taperecorder.ftl | 2 +- .../Locale/ru-RU/ss220/verbs/verb-system.ftl | 5 +- .../Mobs/Cyborgs/base_borg_chassis.yml | 7 + .../Entities/Mobs/Species/arachnid.yml | 6 + .../Entities/Mobs/Species/diona.yml | 6 + .../Entities/Mobs/Species/dwarf.yml | 6 + .../Entities/Mobs/Species/human.yml | 6 + .../Prototypes/Entities/Mobs/Species/moth.yml | 6 + .../Entities/Mobs/Species/reptilian.yml | 6 + .../Entities/Mobs/Species/slime.yml | 6 + .../Prototypes/Entities/Mobs/Species/vox.yml | 6 + .../Prototypes/Entities/Objects/Fun/pai.yml | 6 + .../Objects/Specific/Robotics/mmi.yml | 12 ++ .../Prototypes/Roles/Jobs/Civilian/clown.yml | 5 + .../SS220/Entities/Mobs/NPCs/animals.yml | 5 + .../SS220/Entities/Mobs/Species/felinid.yml | 3 + .../SS220/Entities/Mobs/Species/tajaran.yml | 4 + .../SS220/Entities/Mobs/Species/vulpkanin.yml | 4 + .../SS220/Entities/Objects/Fun/pai.yml | 6 + Resources/Prototypes/SS220/Geras/slime.yml | 6 + .../Prototypes/SS220/Language/language.yml | 176 ++++++++++++++++++ .../SS220/Traits/language_traits.yml | 47 +++++ Resources/Prototypes/Traits/categories.yml | 7 + .../Interface/VerbIcons/language_icon.svg | 7 + .../VerbIcons/language_icon.svg.192dpi.png | Bin 0 -> 3213 bytes .../VerbIcons/language_icon.svg.192dpi.yml | 2 + 51 files changed, 1234 insertions(+), 54 deletions(-) create mode 100644 Content.Client/SS220/Language/LanguageSystem.cs create mode 100644 Content.Server/Administration/Commands/LanguageCommands.cs create mode 100644 Content.Server/SS220/Language/LanguageSystem.cs create mode 100644 Content.Server/SS220/Language/Special/AddLanguageSpecial.cs create mode 100644 Content.Shared/SS220/Language/LanguageComponent.cs create mode 100644 Content.Shared/SS220/Language/LanguageVerbs.cs create mode 100644 Content.Shared/SS220/Language/LanguagesPrototype.cs create mode 100644 Content.Shared/SS220/Language/SharedLanguageSystem.cs create mode 100644 Resources/Locale/ru-RU/ss220/language/language-cmd.ftl create mode 100644 Resources/Locale/ru-RU/ss220/language/language-desc.ftl create mode 100644 Resources/Locale/ru-RU/ss220/language/language-name.ftl create mode 100644 Resources/Locale/ru-RU/ss220/language/language-trait-category.ftl create mode 100644 Resources/Prototypes/SS220/Language/language.yml create mode 100644 Resources/Prototypes/SS220/Traits/language_traits.yml create mode 100644 Resources/Textures/SS220/Interface/VerbIcons/language_icon.svg create mode 100644 Resources/Textures/SS220/Interface/VerbIcons/language_icon.svg.192dpi.png create mode 100644 Resources/Textures/SS220/Interface/VerbIcons/language_icon.svg.192dpi.yml diff --git a/Content.Client/SS220/Language/LanguageSystem.cs b/Content.Client/SS220/Language/LanguageSystem.cs new file mode 100644 index 000000000000..31999726a9f7 --- /dev/null +++ b/Content.Client/SS220/Language/LanguageSystem.cs @@ -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; + + +namespace Content.Client.SS220.Language; +public sealed class LanguageSystem : SharedLanguageSystem; + diff --git a/Content.Server/Administration/Commands/LanguageCommands.cs b/Content.Server/Administration/Commands/LanguageCommands.cs new file mode 100644 index 000000000000..83bf09024091 --- /dev/null +++ b/Content.Server/Administration/Commands/LanguageCommands.cs @@ -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 "; + + public void Execute(IConsoleShell shell, string argStr, string[] args) + { + if (args.Length != 2) + { + shell.WriteError("addlanguage "); + 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(languageId, out var languageProto)) + { + shell.WriteError(Loc.GetString("cmd-language-proto-miss")); + return; + } + + if (!_entities.TryGetComponent(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 "; + + public void Execute(IConsoleShell shell, string argStr, string[] args) + { + if (args.Length != 2) + { + shell.WriteError("removelanguage "); + 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(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 "; + + public void Execute(IConsoleShell shell, string argStr, string[] args) + { + if (args.Length != 1) + { + shell.WriteError("clearlanguages "); + return; + } + + if (!EntityUid.TryParse(args[0], out var entityId)) + { + shell.WriteError(Loc.GetString("cmd-language-invalid-id")); + return; + } + + if (!_entities.TryGetComponent(entityId, out var languageComp)) + { + shell.WriteError(Loc.GetString("cmd-language-comp-miss")); + return; + } + + languageComp.LearnedLanguages.Clear(); + shell.WriteLine(Loc.GetString("cmd-language-clear")); + } +} diff --git a/Content.Server/Chat/Managers/ChatSanitizationManager.cs b/Content.Server/Chat/Managers/ChatSanitizationManager.cs index 14566c2d66f0..bd5091f7ae0e 100644 --- a/Content.Server/Chat/Managers/ChatSanitizationManager.cs +++ b/Content.Server/Chat/Managers/ChatSanitizationManager.cs @@ -53,7 +53,7 @@ public sealed class ChatSanitizationManager : IChatSanitizationManager { ":D", "chatsan-smiles-widely" }, { "D:", "chatsan-frowns-deeply" }, { ":O", "chatsan-surprised" }, - { ":3", "chatsan-smiles" }, + { ":3", "chatsan-smiles" }, { ":S", "chatsan-uncertain" }, { ":>", "chatsan-grins" }, { ":<", "chatsan-pouts" }, @@ -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); + //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(); diff --git a/Content.Server/Chat/Systems/ChatSystem.cs b/Content.Server/Chat/Systems/ChatSystem.cs index c8d3e309523c..dc8e1c2d9ad8 100644 --- a/Content.Server/Chat/Systems/ChatSystem.cs +++ b/Content.Server/Chat/Systems/ChatSystem.cs @@ -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; @@ -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 @@ -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 } /// @@ -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(source)) { @@ -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); @@ -461,13 +468,13 @@ public void DispatchStationAnnouncement( #region Private API private void SendEntitySpeak( - EntityUid source, - string originalMessage, - ChatTransmitRange range, - string? nameOverride, - bool hideLog = false, - bool ignoreActionBlocker = false - ) + EntityUid source, + string originalMessage, + ChatTransmitRange range, + string? nameOverride, + bool hideLog = false, + bool ignoreActionBlocker = false + ) { if (!_actionBlocker.CanSpeak(source) && !ignoreActionBlocker) return; @@ -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 - SendInVoiceRange(ChatChannel.Local, message, wrappedMessage, source, range); + 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*/)); + + _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); @@ -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; @@ -566,38 +594,68 @@ private void SendEntityWhisper( name = nameEv.VoiceName; } name = FormattedMessage.EscapeText(name); + // SS220-Add-Languages begin + if (languageProto == null) + languageProto = _languageSystem.GetProto(source); - var wrappedMessage = Loc.GetString("chat-manager-entity-whisper-wrap-message", - ("entityName", name), ("message", FormattedMessage.EscapeText(message))); + 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", message /*SS220-Add-Languages*/)); var wrappedobfuscatedMessage = Loc.GetString("chat-manager-entity-whisper-wrap-message", ("entityName", nameIdentity), ("message", FormattedMessage.EscapeText(obfuscatedMessage))); - var wrappedUnknownMessage = Loc.GetString("chat-manager-entity-whisper-unknown-wrap-message", ("message", FormattedMessage.EscapeText(obfuscatedMessage))); - foreach (var (session, data) in GetRecipients(source, WhisperMuffledRange)) { - EntityUid listener; - 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))); var ev = new EntitySpokeEvent(source, message, originalMessage, channel, obfuscatedMessage); diff --git a/Content.Server/EntityEffects/Effects/MakeSentient.cs b/Content.Server/EntityEffects/Effects/MakeSentient.cs index c4870438486f..49d56e8cfb89 100644 --- a/Content.Server/EntityEffects/Effects/MakeSentient.cs +++ b/Content.Server/EntityEffects/Effects/MakeSentient.cs @@ -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; @@ -22,6 +23,15 @@ public override void Effect(EntityEffectBaseArgs args) entityManager.RemoveComponent(uid); entityManager.RemoveComponent(uid); + // SS220-Add-Languages begin + if (!entityManager.HasComponent(uid)) + { + var language = entityManager.AddComponent(uid); + language.LearnedLanguages.Add("Galactic"); + 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(uid, out var mindContainer) && mindContainer.HasMind) { diff --git a/Content.Server/PAI/PAISystem.cs b/Content.Server/PAI/PAISystem.cs index 0cdb0bc29a2d..45b79cda7e54 100644 --- a/Content.Server/PAI/PAISystem.cs +++ b/Content.Server/PAI/PAISystem.cs @@ -9,6 +9,7 @@ using Robust.Shared.Random; using System.Text; using Robust.Shared.Player; +using Content.Shared.SS220.Language; // SS220-Add-Languages namespace Content.Server.PAI; @@ -55,6 +56,7 @@ private void OnMindAdded(EntityUid uid, PAIComponent component, MindAddedMessage // Cause then you could remotely figure out information about the owner's equipped items. _metaData.SetEntityName(uid, val); + GetUserLanguages(component.LastUser, uid); // SS220-Add-Languages } private void OnMindRemoved(EntityUid uid, PAIComponent component, MindRemovedMessage args) @@ -117,5 +119,30 @@ public void PAITurningOff(EntityUid uid) if (proto != null) _metaData.SetEntityName(uid, proto.Name); } + // SS220-Add-Languages begin + if (TryComp(uid, out var languages)) + { + languages.LearnedLanguages.Clear(); + languages.LearnedLanguages.Add("Galactic"); + languages.LearnedLanguages.Add("Universal"); + languages.CurrentLanguage = languages.LearnedLanguages[0]; + } + } + + public void GetUserLanguages(EntityUid? ent, EntityUid pai) + { + if (!TryComp(ent, out var languages) || languages == null) + return; + + if (!TryComp(pai, out var paiLanguages)) + return; + + foreach (var language in languages.LearnedLanguages) + { + if (!paiLanguages.LearnedLanguages.Contains(language)) + paiLanguages.LearnedLanguages.Add(language); + } + Dirty(pai, paiLanguages); } + // SS220-Add-Languages end } diff --git a/Content.Server/Radio/EntitySystems/HeadsetSystem.cs b/Content.Server/Radio/EntitySystems/HeadsetSystem.cs index 914ff57a86a0..3bab4ed1ff20 100644 --- a/Content.Server/Radio/EntitySystems/HeadsetSystem.cs +++ b/Content.Server/Radio/EntitySystems/HeadsetSystem.cs @@ -8,6 +8,7 @@ using Content.Shared.Radio.EntitySystems; using Robust.Shared.Network; using Robust.Shared.Player; +using Content.Server.SS220.Language; // SS220-Add-Languages namespace Content.Server.Radio.EntitySystems; @@ -15,6 +16,7 @@ public sealed class HeadsetSystem : SharedHeadsetSystem { [Dependency] private readonly INetManager _netMan = default!; [Dependency] private readonly RadioSystem _radio = default!; + [Dependency] private readonly LanguageSystem _languageSystem = default!; // SS220-Add-Languages public override void Initialize() { @@ -104,7 +106,12 @@ private void OnHeadsetReceive(EntityUid uid, HeadsetComponent component, ref Rad var actorUid = Transform(uid).ParentUid; if (TryComp(actorUid, out ActorComponent? actor)) { - _netMan.ServerSendMessage(args.ChatMsg, actor.PlayerSession.Channel); + // SS220-Add-Languages begin + if (_languageSystem.CheckLanguage(actorUid, args.LanguageProto)) + _netMan.ServerSendMessage(args.ChatMsg, actor.PlayerSession.Channel); + else + _netMan.ServerSendMessage(args.ScrambledChatMsg, actor.PlayerSession.Channel); + // SS220-Add-Languages end if (actorUid != args.MessageSource && TryComp(args.MessageSource, out TTSComponent? _)) { args.Receivers.Add(actorUid); diff --git a/Content.Server/Radio/EntitySystems/RadioDeviceSystem.cs b/Content.Server/Radio/EntitySystems/RadioDeviceSystem.cs index 0c488f06ae95..faceefd6855e 100644 --- a/Content.Server/Radio/EntitySystems/RadioDeviceSystem.cs +++ b/Content.Server/Radio/EntitySystems/RadioDeviceSystem.cs @@ -19,6 +19,8 @@ using Content.Shared.Chat; using Content.Shared.UserInterface; using Robust.Server.GameObjects; +using Robust.Shared.Utility; +using Content.Server.SS220.Language; // SS220-Add-Languages namespace Content.Server.Radio.EntitySystems; @@ -34,6 +36,7 @@ public sealed class RadioDeviceSystem : EntitySystem [Dependency] private readonly InteractionSystem _interaction = default!; [Dependency] private readonly SharedAppearanceSystem _appearance = default!; [Dependency] private readonly UserInterfaceSystem _ui = default!; + [Dependency] private readonly LanguageSystem _languageSystem = default!; // SS220-Add-Languages // Used to prevent a shitter from using a bunch of radios to spam chat. private HashSet<(string, EntityUid, RadioChannelPrototype)> _recentlySent = new(); @@ -203,10 +206,13 @@ private void OnListen(EntityUid uid, RadioMicrophoneComponent component, ListenE if (HasComp(args.Source)) return; // no feedback loops please. + // SS220-Add-Languages begin + var message = _languageSystem.RemoveColorTags(args.Message); var channel = _protoMan.Index(component.BroadcastChannel)!; if (_recentlySent.Add((args.Message, args.Source, channel))) - _radio.SendRadioMessage(args.Source, args.Message, channel, uid); - } + _radio.SendRadioMessage(args.Source, message, channel, uid); + // SS220-Add-Languages end + } private void OnAttemptListen(EntityUid uid, RadioMicrophoneComponent component, ListenAttemptEvent args) { @@ -228,9 +234,10 @@ private void OnReceiveRadio(EntityUid uid, RadioSpeakerComponent component, ref var name = Loc.GetString("speech-name-relay", ("speaker", Name(uid)), ("originalName", nameEv.VoiceName)); - // log to chat so people can identity the speaker/source, but avoid clogging ghost chat if there are many radios - _chat.TrySendInGameICMessage(uid, args.Message, InGameICChatType.Whisper, ChatTransmitRange.GhostRangeLimit, nameOverride: name, checkRadioPrefix: false); + _chat.TrySendInGameICMessage(uid, args.Message, InGameICChatType.Whisper, + ChatTransmitRange.GhostRangeLimit, nameOverride: name, checkRadioPrefix: false, + languageProto: args.LanguageProto); // SS220-Add-Languages } private void OnIntercomEncryptionChannelsChanged(Entity ent, ref EncryptionChannelsChangedEvent args) diff --git a/Content.Server/Radio/EntitySystems/RadioSystem.cs b/Content.Server/Radio/EntitySystems/RadioSystem.cs index dc9689f7ee0c..8798ea283ea8 100644 --- a/Content.Server/Radio/EntitySystems/RadioSystem.cs +++ b/Content.Server/Radio/EntitySystems/RadioSystem.cs @@ -19,6 +19,7 @@ using Content.Shared.PDA; using System.Globalization; using Content.Server.Popups; +using Content.Server.SS220.Language; // SS220-Add-Languages namespace Content.Server.Radio.EntitySystems; @@ -35,6 +36,7 @@ public sealed class RadioSystem : EntitySystem [Dependency] private readonly PopupSystem _popup = default!; [Dependency] private readonly InventorySystem _inventorySystem = default!; [Dependency] private readonly ChatSystem _chat = default!; + [Dependency] private readonly LanguageSystem _languageSystem = default!; // SS220-Add-Languages // set used to prevent radio feedback loops. private readonly HashSet _messages = new(); @@ -68,7 +70,12 @@ private void OnIntrinsicSpeak(EntityUid uid, IntrinsicRadioTransmitterComponent private void OnIntrinsicReceive(EntityUid uid, IntrinsicRadioReceiverComponent component, ref RadioReceiveEvent args) { if (TryComp(uid, out ActorComponent? actor)) - _netMan.ServerSendMessage(args.ChatMsg, actor.PlayerSession.Channel); + // SS220-Add-Languages begin + if (_languageSystem.CheckLanguage(uid, args.LanguageProto)) + _netMan.ServerSendMessage(args.ChatMsg, actor.PlayerSession.Channel); + else + _netMan.ServerSendMessage(args.ScrambledChatMsg, actor.PlayerSession.Channel); + // SS220-Add-Languages end } /// @@ -89,6 +96,7 @@ public void SendRadioMessage(EntityUid messageSource, string message, RadioChann // TODO if radios ever garble / modify messages, feedback-prevention needs to be handled better than this. if (!_messages.Add(message)) return; + message = _languageSystem.RemoveColorTags(message); // SS220-Add-Languages var evt = new TransformSpeakerNameEvent(messageSource, MetaData(messageSource).EntityName); RaiseLocalEvent(messageSource, evt); @@ -108,12 +116,43 @@ public void SendRadioMessage(EntityUid messageSource, string message, RadioChann var content = escapeMarkup ? FormattedMessage.EscapeText(message) : message; + // SS220-Add-Languages begin + var languageProto = _languageSystem.GetProto(messageSource); + if (languageProto == null) + return; + + var scrambledMessage = _languageSystem.ScrambleText(messageSource, content, languageProto); if (GetIdCardIsBold(messageSource)) { content = $"[bold]{content}[/bold]"; + scrambledMessage = $"[bold]{scrambledMessage}[/bold]"; + } + + if (languageProto.Color != null) + { + content = _languageSystem.SetColor(content, languageProto); + scrambledMessage = _languageSystem.SetColor(scrambledMessage, languageProto); } + var wrappedScrambledMessage = Loc.GetString(speech.Bold ? "chat-radio-message-wrap-bold" : "chat-radio-message-wrap", + ("color", channel.Color), + ("fontType", speech.FontId), + ("fontSize", speech.FontSize), + ("verb", Loc.GetString(_random.Pick(speech.SpeechVerbStrings))), + ("channel", $"\\[{channel.LocalizedName}\\]"), + ("name", formattedName), + ("message", scrambledMessage)); + + var scrambledChat = new ChatMessage( + ChatChannel.Radio, + message, + wrappedScrambledMessage, + NetEntity.Invalid, + null); + var scrambledChatMsg = new MsgChatMessage { Message = scrambledChat }; + // SS220-Add-Languages end + var wrappedMessage = Loc.GetString(speech.Bold ? "chat-radio-message-wrap-bold" : "chat-radio-message-wrap", ("color", channel.Color), ("fontType", speech.FontId), @@ -131,7 +170,8 @@ public void SendRadioMessage(EntityUid messageSource, string message, RadioChann NetEntity.Invalid, null); var chatMsg = new MsgChatMessage { Message = chat }; - var ev = new RadioReceiveEvent(message, messageSource, channel, radioSource, chatMsg, new()); + var ev = new RadioReceiveEvent(message, messageSource, channel, radioSource, + chatMsg, scrambledChatMsg, languageProto, new()); // SS220-Add-Languages var sendAttemptEv = new RadioSendAttemptEvent(channel, radioSource); RaiseLocalEvent(ref sendAttemptEv); diff --git a/Content.Server/Radio/RadioEvent.cs b/Content.Server/Radio/RadioEvent.cs index e0e99cdeeb01..85d8915b18ab 100644 --- a/Content.Server/Radio/RadioEvent.cs +++ b/Content.Server/Radio/RadioEvent.cs @@ -1,10 +1,14 @@ using Content.Shared.Chat; +using Content.Shared.SS220.Language; // SS220-Add-Languages using Content.Shared.Radio; namespace Content.Server.Radio; [ByRefEvent] -public readonly record struct RadioReceiveEvent(string Message, EntityUid MessageSource, RadioChannelPrototype Channel, EntityUid RadioSource, MsgChatMessage ChatMsg, List Receivers); +public readonly record struct RadioReceiveEvent(string Message, EntityUid MessageSource, + RadioChannelPrototype Channel,EntityUid RadioSource, + MsgChatMessage ChatMsg, MsgChatMessage ScrambledChatMsg, + LanguagesPrototype? LanguageProto, List Receivers); // SS220-Add-Languages /// /// Use this event to cancel sending message per receiver diff --git a/Content.Server/SS220/Language/LanguageSystem.cs b/Content.Server/SS220/Language/LanguageSystem.cs new file mode 100644 index 000000000000..dc33c8e87988 --- /dev/null +++ b/Content.Server/SS220/Language/LanguageSystem.cs @@ -0,0 +1,152 @@ +// © SS220, An EULA/CLA with a hosting restriction, full text: https://raw.githubusercontent.com/SerbiaStrong-220/space-station-14/master/CLA.txt +using Content.Server.GameTicking.Events; +using Content.Shared.SS220.Language; +using Robust.Shared.Prototypes; +using Robust.Shared.Random; +using System.Linq; +using System.Text; +using System.Text.RegularExpressions; + + +namespace Content.Server.SS220.Language; +public sealed partial class LanguageSystem : SharedLanguageSystem +{ + [Dependency] private readonly IRobustRandom _random = default!; + [Dependency] private readonly IPrototypeManager _prototypeManager = default!; + + public override void Initialize() + { + base.Initialize(); + SubscribeLocalEvent(OnRoundStart); + SubscribeLocalEvent(OnMapInit); + } + + private static readonly Dictionary ScrambleCache = new Dictionary(); + private const int SCRAMBLE_CACHE_LEN = 20; + + private void OnRoundStart(RoundStartingEvent args) + { + ScrambleCache.Clear(); + } + + /// + /// Initializes an entity with a language component, + /// either the first language in the LearnedLanguages list into the CurrentLanguage variable + /// + private void OnMapInit(Entity ent, ref MapInitEvent args) + { + if (ent.Comp.CurrentLanguage == null) + ent.Comp.CurrentLanguage = ent.Comp.LearnedLanguages.FirstOrDefault("Universal"); + + Dirty(ent.Owner, ent.Comp); + } + + /// + /// A method of encrypting the original message into a message created + /// from the syllables of prototypes languages + /// + public string ScrambleText(EntityUid? ent, string input, LanguagesPrototype proto) + { + input = RemoveColorTags(input); + var cacheKey = $"{proto.ID}:{input}"; + + // If the original message is already there earlier encrypted, + // it is taken from the cache, it is necessary for the correct display when sending in the radio, + // when the character whispers and transmits a message to the radio + if (ScrambleCache.TryGetValue(cacheKey, out var cachedValue)) + { + ScrambleCache.Remove(cacheKey); + ScrambleCache[cacheKey] = cachedValue; + return cachedValue; + } + + var scrambledText = Scramble(input, proto); + + ScrambleCache[cacheKey] = scrambledText; + // Removes the first message from the cache if it fills up + if (ScrambleCache.Count > SCRAMBLE_CACHE_LEN) + { + var keysToRemove = ScrambleCache.Keys.Take(ScrambleCache.Count - SCRAMBLE_CACHE_LEN).ToList(); + foreach (var key in keysToRemove) + { + ScrambleCache.Remove(key); + } + } + + return scrambledText; + } + + private string Scramble(string input, LanguagesPrototype proto) + { + if (proto.Syllables == null || proto.Syllables.Count == 0) + return input; + + var scrambledText = new StringBuilder(); + bool capitalize = true; + + while (scrambledText.Length < input.Length) + { + var next = proto.Syllables[_random.Next(proto.Syllables.Count)]; + + if (capitalize) + { + next = char.ToUpper(next[0]) + next.Substring(1); + capitalize = false; + } + + scrambledText.Append(next); + + var chance = _random.Next(100); + if (chance <= 5) + { + scrambledText.Append(proto.JoinOverride); + capitalize = true; + } + else if (chance > 5 && chance <= proto.SpaceChance) + { + scrambledText.Append(" "); + } + } + + var result = scrambledText.ToString().Trim(); + var punctuation = ExtractPunctuation(input); + + result += punctuation; + + return result; + } + + /// + /// Takes the last punctuation out of the original post + /// (Does not affect the internal punctuation of the sentence) + /// + private string ExtractPunctuation(string input) + { + var punctuationBuilder = new StringBuilder(); + for (int i = input.Length - 1; i >= 0; i--) + { + if (char.IsPunctuation(input[i])) + punctuationBuilder.Insert(0, input[i]); + else + break; + } + return punctuationBuilder.ToString(); + } + + /// + /// Workaround for some message transmissions. + /// Removes BBCodes colors leaving only the original message. + /// (I couldn't think of anything cleverer) + /// + public string RemoveColorTags(string input) + { + if (string.IsNullOrEmpty(input)) + return input; + + string pattern = @"\[color=#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{8})\](.*?)\[/color\]"; + string cleanedText = Regex.Replace(input, pattern, "$2"); + + return cleanedText; + } +} + diff --git a/Content.Server/SS220/Language/Special/AddLanguageSpecial.cs b/Content.Server/SS220/Language/Special/AddLanguageSpecial.cs new file mode 100644 index 000000000000..2ec6f8dcf12a --- /dev/null +++ b/Content.Server/SS220/Language/Special/AddLanguageSpecial.cs @@ -0,0 +1,23 @@ +// © 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.SS220.Language; +using Content.Shared.Roles; +using JetBrains.Annotations; + + +namespace Content.Server.SS220.Language.Special; +/// +/// Type for giving language to individual job roles +/// +[UsedImplicitly] +public sealed partial class AddLanguageSpecial : JobSpecial +{ + [DataField] + public List Languages { get; private set; } = new(); + + public override void AfterEquip(EntityUid mob) + { + var entMan = IoCManager.Resolve(); + var languageSystem = entMan.System(); + languageSystem.AddLanguage(mob, Languages); + } +} diff --git a/Content.Server/TapeRecorder/TapeRecorderSystem.cs b/Content.Server/TapeRecorder/TapeRecorderSystem.cs index d40499a323b8..d249507a5e42 100644 --- a/Content.Server/TapeRecorder/TapeRecorderSystem.cs +++ b/Content.Server/TapeRecorder/TapeRecorderSystem.cs @@ -2,6 +2,7 @@ using Content.Server.Hands.Systems; using Content.Server.Speech; using Content.Server.Speech.Components; +using Content.Server.SS220.Language; // SS220-Add-Languages using Content.Server.SS220.TTS; // SS220 Tape recorder TTS using Content.Shared.Chat; using Content.Shared.Paper; @@ -24,6 +25,7 @@ public sealed class TapeRecorderSystem : SharedTapeRecorderSystem [Dependency] private readonly IPrototypeManager _proto = default!; [Dependency] private readonly PaperSystem _paper = default!; [Dependency] private readonly TTSSystem _ttsSystem = default!; // SS220 Tape recorder TTS + [Dependency] private readonly LanguageSystem _languageSystem = default!; // SS220-Add-Languages public override void Initialize() { @@ -41,6 +43,7 @@ protected override void ReplayMessagesInSegment(Entity en { var voice = EnsureComp(ent); var speech = EnsureComp(ent); + var language = _languageSystem.GetProto(ent); // SS220 Add languages TryComp(ent, out var tts); // SS220 Tape recorder TTS foreach (var message in tape.RecordedData) @@ -60,7 +63,7 @@ protected override void ReplayMessagesInSegment(Entity en } // SS220 Tape recorder TTS end //Play the message - _chat.TrySendInGameICMessage(ent, message.Message, InGameICChatType.Speak, false); + _chat.TrySendInGameICMessage(ent, message.Message, InGameICChatType.Speak, false, languageProto: language); // SS220-Add-Languages } } diff --git a/Content.Server/Traits/TraitSystem.cs b/Content.Server/Traits/TraitSystem.cs index e19f736f0676..7be11c67ad12 100644 --- a/Content.Server/Traits/TraitSystem.cs +++ b/Content.Server/Traits/TraitSystem.cs @@ -1,6 +1,7 @@ using Content.Server.GameTicking; using Content.Shared.Hands.Components; using Content.Shared.Hands.EntitySystems; +using Content.Shared.SS220.Language; // SS220-Add-Languages using Content.Shared.Roles; using Content.Shared.Traits; using Content.Shared.Whitelist; @@ -47,6 +48,13 @@ private void OnPlayerSpawnComplete(PlayerSpawnCompleteEvent args) // Add all components required by the prototype EntityManager.AddComponents(args.Mob, traitPrototype.Components, false); + // SS220-Add-Languages begin + if (traitPrototype.LearnedLanguage != null) + { + if (TryComp(args.Mob, out var language) && !language.LearnedLanguages.Contains(traitPrototype.LearnedLanguage)) + language.LearnedLanguages.Add(traitPrototype.LearnedLanguage); + } + // SS220-Add-Languages end // Add item required by the trait if (traitPrototype.TraitGear == null) diff --git a/Content.Server/Zombies/ZombieSystem.Transform.cs b/Content.Server/Zombies/ZombieSystem.Transform.cs index 2a88e9df41b9..6998a0d37a9e 100644 --- a/Content.Server/Zombies/ZombieSystem.Transform.cs +++ b/Content.Server/Zombies/ZombieSystem.Transform.cs @@ -40,6 +40,7 @@ using Content.Shared.Humanoid.Markings; using Robust.Server.Player; using Content.Shared.Ghost.Roles.Components; +using Content.Shared.SS220.Language; // SS220-Add-Languages namespace Content.Server.Zombies; @@ -111,6 +112,7 @@ public void ZombifyEntity(EntityUid target, MobStateComponent? mobState = null) RemComp(target); RemComp(target); RemComp(target); + RemComp(target); // SS220-Add-Languages //funny voice var accentType = "zombie"; diff --git a/Content.Shared/SS220/Language/LanguageComponent.cs b/Content.Shared/SS220/Language/LanguageComponent.cs new file mode 100644 index 000000000000..2b0c87f8f5c2 --- /dev/null +++ b/Content.Shared/SS220/Language/LanguageComponent.cs @@ -0,0 +1,29 @@ +// © SS220, An EULA/CLA with a hosting restriction, full text: https://raw.githubusercontent.com/SerbiaStrong-220/space-station-14/master/CLA.txt +using Robust.Shared.GameStates; +using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.List; + + +namespace Content.Shared.SS220.Language; + +/// +/// A component that allows an entity to speak and understand languages. +/// Language prototypes are taken from YML of +/// The absence of this component gives the entity “Universal” language +/// +[RegisterComponent, NetworkedComponent] +[AutoGenerateComponentState] +public sealed partial class LanguageComponent : Component +{ + /// + /// Selected language in which the entity will speak. + /// + [DataField, ViewVariables(VVAccess.ReadWrite), AutoNetworkedField] + public string? CurrentLanguage = default!; + + /// + /// List of languages that the Entity speaks and understands. + /// + [DataField("learnedLanguages", customTypeSerializer: typeof(PrototypeIdListSerializer))] + [AutoNetworkedField] + public List LearnedLanguages { get; set; } = new(); +} diff --git a/Content.Shared/SS220/Language/LanguageVerbs.cs b/Content.Shared/SS220/Language/LanguageVerbs.cs new file mode 100644 index 000000000000..2a5e793958b8 --- /dev/null +++ b/Content.Shared/SS220/Language/LanguageVerbs.cs @@ -0,0 +1,96 @@ +// © 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.Verbs; +using Robust.Shared.Prototypes; + + +namespace Content.Shared.SS220.Language; + +/// +/// I was bored and lazy to understand the UI, +/// according to this language is selected with Verb at the entity +/// +// TODO: Make the language selection in the UI instead of this crap +public sealed partial class LanguageVerbs : EntitySystem +{ + [Dependency] private readonly IPrototypeManager _proto = default!; + [Dependency] private readonly SharedLanguageSystem _languageSystem = default!; + + public override void Initialize() + { + base.Initialize(); + SubscribeLocalEvent>(OnVerb); + } + + private void OnVerb(EntityUid ent, LanguageComponent comp, ref GetVerbsEvent args) + { + if (args.User != args.Target) + return; + + if (!args.CanAccess) + return; + + var verbs = CreateVerbs(ent, comp.LearnedLanguages); + foreach (var verb in verbs) + { + args.Verbs.Add(verb); + } + } + + private List CreateVerbs(EntityUid ent, List languages) + { + var verbs = new List(); + + if (!TryComp(ent, out var comp)) + return verbs; + + foreach (string language in languages) + { + if (language == "Universal") // no verb for a universal language is created + continue; + + verbs.Add(new Verb + { + Text = GetName(language), + Message = GetDescription(language), + Category = VerbCategory.Languages, + Disabled = language == comp.CurrentLanguage, + Act = () => ChangeLanguage(ent, language) + }); + } + + return verbs; + } + + public string GetName(string language) + { + if (!_proto.TryIndex(language, out var proto)) + return language; + + if (proto.Name == null) + return language; + + var name = Loc.GetString(proto.Name); + return name; + } + + public string? GetDescription(string language) + { + if (!_proto.TryIndex(language, out var proto)) + return null; + + if (proto.Description == null) + return null; + + var desc = Loc.GetString(proto.Description); + return desc; + } + + private void ChangeLanguage(EntityUid ent, string language) + { + if (!TryComp(ent, out var comp)) + return; + + comp.CurrentLanguage = language; + Dirty(ent, comp); + } +} diff --git a/Content.Shared/SS220/Language/LanguagesPrototype.cs b/Content.Shared/SS220/Language/LanguagesPrototype.cs new file mode 100644 index 000000000000..626258064dcf --- /dev/null +++ b/Content.Shared/SS220/Language/LanguagesPrototype.cs @@ -0,0 +1,41 @@ +// © SS220, An EULA/CLA with a hosting restriction, full text: https://raw.githubusercontent.com/SerbiaStrong-220/space-station-14/master/CLA.txt +using Robust.Shared.Prototypes; + + +namespace Content.Shared.SS220.Language; + +[Prototype("languages")] +public sealed partial class LanguagesPrototype : IPrototype +{ + [ViewVariables, IdDataField] + public string ID { get; private set; } = default!; + + [DataField] + public string? Name { get; private set; } + + [DataField] + public string? Description { get; private set; } + /// + /// List of syllables from which the original message will be encrypted + /// A null value does not scramlbe the message in any way + /// + [DataField] + public List? Syllables = new(); + /// + /// Chance of space between scrambled syllables + /// + [DataField] + public float SpaceChance { get; private set; } = default!; + /// + /// Chance for a dot after a scrambled syllable, + /// here you can assign any character instead of a dot + /// + [DataField] + public string JoinOverride { get; private set; } = ". "; + /// + /// The color of the language in which messages will be recolored, + /// an empty value will not be recolored + /// + [DataField] + public Color? Color; +} diff --git a/Content.Shared/SS220/Language/SharedLanguageSystem.cs b/Content.Shared/SS220/Language/SharedLanguageSystem.cs new file mode 100644 index 000000000000..b7b90f45ae6b --- /dev/null +++ b/Content.Shared/SS220/Language/SharedLanguageSystem.cs @@ -0,0 +1,121 @@ +// © 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.Ghost; +using Robust.Shared.Prototypes; + + + +namespace Content.Shared.SS220.Language; + +public abstract class SharedLanguageSystem : EntitySystem +{ + [Dependency] private readonly IPrototypeManager _proto = default!; + + /// + /// Method that checks an entity for the presence of a prototype language + /// or for the presence of a universal language + /// + public bool CheckLanguage(EntityUid ent, LanguagesPrototype? proto) + { + if (proto == null) + return false; + + if (KnowsUniversalLanguage(ent)) + return true; + + return KnowsLanguages(ent, proto.ID); + } + + public bool KnowsLanguages(EntityUid ent, string languageId) + { + if (!TryComp(ent, out var comp)) + return false; + + if (comp.CurrentLanguage == languageId) + return true; + + return comp.LearnedLanguages.Contains(languageId); + } + + public bool KnowsUniversalLanguage(EntityUid ent) + { + if (HasComp(ent)) + return true; + + if (!TryComp(ent, out var comp) && _proto.TryIndex("Universal", out _)) + return true; + + if (comp != null && comp.CurrentLanguage == "Universal") + return true; + + if (comp != null && comp.LearnedLanguages.Contains("Universal")) + return true; + + return false; + } + + /// + /// A method to get a prototype language from an entity. + /// If the entity does not have a language component, a universal language is assigned. + /// + public LanguagesPrototype? GetProto(EntityUid ent) + { + if (!TryComp(ent, out var comp)) + { + if (_proto.TryIndex("Universal", out var universalProto)) + return universalProto; + } + + var languageID = GetLanguage(ent); + + if (languageID == null) + return null; + + if (_proto.TryIndex(languageID, out var proto)) + return proto; + + return null; + } + + public string? GetLanguage(EntityUid ent) + { + if (!TryComp(ent, out var comp)) + return null; + + return comp.CurrentLanguage; + } + + public void AddLanguage(EntityUid ent, List languages) + { + if (!TryComp(ent, out var comp)) + return; + + foreach(var language in languages) + { + if (!_proto.TryIndex(language, out var proto)) + continue; + + if (!comp.LearnedLanguages.Contains(language)) + comp.LearnedLanguages.Add(language); + } + } + + /// + /// Sets the color of the prototype language to the message + /// + public string SetColor(string message, LanguagesPrototype proto) + { + if (proto.Color == null) + return message; + + var color = proto.Color.Value.ToHex(); + message = $"[color={color}]{message}[/color]"; + return message; + } +} + + + + + + + diff --git a/Content.Shared/Traits/TraitPrototype.cs b/Content.Shared/Traits/TraitPrototype.cs index c79d3cbf308e..f6198a8d14c5 100644 --- a/Content.Shared/Traits/TraitPrototype.cs +++ b/Content.Shared/Traits/TraitPrototype.cs @@ -60,4 +60,7 @@ public sealed partial class TraitPrototype : IPrototype /// [DataField] public ProtoId? Category; + + [DataField] + public string? LearnedLanguage { get; private set; } // SS220-Add-Languages } diff --git a/Content.Shared/Verbs/VerbCategory.cs b/Content.Shared/Verbs/VerbCategory.cs index 4647a921d545..6ed0a55a81ce 100644 --- a/Content.Shared/Verbs/VerbCategory.cs +++ b/Content.Shared/Verbs/VerbCategory.cs @@ -95,5 +95,9 @@ public VerbCategory(string text, string? icon, bool iconsOnly = false) //SS220-SpecialSound-system end public static readonly VerbCategory PowerLevel = new("verb-categories-power-level", null); + + // SS220-Add-Languages begin + public static readonly VerbCategory Languages = new("verb-categories-languages-selector", "/Textures/SS220/Interface/VerbIcons/language_icon.svg.192dpi.png"); + // SS220-Add-Languages end } } diff --git a/Resources/Locale/ru-RU/ss220/language/language-cmd.ftl b/Resources/Locale/ru-RU/ss220/language/language-cmd.ftl new file mode 100644 index 000000000000..ceec4fdcbc71 --- /dev/null +++ b/Resources/Locale/ru-RU/ss220/language/language-cmd.ftl @@ -0,0 +1,13 @@ +# Desc +cmd-language-add-desc = Добавляет язык в LanguageComponent энтити +cmd-language-remove-desc = Удаляет язык из LanguageComponent энтити +cmd-language-clear-desc = Удаляет все языки из LanguageComponent энтити +# Message +cmd-language-invalid-id = Некорректный энтити ID +cmd-language-comp-miss = У энтити отсутсвует LanguageComponent +cmd-language-proto-miss = Некорректный прототип языка +cmd-language-success-add = Язык успешно добавлен +cmd-language-succes-remove = Язык удален +cmd-language-fail-remove = Энтити не обладает таким языком +cmd-language-already-have = Энтити уже знает этот язык +cmd-language-clear = Все языки энтити - удалены \ No newline at end of file diff --git a/Resources/Locale/ru-RU/ss220/language/language-desc.ftl b/Resources/Locale/ru-RU/ss220/language/language-desc.ftl new file mode 100644 index 000000000000..f13bce4d0de2 --- /dev/null +++ b/Resources/Locale/ru-RU/ss220/language/language-desc.ftl @@ -0,0 +1,21 @@ +# Sources: https://wiki.ss220.club/index.php/%D0%AF%D0%B7%D1%8B%D0%BA%D0%B8 and https://wiki14.ss220.club/index.php?title=%D0%9B%D0%BE%D1%80 + +# Galactic common languages +language-galacticcommon-desc = Дружелюбный для иных рас язык, введёный правительством ТСФ в связи с насплывом сектор иммигрантов представляющие многочисленное количества рас. +language-solcommon-desc = Родной язык людей. Убийственный гибрид неформального английского и элементов мандаринского китайского, общий язык Солнечной системы. +language-tradeband-desc = Это тщательно продуманная манера говорить с использованием множества слов из многих инопланетных языков, а также из ряда человеческих. +language-gutter-desc = Используется в основном только гражданами НЕИЗВЕСТНОЙ забытой республики. Современный является продуктом смешения латинских языков, французского и итальянского. +language-clownish-desc = Язык клоунской планеты. Родной язык клоунов по всей галактике. +language-neorusskiya-desc = Смесь общесолнечного и славянских языков. Официальный язык СССП. +# Languages of race +language-unathi-desc = Язык с множеством разных акцентов и диалектов, и унати может почти сразу сказать, откуда произошел другой, из-за их разрозненного, сгруппированного и широко распространенного обитания в Могесе. +language-siiktajr-desc = Один из многих языков, на которых говорят таяраны Адомая, — это примитивный язык, который считается наиболее часто встречающимся у представителей этого вида. +language-voxpidgin-desc = Общий язык различных воксов, составляющих Шоал. Для всех прочих звучит как хаотичные вопли. +language-rootspeak-desc = Скрипучий субголосый язык, на котором инстинктивно говорят дионы. Из-за уникального состава средней дионы фразы песни корней могут представлять собой комбинацию от одного до двенадцати отдельных голосов и нот. +language-bobblish-desc = Произносится с помощью определенной комбинации хлопающих звуков, легко понимаемых другими слаймами. +language-tkachi-desc = В основе языка лежат жужжащие звуки. Для построения речи используется ритмичность, длительность издаваемых звуков, интервал, интонация. +language-eldwarf-desc = Грубый язык с малым количеством гласных. +language-arati-desc = Достаточно грубый язык, в котором большое количество шипящих звуков. +language-canilunzt-desc = Гортанный язык, на котором говорят и используют жители системы Ваззенда, состоит из рычания, лая, тявканья и интенсивного использования ушей и движений хвоста. +# Misc +language-binary-desc = Свободные протоколы связи и концентраторы маршрутизации для использования синтетиками. Большинство человеческих станций их поддерживают. \ No newline at end of file diff --git a/Resources/Locale/ru-RU/ss220/language/language-name.ftl b/Resources/Locale/ru-RU/ss220/language/language-name.ftl new file mode 100644 index 000000000000..029c6c1a2202 --- /dev/null +++ b/Resources/Locale/ru-RU/ss220/language/language-name.ftl @@ -0,0 +1,19 @@ +# Galactic common languages +language-galacticcommon-name = Общегалактический +language-solcommon-name = Общесолнечный +language-tradeband-name = Торговый +language-gutter-name = Гуттэр +language-clownish-name = Клоунский +language-neorusskiya-name = Нео-Русский +# Languages of race +language-unathi-name = Синта’Унати +language-siiktajr-name = Сик’таир +language-voxpidgin-name = Вокс-пиджин +language-rootspeak-name = Песнь корней +language-bobblish-name = Пузырчатый +language-tkachi-name = Ткачий +language-eldwarf-name = Эл’Дварф +language-arati-name = Арати +language-canilunzt-name = Канилунц +# Misc +language-binary-name = Бинарный канал \ No newline at end of file diff --git a/Resources/Locale/ru-RU/ss220/language/language-trait-category.ftl b/Resources/Locale/ru-RU/ss220/language/language-trait-category.ftl new file mode 100644 index 000000000000..6ffcdc16e017 --- /dev/null +++ b/Resources/Locale/ru-RU/ss220/language/language-trait-category.ftl @@ -0,0 +1 @@ +trait-category-languages = Дополнительный язык \ No newline at end of file diff --git a/Resources/Locale/ru-RU/ss220/taperecorder/taperecorder.ftl b/Resources/Locale/ru-RU/ss220/taperecorder/taperecorder.ftl index 9d0ad1600699..fb49356f0585 100644 --- a/Resources/Locale/ru-RU/ss220/taperecorder/taperecorder.ftl +++ b/Resources/Locale/ru-RU/ss220/taperecorder/taperecorder.ftl @@ -28,7 +28,7 @@ tape-recorder-print-message-text = [bold][{$time}] {$source}: [/bold] {$message} tape-recorder-print-end-text = [bold]Конец стенограммы записи[/bold] ent-TapeRecorder = диктофон - .desc = Всё что будет сказано в это устройство может и будет использовано против вас в суде космического закона. + .desc = Всё что будет сказано в это устройство может и будет использовано против вас в суде космического закона. Во время великой межсистемной войны, в целях разведки ТСФ, был оснащён встроенным переводчиком. ent-CassetteTape = кассета диктофона .desc = Кассета с магнитной лентой которая может содержать до двух минут записи. ent-TapeRecorderTranscript = стенограмма записи диктофона diff --git a/Resources/Locale/ru-RU/ss220/verbs/verb-system.ftl b/Resources/Locale/ru-RU/ss220/verbs/verb-system.ftl index 3458203a78a2..f6a020c244ce 100644 --- a/Resources/Locale/ru-RU/ss220/verbs/verb-system.ftl +++ b/Resources/Locale/ru-RU/ss220/verbs/verb-system.ftl @@ -1,2 +1,5 @@ verb-categories-attach-cart = Прикрепить -verb-categories-deattach-cart = Открепить \ No newline at end of file +verb-categories-deattach-cart = Открепить +#SS220-Add-Languages begin +verb-categories-languages-selector = Выбрать язык +#SS220-Add-Languages end \ No newline at end of file diff --git a/Resources/Prototypes/Entities/Mobs/Cyborgs/base_borg_chassis.yml b/Resources/Prototypes/Entities/Mobs/Cyborgs/base_borg_chassis.yml index 906994db6b64..361ff1eadf10 100644 --- a/Resources/Prototypes/Entities/Mobs/Cyborgs/base_borg_chassis.yml +++ b/Resources/Prototypes/Entities/Mobs/Cyborgs/base_borg_chassis.yml @@ -248,6 +248,13 @@ damageProtection: flatReductions: Heat: 10 # capable of touching light bulbs and stoves without feeling pain! + # SS220-Add-Languages begin + - type: Language + learnedLanguages: + - Galactic + - Binary + - Universal + # SS220-Add-Languages end - type: entity abstract: true diff --git a/Resources/Prototypes/Entities/Mobs/Species/arachnid.yml b/Resources/Prototypes/Entities/Mobs/Species/arachnid.yml index 2c17e881ddcd..024f10bcb7d1 100644 --- a/Resources/Prototypes/Entities/Mobs/Species/arachnid.yml +++ b/Resources/Prototypes/Entities/Mobs/Species/arachnid.yml @@ -80,6 +80,12 @@ speechVerb: Arachnid speechSounds: Arachnid allowedEmotes: ['Click', 'Chitter', 'Hiss'] #ss-220-emote-fix + # SS220-Add-Languages begin + - type: Language + learnedLanguages: + - Galactic + - Arati + # SS220-Add-Languages end - type: Vocal sounds: Male: UnisexArachnid diff --git a/Resources/Prototypes/Entities/Mobs/Species/diona.yml b/Resources/Prototypes/Entities/Mobs/Species/diona.yml index 79c913af06cb..916111fd155b 100644 --- a/Resources/Prototypes/Entities/Mobs/Species/diona.yml +++ b/Resources/Prototypes/Entities/Mobs/Species/diona.yml @@ -118,6 +118,12 @@ actionPrototype: DionaGibAction allowedStates: - Dead + # SS220-Add-Languages begin + - type: Language + learnedLanguages: + - Galactic + - Rootspeak + # SS220-Add-Languages end - type: Inventory templateId: diona femaleDisplacements: diff --git a/Resources/Prototypes/Entities/Mobs/Species/dwarf.yml b/Resources/Prototypes/Entities/Mobs/Species/dwarf.yml index 69f0a51825aa..7a7daa6b2e9c 100644 --- a/Resources/Prototypes/Entities/Mobs/Species/dwarf.yml +++ b/Resources/Prototypes/Entities/Mobs/Species/dwarf.yml @@ -61,6 +61,12 @@ accent: dwarf - type: Speech speechSounds: Bass + # SS220-Add-Languages begin + - type: Language + learnedLanguages: + - Galactic + - Eldwarf + # SS220-Add-Languages end - type: HumanoidAppearance species: Human hideLayersOnEquip: diff --git a/Resources/Prototypes/Entities/Mobs/Species/human.yml b/Resources/Prototypes/Entities/Mobs/Species/human.yml index 9aa36e4ec528..82d65b4c3eac 100644 --- a/Resources/Prototypes/Entities/Mobs/Species/human.yml +++ b/Resources/Prototypes/Entities/Mobs/Species/human.yml @@ -20,6 +20,12 @@ hideLayersOnEquip: - Hair - Snout + # SS220-Add-Languages begin + - type: Language + learnedLanguages: + - Galactic + - SolCommon + # SS220-Add-Languages end - type: Inventory femaleDisplacements: jumpsuit: diff --git a/Resources/Prototypes/Entities/Mobs/Species/moth.yml b/Resources/Prototypes/Entities/Mobs/Species/moth.yml index 05057ceddfb8..5ad75e1a4270 100644 --- a/Resources/Prototypes/Entities/Mobs/Species/moth.yml +++ b/Resources/Prototypes/Entities/Mobs/Species/moth.yml @@ -140,6 +140,12 @@ sprite: "Effects/creampie.rsi" state: "creampie_moth" visible: false + # SS220-Add-Languages begin + - type: Language + learnedLanguages: + - Galactic + - Tkachi + # SS220-Add-Languages end - type: Inventory femaleDisplacements: jumpsuit: diff --git a/Resources/Prototypes/Entities/Mobs/Species/reptilian.yml b/Resources/Prototypes/Entities/Mobs/Species/reptilian.yml index 35ed18a135ca..092c700f07cc 100644 --- a/Resources/Prototypes/Entities/Mobs/Species/reptilian.yml +++ b/Resources/Prototypes/Entities/Mobs/Species/reptilian.yml @@ -88,6 +88,12 @@ 295: 0.6 285: 0.4 - type: Wagging + # SS220-Add-Languages begin + - type: Language + learnedLanguages: + - Galactic + - Sintaunathi + # SS220-Add-Languages end - type: Inventory speciesId: reptilian femaleDisplacements: diff --git a/Resources/Prototypes/Entities/Mobs/Species/slime.yml b/Resources/Prototypes/Entities/Mobs/Species/slime.yml index 00a5db311dd5..721cafb8a7dd 100644 --- a/Resources/Prototypes/Entities/Mobs/Species/slime.yml +++ b/Resources/Prototypes/Entities/Mobs/Species/slime.yml @@ -140,6 +140,12 @@ types: Asphyxiation: -1.0 maxSaturation: 15 + # SS220-Add-Languages begin + - type: Language + learnedLanguages: + - Galactic + - Bubblish + # SS220-Add-Languages end - type: Inventory femaleDisplacements: jumpsuit: diff --git a/Resources/Prototypes/Entities/Mobs/Species/vox.yml b/Resources/Prototypes/Entities/Mobs/Species/vox.yml index 31a7d92bd6cf..cd2cb49a4a7a 100644 --- a/Resources/Prototypes/Entities/Mobs/Species/vox.yml +++ b/Resources/Prototypes/Entities/Mobs/Species/vox.yml @@ -113,6 +113,12 @@ sprite: "Effects/creampie.rsi" state: "creampie_vox" # Not default visible: false + # SS220-Add-Languages begin + - type: Language + learnedLanguages: + - Galactic + - VoxPidgin + # SS220-Add-Languages end - type: Inventory speciesId: vox displacements: diff --git a/Resources/Prototypes/Entities/Objects/Fun/pai.yml b/Resources/Prototypes/Entities/Objects/Fun/pai.yml index 4bf55be52bd9..838467982052 100644 --- a/Resources/Prototypes/Entities/Objects/Fun/pai.yml +++ b/Resources/Prototypes/Entities/Objects/Fun/pai.yml @@ -79,6 +79,12 @@ whitelist: components: - SecretStash + # SS220-Add-Languages begin + - type: Language + learnedLanguages: + - Galactic + - Universal + # SS220-Add-Languages end - type: entity parent: [ PersonalAI] diff --git a/Resources/Prototypes/Entities/Objects/Specific/Robotics/mmi.yml b/Resources/Prototypes/Entities/Objects/Specific/Robotics/mmi.yml index 33eabbb60b52..82b023a5f270 100644 --- a/Resources/Prototypes/Entities/Objects/Specific/Robotics/mmi.yml +++ b/Resources/Prototypes/Entities/Objects/Specific/Robotics/mmi.yml @@ -53,6 +53,13 @@ whitelist: components: - SecretStash + # SS220-Add-Languages begin + - type: Language + learnedLanguages: + - Galactic + - Binary + - Universal + # SS220-Add-Languages end - type: entity parent: MMI @@ -101,6 +108,11 @@ - type: IntrinsicRadioTransmitter channels: - Binary + - type: Language + learnedLanguages: + - Galactic + - Binary + - Universal - type: ActiveRadio channels: - Binary diff --git a/Resources/Prototypes/Roles/Jobs/Civilian/clown.yml b/Resources/Prototypes/Roles/Jobs/Civilian/clown.yml index c84f9079e566..bce11c7e4d9a 100644 --- a/Resources/Prototypes/Roles/Jobs/Civilian/clown.yml +++ b/Resources/Prototypes/Roles/Jobs/Civilian/clown.yml @@ -30,6 +30,11 @@ interval: 10 - !type:AddImplantSpecial implants: [ SadTromboneImplant ] + # SS220-Add-Languages begin + - !type:AddLanguageSpecial + languages: + - Clownish + # SS220-Add-Languages end - type: startingGear id: ClownGear diff --git a/Resources/Prototypes/SS220/Entities/Mobs/NPCs/animals.yml b/Resources/Prototypes/SS220/Entities/Mobs/NPCs/animals.yml index 6048b02bce6b..96ae966a9c2c 100644 --- a/Resources/Prototypes/SS220/Entities/Mobs/NPCs/animals.yml +++ b/Resources/Prototypes/SS220/Entities/Mobs/NPCs/animals.yml @@ -268,6 +268,11 @@ autoRot: true radius: 2 netsync: false + - type: Language + learnedLanguages: + - Galactic + - Binary + - Universal - type: entity name: крокодил diff --git a/Resources/Prototypes/SS220/Entities/Mobs/Species/felinid.yml b/Resources/Prototypes/SS220/Entities/Mobs/Species/felinid.yml index 2a0a03d333e8..de349fdadf47 100644 --- a/Resources/Prototypes/SS220/Entities/Mobs/Species/felinid.yml +++ b/Resources/Prototypes/SS220/Entities/Mobs/Species/felinid.yml @@ -111,6 +111,9 @@ #MEOW LESS OK THX - type: Emoting chatEmoteCooldown: 5.0 + - type: Language + learnedLanguages: + - Galactic - type: entity save: false diff --git a/Resources/Prototypes/SS220/Entities/Mobs/Species/tajaran.yml b/Resources/Prototypes/SS220/Entities/Mobs/Species/tajaran.yml index 25db56f1d01c..72d99a3f25d2 100644 --- a/Resources/Prototypes/SS220/Entities/Mobs/Species/tajaran.yml +++ b/Resources/Prototypes/SS220/Entities/Mobs/Species/tajaran.yml @@ -107,6 +107,10 @@ visionRadius: 5 highSensitiveVisionRadius: 2 addAction: true + - type: Language + learnedLanguages: + - Galactic + - Siiktajr - type: entity id: MobTajaranDummy diff --git a/Resources/Prototypes/SS220/Entities/Mobs/Species/vulpkanin.yml b/Resources/Prototypes/SS220/Entities/Mobs/Species/vulpkanin.yml index e369d58d687b..201d37b18eb9 100644 --- a/Resources/Prototypes/SS220/Entities/Mobs/Species/vulpkanin.yml +++ b/Resources/Prototypes/SS220/Entities/Mobs/Species/vulpkanin.yml @@ -69,6 +69,10 @@ damage: types: Slash: 5.5 + - type: Language + learnedLanguages: + - Galactic + - Canilunzt #если будет дальнейшее обсуждение и одобрение, займусь этой рассой для раундстартового состояния. Пока так diff --git a/Resources/Prototypes/SS220/Entities/Objects/Fun/pai.yml b/Resources/Prototypes/SS220/Entities/Objects/Fun/pai.yml index abaf5689ddb8..1f829f388de2 100644 --- a/Resources/Prototypes/SS220/Entities/Objects/Fun/pai.yml +++ b/Resources/Prototypes/SS220/Entities/Objects/Fun/pai.yml @@ -84,3 +84,9 @@ - type: Vocal # SS220 borg emotes to PAI start sounds: Unsexed: UnisexSilicon # SS220 borg emotes to PAI end + # SS220-Add-Languages begin + - type: Language + learnedLanguages: + - Galactic + - Universal + # SS220-Add-Languages end \ No newline at end of file diff --git a/Resources/Prototypes/SS220/Geras/slime.yml b/Resources/Prototypes/SS220/Geras/slime.yml index 8fe21ee27960..27cb6d444c89 100644 --- a/Resources/Prototypes/SS220/Geras/slime.yml +++ b/Resources/Prototypes/SS220/Geras/slime.yml @@ -32,3 +32,9 @@ Base: blue_adult_slime Dead: Base: blue_adult_slime_dead + # SS220-Add-Languages begin + - type: Language + learnedLanguages: + - Galactic + - Bubblish + # SS220-Add-Languages end \ No newline at end of file diff --git a/Resources/Prototypes/SS220/Language/language.yml b/Resources/Prototypes/SS220/Language/language.yml new file mode 100644 index 000000000000..1fbc677bb58e --- /dev/null +++ b/Resources/Prototypes/SS220/Language/language.yml @@ -0,0 +1,176 @@ +# Based on SS13 Paradise (https://github.com/ParadiseSS13/Paradise/blob/017a56f8080361f04c296c94859802aaddf25114/code/modules/mob/language.dm#L4) + +# Everyone understands you, you understand everyone, but there's no right to speak all languages +- type: languages + id: Universal + syllables: [] + +# Galactic common lanaguges region: +- type: languages + id: Galactic + name: "language-galacticcommon-name" + description: "language-galacticcommon-desc" + spaceChance: 50 + syllables: [бла, бла, бла, бле, мех, ньех, нах, ах, угу, увы] + +- type: languages + id: SolCommon + name: "language-solcommon-name" + description: "language-solcommon-desc" + color: "#2f2fad" + spaceChance: 50 + syllables: [tao, shi, tzu, yi, com, be, is, i, op, vi, ed, lec, mo, cle, te, dis, e] + +- type: languages + id: Tradeband + name: "language-tradeband-name" + description: "language-tradeband-desc" + color: "#87451c" + spaceChance: 100 + syllables: [lorem, ipsum, dolor, sit, amet, consectetur, adipiscing, elit, sed, do, eiusmod, tempor, incididunt, ut, labore, + et, dolore, magna, aliqua, ut, enim, ad, minim, veniam, quis, nostrud, exercitation, + ullamco, laboris, nisi, ut, aliquip, ex, ea, commodo, consequat, duis, aute, irure, + dolor, in, reprehenderit, in, voluptate, velit, esse, cillum, dolore, eu, fugiat, + nulla, pariatur, excepteur, sint, occaecat, cupidatat, non, proident, sunt, in, + culpa, qui, officia, deserunt, mollit, anim, id, est, laborum] + +- type: languages + id: Gutter + name: "language-gutter-name" + description: "language-gutter-desc" + color: "#7092BE" + spaceChance: 55 + syllables: [gra, ba, ba, breh, bra, rah, dur, ra, ro, gro, go, ber, bar, geh, heh, gra] + +- type: languages + id: Clownish + name: "language-clownish-name" + description: "language-clownish-desc" + color: "#ff0000" + spaceChance: 60 + syllables: [хонк, cкуик, ойк, бонк, тут, наф, пуп, ви, вуб, ниф] + +- type: languages + id: NeoRusskiya + name: "language-neorusskiya-name" + description: "language-neorusskiya-desc" + color: "#7c4848" + spaceChance: 65 + syllables: [dyen, bar, bota, vyek, tvo, slov, slav, syen, doup, vah, laz, gloz, + yet, nyet, da, sky, glav, glaz, netz, doomat, zat, moch, boz, comy, vrad, vrade, + tay, bli, ay, nov, livn, tolv, glaz, gliz, ouy, zet, yevt, dat, botat, nev, novy, vzy, + nov, sho, obsh, dasky, key, skey, ovsky, skaya, bib, kiev, studen, var, bul, vyan, tzion, + vaya, myak, gino, volo, olam, miti, nino, menov, perov, odasky, trov, niki, ivano, dostov, + sokol, oupa, pervom, schel, tizan, chka, tagan, dobry, okt, boda, veta, idi, cyk, blyt, hui, + na, udi, litchki, casa, linka, toly, anatov, vich, vech, vuch, toi, ka, vod] + +# Race region: +- type: languages + id: Sintaunathi + name: "language-unathi-name" + description: "language-unathi-desc" + color: "#228B22" + spaceChance: 50 + syllables: [za, az, ze, ez, zi, iz, zo, oz, zu, uz, zs, sz, ha, ah, he, eh, + hi, ih, ho, oh, hu, uh, hs, sh, la, al, le, el, li, il, lo, ol, + lu, ul, ls, sl, ka, ak, ke, ek, ki, ik, ko, ok, ku, uk, ks, sk, + sa, as, se, es, si, is, so, os, su, us, ss, ss, ra, ar, re, er, + ri, ir, ro, or, ru, ur, rs, sr, a, a, e, e, i, i, o, o, u, u, + s, s] + +- type: languages + id: Siiktajr + name: "language-siiktajr-name" + description: "language-siiktajr-desc" + color: "#803B56" + spaceChance: 40 + syllables: [rr, rrr, taj'r, kir, raj, kii, mir, kah, hrar, jun, + kra, ahkъ, nal, vah, khaz, jri, ran, hal, nja, dar, + darr, mi, jr'i, dynh, manq', rhe, zar, ketъ, rir, rik, + r'rhaz, kal, chur, eech, thaa, dra, jurl, jurl, azuъ, + mah, sanu, dra, ii'r, ъka, aasi, far, mah, tul, ragh + wa, baq, ara, qara, zir', sam, mak, cresh, khan] + +- type: languages + id: VoxPidgin + name: "language-voxpidgin-name" + description: "language-voxpidgin-desc" + color: "#AA00AA" + spaceChance: 50 + syllables: [ti, ti, ti, hi, hi, ki, ki, ki, + ki, ya, ta, ha, ka, ya, yi, chi, cha, kah, + SKRE, AHK, EHK, RAWK, KRA, AAA, EEE, KI, + II, KRI, KA] + +- type: languages + id: Rootspeak + name: "language-rootspeak-name" + description: "language-rootspeak-desc" + color: "#804000" + spaceChance: 30 + syllables: [hs, zt, kr, st, sh] + +- type: languages + id: Bubblish + name: "language-bobblish-name" + description: "language-bobblish-desc" + color: "#0077AA" + spaceChance: 60 + syllables: [блоб, плап, поп, боп, буп, пламп, буб, баб, бламп] + +- type: languages + id: Tkachi + name: "language-tkachi-name" + description: "language-tkachi-desc" + color: "#869b29" + spaceChance: 55 + joinOverride: "-" + syllables: [år, i, går, sek, mo, ff, ok, gj, ø, gå, la, le, lit, ygg, van, + dår, næ, møt, idd, hvo, ja, på, han, så, ån, det, att, nå, gö, bra, + int, tyc, om, när, två, må, dag, sjä, vii, vuo, eil, tun, käyt, teh, + vä, hei, huo, suo, ää, ten, ja, heu, stu, uhr, kön, we, hön] + +- type: languages + id: Eldwarf + name: "language-eldwarf-name" + description: "language-eldwarf-desc" + color: "#515d63" + spaceChance: 55 + syllables: [вр, врон, рон, крон, друк, трым, бд, шкж, брм, рыт, грн, драш, клм, трк, врг, хрм, + рд, клыт, зм, эмээ, гнык, зрм, длк, брг, грд, скрын, вродд, бдар, глтх, скрр, + трг, бртх, хыкл, тр, крг, рдм, грыж, мд, гхрм, клм, прк, кнур] + +- type: languages + id: Arati + name: "language-arati-name" + description: "language-arati-desc" + color: "#68477a" + spaceChance: 52 + joinOverride: "'" + syllables: [шаш, хаш, раш, шар, хра, хашт, шара, шкар, храк, тар, хар, схр, + карш, аш, шр, зз, ср, хаз, рашк, харш, рашн, шан, харз, шах, шарз, рашар, + кар, харат, хш, харр, арш', ашан, шанн, хсар, ашат, хаа, хазт, рашта, зара, + хаш, анн, аро', хат] + +- type: languages + id: Canilunzt + name: "language-canilunzt-name" + description: "language-canilunzt-desc" + color: "#B97A57" + spaceChance: 45 + syllables: [rur, ya, cen, rawr, bar, kuk, tek, qat, uk, wu, vuh, tah, tch, schz, auch, + ist, ein, entch, zwichs, tut, mir, wo, bis, es, vor, nic, gro, lll, + enem, zandt, tzch, noch, hel, ischt, far, wa, baram, iereng, tech, lach, + sam, mak, lich, gen, or, ag, eck, gec, stag, onn, bin, ket, jarl, vulf, + einech, cresthz, azunein, ghzth] + +# Misc region: +- type: languages + id: Binary + name: "language-binary-name" + description: "language-binary-desc" + color: "#2cc2e8" + spaceChance: 80 + joinOverride: " " + syllables: [1, 0, 01, 10, 11, 100, 101, 110, 111, 1000, 1001, 1010, 1011, + 1100, 1110, 1111, 10000, 10001, 10010, 10011, 10100, 10101] \ No newline at end of file diff --git a/Resources/Prototypes/SS220/Traits/language_traits.yml b/Resources/Prototypes/SS220/Traits/language_traits.yml new file mode 100644 index 000000000000..85daa97d4525 --- /dev/null +++ b/Resources/Prototypes/SS220/Traits/language_traits.yml @@ -0,0 +1,47 @@ +- type: trait + id: TradebandLanguage + name: "language-tradeband-name" + description: "language-tradeband-desc" + category: Languages + cost: 1 + components: + - type: Language + learnedLanguages: + - Tradeband + learnedLanguage: Tradeband + +- type: trait + id: GutterLanguage + name: "language-gutter-name" + description: "language-gutter-desc" + category: Languages + cost: 1 + components: + - type: Language + learnedLanguages: + - Gutter + learnedLanguage: Gutter + +- type: trait + id: ClownishLanguage + name: "language-clownish-name" + description: "language-clownish-desc" + category: Languages + cost: 1 + components: + - type: Language + learnedLanguages: + - Clownish + learnedLanguage: Clownish + +- type: trait + id: NeoRusskiyaLanguage + name: "language-neorusskiya-name" + description: "language-neorusskiya-desc" + category: Languages + cost: 1 + components: + - type: Language + learnedLanguages: + - NeoRusskiya + learnedLanguage: NeoRusskiya \ No newline at end of file diff --git a/Resources/Prototypes/Traits/categories.yml b/Resources/Prototypes/Traits/categories.yml index d024b3fcff31..b9810d8f3082 100644 --- a/Resources/Prototypes/Traits/categories.yml +++ b/Resources/Prototypes/Traits/categories.yml @@ -10,3 +10,10 @@ - type: traitCategory id: Quirks name: trait-category-quirks + +# SS220-Add-Languages begin +- type: traitCategory + id: Languages + name: trait-category-languages + maxTraitPoints: 1 +# SS220-Add-Languages end \ No newline at end of file diff --git a/Resources/Textures/SS220/Interface/VerbIcons/language_icon.svg b/Resources/Textures/SS220/Interface/VerbIcons/language_icon.svg new file mode 100644 index 000000000000..3a510738a2ec --- /dev/null +++ b/Resources/Textures/SS220/Interface/VerbIcons/language_icon.svg @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/Resources/Textures/SS220/Interface/VerbIcons/language_icon.svg.192dpi.png b/Resources/Textures/SS220/Interface/VerbIcons/language_icon.svg.192dpi.png new file mode 100644 index 0000000000000000000000000000000000000000..ec625cd24a7d3e63fb6f2a56cb6a2a50369dcc52 GIT binary patch literal 3213 zcmbVP2~-p37EXXb0tLak0%8a**pih%7KlIzOCCf)V_6i*kW5GfG9if&1cYc2L6Lw~ zun2X*wIa3nYOI36jVc8Z6&IF*N&zVp5d{Rb69mrdJ9aspGjrzuXTJO0<-2pwnXI4{ ze&(jurU(SWoa4`41>ZgO7upzsK( zSZ_!UVrc|2UO*y|urvk%6atheXOR<@LZXm~WcZ}w$rPqDiAkkkCl4I#PA(KNSFwF3 zoxwX6POMbQm_%Y?Vj>~YnE=V7iDU+YK_pR#6bc?j;1x+yC7{Af6%JDjY)~PPOJqt3 zB*p3(fhcIBl7)jqeV;>|Y?@Z8n5+|AF`^2P5y=FSKBozwP%w>?ZIs7OI2Q_tU@RC1 zN|g#2OPSH8Pz^rhQ7HGD)QOP%hjELO=<82uz_eot^&xhJ+GP(%(Xb0;UL(#{qDa zBym7ANR&yVC%kdFOpa8c1f&9x!)D>&Pze%=km)KCk)r^*3tm75o$&%16~F^@K!68H z00=k(bcTpdow8>`f{l6wr|gBWz0j3HqtHmscq#~p@DzYb!83$ZGG4@>gF-M009;AH zl>JJ%1pb78*niJ6tq{{2iiPA{NC;QiS>L}CeZ=&aC}6RYCclW)VEp7NR)U>q9VQ^q zcQ*?s(8~%6ag&cFAE?Yf%j`XEq8Nlp|3dEfFa;!1CIWKMD;loi-?kI+&w^I~34a~> zKNI!OL;pkb{hQDy%PJ59(r6H#l|-CA8KQouycdP||9VZl`=0?c1&61aemOl);m!0! z2Bk2y9GP8i9XF|APlS#48rEMQ7a#w@*XkYx6jVsD3`FRh_!k()^#DG1CDR|PSYt*Xk5BA^S z(Y9_19$qm18#=beD2(gAWRX=N=BH!sHWjwl>{~|OE;7)#ACB=shUUvoQwJ+{sxiDD z%EOB+TAa)76x<&fM6VPpE_%%|$UL6X^k%is@WS@M_Rw~*$uD>RgO%S~zHaE%H|6h2 z4n!IyB!9=!8AMiDjku*`R1@1BuUikiR0x>ms?pEQcU7Kho1g!P+iJY|O`iL#&yFQU z2XC>>k7T(-mOgZ>JF7KuH7K89sE%K}q^uyg%_uyg0oQ=DOq-d2w2}SXo>O9%hRiki z=2XLqD;RBJTE!VdE&b#Jf~xu5E{9}y`ew9|=u!4d&pdhep4qKBwY|nM!l9%xcGjl& zVBX0(QQa03^&O7sm5)yPu&wHmuA_qw*9_SiH+8fmH`I!P5{Aok*1P;T)pCfZDg+VetP?KSVR z+4a<)M+Yw(wJvBIm_Z&jerL0CIiplrot{_RS!;-iXy^hJIlqQ_mOr+>hdwp%@=z)3 z?RFBQdZ2Fo=8F3(Z#Ii?K|D$o#&Tp$BZ2dT*K;kp@@@KU?qX7NLGJaP4`W-p=cyO_ z9^;;_jde@*K2gz5X`$4Ghz5KLx7IeLn%f?AH%l<|dv3-yPSwrT`Rp-CmCPySUZGNl zA~a@BYG2TITOhyaUGXaKF^}HG{2Cob`|XK`576sua0mi6$)M2ZiQuw_dMv9mEBtE_ z-r)SlKc-s#lGBomh0fY)XzGi%<(_RugT5{%fvE2(?g52$?%%&o#^8EfR7(f6CoW|L z{MyG=hV*T3lAddyGrK4U)OwyX;8-|9ty^u<3%+8XwCTE=C&@PVBzE?>EndV`TOD0D z>~|~8$lb`2;iEJ5u6Kw6-a3H;Q|9D4lDixdC zaNO$KS&3IFwaZ?Z5d2a`E&E!1RoutG;R@@nAx)dO{f^Vz4Oh`xYZVjgfjJlV)RZ5R z<67`IUlEq9H6Jkw&1z;e8t>0P0#sTQqAqTDMjU&+sl~mxyEeq&(p~;JGg`K>j3!@p z?_8FhuB_T;?S{RhF~=M<$vM%xcPE&x{8IU#JJnut$Rn}flQUt`BRJ{dwH*s;#-4so z)igW2lX@<_yqr|z1Z(Mf+jTbp~3$5^N?C17THiQ^nR{Xzl9TIr!EjNJrZhty6A@gr?Cthv#rdZThLUf-+-h-z@_>0g$3)X zEQU=o13Nb2ExHG`bp>yp3nAwmJKKx0J8awEwqvdQ;hwvQb1uJO`f@T|Wg>^p~^9_FI&YFw@n#+#cB*0uY yx4(~sF8lJ}Ma Date: Tue, 12 Nov 2024 06:57:05 +0400 Subject: [PATCH 02/48] whitespaces remove --- .../Chat/Managers/ChatSanitizationManager.cs | 2 +- Content.Server/Chat/Systems/ChatSystem.cs | 18 +++++++++++------- .../Radio/EntitySystems/RadioDeviceSystem.cs | 1 + .../SS220/Language/SharedLanguageSystem.cs | 9 +-------- .../Entities/Objects/Specific/Robotics/mmi.yml | 2 ++ 5 files changed, 16 insertions(+), 16 deletions(-) diff --git a/Content.Server/Chat/Managers/ChatSanitizationManager.cs b/Content.Server/Chat/Managers/ChatSanitizationManager.cs index bd5091f7ae0e..ae5da290ab58 100644 --- a/Content.Server/Chat/Managers/ChatSanitizationManager.cs +++ b/Content.Server/Chat/Managers/ChatSanitizationManager.cs @@ -53,7 +53,7 @@ public sealed class ChatSanitizationManager : IChatSanitizationManager { ":D", "chatsan-smiles-widely" }, { "D:", "chatsan-frowns-deeply" }, { ":O", "chatsan-surprised" }, - { ":3", "chatsan-smiles" }, + { ":3", "chatsan-smiles" }, { ":S", "chatsan-uncertain" }, { ":>", "chatsan-grins" }, { ":<", "chatsan-pouts" }, diff --git a/Content.Server/Chat/Systems/ChatSystem.cs b/Content.Server/Chat/Systems/ChatSystem.cs index dc8e1c2d9ad8..482065d4e35d 100644 --- a/Content.Server/Chat/Systems/ChatSystem.cs +++ b/Content.Server/Chat/Systems/ChatSystem.cs @@ -468,13 +468,13 @@ public void DispatchStationAnnouncement( #region Private API private void SendEntitySpeak( - EntityUid source, - string originalMessage, - ChatTransmitRange range, - string? nameOverride, - bool hideLog = false, - bool ignoreActionBlocker = false - ) + EntityUid source, + string originalMessage, + ChatTransmitRange range, + string? nameOverride, + bool hideLog = false, + bool ignoreActionBlocker = false + ) { if (!_actionBlocker.CanSpeak(source) && !ignoreActionBlocker) return; @@ -606,11 +606,14 @@ private void SendEntityWhisper( var wrappedMessage = Loc.GetString("chat-manager-entity-whisper-wrap-message", ("entityName", name), ("message", message /*SS220-Add-Languages*/)); + var wrappedobfuscatedMessage = Loc.GetString("chat-manager-entity-whisper-wrap-message", ("entityName", nameIdentity), ("message", FormattedMessage.EscapeText(obfuscatedMessage))); + var wrappedUnknownMessage = Loc.GetString("chat-manager-entity-whisper-unknown-wrap-message", ("message", FormattedMessage.EscapeText(obfuscatedMessage))); + foreach (var (session, data) in GetRecipients(source, WhisperMuffledRange)) { if (session.AttachedEntity is not { Valid: true } playerEntity) @@ -656,6 +659,7 @@ private void SendEntityWhisper( else _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))); var ev = new EntitySpokeEvent(source, message, originalMessage, channel, obfuscatedMessage); diff --git a/Content.Server/Radio/EntitySystems/RadioDeviceSystem.cs b/Content.Server/Radio/EntitySystems/RadioDeviceSystem.cs index faceefd6855e..565bbf53bee9 100644 --- a/Content.Server/Radio/EntitySystems/RadioDeviceSystem.cs +++ b/Content.Server/Radio/EntitySystems/RadioDeviceSystem.cs @@ -234,6 +234,7 @@ private void OnReceiveRadio(EntityUid uid, RadioSpeakerComponent component, ref var name = Loc.GetString("speech-name-relay", ("speaker", Name(uid)), ("originalName", nameEv.VoiceName)); + // log to chat so people can identity the speaker/source, but avoid clogging ghost chat if there are many radios _chat.TrySendInGameICMessage(uid, args.Message, InGameICChatType.Whisper, ChatTransmitRange.GhostRangeLimit, nameOverride: name, checkRadioPrefix: false, diff --git a/Content.Shared/SS220/Language/SharedLanguageSystem.cs b/Content.Shared/SS220/Language/SharedLanguageSystem.cs index b7b90f45ae6b..e19062e9d931 100644 --- a/Content.Shared/SS220/Language/SharedLanguageSystem.cs +++ b/Content.Shared/SS220/Language/SharedLanguageSystem.cs @@ -111,11 +111,4 @@ public string SetColor(string message, LanguagesPrototype proto) message = $"[color={color}]{message}[/color]"; return message; } -} - - - - - - - +} \ No newline at end of file diff --git a/Resources/Prototypes/Entities/Objects/Specific/Robotics/mmi.yml b/Resources/Prototypes/Entities/Objects/Specific/Robotics/mmi.yml index 82b023a5f270..f3259ce1b6db 100644 --- a/Resources/Prototypes/Entities/Objects/Specific/Robotics/mmi.yml +++ b/Resources/Prototypes/Entities/Objects/Specific/Robotics/mmi.yml @@ -108,11 +108,13 @@ - type: IntrinsicRadioTransmitter channels: - Binary + # SS220-Add-Languages begin - type: Language learnedLanguages: - Galactic - Binary - Universal + # SS220-Add-Languages end - type: ActiveRadio channels: - Binary From e24388aebdcfaea081326cb75deac3834df7fd66 Mon Sep 17 00:00:00 2001 From: Jopaglazik Date: Tue, 12 Nov 2024 07:04:04 +0400 Subject: [PATCH 03/48] more --- Content.Server/Chat/Systems/ChatSystem.cs | 2 +- Content.Server/Radio/EntitySystems/RadioDeviceSystem.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Content.Server/Chat/Systems/ChatSystem.cs b/Content.Server/Chat/Systems/ChatSystem.cs index 482065d4e35d..93dfd1683900 100644 --- a/Content.Server/Chat/Systems/ChatSystem.cs +++ b/Content.Server/Chat/Systems/ChatSystem.cs @@ -659,7 +659,7 @@ private void SendEntityWhisper( else _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))); var ev = new EntitySpokeEvent(source, message, originalMessage, channel, obfuscatedMessage); diff --git a/Content.Server/Radio/EntitySystems/RadioDeviceSystem.cs b/Content.Server/Radio/EntitySystems/RadioDeviceSystem.cs index 565bbf53bee9..f2ed606b7a7b 100644 --- a/Content.Server/Radio/EntitySystems/RadioDeviceSystem.cs +++ b/Content.Server/Radio/EntitySystems/RadioDeviceSystem.cs @@ -234,7 +234,7 @@ private void OnReceiveRadio(EntityUid uid, RadioSpeakerComponent component, ref var name = Loc.GetString("speech-name-relay", ("speaker", Name(uid)), ("originalName", nameEv.VoiceName)); - + // log to chat so people can identity the speaker/source, but avoid clogging ghost chat if there are many radios _chat.TrySendInGameICMessage(uid, args.Message, InGameICChatType.Whisper, ChatTransmitRange.GhostRangeLimit, nameOverride: name, checkRadioPrefix: false, From da2b0431ea3ee5f4dcbcdff8999ae524fd8a320e Mon Sep 17 00:00:00 2001 From: Jopaglazik Date: Thu, 14 Nov 2024 05:25:27 +0400 Subject: [PATCH 04/48] fixes --- Content.Client/SS220/Language/LanguageSystem.cs | 4 ---- Content.Server/Chat/Systems/ChatSystem.cs | 9 +++++---- Content.Server/EntityEffects/Effects/MakeSentient.cs | 2 +- Content.Server/PAI/PAISystem.cs | 4 ++-- .../Administration/Commands/LanguageCommands.cs | 2 +- Content.Server/SS220/Language/LanguageSystem.cs | 6 +----- Content.Shared/SS220/Language/LanguageComponent.cs | 7 +++---- Content.Shared/SS220/Language/LanguagesPrototype.cs | 3 +++ .../SS220/Language/SharedLanguageSystem.cs | 12 ++++++------ .../SS220/{Language => Verbs}/LanguageVerbs.cs | 9 ++++++--- .../Locale/ru-RU/ss220/language/language-desc.ftl | 2 +- Resources/Locale/ru-RU/ss220/verbs/verb-system.ftl | 3 +-- 12 files changed, 30 insertions(+), 33 deletions(-) rename Content.Server/{ => SS220}/Administration/Commands/LanguageCommands.cs (96%) rename Content.Shared/SS220/{Language => Verbs}/LanguageVerbs.cs (88%) diff --git a/Content.Client/SS220/Language/LanguageSystem.cs b/Content.Client/SS220/Language/LanguageSystem.cs index 31999726a9f7..248e9d3356a8 100644 --- a/Content.Client/SS220/Language/LanguageSystem.cs +++ b/Content.Client/SS220/Language/LanguageSystem.cs @@ -1,8 +1,4 @@ using Content.Shared.SS220.Language; -using Content.Shared.Verbs; -using Robust.Client.Console; -using Robust.Shared.Player; -using Robust.Shared.Utility; namespace Content.Client.SS220.Language; diff --git a/Content.Server/Chat/Systems/ChatSystem.cs b/Content.Server/Chat/Systems/ChatSystem.cs index 93dfd1683900..29ca17cb333b 100644 --- a/Content.Server/Chat/Systems/ChatSystem.cs +++ b/Content.Server/Chat/Systems/ChatSystem.cs @@ -533,7 +533,7 @@ private void SendEntitySpeak( _chatManager.ChatMessageToOne(ChatChannel.Local, currentMessage, wrappedMessage, source, false, session.Channel); //SS220-Add-Languages } - + //SendInVoiceRange(ChatChannel.Local, message, wrappedMessage, source, range); //SS220-Add-Languages var ev = new EntitySpokeEvent(source, message, originalMessage, null, null); RaiseLocalEvent(source, ev, true); @@ -616,12 +616,13 @@ private void SendEntityWhisper( foreach (var (session, data) in GetRecipients(source, WhisperMuffledRange)) { + EntityUid listener; + if (session.AttachedEntity is not { Valid: true } playerEntity) continue; - // SS220-Add-Languages begin - - var listener = session.AttachedEntity.Value; + listener = session.AttachedEntity.Value; + // SS220-Add-Languages begin var scrambledMessage = message; var obfuscatedScrambledMessage = obfuscatedMessage; var wrappedScrambledMessage = wrappedMessage; diff --git a/Content.Server/EntityEffects/Effects/MakeSentient.cs b/Content.Server/EntityEffects/Effects/MakeSentient.cs index 49d56e8cfb89..58ff79a5e300 100644 --- a/Content.Server/EntityEffects/Effects/MakeSentient.cs +++ b/Content.Server/EntityEffects/Effects/MakeSentient.cs @@ -27,7 +27,7 @@ public override void Effect(EntityEffectBaseArgs args) if (!entityManager.HasComponent(uid)) { var language = entityManager.AddComponent(uid); - language.LearnedLanguages.Add("Galactic"); + language.LearnedLanguages.Add(LanguagesPrototype.Galactic); language.CurrentLanguage = language.LearnedLanguages[0]; } // SS220-Add-Languages end diff --git a/Content.Server/PAI/PAISystem.cs b/Content.Server/PAI/PAISystem.cs index 45b79cda7e54..d5c5da5a95d2 100644 --- a/Content.Server/PAI/PAISystem.cs +++ b/Content.Server/PAI/PAISystem.cs @@ -123,8 +123,8 @@ public void PAITurningOff(EntityUid uid) if (TryComp(uid, out var languages)) { languages.LearnedLanguages.Clear(); - languages.LearnedLanguages.Add("Galactic"); - languages.LearnedLanguages.Add("Universal"); + languages.LearnedLanguages.Add(LanguagesPrototype.Galactic); + languages.LearnedLanguages.Add(LanguagesPrototype.Universal); languages.CurrentLanguage = languages.LearnedLanguages[0]; } } diff --git a/Content.Server/Administration/Commands/LanguageCommands.cs b/Content.Server/SS220/Administration/Commands/LanguageCommands.cs similarity index 96% rename from Content.Server/Administration/Commands/LanguageCommands.cs rename to Content.Server/SS220/Administration/Commands/LanguageCommands.cs index 83bf09024091..668aa8dc1a6d 100644 --- a/Content.Server/Administration/Commands/LanguageCommands.cs +++ b/Content.Server/SS220/Administration/Commands/LanguageCommands.cs @@ -4,7 +4,7 @@ using Content.Shared.SS220.Language; using Robust.Shared.Prototypes; -namespace Content.Server.Administration.Commands; +namespace Content.Server.Administration.Commands; // If I change namespace in SS220 the AdminCommand attribute is no longer located.... [AdminCommand(AdminFlags.Admin)] public sealed class AddLanguageCommand : IConsoleCommand diff --git a/Content.Server/SS220/Language/LanguageSystem.cs b/Content.Server/SS220/Language/LanguageSystem.cs index dc33c8e87988..87f00ba3bf75 100644 --- a/Content.Server/SS220/Language/LanguageSystem.cs +++ b/Content.Server/SS220/Language/LanguageSystem.cs @@ -36,7 +36,7 @@ private void OnRoundStart(RoundStartingEvent args) private void OnMapInit(Entity ent, ref MapInitEvent args) { if (ent.Comp.CurrentLanguage == null) - ent.Comp.CurrentLanguage = ent.Comp.LearnedLanguages.FirstOrDefault("Universal"); + ent.Comp.CurrentLanguage = ent.Comp.LearnedLanguages.FirstOrDefault(LanguagesPrototype.Universal); Dirty(ent.Owner, ent.Comp); } @@ -54,11 +54,7 @@ public string ScrambleText(EntityUid? ent, string input, LanguagesPrototype prot // it is taken from the cache, it is necessary for the correct display when sending in the radio, // when the character whispers and transmits a message to the radio if (ScrambleCache.TryGetValue(cacheKey, out var cachedValue)) - { - ScrambleCache.Remove(cacheKey); - ScrambleCache[cacheKey] = cachedValue; return cachedValue; - } var scrambledText = Scramble(input, proto); diff --git a/Content.Shared/SS220/Language/LanguageComponent.cs b/Content.Shared/SS220/Language/LanguageComponent.cs index 2b0c87f8f5c2..5481f0351282 100644 --- a/Content.Shared/SS220/Language/LanguageComponent.cs +++ b/Content.Shared/SS220/Language/LanguageComponent.cs @@ -1,6 +1,6 @@ // © SS220, An EULA/CLA with a hosting restriction, full text: https://raw.githubusercontent.com/SerbiaStrong-220/space-station-14/master/CLA.txt using Robust.Shared.GameStates; -using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.List; +using Robust.Shared.Prototypes; namespace Content.Shared.SS220.Language; @@ -23,7 +23,6 @@ public sealed partial class LanguageComponent : Component /// /// List of languages that the Entity speaks and understands. /// - [DataField("learnedLanguages", customTypeSerializer: typeof(PrototypeIdListSerializer))] - [AutoNetworkedField] - public List LearnedLanguages { get; set; } = new(); + [DataField("learnedLanguages"), AutoNetworkedField] + public List> LearnedLanguages { get; set; } = new(); } diff --git a/Content.Shared/SS220/Language/LanguagesPrototype.cs b/Content.Shared/SS220/Language/LanguagesPrototype.cs index 626258064dcf..3dcb3a554c26 100644 --- a/Content.Shared/SS220/Language/LanguagesPrototype.cs +++ b/Content.Shared/SS220/Language/LanguagesPrototype.cs @@ -7,6 +7,9 @@ namespace Content.Shared.SS220.Language; [Prototype("languages")] public sealed partial class LanguagesPrototype : IPrototype { + public const string Universal = "Universal"; + public const string Galactic = "Galactic"; + [ViewVariables, IdDataField] public string ID { get; private set; } = default!; diff --git a/Content.Shared/SS220/Language/SharedLanguageSystem.cs b/Content.Shared/SS220/Language/SharedLanguageSystem.cs index e19062e9d931..3d3254c93980 100644 --- a/Content.Shared/SS220/Language/SharedLanguageSystem.cs +++ b/Content.Shared/SS220/Language/SharedLanguageSystem.cs @@ -41,13 +41,13 @@ public bool KnowsUniversalLanguage(EntityUid ent) if (HasComp(ent)) return true; - if (!TryComp(ent, out var comp) && _proto.TryIndex("Universal", out _)) + if (!TryComp(ent, out var comp)) return true; - if (comp != null && comp.CurrentLanguage == "Universal") + if (comp != null && comp.CurrentLanguage == LanguagesPrototype.Universal) return true; - if (comp != null && comp.LearnedLanguages.Contains("Universal")) + if (comp != null && comp.LearnedLanguages.Contains(LanguagesPrototype.Universal)) return true; return false; @@ -61,11 +61,11 @@ public bool KnowsUniversalLanguage(EntityUid ent) { if (!TryComp(ent, out var comp)) { - if (_proto.TryIndex("Universal", out var universalProto)) + if (_proto.TryIndex(LanguagesPrototype.Universal, out var universalProto)) return universalProto; } - var languageID = GetLanguage(ent); + var languageID = GetCurrentLanguage(ent); if (languageID == null) return null; @@ -76,7 +76,7 @@ public bool KnowsUniversalLanguage(EntityUid ent) return null; } - public string? GetLanguage(EntityUid ent) + public string? GetCurrentLanguage(EntityUid ent) { if (!TryComp(ent, out var comp)) return null; diff --git a/Content.Shared/SS220/Language/LanguageVerbs.cs b/Content.Shared/SS220/Verbs/LanguageVerbs.cs similarity index 88% rename from Content.Shared/SS220/Language/LanguageVerbs.cs rename to Content.Shared/SS220/Verbs/LanguageVerbs.cs index 2a5e793958b8..2b9933d0b29b 100644 --- a/Content.Shared/SS220/Language/LanguageVerbs.cs +++ b/Content.Shared/SS220/Verbs/LanguageVerbs.cs @@ -1,9 +1,11 @@ // © 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.SS220.Language; using Content.Shared.Verbs; using Robust.Shared.Prototypes; +using System.Linq; -namespace Content.Shared.SS220.Language; +namespace Content.Shared.SS220.Verbs; /// /// I was bored and lazy to understand the UI, @@ -29,7 +31,8 @@ private void OnVerb(EntityUid ent, LanguageComponent comp, ref GetVerbsEvent lang.ToString()).ToList(); + var verbs = CreateVerbs(ent, learnedLanguages); foreach (var verb in verbs) { args.Verbs.Add(verb); @@ -45,7 +48,7 @@ private List CreateVerbs(EntityUid ent, List languages) foreach (string language in languages) { - if (language == "Universal") // no verb for a universal language is created + if (language == LanguagesPrototype.Universal) // no verb for a universal language is created continue; verbs.Add(new Verb diff --git a/Resources/Locale/ru-RU/ss220/language/language-desc.ftl b/Resources/Locale/ru-RU/ss220/language/language-desc.ftl index f13bce4d0de2..46a4af084d93 100644 --- a/Resources/Locale/ru-RU/ss220/language/language-desc.ftl +++ b/Resources/Locale/ru-RU/ss220/language/language-desc.ftl @@ -1,4 +1,4 @@ -# Sources: https://wiki.ss220.club/index.php/%D0%AF%D0%B7%D1%8B%D0%BA%D0%B8 and https://wiki14.ss220.club/index.php?title=%D0%9B%D0%BE%D1%80 +# Sources: https://wiki.ss220.club/index.php/Языки and https://wiki14.ss220.club/index.php?title=Лор # Galactic common languages language-galacticcommon-desc = Дружелюбный для иных рас язык, введёный правительством ТСФ в связи с насплывом сектор иммигрантов представляющие многочисленное количества рас. diff --git a/Resources/Locale/ru-RU/ss220/verbs/verb-system.ftl b/Resources/Locale/ru-RU/ss220/verbs/verb-system.ftl index f6a020c244ce..c0323ae6d791 100644 --- a/Resources/Locale/ru-RU/ss220/verbs/verb-system.ftl +++ b/Resources/Locale/ru-RU/ss220/verbs/verb-system.ftl @@ -1,5 +1,4 @@ verb-categories-attach-cart = Прикрепить verb-categories-deattach-cart = Открепить -#SS220-Add-Languages begin + verb-categories-languages-selector = Выбрать язык -#SS220-Add-Languages end \ No newline at end of file From 9ea1cec4f3ff5b9afd491e61cb8a2fb1d455f337 Mon Sep 17 00:00:00 2001 From: Bomjojuk Date: Mon, 24 Feb 2025 01:52:27 +0300 Subject: [PATCH 05/48] try on fixing conflicts --- RobustToolbox | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RobustToolbox b/RobustToolbox index fea592e1d53b..32bca7cfd417 160000 --- a/RobustToolbox +++ b/RobustToolbox @@ -1 +1 @@ -Subproject commit fea592e1d53b043bda73a66248576caa6e3f65dc +Subproject commit 32bca7cfd417edcad9a60c2b1703eba8675f56af From d62e6522fec3146d8ce928685090dae2b97c10b8 Mon Sep 17 00:00:00 2001 From: Bomjojuk Date: Mon, 24 Feb 2025 02:42:33 +0300 Subject: [PATCH 06/48] Update RobustToolbox --- RobustToolbox | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RobustToolbox b/RobustToolbox index 32bca7cfd417..f8410a4674a4 160000 --- a/RobustToolbox +++ b/RobustToolbox @@ -1 +1 @@ -Subproject commit 32bca7cfd417edcad9a60c2b1703eba8675f56af +Subproject commit f8410a4674a4978fcea3fd267c6fb26b2ba6e7de From 853df29fd6b5f0770a94ab7d00b790f3879b30c1 Mon Sep 17 00:00:00 2001 From: UrPrice Date: Mon, 24 Feb 2025 03:44:16 +0300 Subject: [PATCH 07/48] submodulte update --- RobustToolbox | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RobustToolbox b/RobustToolbox index f8410a4674a4..fea592e1d53b 160000 --- a/RobustToolbox +++ b/RobustToolbox @@ -1 +1 @@ -Subproject commit f8410a4674a4978fcea3fd267c6fb26b2ba6e7de +Subproject commit fea592e1d53b043bda73a66248576caa6e3f65dc From 804273efc6e428d06923569cad5ceee2e9f5949f Mon Sep 17 00:00:00 2001 From: Kirus59 <145689588+Kirus59@users.noreply.github.com> Date: Mon, 24 Feb 2025 19:10:51 +0300 Subject: [PATCH 08/48] test --- Resources/Locale/ru-RU/ss220/verbs/verb-system.ftl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Resources/Locale/ru-RU/ss220/verbs/verb-system.ftl b/Resources/Locale/ru-RU/ss220/verbs/verb-system.ftl index 096382fb0f5c..654632c9c9e9 100644 --- a/Resources/Locale/ru-RU/ss220/verbs/verb-system.ftl +++ b/Resources/Locale/ru-RU/ss220/verbs/verb-system.ftl @@ -4,4 +4,4 @@ verb-categories-deattach-cart = Открепить verb-categories-languages-selector = Выбрать язык -verb-shuffle-cards = Перемешать +verb-shuffle-cards = Перемешать test From 961a084399870aef4881655fad890730262604d3 Mon Sep 17 00:00:00 2001 From: Kirus59 <145689588+Kirus59@users.noreply.github.com> Date: Mon, 24 Feb 2025 19:11:34 +0300 Subject: [PATCH 09/48] Revert "test" This reverts commit 804273efc6e428d06923569cad5ceee2e9f5949f. --- Resources/Locale/ru-RU/ss220/verbs/verb-system.ftl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Resources/Locale/ru-RU/ss220/verbs/verb-system.ftl b/Resources/Locale/ru-RU/ss220/verbs/verb-system.ftl index 654632c9c9e9..096382fb0f5c 100644 --- a/Resources/Locale/ru-RU/ss220/verbs/verb-system.ftl +++ b/Resources/Locale/ru-RU/ss220/verbs/verb-system.ftl @@ -4,4 +4,4 @@ verb-categories-deattach-cart = Открепить verb-categories-languages-selector = Выбрать язык -verb-shuffle-cards = Перемешать test +verb-shuffle-cards = Перемешать From 71520be12ac6553dbc12328f14b2029ab832c65b Mon Sep 17 00:00:00 2001 From: Kirus59 <145689588+Kirus59@users.noreply.github.com> Date: Mon, 24 Feb 2025 19:43:27 +0300 Subject: [PATCH 10/48] some fixes --- Content.Server/Chat/Systems/ChatSystem.cs | 37 +++---------------- .../EntityEffects/Effects/MakeSentient.cs | 14 ++++--- Content.Server/PAI/PAISystem.cs | 8 ++-- .../Commands/LanguageCommands.cs | 7 ++-- .../SS220/Language/LanguageSystem.cs | 13 ++++++- .../SS220/Language/LanguagesPrototype.cs | 1 - .../SS220/Language/SharedLanguageSystem.cs | 11 ++++-- Content.Shared/SS220/Verbs/LanguageVerbs.cs | 2 +- 8 files changed, 43 insertions(+), 50 deletions(-) rename Content.Server/SS220/{Administration => }/Commands/LanguageCommands.cs (93%) diff --git a/Content.Server/Chat/Systems/ChatSystem.cs b/Content.Server/Chat/Systems/ChatSystem.cs index a2c2da0292dd..ca2b7c1bef18 100644 --- a/Content.Server/Chat/Systems/ChatSystem.cs +++ b/Content.Server/Chat/Systems/ChatSystem.cs @@ -516,18 +516,7 @@ private void SendEntitySpeak( continue; 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); - } + var currentMessage = _languageSystem.SanitizeMessage(source, listener, message); // SS220-Add-Languages end var wrappedMessage = Loc.GetString(speech.Bold ? "chat-manager-entity-say-bold-wrap-message" : "chat-manager-entity-say-wrap-message", @@ -629,29 +618,15 @@ private void SendEntityWhisper( listener = session.AttachedEntity.Value; // SS220-Add-Languages begin - var scrambledMessage = message; - var obfuscatedScrambledMessage = obfuscatedMessage; - var wrappedScrambledMessage = wrappedMessage; - var wrappedObfuscatedScrambledMessage = wrappedobfuscatedMessage; - var wrappedUnknownScrambledMessage = wrappedUnknownMessage; + var scrambledMessage = _languageSystem.SanitizeMessage(source, listener, message); + var obfuscatedScrambledMessage = _languageSystem.SanitizeMessage(source, listener, obfuscatedMessage); - 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", + var wrappedScrambledMessage = Loc.GetString("chat-manager-entity-whisper-wrap-message", ("entityName", name), ("message", scrambledMessage)); - wrappedObfuscatedScrambledMessage = Loc.GetString("chat-manager-entity-whisper-wrap-message", + var 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", + var 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) diff --git a/Content.Server/EntityEffects/Effects/MakeSentient.cs b/Content.Server/EntityEffects/Effects/MakeSentient.cs index 58ff79a5e300..3f7ebbcc9401 100644 --- a/Content.Server/EntityEffects/Effects/MakeSentient.cs +++ b/Content.Server/EntityEffects/Effects/MakeSentient.cs @@ -1,5 +1,6 @@ using Content.Server.Ghost.Roles.Components; using Content.Server.Speech.Components; +using Content.Server.SS220.Language; using Content.Shared.EntityEffects; using Content.Shared.Mind.Components; using Content.Shared.SS220.Language; // SS220-Add-Languages @@ -24,12 +25,13 @@ public override void Effect(EntityEffectBaseArgs args) entityManager.RemoveComponent(uid); // SS220-Add-Languages begin - if (!entityManager.HasComponent(uid)) - { - var language = entityManager.AddComponent(uid); - language.LearnedLanguages.Add(LanguagesPrototype.Galactic); - language.CurrentLanguage = language.LearnedLanguages[0]; - } + var language = entityManager.EnsureComponent(uid); + var languageSystem = entityManager.System(); + + if (!language.LearnedLanguages.Contains(languageSystem.GalacticLanguage)) + language.LearnedLanguages.Add(languageSystem.GalacticLanguage); + + language.CurrentLanguage = language.LearnedLanguages[0]; // SS220-Add-Languages end // Stops from adding a ghost role to things like people who already have a mind diff --git a/Content.Server/PAI/PAISystem.cs b/Content.Server/PAI/PAISystem.cs index d5c5da5a95d2..23d910b7314a 100644 --- a/Content.Server/PAI/PAISystem.cs +++ b/Content.Server/PAI/PAISystem.cs @@ -9,7 +9,8 @@ using Robust.Shared.Random; using System.Text; using Robust.Shared.Player; -using Content.Shared.SS220.Language; // SS220-Add-Languages +using Content.Shared.SS220.Language; +using Content.Server.SS220.Language; // SS220-Add-Languages namespace Content.Server.PAI; @@ -20,6 +21,7 @@ public sealed class PAISystem : SharedPAISystem [Dependency] private readonly MetaDataSystem _metaData = default!; [Dependency] private readonly SharedPopupSystem _popup = default!; [Dependency] private readonly ToggleableGhostRoleSystem _toggleableGhostRole = default!; + [Dependency] private readonly LanguageSystem _language = default!; // SS220 Languages /// /// Possible symbols that can be part of a scrambled pai's name. @@ -123,8 +125,8 @@ public void PAITurningOff(EntityUid uid) if (TryComp(uid, out var languages)) { languages.LearnedLanguages.Clear(); - languages.LearnedLanguages.Add(LanguagesPrototype.Galactic); - languages.LearnedLanguages.Add(LanguagesPrototype.Universal); + languages.LearnedLanguages.Add(_language.UniversalLanguage); + languages.LearnedLanguages.Add(_language.GalacticLanguage); languages.CurrentLanguage = languages.LearnedLanguages[0]; } } diff --git a/Content.Server/SS220/Administration/Commands/LanguageCommands.cs b/Content.Server/SS220/Commands/LanguageCommands.cs similarity index 93% rename from Content.Server/SS220/Administration/Commands/LanguageCommands.cs rename to Content.Server/SS220/Commands/LanguageCommands.cs index 668aa8dc1a6d..7628e30ac437 100644 --- a/Content.Server/SS220/Administration/Commands/LanguageCommands.cs +++ b/Content.Server/SS220/Commands/LanguageCommands.cs @@ -1,10 +1,10 @@ -// © SS220, An EULA/CLA with a hosting restriction, full text: https://raw.githubusercontent.com/SerbiaStrong-220/space-station-14/master/CLA.txt +using Content.Server.Administration; using Content.Shared.Administration; -using Robust.Shared.Console; using Content.Shared.SS220.Language; +using Robust.Shared.Console; using Robust.Shared.Prototypes; -namespace Content.Server.Administration.Commands; // If I change namespace in SS220 the AdminCommand attribute is no longer located.... +namespace Content.Server.SS220.Commands; [AdminCommand(AdminFlags.Admin)] public sealed class AddLanguageCommand : IConsoleCommand @@ -131,3 +131,4 @@ public void Execute(IConsoleShell shell, string argStr, string[] args) shell.WriteLine(Loc.GetString("cmd-language-clear")); } } + diff --git a/Content.Server/SS220/Language/LanguageSystem.cs b/Content.Server/SS220/Language/LanguageSystem.cs index 87f00ba3bf75..e1e1fb3e16ef 100644 --- a/Content.Server/SS220/Language/LanguageSystem.cs +++ b/Content.Server/SS220/Language/LanguageSystem.cs @@ -36,7 +36,7 @@ private void OnRoundStart(RoundStartingEvent args) private void OnMapInit(Entity ent, ref MapInitEvent args) { if (ent.Comp.CurrentLanguage == null) - ent.Comp.CurrentLanguage = ent.Comp.LearnedLanguages.FirstOrDefault(LanguagesPrototype.Universal); + ent.Comp.CurrentLanguage = ent.Comp.LearnedLanguages.FirstOrDefault(UniversalLanguage); Dirty(ent.Owner, ent.Comp); } @@ -144,5 +144,16 @@ public string RemoveColorTags(string input) return cleanedText; } + + public string SanitizeMessage(EntityUid source, EntityUid listener, string message) + { + var languageProto = GetProto(source); + if (languageProto == null || CheckLanguage(listener, languageProto)) + return message; + + var newMessage = ScrambleText(source, message, languageProto); + newMessage = SetColor(newMessage, languageProto); + return newMessage; + } } diff --git a/Content.Shared/SS220/Language/LanguagesPrototype.cs b/Content.Shared/SS220/Language/LanguagesPrototype.cs index 3dcb3a554c26..3058f0896d21 100644 --- a/Content.Shared/SS220/Language/LanguagesPrototype.cs +++ b/Content.Shared/SS220/Language/LanguagesPrototype.cs @@ -7,7 +7,6 @@ namespace Content.Shared.SS220.Language; [Prototype("languages")] public sealed partial class LanguagesPrototype : IPrototype { - public const string Universal = "Universal"; public const string Galactic = "Galactic"; [ViewVariables, IdDataField] diff --git a/Content.Shared/SS220/Language/SharedLanguageSystem.cs b/Content.Shared/SS220/Language/SharedLanguageSystem.cs index 3d3254c93980..daed037776f1 100644 --- a/Content.Shared/SS220/Language/SharedLanguageSystem.cs +++ b/Content.Shared/SS220/Language/SharedLanguageSystem.cs @@ -10,6 +10,9 @@ public abstract class SharedLanguageSystem : EntitySystem { [Dependency] private readonly IPrototypeManager _proto = default!; + public readonly string UniversalLanguage = "Universal"; + public readonly string GalacticLanguage = "Galactic"; + /// /// Method that checks an entity for the presence of a prototype language /// or for the presence of a universal language @@ -44,10 +47,10 @@ public bool KnowsUniversalLanguage(EntityUid ent) if (!TryComp(ent, out var comp)) return true; - if (comp != null && comp.CurrentLanguage == LanguagesPrototype.Universal) + if (comp != null && comp.CurrentLanguage == UniversalLanguage) return true; - if (comp != null && comp.LearnedLanguages.Contains(LanguagesPrototype.Universal)) + if (comp != null && comp.LearnedLanguages.Contains(UniversalLanguage)) return true; return false; @@ -61,7 +64,7 @@ public bool KnowsUniversalLanguage(EntityUid ent) { if (!TryComp(ent, out var comp)) { - if (_proto.TryIndex(LanguagesPrototype.Universal, out var universalProto)) + if (_proto.TryIndex(UniversalLanguage, out var universalProto)) return universalProto; } @@ -111,4 +114,4 @@ public string SetColor(string message, LanguagesPrototype proto) message = $"[color={color}]{message}[/color]"; return message; } -} \ No newline at end of file +} diff --git a/Content.Shared/SS220/Verbs/LanguageVerbs.cs b/Content.Shared/SS220/Verbs/LanguageVerbs.cs index 2b9933d0b29b..2fbb8f92b545 100644 --- a/Content.Shared/SS220/Verbs/LanguageVerbs.cs +++ b/Content.Shared/SS220/Verbs/LanguageVerbs.cs @@ -48,7 +48,7 @@ private List CreateVerbs(EntityUid ent, List languages) foreach (string language in languages) { - if (language == LanguagesPrototype.Universal) // no verb for a universal language is created + if (language == _languageSystem.UniversalLanguage) // no verb for a universal language is created continue; verbs.Add(new Verb From 9cc5ff1183e136bce2a72e947d3a9bae84e01bbe Mon Sep 17 00:00:00 2001 From: Kirus59 <145689588+Kirus59@users.noreply.github.com> Date: Mon, 24 Feb 2025 20:09:44 +0300 Subject: [PATCH 11/48] some fixes 2 --- Content.Server/PAI/PAISystem.cs | 21 +--------- .../Language/Special/AddLanguageSpecial.cs | 2 +- .../SS220/Language/SharedLanguageSystem.cs | 39 +++++++++++++++---- 3 files changed, 34 insertions(+), 28 deletions(-) diff --git a/Content.Server/PAI/PAISystem.cs b/Content.Server/PAI/PAISystem.cs index 23d910b7314a..a1e7499d57a8 100644 --- a/Content.Server/PAI/PAISystem.cs +++ b/Content.Server/PAI/PAISystem.cs @@ -58,7 +58,7 @@ private void OnMindAdded(EntityUid uid, PAIComponent component, MindAddedMessage // Cause then you could remotely figure out information about the owner's equipped items. _metaData.SetEntityName(uid, val); - GetUserLanguages(component.LastUser, uid); // SS220-Add-Languages + _language.AddLanguagesFromSource(component.LastUser.Value, uid); // SS220-Add-Languages } private void OnMindRemoved(EntityUid uid, PAIComponent component, MindRemovedMessage args) @@ -125,26 +125,9 @@ public void PAITurningOff(EntityUid uid) if (TryComp(uid, out var languages)) { languages.LearnedLanguages.Clear(); - languages.LearnedLanguages.Add(_language.UniversalLanguage); - languages.LearnedLanguages.Add(_language.GalacticLanguage); + _language.AddLanguages(uid, [_language.UniversalLanguage, _language.UniversalLanguage]); languages.CurrentLanguage = languages.LearnedLanguages[0]; } } - - public void GetUserLanguages(EntityUid? ent, EntityUid pai) - { - if (!TryComp(ent, out var languages) || languages == null) - return; - - if (!TryComp(pai, out var paiLanguages)) - return; - - foreach (var language in languages.LearnedLanguages) - { - if (!paiLanguages.LearnedLanguages.Contains(language)) - paiLanguages.LearnedLanguages.Add(language); - } - Dirty(pai, paiLanguages); - } // SS220-Add-Languages end } diff --git a/Content.Server/SS220/Language/Special/AddLanguageSpecial.cs b/Content.Server/SS220/Language/Special/AddLanguageSpecial.cs index 2ec6f8dcf12a..162a31d32ed2 100644 --- a/Content.Server/SS220/Language/Special/AddLanguageSpecial.cs +++ b/Content.Server/SS220/Language/Special/AddLanguageSpecial.cs @@ -18,6 +18,6 @@ public override void AfterEquip(EntityUid mob) { var entMan = IoCManager.Resolve(); var languageSystem = entMan.System(); - languageSystem.AddLanguage(mob, Languages); + languageSystem.AddLanguages(mob, Languages); } } diff --git a/Content.Shared/SS220/Language/SharedLanguageSystem.cs b/Content.Shared/SS220/Language/SharedLanguageSystem.cs index daed037776f1..3e20daec32e1 100644 --- a/Content.Shared/SS220/Language/SharedLanguageSystem.cs +++ b/Content.Shared/SS220/Language/SharedLanguageSystem.cs @@ -87,19 +87,27 @@ public bool KnowsUniversalLanguage(EntityUid ent) return comp.CurrentLanguage; } - public void AddLanguage(EntityUid ent, List languages) + public void AddLanguages(EntityUid uid, List languages) { - if (!TryComp(ent, out var comp)) + foreach (var language in languages) + { + AddLanguage(uid, language); + } + } + + public void AddLanguage(EntityUid uid, string languageId) + { + if (!TryComp(uid, out var comp)) return; - foreach(var language in languages) + if (!_proto.TryIndex(languageId, out var proto)) { - if (!_proto.TryIndex(language, out var proto)) - continue; - - if (!comp.LearnedLanguages.Contains(language)) - comp.LearnedLanguages.Add(language); + Log.Error($"Doesn't found a LanguagePrototype with id: {languageId}"); + return; } + + if (!comp.LearnedLanguages.Contains(proto)) + comp.LearnedLanguages.Add(proto); } /// @@ -114,4 +122,19 @@ public string SetColor(string message, LanguagesPrototype proto) message = $"[color={color}]{message}[/color]"; return message; } + + public void AddLanguagesFromSource(EntityUid source, EntityUid target) + { + if (!TryComp(source, out var sourceComp)) + return; + + var targetComp = EnsureComp(target); + foreach (var language in sourceComp.LearnedLanguages) + { + if (!targetComp.LearnedLanguages.Contains(language)) + targetComp.LearnedLanguages.Add(language); + } + + Dirty(target, targetComp); + } } From d93e199d5cc1e71dd069d3a63810f5cbcc560365 Mon Sep 17 00:00:00 2001 From: Kirus59 <145689588+Kirus59@users.noreply.github.com> Date: Mon, 24 Feb 2025 21:04:23 +0300 Subject: [PATCH 12/48] add encryption methods API --- .../SS220/Language/LanguageSystem.cs | 59 +------ .../EncryptionMethods/BaseEncryptionMethod.cs | 9 + .../RandomSyllablesMethod.cs | 98 +++++++++++ .../SS220/Language/LanguagesPrototype.cs | 25 +-- .../Prototypes/SS220/Language/language.yml | 158 ++++++++++-------- 5 files changed, 198 insertions(+), 151 deletions(-) create mode 100644 Content.Shared/SS220/Language/EncryptionMethods/BaseEncryptionMethod.cs create mode 100644 Content.Shared/SS220/Language/EncryptionMethods/RandomSyllablesMethod.cs diff --git a/Content.Server/SS220/Language/LanguageSystem.cs b/Content.Server/SS220/Language/LanguageSystem.cs index e1e1fb3e16ef..2c0427b26cd4 100644 --- a/Content.Server/SS220/Language/LanguageSystem.cs +++ b/Content.Server/SS220/Language/LanguageSystem.cs @@ -56,7 +56,7 @@ public string ScrambleText(EntityUid? ent, string input, LanguagesPrototype prot if (ScrambleCache.TryGetValue(cacheKey, out var cachedValue)) return cachedValue; - var scrambledText = Scramble(input, proto); + var scrambledText = proto.EncryptionMethod.EncryptMessage(input); ScrambleCache[cacheKey] = scrambledText; // Removes the first message from the cache if it fills up @@ -72,63 +72,6 @@ public string ScrambleText(EntityUid? ent, string input, LanguagesPrototype prot return scrambledText; } - private string Scramble(string input, LanguagesPrototype proto) - { - if (proto.Syllables == null || proto.Syllables.Count == 0) - return input; - - var scrambledText = new StringBuilder(); - bool capitalize = true; - - while (scrambledText.Length < input.Length) - { - var next = proto.Syllables[_random.Next(proto.Syllables.Count)]; - - if (capitalize) - { - next = char.ToUpper(next[0]) + next.Substring(1); - capitalize = false; - } - - scrambledText.Append(next); - - var chance = _random.Next(100); - if (chance <= 5) - { - scrambledText.Append(proto.JoinOverride); - capitalize = true; - } - else if (chance > 5 && chance <= proto.SpaceChance) - { - scrambledText.Append(" "); - } - } - - var result = scrambledText.ToString().Trim(); - var punctuation = ExtractPunctuation(input); - - result += punctuation; - - return result; - } - - /// - /// Takes the last punctuation out of the original post - /// (Does not affect the internal punctuation of the sentence) - /// - private string ExtractPunctuation(string input) - { - var punctuationBuilder = new StringBuilder(); - for (int i = input.Length - 1; i >= 0; i--) - { - if (char.IsPunctuation(input[i])) - punctuationBuilder.Insert(0, input[i]); - else - break; - } - return punctuationBuilder.ToString(); - } - /// /// Workaround for some message transmissions. /// Removes BBCodes colors leaving only the original message. diff --git a/Content.Shared/SS220/Language/EncryptionMethods/BaseEncryptionMethod.cs b/Content.Shared/SS220/Language/EncryptionMethods/BaseEncryptionMethod.cs new file mode 100644 index 000000000000..9457bd4893b0 --- /dev/null +++ b/Content.Shared/SS220/Language/EncryptionMethods/BaseEncryptionMethod.cs @@ -0,0 +1,9 @@ +// © SS220, An EULA/CLA with a hosting restriction, full text: https://raw.githubusercontent.com/SerbiaStrong-220/space-station-14/master/CLA.txt + +namespace Content.Shared.SS220.Language.EncryptionMethods; + +[ImplicitDataDefinitionForInheritors] +public abstract partial class BaseEncryptionMethod +{ + public abstract string EncryptMessage(string message); +} diff --git a/Content.Shared/SS220/Language/EncryptionMethods/RandomSyllablesMethod.cs b/Content.Shared/SS220/Language/EncryptionMethods/RandomSyllablesMethod.cs new file mode 100644 index 000000000000..bf6f3c767476 --- /dev/null +++ b/Content.Shared/SS220/Language/EncryptionMethods/RandomSyllablesMethod.cs @@ -0,0 +1,98 @@ +// © SS220, An EULA/CLA with a hosting restriction, full text: https://raw.githubusercontent.com/SerbiaStrong-220/space-station-14/master/CLA.txt + +using System.Text; +using System; +using Robust.Shared.Random; + +namespace Content.Shared.SS220.Language.EncryptionMethods; + +public sealed partial class RandomSyllablesEncryptionMethod : BaseEncryptionMethod +{ + /// + /// List of syllables from which the original message will be encrypted + /// A null value does not scramlbe the message in any way + /// + [DataField(required: true)] + public List Syllables = new(); + + /// + /// Chance of space between scrambled syllables + /// + [DataField] + public float SpaceChance = 0.5f; + + /// + /// Chance for a dot after a scrambled syllable. + /// + [DataField] + public float DotChance = 0.3f; + + /// + /// Chance of the after a scrambled syllable + /// + [DataField] + public float SpecialCharacterChance = 0.3f; + + [DataField] + public string SpecialCharacter = string.Empty; + + public override string EncryptMessage(string message) + { + if (Syllables.Count == 0) + return message; + + var random = IoCManager.Resolve(); + + var encryptedMessage = new StringBuilder(); + bool capitalize = false; + while (encryptedMessage.Length < message.Length) + { + var curSyllable = random.Pick(Syllables); + + if (capitalize) + { + curSyllable = curSyllable.Substring(0, 1).ToUpper() + curSyllable.Substring(1); + capitalize = false; + } + encryptedMessage.Append(curSyllable); + + if (random.Prob(SpecialCharacterChance)) + { + encryptedMessage.Append(SpecialCharacter); + } + else if (random.Prob(SpaceChance)) + { + encryptedMessage.Append(' '); + } + else if (random.Prob(DotChance)) + { + encryptedMessage.Append(". "); + capitalize = true; + } + } + + var result = encryptedMessage.ToString().Trim(); + var punctuation = ExtractPunctuation(message); + + result += punctuation; + + return result; + } + + /// + /// Takes the last punctuation out of the original post + /// (Does not affect the internal punctuation of the sentence) + /// + private static string ExtractPunctuation(string input) + { + var punctuationBuilder = new StringBuilder(); + for (var i = input.Length - 1; i >= 0; i--) + { + if (char.IsPunctuation(input[i])) + punctuationBuilder.Insert(0, input[i]); + else + break; + } + return punctuationBuilder.ToString(); + } +} diff --git a/Content.Shared/SS220/Language/LanguagesPrototype.cs b/Content.Shared/SS220/Language/LanguagesPrototype.cs index 3058f0896d21..3925d10e2f61 100644 --- a/Content.Shared/SS220/Language/LanguagesPrototype.cs +++ b/Content.Shared/SS220/Language/LanguagesPrototype.cs @@ -1,14 +1,12 @@ // © 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.SS220.Language.EncryptionMethods; using Robust.Shared.Prototypes; - namespace Content.Shared.SS220.Language; [Prototype("languages")] public sealed partial class LanguagesPrototype : IPrototype { - public const string Galactic = "Galactic"; - [ViewVariables, IdDataField] public string ID { get; private set; } = default!; @@ -17,27 +15,14 @@ public sealed partial class LanguagesPrototype : IPrototype [DataField] public string? Description { get; private set; } - /// - /// List of syllables from which the original message will be encrypted - /// A null value does not scramlbe the message in any way - /// - [DataField] - public List? Syllables = new(); - /// - /// Chance of space between scrambled syllables - /// - [DataField] - public float SpaceChance { get; private set; } = default!; - /// - /// Chance for a dot after a scrambled syllable, - /// here you can assign any character instead of a dot - /// - [DataField] - public string JoinOverride { get; private set; } = ". "; + /// /// The color of the language in which messages will be recolored, /// an empty value will not be recolored /// [DataField] public Color? Color; + + [DataField] + public BaseEncryptionMethod EncryptionMethod = new RandomSyllablesEncryptionMethod(); } diff --git a/Resources/Prototypes/SS220/Language/language.yml b/Resources/Prototypes/SS220/Language/language.yml index 1fbc677bb58e..cd0ed93e20ab 100644 --- a/Resources/Prototypes/SS220/Language/language.yml +++ b/Resources/Prototypes/SS220/Language/language.yml @@ -3,66 +3,69 @@ # Everyone understands you, you understand everyone, but there's no right to speak all languages - type: languages id: Universal - syllables: [] # Galactic common lanaguges region: - type: languages id: Galactic name: "language-galacticcommon-name" description: "language-galacticcommon-desc" - spaceChance: 50 - syllables: [бла, бла, бла, бле, мех, ньех, нах, ах, угу, увы] + encryptionMethod: !type:RandomSyllablesEncryptionMethod + syllables: [бла, бла, бла, бле, мех, ньех, нах, ах, угу, увы] - type: languages id: SolCommon name: "language-solcommon-name" description: "language-solcommon-desc" color: "#2f2fad" - spaceChance: 50 - syllables: [tao, shi, tzu, yi, com, be, is, i, op, vi, ed, lec, mo, cle, te, dis, e] + encryptionMethod: !type:RandomSyllablesEncryptionMethod + syllables: [tao, shi, tzu, yi, com, be, is, i, op, vi, ed, lec, mo, cle, te, dis, e] - type: languages id: Tradeband name: "language-tradeband-name" description: "language-tradeband-desc" color: "#87451c" - spaceChance: 100 - syllables: [lorem, ipsum, dolor, sit, amet, consectetur, adipiscing, elit, sed, do, eiusmod, tempor, incididunt, ut, labore, - et, dolore, magna, aliqua, ut, enim, ad, minim, veniam, quis, nostrud, exercitation, - ullamco, laboris, nisi, ut, aliquip, ex, ea, commodo, consequat, duis, aute, irure, - dolor, in, reprehenderit, in, voluptate, velit, esse, cillum, dolore, eu, fugiat, - nulla, pariatur, excepteur, sint, occaecat, cupidatat, non, proident, sunt, in, - culpa, qui, officia, deserunt, mollit, anim, id, est, laborum] + encryptionMethod: !type:RandomSyllablesEncryptionMethod + spaceChance: 1 + syllables: [lorem, ipsum, dolor, sit, amet, consectetur, adipiscing, elit, sed, do, eiusmod, tempor, incididunt, ut, labore, + et, dolore, magna, aliqua, ut, enim, ad, minim, veniam, quis, nostrud, exercitation, + ullamco, laboris, nisi, ut, aliquip, ex, ea, commodo, consequat, duis, aute, irure, + dolor, in, reprehenderit, in, voluptate, velit, esse, cillum, dolore, eu, fugiat, + nulla, pariatur, excepteur, sint, occaecat, cupidatat, non, proident, sunt, in, + culpa, qui, officia, deserunt, mollit, anim, id, est, laborum] - type: languages id: Gutter name: "language-gutter-name" description: "language-gutter-desc" color: "#7092BE" - spaceChance: 55 - syllables: [gra, ba, ba, breh, bra, rah, dur, ra, ro, gro, go, ber, bar, geh, heh, gra] + encryptionMethod: !type:RandomSyllablesEncryptionMethod + spaceChance: 0.55 + syllables: [gra, ba, ba, breh, bra, rah, dur, ra, ro, gro, go, ber, bar, geh, heh, gra] - type: languages id: Clownish name: "language-clownish-name" description: "language-clownish-desc" color: "#ff0000" - spaceChance: 60 - syllables: [хонк, cкуик, ойк, бонк, тут, наф, пуп, ви, вуб, ниф] + encryptionMethod: !type:RandomSyllablesEncryptionMethod + spaceChance: 0.6 + syllables: [хонк, cкуик, ойк, бонк, тут, наф, пуп, ви, вуб, ниф] - type: languages id: NeoRusskiya name: "language-neorusskiya-name" description: "language-neorusskiya-desc" color: "#7c4848" - spaceChance: 65 - syllables: [dyen, bar, bota, vyek, tvo, slov, slav, syen, doup, vah, laz, gloz, - yet, nyet, da, sky, glav, glaz, netz, doomat, zat, moch, boz, comy, vrad, vrade, - tay, bli, ay, nov, livn, tolv, glaz, gliz, ouy, zet, yevt, dat, botat, nev, novy, vzy, - nov, sho, obsh, dasky, key, skey, ovsky, skaya, bib, kiev, studen, var, bul, vyan, tzion, - vaya, myak, gino, volo, olam, miti, nino, menov, perov, odasky, trov, niki, ivano, dostov, - sokol, oupa, pervom, schel, tizan, chka, tagan, dobry, okt, boda, veta, idi, cyk, blyt, hui, - na, udi, litchki, casa, linka, toly, anatov, vich, vech, vuch, toi, ka, vod] + encryptionMethod: !type:RandomSyllablesEncryptionMethod + spaceChance: 0.65 + syllables: [dyen, bar, bota, vyek, tvo, slov, slav, syen, doup, vah, laz, gloz, + yet, nyet, da, sky, glav, glaz, netz, doomat, zat, moch, boz, comy, vrad, vrade, + tay, bli, ay, nov, livn, tolv, glaz, gliz, ouy, zet, yevt, dat, botat, nev, novy, vzy, + nov, sho, obsh, dasky, key, skey, ovsky, skaya, bib, kiev, studen, var, bul, vyan, tzion, + vaya, myak, gino, volo, olam, miti, nino, menov, perov, odasky, trov, niki, ivano, dostov, + sokol, oupa, pervom, schel, tizan, chka, tagan, dobry, okt, boda, veta, idi, cyk, blyt, hui, + na, udi, litchki, casa, linka, toly, anatov, vich, vech, vuch, toi, ka, vod] # Race region: - type: languages @@ -70,99 +73,107 @@ name: "language-unathi-name" description: "language-unathi-desc" color: "#228B22" - spaceChance: 50 - syllables: [za, az, ze, ez, zi, iz, zo, oz, zu, uz, zs, sz, ha, ah, he, eh, - hi, ih, ho, oh, hu, uh, hs, sh, la, al, le, el, li, il, lo, ol, - lu, ul, ls, sl, ka, ak, ke, ek, ki, ik, ko, ok, ku, uk, ks, sk, - sa, as, se, es, si, is, so, os, su, us, ss, ss, ra, ar, re, er, - ri, ir, ro, or, ru, ur, rs, sr, a, a, e, e, i, i, o, o, u, u, - s, s] + encryptionMethod: !type:RandomSyllablesEncryptionMethod + syllables: [za, az, ze, ez, zi, iz, zo, oz, zu, uz, zs, sz, ha, ah, he, eh, + hi, ih, ho, oh, hu, uh, hs, sh, la, al, le, el, li, il, lo, ol, + lu, ul, ls, sl, ka, ak, ke, ek, ki, ik, ko, ok, ku, uk, ks, sk, + sa, as, se, es, si, is, so, os, su, us, ss, ss, ra, ar, re, er, + ri, ir, ro, or, ru, ur, rs, sr, a, a, e, e, i, i, o, o, u, u, + s, s] - type: languages id: Siiktajr name: "language-siiktajr-name" description: "language-siiktajr-desc" color: "#803B56" - spaceChance: 40 - syllables: [rr, rrr, taj'r, kir, raj, kii, mir, kah, hrar, jun, - kra, ahkъ, nal, vah, khaz, jri, ran, hal, nja, dar, - darr, mi, jr'i, dynh, manq', rhe, zar, ketъ, rir, rik, - r'rhaz, kal, chur, eech, thaa, dra, jurl, jurl, azuъ, - mah, sanu, dra, ii'r, ъka, aasi, far, mah, tul, ragh - wa, baq, ara, qara, zir', sam, mak, cresh, khan] + encryptionMethod: !type:RandomSyllablesEncryptionMethod + spaceChance: 0.4 + syllables: [rr, rrr, taj'r, kir, raj, kii, mir, kah, hrar, jun, + kra, ahkъ, nal, vah, khaz, jri, ran, hal, nja, dar, + darr, mi, jr'i, dynh, manq', rhe, zar, ketъ, rir, rik, + r'rhaz, kal, chur, eech, thaa, dra, jurl, jurl, azuъ, + mah, sanu, dra, ii'r, ъka, aasi, far, mah, tul, ragh + wa, baq, ara, qara, zir', sam, mak, cresh, khan] - type: languages id: VoxPidgin name: "language-voxpidgin-name" description: "language-voxpidgin-desc" color: "#AA00AA" - spaceChance: 50 - syllables: [ti, ti, ti, hi, hi, ki, ki, ki, - ki, ya, ta, ha, ka, ya, yi, chi, cha, kah, - SKRE, AHK, EHK, RAWK, KRA, AAA, EEE, KI, - II, KRI, KA] + encryptionMethod: !type:RandomSyllablesEncryptionMethod + syllables: [ti, ti, ti, hi, hi, ki, ki, ki, + ki, ya, ta, ha, ka, ya, yi, chi, cha, kah, + SKRE, AHK, EHK, RAWK, KRA, AAA, EEE, KI, + II, KRI, KA] - type: languages id: Rootspeak name: "language-rootspeak-name" description: "language-rootspeak-desc" color: "#804000" - spaceChance: 30 - syllables: [hs, zt, kr, st, sh] + encryptionMethod: !type:RandomSyllablesEncryptionMethod + spaceChance: 0.3 + syllables: [hs, zt, kr, st, sh] - type: languages id: Bubblish name: "language-bobblish-name" description: "language-bobblish-desc" color: "#0077AA" - spaceChance: 60 - syllables: [блоб, плап, поп, боп, буп, пламп, буб, баб, бламп] + encryptionMethod: !type:RandomSyllablesEncryptionMethod + spaceChance: 0.6 + syllables: [блоб, плап, поп, боп, буп, пламп, буб, баб, бламп] - type: languages id: Tkachi name: "language-tkachi-name" description: "language-tkachi-desc" color: "#869b29" - spaceChance: 55 - joinOverride: "-" - syllables: [år, i, går, sek, mo, ff, ok, gj, ø, gå, la, le, lit, ygg, van, - dår, næ, møt, idd, hvo, ja, på, han, så, ån, det, att, nå, gö, bra, - int, tyc, om, när, två, må, dag, sjä, vii, vuo, eil, tun, käyt, teh, - vä, hei, huo, suo, ää, ten, ja, heu, stu, uhr, kön, we, hön] + encryptionMethod: !type:RandomSyllablesEncryptionMethod + spaceChance: 0.55 + specialCharacter: "-" + syllables: [år, i, går, sek, mo, ff, ok, gj, ø, gå, la, le, lit, ygg, van, + dår, næ, møt, idd, hvo, ja, på, han, så, ån, det, att, nå, gö, bra, + int, tyc, om, när, två, må, dag, sjä, vii, vuo, eil, tun, käyt, teh, + vä, hei, huo, suo, ää, ten, ja, heu, stu, uhr, kön, we, hön] - type: languages id: Eldwarf name: "language-eldwarf-name" description: "language-eldwarf-desc" color: "#515d63" - spaceChance: 55 - syllables: [вр, врон, рон, крон, друк, трым, бд, шкж, брм, рыт, грн, драш, клм, трк, врг, хрм, - рд, клыт, зм, эмээ, гнык, зрм, длк, брг, грд, скрын, вродд, бдар, глтх, скрр, - трг, бртх, хыкл, тр, крг, рдм, грыж, мд, гхрм, клм, прк, кнур] + encryptionMethod: !type:RandomSyllablesEncryptionMethod + spaceChance: 0.55 + syllables: [вр, врон, рон, крон, друк, трым, бд, шкж, брм, рыт, грн, драш, клм, трк, врг, хрм, + рд, клыт, зм, эмээ, гнык, зрм, длк, брг, грд, скрын, вродд, бдар, глтх, скрр, + трг, бртх, хыкл, тр, крг, рдм, грыж, мд, гхрм, клм, прк, кнур] - type: languages id: Arati name: "language-arati-name" description: "language-arati-desc" color: "#68477a" - spaceChance: 52 - joinOverride: "'" - syllables: [шаш, хаш, раш, шар, хра, хашт, шара, шкар, храк, тар, хар, схр, - карш, аш, шр, зз, ср, хаз, рашк, харш, рашн, шан, харз, шах, шарз, рашар, - кар, харат, хш, харр, арш', ашан, шанн, хсар, ашат, хаа, хазт, рашта, зара, - хаш, анн, аро', хат] + encryptionMethod: !type:RandomSyllablesEncryptionMethod + spaceChance: 0.52 + specialCharacter: "'" + specialCharacterChance: 0.4 + syllables: [шаш, хаш, раш, шар, хра, хашт, шара, шкар, храк, тар, хар, схр, + карш, аш, шр, зз, ср, хаз, рашк, харш, рашн, шан, харз, шах, шарз, рашар, + кар, харат, хш, харр, арш', ашан, шанн, хсар, ашат, хаа, хазт, рашта, зара, + хаш, анн, аро', хат] - type: languages id: Canilunzt name: "language-canilunzt-name" description: "language-canilunzt-desc" color: "#B97A57" - spaceChance: 45 - syllables: [rur, ya, cen, rawr, bar, kuk, tek, qat, uk, wu, vuh, tah, tch, schz, auch, - ist, ein, entch, zwichs, tut, mir, wo, bis, es, vor, nic, gro, lll, - enem, zandt, tzch, noch, hel, ischt, far, wa, baram, iereng, tech, lach, - sam, mak, lich, gen, or, ag, eck, gec, stag, onn, bin, ket, jarl, vulf, - einech, cresthz, azunein, ghzth] + encryptionMethod: !type:RandomSyllablesEncryptionMethod + spaceChance: 0.45 + syllables: [rur, ya, cen, rawr, bar, kuk, tek, qat, uk, wu, vuh, tah, tch, schz, auch, + ist, ein, entch, zwichs, tut, mir, wo, bis, es, vor, nic, gro, lll, + enem, zandt, tzch, noch, hel, ischt, far, wa, baram, iereng, tech, lach, + sam, mak, lich, gen, or, ag, eck, gec, stag, onn, bin, ket, jarl, vulf, + einech, cresthz, azunein, ghzth] # Misc region: - type: languages @@ -170,7 +181,8 @@ name: "language-binary-name" description: "language-binary-desc" color: "#2cc2e8" - spaceChance: 80 - joinOverride: " " - syllables: [1, 0, 01, 10, 11, 100, 101, 110, 111, 1000, 1001, 1010, 1011, - 1100, 1110, 1111, 10000, 10001, 10010, 10011, 10100, 10101] \ No newline at end of file + encryptionMethod: !type:RandomSyllablesEncryptionMethod + spaceChance: 0.8 + dotChance: 0 + syllables: [1, 0, 01, 10, 11, 100, 101, 110, 111, 1000, 1001, 1010, 1011, + 1100, 1110, 1111, 10000, 10001, 10010, 10011, 10100, 10101] From a21a5e90b9cd82a5d79c8996de275d03b9270177 Mon Sep 17 00:00:00 2001 From: Kirus59 <145689588+Kirus59@users.noreply.github.com> Date: Mon, 24 Feb 2025 22:30:53 +0300 Subject: [PATCH 13/48] Encrypt -> Scramble --- .../SS220/Language/LanguageSystem.cs | 2 +- .../EncryptionMethods/BaseEncryptionMethod.cs | 4 +-- .../RandomSyllablesMethod.cs | 5 ++- .../SS220/Language/LanguagesPrototype.cs | 2 +- .../Prototypes/SS220/Language/language.yml | 32 +++++++++---------- 5 files changed, 22 insertions(+), 23 deletions(-) diff --git a/Content.Server/SS220/Language/LanguageSystem.cs b/Content.Server/SS220/Language/LanguageSystem.cs index 2c0427b26cd4..8920d5b5cc51 100644 --- a/Content.Server/SS220/Language/LanguageSystem.cs +++ b/Content.Server/SS220/Language/LanguageSystem.cs @@ -56,7 +56,7 @@ public string ScrambleText(EntityUid? ent, string input, LanguagesPrototype prot if (ScrambleCache.TryGetValue(cacheKey, out var cachedValue)) return cachedValue; - var scrambledText = proto.EncryptionMethod.EncryptMessage(input); + var scrambledText = proto.ScrambleMethod.ScrambleMessage(input); ScrambleCache[cacheKey] = scrambledText; // Removes the first message from the cache if it fills up diff --git a/Content.Shared/SS220/Language/EncryptionMethods/BaseEncryptionMethod.cs b/Content.Shared/SS220/Language/EncryptionMethods/BaseEncryptionMethod.cs index 9457bd4893b0..fb437a151dfd 100644 --- a/Content.Shared/SS220/Language/EncryptionMethods/BaseEncryptionMethod.cs +++ b/Content.Shared/SS220/Language/EncryptionMethods/BaseEncryptionMethod.cs @@ -3,7 +3,7 @@ namespace Content.Shared.SS220.Language.EncryptionMethods; [ImplicitDataDefinitionForInheritors] -public abstract partial class BaseEncryptionMethod +public abstract partial class ScrambleMethod { - public abstract string EncryptMessage(string message); + public abstract string ScrambleMessage(string message); } diff --git a/Content.Shared/SS220/Language/EncryptionMethods/RandomSyllablesMethod.cs b/Content.Shared/SS220/Language/EncryptionMethods/RandomSyllablesMethod.cs index bf6f3c767476..66bd4cb4066d 100644 --- a/Content.Shared/SS220/Language/EncryptionMethods/RandomSyllablesMethod.cs +++ b/Content.Shared/SS220/Language/EncryptionMethods/RandomSyllablesMethod.cs @@ -1,12 +1,11 @@ // © SS220, An EULA/CLA with a hosting restriction, full text: https://raw.githubusercontent.com/SerbiaStrong-220/space-station-14/master/CLA.txt using System.Text; -using System; using Robust.Shared.Random; namespace Content.Shared.SS220.Language.EncryptionMethods; -public sealed partial class RandomSyllablesEncryptionMethod : BaseEncryptionMethod +public sealed partial class RandomSyllablesScrambleMethod : ScrambleMethod { /// /// List of syllables from which the original message will be encrypted @@ -36,7 +35,7 @@ public sealed partial class RandomSyllablesEncryptionMethod : BaseEncryptionMeth [DataField] public string SpecialCharacter = string.Empty; - public override string EncryptMessage(string message) + public override string ScrambleMessage(string message) { if (Syllables.Count == 0) return message; diff --git a/Content.Shared/SS220/Language/LanguagesPrototype.cs b/Content.Shared/SS220/Language/LanguagesPrototype.cs index 3925d10e2f61..b0661de12d34 100644 --- a/Content.Shared/SS220/Language/LanguagesPrototype.cs +++ b/Content.Shared/SS220/Language/LanguagesPrototype.cs @@ -24,5 +24,5 @@ public sealed partial class LanguagesPrototype : IPrototype public Color? Color; [DataField] - public BaseEncryptionMethod EncryptionMethod = new RandomSyllablesEncryptionMethod(); + public ScrambleMethod ScrambleMethod = new RandomSyllablesScrambleMethod(); } diff --git a/Resources/Prototypes/SS220/Language/language.yml b/Resources/Prototypes/SS220/Language/language.yml index cd0ed93e20ab..9d028fff36c2 100644 --- a/Resources/Prototypes/SS220/Language/language.yml +++ b/Resources/Prototypes/SS220/Language/language.yml @@ -9,7 +9,7 @@ id: Galactic name: "language-galacticcommon-name" description: "language-galacticcommon-desc" - encryptionMethod: !type:RandomSyllablesEncryptionMethod + scrambleMethod: !type:RandomSyllablesScrambleMethod syllables: [бла, бла, бла, бле, мех, ньех, нах, ах, угу, увы] - type: languages @@ -17,7 +17,7 @@ name: "language-solcommon-name" description: "language-solcommon-desc" color: "#2f2fad" - encryptionMethod: !type:RandomSyllablesEncryptionMethod + scrambleMethod: !type:RandomSyllablesScrambleMethod syllables: [tao, shi, tzu, yi, com, be, is, i, op, vi, ed, lec, mo, cle, te, dis, e] - type: languages @@ -25,7 +25,7 @@ name: "language-tradeband-name" description: "language-tradeband-desc" color: "#87451c" - encryptionMethod: !type:RandomSyllablesEncryptionMethod + scrambleMethod: !type:RandomSyllablesScrambleMethod spaceChance: 1 syllables: [lorem, ipsum, dolor, sit, amet, consectetur, adipiscing, elit, sed, do, eiusmod, tempor, incididunt, ut, labore, et, dolore, magna, aliqua, ut, enim, ad, minim, veniam, quis, nostrud, exercitation, @@ -39,7 +39,7 @@ name: "language-gutter-name" description: "language-gutter-desc" color: "#7092BE" - encryptionMethod: !type:RandomSyllablesEncryptionMethod + scrambleMethod: !type:RandomSyllablesScrambleMethod spaceChance: 0.55 syllables: [gra, ba, ba, breh, bra, rah, dur, ra, ro, gro, go, ber, bar, geh, heh, gra] @@ -48,7 +48,7 @@ name: "language-clownish-name" description: "language-clownish-desc" color: "#ff0000" - encryptionMethod: !type:RandomSyllablesEncryptionMethod + scrambleMethod: !type:RandomSyllablesScrambleMethod spaceChance: 0.6 syllables: [хонк, cкуик, ойк, бонк, тут, наф, пуп, ви, вуб, ниф] @@ -57,7 +57,7 @@ name: "language-neorusskiya-name" description: "language-neorusskiya-desc" color: "#7c4848" - encryptionMethod: !type:RandomSyllablesEncryptionMethod + scrambleMethod: !type:RandomSyllablesScrambleMethod spaceChance: 0.65 syllables: [dyen, bar, bota, vyek, tvo, slov, slav, syen, doup, vah, laz, gloz, yet, nyet, da, sky, glav, glaz, netz, doomat, zat, moch, boz, comy, vrad, vrade, @@ -73,7 +73,7 @@ name: "language-unathi-name" description: "language-unathi-desc" color: "#228B22" - encryptionMethod: !type:RandomSyllablesEncryptionMethod + scrambleMethod: !type:RandomSyllablesScrambleMethod syllables: [za, az, ze, ez, zi, iz, zo, oz, zu, uz, zs, sz, ha, ah, he, eh, hi, ih, ho, oh, hu, uh, hs, sh, la, al, le, el, li, il, lo, ol, lu, ul, ls, sl, ka, ak, ke, ek, ki, ik, ko, ok, ku, uk, ks, sk, @@ -86,7 +86,7 @@ name: "language-siiktajr-name" description: "language-siiktajr-desc" color: "#803B56" - encryptionMethod: !type:RandomSyllablesEncryptionMethod + scrambleMethod: !type:RandomSyllablesScrambleMethod spaceChance: 0.4 syllables: [rr, rrr, taj'r, kir, raj, kii, mir, kah, hrar, jun, kra, ahkъ, nal, vah, khaz, jri, ran, hal, nja, dar, @@ -100,7 +100,7 @@ name: "language-voxpidgin-name" description: "language-voxpidgin-desc" color: "#AA00AA" - encryptionMethod: !type:RandomSyllablesEncryptionMethod + scrambleMethod: !type:RandomSyllablesScrambleMethod syllables: [ti, ti, ti, hi, hi, ki, ki, ki, ki, ya, ta, ha, ka, ya, yi, chi, cha, kah, SKRE, AHK, EHK, RAWK, KRA, AAA, EEE, KI, @@ -111,7 +111,7 @@ name: "language-rootspeak-name" description: "language-rootspeak-desc" color: "#804000" - encryptionMethod: !type:RandomSyllablesEncryptionMethod + scrambleMethod: !type:RandomSyllablesScrambleMethod spaceChance: 0.3 syllables: [hs, zt, kr, st, sh] @@ -120,7 +120,7 @@ name: "language-bobblish-name" description: "language-bobblish-desc" color: "#0077AA" - encryptionMethod: !type:RandomSyllablesEncryptionMethod + scrambleMethod: !type:RandomSyllablesScrambleMethod spaceChance: 0.6 syllables: [блоб, плап, поп, боп, буп, пламп, буб, баб, бламп] @@ -129,7 +129,7 @@ name: "language-tkachi-name" description: "language-tkachi-desc" color: "#869b29" - encryptionMethod: !type:RandomSyllablesEncryptionMethod + scrambleMethod: !type:RandomSyllablesScrambleMethod spaceChance: 0.55 specialCharacter: "-" syllables: [år, i, går, sek, mo, ff, ok, gj, ø, gå, la, le, lit, ygg, van, @@ -142,7 +142,7 @@ name: "language-eldwarf-name" description: "language-eldwarf-desc" color: "#515d63" - encryptionMethod: !type:RandomSyllablesEncryptionMethod + scrambleMethod: !type:RandomSyllablesScrambleMethod spaceChance: 0.55 syllables: [вр, врон, рон, крон, друк, трым, бд, шкж, брм, рыт, грн, драш, клм, трк, врг, хрм, рд, клыт, зм, эмээ, гнык, зрм, длк, брг, грд, скрын, вродд, бдар, глтх, скрр, @@ -153,7 +153,7 @@ name: "language-arati-name" description: "language-arati-desc" color: "#68477a" - encryptionMethod: !type:RandomSyllablesEncryptionMethod + scrambleMethod: !type:RandomSyllablesScrambleMethod spaceChance: 0.52 specialCharacter: "'" specialCharacterChance: 0.4 @@ -167,7 +167,7 @@ name: "language-canilunzt-name" description: "language-canilunzt-desc" color: "#B97A57" - encryptionMethod: !type:RandomSyllablesEncryptionMethod + scrambleMethod: !type:RandomSyllablesScrambleMethod spaceChance: 0.45 syllables: [rur, ya, cen, rawr, bar, kuk, tek, qat, uk, wu, vuh, tah, tch, schz, auch, ist, ein, entch, zwichs, tut, mir, wo, bis, es, vor, nic, gro, lll, @@ -181,7 +181,7 @@ name: "language-binary-name" description: "language-binary-desc" color: "#2cc2e8" - encryptionMethod: !type:RandomSyllablesEncryptionMethod + scrambleMethod: !type:RandomSyllablesScrambleMethod spaceChance: 0.8 dotChance: 0 syllables: [1, 0, 01, 10, 11, 100, 101, 110, 111, 1000, 1001, 1010, 1011, From b115ea497fdd9641c1bc581fd93f6aad3b0a3f63 Mon Sep 17 00:00:00 2001 From: Kirus59 <145689588+Kirus59@users.noreply.github.com> Date: Wed, 26 Feb 2025 18:20:26 +0300 Subject: [PATCH 14/48] moving to the server --- Content.Client/Entry/EntryPoint.cs | 1 + .../SS220/Language/LanguageSystem.cs | 6 - Content.Server/Chat/Systems/ChatSystem.cs | 7 +- .../EntityEffects/Effects/MakeSentient.cs | 3 +- Content.Server/PAI/PAISystem.cs | 1 - Content.Server/Radio/RadioEvent.cs | 4 +- .../SS220/Commands/LanguageCommands.cs | 4 +- .../EncryptionMethods/BaseEncryptionMethod.cs | 2 +- .../RandomSyllablesMethod.cs | 5 +- .../SS220/Language/LanguageComponent.cs | 13 +- .../SS220/Language/LanguageSystem.Verbs.cs | 25 +-- .../SS220/Language/LanguageSystem.cs | 145 ++++++++++++++++-- .../SS220/Language/LanguagesPrototype.cs | 8 +- .../Language/Special/AddLanguageSpecial.cs | 4 +- Content.Server/Traits/TraitSystem.cs | 2 +- .../Zombies/ZombieSystem.Transform.cs | 2 +- .../SS220/Language/SharedLanguageSystem.cs | 140 ----------------- .../Prototypes/SS220/Language/language.yml | 34 ++-- 18 files changed, 183 insertions(+), 223 deletions(-) delete mode 100644 Content.Client/SS220/Language/LanguageSystem.cs rename {Content.Shared => Content.Server}/SS220/Language/EncryptionMethods/BaseEncryptionMethod.cs (83%) rename {Content.Shared => Content.Server}/SS220/Language/EncryptionMethods/RandomSyllablesMethod.cs (96%) rename {Content.Shared => Content.Server}/SS220/Language/LanguageComponent.cs (69%) rename Content.Shared/SS220/Verbs/LanguageVerbs.cs => Content.Server/SS220/Language/LanguageSystem.Verbs.cs (72%) rename {Content.Shared => Content.Server}/SS220/Language/LanguagesPrototype.cs (79%) delete mode 100644 Content.Shared/SS220/Language/SharedLanguageSystem.cs diff --git a/Content.Client/Entry/EntryPoint.cs b/Content.Client/Entry/EntryPoint.cs index acb98563b913..d0e207d0f494 100644 --- a/Content.Client/Entry/EntryPoint.cs +++ b/Content.Client/Entry/EntryPoint.cs @@ -133,6 +133,7 @@ public override void Init() _prototypeManager.RegisterIgnore("nukeopsRole"); _prototypeManager.RegisterIgnore("stationGoal"); // Corvax-StationGoal _prototypeManager.RegisterIgnore("ghostRoleRaffleDecider"); + _prototypeManager.RegisterIgnore("language"); // SS220 languages _componentFactory.GenerateNetIds(); _adminManager.Initialize(); diff --git a/Content.Client/SS220/Language/LanguageSystem.cs b/Content.Client/SS220/Language/LanguageSystem.cs deleted file mode 100644 index 248e9d3356a8..000000000000 --- a/Content.Client/SS220/Language/LanguageSystem.cs +++ /dev/null @@ -1,6 +0,0 @@ -using Content.Shared.SS220.Language; - - -namespace Content.Client.SS220.Language; -public sealed class LanguageSystem : SharedLanguageSystem; - diff --git a/Content.Server/Chat/Systems/ChatSystem.cs b/Content.Server/Chat/Systems/ChatSystem.cs index ca2b7c1bef18..1c20ef910733 100644 --- a/Content.Server/Chat/Systems/ChatSystem.cs +++ b/Content.Server/Chat/Systems/ChatSystem.cs @@ -42,7 +42,6 @@ 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 using Robust.Shared.Map; @@ -175,7 +174,7 @@ public void TrySendInGameICMessage( ICommonSession? player = null, string? nameOverride = null, bool checkRadioPrefix = true, bool ignoreActionBlocker = false, - LanguagesPrototype? languageProto = null) // SS220-Add-Languages + LanguagePrototype? languageProto = null) // SS220-Add-Languages { TrySendInGameICMessage(source, message, desiredType, hideChat ? ChatTransmitRange.HideChat : ChatTransmitRange.Normal, @@ -205,7 +204,7 @@ public void TrySendInGameICMessage( string? nameOverride = null, bool checkRadioPrefix = true, bool ignoreActionBlocker = false, - LanguagesPrototype? languageProto = null) // SS220-Add-Languages + LanguagePrototype? languageProto = null) // SS220-Add-Languages { if (HasComp(source)) { @@ -563,7 +562,7 @@ private void SendEntityWhisper( string? nameOverride, bool hideLog = false, bool ignoreActionBlocker = false, - LanguagesPrototype? languageProto = null) // SS220-Add-Languages + LanguagePrototype? languageProto = null) // SS220-Add-Languages { if (!_actionBlocker.CanSpeak(source) && !ignoreActionBlocker) return; diff --git a/Content.Server/EntityEffects/Effects/MakeSentient.cs b/Content.Server/EntityEffects/Effects/MakeSentient.cs index 3f7ebbcc9401..9029d0176480 100644 --- a/Content.Server/EntityEffects/Effects/MakeSentient.cs +++ b/Content.Server/EntityEffects/Effects/MakeSentient.cs @@ -1,9 +1,8 @@ using Content.Server.Ghost.Roles.Components; using Content.Server.Speech.Components; -using Content.Server.SS220.Language; +using Content.Server.SS220.Language; 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; diff --git a/Content.Server/PAI/PAISystem.cs b/Content.Server/PAI/PAISystem.cs index a1e7499d57a8..51238df6fceb 100644 --- a/Content.Server/PAI/PAISystem.cs +++ b/Content.Server/PAI/PAISystem.cs @@ -9,7 +9,6 @@ using Robust.Shared.Random; using System.Text; using Robust.Shared.Player; -using Content.Shared.SS220.Language; using Content.Server.SS220.Language; // SS220-Add-Languages namespace Content.Server.PAI; diff --git a/Content.Server/Radio/RadioEvent.cs b/Content.Server/Radio/RadioEvent.cs index 528ac7551f43..b56d67e26173 100644 --- a/Content.Server/Radio/RadioEvent.cs +++ b/Content.Server/Radio/RadioEvent.cs @@ -1,7 +1,7 @@ using Content.Server.Chat.Systems; using Content.Shared.Chat; -using Content.Shared.SS220.Language; // SS220-Add-Languages using Content.Shared.Radio; +using Content.Server.SS220.Language; namespace Content.Server.Radio; @@ -9,7 +9,7 @@ namespace Content.Server.Radio; public readonly record struct RadioReceiveEvent(string Message, EntityUid MessageSource, RadioChannelPrototype Channel, EntityUid RadioSource, MsgChatMessage ChatMsg, MsgChatMessage ScrambledChatMsg, - LanguagesPrototype? LanguageProto, List Receivers); // SS220-Add-Languages + LanguagePrototype? LanguageProto, List Receivers); // SS220-Add-Languages /// /// Use this event to cancel sending message per receiver diff --git a/Content.Server/SS220/Commands/LanguageCommands.cs b/Content.Server/SS220/Commands/LanguageCommands.cs index 7628e30ac437..d8c92bb0fb24 100644 --- a/Content.Server/SS220/Commands/LanguageCommands.cs +++ b/Content.Server/SS220/Commands/LanguageCommands.cs @@ -1,6 +1,6 @@ using Content.Server.Administration; +using Content.Server.SS220.Language; using Content.Shared.Administration; -using Content.Shared.SS220.Language; using Robust.Shared.Console; using Robust.Shared.Prototypes; @@ -32,7 +32,7 @@ public void Execute(IConsoleShell shell, string argStr, string[] args) var languageId = args[1]; - if (!_proto.TryIndex(languageId, out var languageProto)) + if (!_proto.TryIndex(languageId, out var languageProto)) { shell.WriteError(Loc.GetString("cmd-language-proto-miss")); return; diff --git a/Content.Shared/SS220/Language/EncryptionMethods/BaseEncryptionMethod.cs b/Content.Server/SS220/Language/EncryptionMethods/BaseEncryptionMethod.cs similarity index 83% rename from Content.Shared/SS220/Language/EncryptionMethods/BaseEncryptionMethod.cs rename to Content.Server/SS220/Language/EncryptionMethods/BaseEncryptionMethod.cs index fb437a151dfd..c47bece2ce04 100644 --- a/Content.Shared/SS220/Language/EncryptionMethods/BaseEncryptionMethod.cs +++ b/Content.Server/SS220/Language/EncryptionMethods/BaseEncryptionMethod.cs @@ -1,6 +1,6 @@ // © SS220, An EULA/CLA with a hosting restriction, full text: https://raw.githubusercontent.com/SerbiaStrong-220/space-station-14/master/CLA.txt -namespace Content.Shared.SS220.Language.EncryptionMethods; +namespace Content.Server.SS220.Language.EncryptionMethods; [ImplicitDataDefinitionForInheritors] public abstract partial class ScrambleMethod diff --git a/Content.Shared/SS220/Language/EncryptionMethods/RandomSyllablesMethod.cs b/Content.Server/SS220/Language/EncryptionMethods/RandomSyllablesMethod.cs similarity index 96% rename from Content.Shared/SS220/Language/EncryptionMethods/RandomSyllablesMethod.cs rename to Content.Server/SS220/Language/EncryptionMethods/RandomSyllablesMethod.cs index 66bd4cb4066d..8e0c8084501d 100644 --- a/Content.Shared/SS220/Language/EncryptionMethods/RandomSyllablesMethod.cs +++ b/Content.Server/SS220/Language/EncryptionMethods/RandomSyllablesMethod.cs @@ -1,9 +1,8 @@ // © SS220, An EULA/CLA with a hosting restriction, full text: https://raw.githubusercontent.com/SerbiaStrong-220/space-station-14/master/CLA.txt - using System.Text; using Robust.Shared.Random; -namespace Content.Shared.SS220.Language.EncryptionMethods; +namespace Content.Server.SS220.Language.EncryptionMethods; public sealed partial class RandomSyllablesScrambleMethod : ScrambleMethod { @@ -43,7 +42,7 @@ public override string ScrambleMessage(string message) var random = IoCManager.Resolve(); var encryptedMessage = new StringBuilder(); - bool capitalize = false; + var capitalize = false; while (encryptedMessage.Length < message.Length) { var curSyllable = random.Pick(Syllables); diff --git a/Content.Shared/SS220/Language/LanguageComponent.cs b/Content.Server/SS220/Language/LanguageComponent.cs similarity index 69% rename from Content.Shared/SS220/Language/LanguageComponent.cs rename to Content.Server/SS220/Language/LanguageComponent.cs index 5481f0351282..01f33896f435 100644 --- a/Content.Shared/SS220/Language/LanguageComponent.cs +++ b/Content.Server/SS220/Language/LanguageComponent.cs @@ -3,26 +3,25 @@ using Robust.Shared.Prototypes; -namespace Content.Shared.SS220.Language; +namespace Content.Server.SS220.Language; /// /// A component that allows an entity to speak and understand languages. -/// Language prototypes are taken from YML of +/// Language prototypes are taken from YML of /// The absence of this component gives the entity “Universal” language /// -[RegisterComponent, NetworkedComponent] -[AutoGenerateComponentState] +[RegisterComponent] public sealed partial class LanguageComponent : Component { /// /// Selected language in which the entity will speak. /// - [DataField, ViewVariables(VVAccess.ReadWrite), AutoNetworkedField] + [DataField, ViewVariables(VVAccess.ReadWrite)] public string? CurrentLanguage = default!; /// /// List of languages that the Entity speaks and understands. /// - [DataField("learnedLanguages"), AutoNetworkedField] - public List> LearnedLanguages { get; set; } = new(); + [DataField("learnedLanguages")] + public List> LearnedLanguages { get; set; } = new(); } diff --git a/Content.Shared/SS220/Verbs/LanguageVerbs.cs b/Content.Server/SS220/Language/LanguageSystem.Verbs.cs similarity index 72% rename from Content.Shared/SS220/Verbs/LanguageVerbs.cs rename to Content.Server/SS220/Language/LanguageSystem.Verbs.cs index 2fbb8f92b545..deb71c018155 100644 --- a/Content.Shared/SS220/Verbs/LanguageVerbs.cs +++ b/Content.Server/SS220/Language/LanguageSystem.Verbs.cs @@ -1,28 +1,16 @@ // © 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.SS220.Language; using Content.Shared.Verbs; -using Robust.Shared.Prototypes; using System.Linq; - -namespace Content.Shared.SS220.Verbs; +namespace Content.Server.SS220.Language; /// /// I was bored and lazy to understand the UI, /// according to this language is selected with Verb at the entity /// // TODO: Make the language selection in the UI instead of this crap -public sealed partial class LanguageVerbs : EntitySystem +public sealed partial class LanguageSystem : EntitySystem { - [Dependency] private readonly IPrototypeManager _proto = default!; - [Dependency] private readonly SharedLanguageSystem _languageSystem = default!; - - public override void Initialize() - { - base.Initialize(); - SubscribeLocalEvent>(OnVerb); - } - private void OnVerb(EntityUid ent, LanguageComponent comp, ref GetVerbsEvent args) { if (args.User != args.Target) @@ -46,9 +34,9 @@ private List CreateVerbs(EntityUid ent, List languages) if (!TryComp(ent, out var comp)) return verbs; - foreach (string language in languages) + foreach (var language in languages) { - if (language == _languageSystem.UniversalLanguage) // no verb for a universal language is created + if (language == UniversalLanguage) // no verb for a universal language is created continue; verbs.Add(new Verb @@ -66,7 +54,7 @@ private List CreateVerbs(EntityUid ent, List languages) public string GetName(string language) { - if (!_proto.TryIndex(language, out var proto)) + if (!_proto.TryIndex(language, out var proto)) return language; if (proto.Name == null) @@ -78,7 +66,7 @@ public string GetName(string language) public string? GetDescription(string language) { - if (!_proto.TryIndex(language, out var proto)) + if (!_proto.TryIndex(language, out var proto)) return null; if (proto.Description == null) @@ -94,6 +82,5 @@ private void ChangeLanguage(EntityUid ent, string language) return; comp.CurrentLanguage = language; - Dirty(ent, comp); } } diff --git a/Content.Server/SS220/Language/LanguageSystem.cs b/Content.Server/SS220/Language/LanguageSystem.cs index 8920d5b5cc51..43ca237a6b6e 100644 --- a/Content.Server/SS220/Language/LanguageSystem.cs +++ b/Content.Server/SS220/Language/LanguageSystem.cs @@ -1,24 +1,28 @@ // © SS220, An EULA/CLA with a hosting restriction, full text: https://raw.githubusercontent.com/SerbiaStrong-220/space-station-14/master/CLA.txt using Content.Server.GameTicking.Events; -using Content.Shared.SS220.Language; +using Content.Shared.Ghost; +using Content.Shared.Verbs; using Robust.Shared.Prototypes; -using Robust.Shared.Random; using System.Linq; -using System.Text; using System.Text.RegularExpressions; - namespace Content.Server.SS220.Language; -public sealed partial class LanguageSystem : SharedLanguageSystem + +public sealed partial class LanguageSystem : EntitySystem { - [Dependency] private readonly IRobustRandom _random = default!; - [Dependency] private readonly IPrototypeManager _prototypeManager = default!; + [Dependency] private readonly IPrototypeManager _proto = default!; + + public readonly string UniversalLanguage = "Universal"; + public readonly string GalacticLanguage = "Galactic"; public override void Initialize() { base.Initialize(); SubscribeLocalEvent(OnRoundStart); SubscribeLocalEvent(OnMapInit); + + // Verbs + SubscribeLocalEvent>(OnVerb); } private static readonly Dictionary ScrambleCache = new Dictionary(); @@ -37,15 +41,13 @@ private void OnMapInit(Entity ent, ref MapInitEvent args) { if (ent.Comp.CurrentLanguage == null) ent.Comp.CurrentLanguage = ent.Comp.LearnedLanguages.FirstOrDefault(UniversalLanguage); - - Dirty(ent.Owner, ent.Comp); } /// /// A method of encrypting the original message into a message created /// from the syllables of prototypes languages /// - public string ScrambleText(EntityUid? ent, string input, LanguagesPrototype proto) + public string ScrambleText(EntityUid? ent, string input, LanguagePrototype proto) { input = RemoveColorTags(input); var cacheKey = $"{proto.ID}:{input}"; @@ -98,5 +100,128 @@ public string SanitizeMessage(EntityUid source, EntityUid listener, string messa newMessage = SetColor(newMessage, languageProto); return newMessage; } + + /// + /// Method that checks an entity for the presence of a prototype language + /// or for the presence of a universal language + /// + public bool CheckLanguage(EntityUid ent, LanguagePrototype? proto) + { + if (proto == null) + return false; + + if (KnowsUniversalLanguage(ent)) + return true; + + return KnowsLanguages(ent, proto.ID); + } + + public bool KnowsLanguages(EntityUid ent, string languageId) + { + if (!TryComp(ent, out var comp)) + return false; + + if (comp.CurrentLanguage == languageId) + return true; + + return comp.LearnedLanguages.Contains(languageId); + } + + public bool KnowsUniversalLanguage(EntityUid ent) + { + if (HasComp(ent)) + return true; + + if (!TryComp(ent, out var comp)) + return true; + + if (comp != null && comp.CurrentLanguage == UniversalLanguage) + return true; + + if (comp != null && comp.LearnedLanguages.Contains(UniversalLanguage)) + return true; + + return false; + } + + /// + /// A method to get a prototype language from an entity. + /// If the entity does not have a language component, a universal language is assigned. + /// + public LanguagePrototype? GetProto(EntityUid ent) + { + if (!TryComp(ent, out var comp)) + { + if (_proto.TryIndex(UniversalLanguage, out var universalProto)) + return universalProto; + } + + var languageID = GetCurrentLanguage(ent); + + if (languageID == null) + return null; + + if (_proto.TryIndex(languageID, out var proto)) + return proto; + + return null; + } + + public string? GetCurrentLanguage(EntityUid ent) + { + if (!TryComp(ent, out var comp)) + return null; + + return comp.CurrentLanguage; + } + + public void AddLanguages(EntityUid uid, List languages) + { + foreach (var language in languages) + { + AddLanguage(uid, language); + } + } + + public void AddLanguage(EntityUid uid, string languageId) + { + if (!TryComp(uid, out var comp)) + return; + + if (!_proto.TryIndex(languageId, out var proto)) + { + Log.Error($"Doesn't found a LanguagePrototype with id: {languageId}"); + return; + } + + if (!comp.LearnedLanguages.Contains(proto)) + comp.LearnedLanguages.Add(proto); + } + + /// + /// Sets the color of the prototype language to the message + /// + public string SetColor(string message, LanguagePrototype proto) + { + if (proto.Color == null) + return message; + + var color = proto.Color.Value.ToHex(); + message = $"[color={color}]{message}[/color]"; + return message; + } + + public void AddLanguagesFromSource(EntityUid source, EntityUid target) + { + if (!TryComp(source, out var sourceComp)) + return; + + var targetComp = EnsureComp(target); + foreach (var language in sourceComp.LearnedLanguages) + { + if (!targetComp.LearnedLanguages.Contains(language)) + targetComp.LearnedLanguages.Add(language); + } + } } diff --git a/Content.Shared/SS220/Language/LanguagesPrototype.cs b/Content.Server/SS220/Language/LanguagesPrototype.cs similarity index 79% rename from Content.Shared/SS220/Language/LanguagesPrototype.cs rename to Content.Server/SS220/Language/LanguagesPrototype.cs index b0661de12d34..dde8030b48a5 100644 --- a/Content.Shared/SS220/Language/LanguagesPrototype.cs +++ b/Content.Server/SS220/Language/LanguagesPrototype.cs @@ -1,11 +1,11 @@ // © 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.SS220.Language.EncryptionMethods; +using Content.Server.SS220.Language.EncryptionMethods; using Robust.Shared.Prototypes; -namespace Content.Shared.SS220.Language; +namespace Content.Server.SS220.Language; -[Prototype("languages")] -public sealed partial class LanguagesPrototype : IPrototype +[Prototype("language")] +public sealed partial class LanguagePrototype : IPrototype { [ViewVariables, IdDataField] public string ID { get; private set; } = default!; diff --git a/Content.Server/SS220/Language/Special/AddLanguageSpecial.cs b/Content.Server/SS220/Language/Special/AddLanguageSpecial.cs index 162a31d32ed2..9b349813c47b 100644 --- a/Content.Server/SS220/Language/Special/AddLanguageSpecial.cs +++ b/Content.Server/SS220/Language/Special/AddLanguageSpecial.cs @@ -1,9 +1,7 @@ // © 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.SS220.Language; using Content.Shared.Roles; using JetBrains.Annotations; - namespace Content.Server.SS220.Language.Special; /// /// Type for giving language to individual job roles @@ -17,7 +15,7 @@ public sealed partial class AddLanguageSpecial : JobSpecial public override void AfterEquip(EntityUid mob) { var entMan = IoCManager.Resolve(); - var languageSystem = entMan.System(); + var languageSystem = entMan.System(); languageSystem.AddLanguages(mob, Languages); } } diff --git a/Content.Server/Traits/TraitSystem.cs b/Content.Server/Traits/TraitSystem.cs index 0268886a8aed..f817e657d6a7 100644 --- a/Content.Server/Traits/TraitSystem.cs +++ b/Content.Server/Traits/TraitSystem.cs @@ -1,11 +1,11 @@ using Content.Shared.GameTicking; using Content.Shared.Hands.Components; using Content.Shared.Hands.EntitySystems; -using Content.Shared.SS220.Language; // SS220-Add-Languages using Content.Shared.Roles; using Content.Shared.Traits; using Content.Shared.Whitelist; using Robust.Shared.Prototypes; +using Content.Server.SS220.Language; namespace Content.Server.Traits; diff --git a/Content.Server/Zombies/ZombieSystem.Transform.cs b/Content.Server/Zombies/ZombieSystem.Transform.cs index 6998a0d37a9e..4e75780145b1 100644 --- a/Content.Server/Zombies/ZombieSystem.Transform.cs +++ b/Content.Server/Zombies/ZombieSystem.Transform.cs @@ -40,7 +40,7 @@ using Content.Shared.Humanoid.Markings; using Robust.Server.Player; using Content.Shared.Ghost.Roles.Components; -using Content.Shared.SS220.Language; // SS220-Add-Languages +using Content.Server.SS220.Language; // SS220-Add-Languages namespace Content.Server.Zombies; diff --git a/Content.Shared/SS220/Language/SharedLanguageSystem.cs b/Content.Shared/SS220/Language/SharedLanguageSystem.cs deleted file mode 100644 index 3e20daec32e1..000000000000 --- a/Content.Shared/SS220/Language/SharedLanguageSystem.cs +++ /dev/null @@ -1,140 +0,0 @@ -// © 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.Ghost; -using Robust.Shared.Prototypes; - - - -namespace Content.Shared.SS220.Language; - -public abstract class SharedLanguageSystem : EntitySystem -{ - [Dependency] private readonly IPrototypeManager _proto = default!; - - public readonly string UniversalLanguage = "Universal"; - public readonly string GalacticLanguage = "Galactic"; - - /// - /// Method that checks an entity for the presence of a prototype language - /// or for the presence of a universal language - /// - public bool CheckLanguage(EntityUid ent, LanguagesPrototype? proto) - { - if (proto == null) - return false; - - if (KnowsUniversalLanguage(ent)) - return true; - - return KnowsLanguages(ent, proto.ID); - } - - public bool KnowsLanguages(EntityUid ent, string languageId) - { - if (!TryComp(ent, out var comp)) - return false; - - if (comp.CurrentLanguage == languageId) - return true; - - return comp.LearnedLanguages.Contains(languageId); - } - - public bool KnowsUniversalLanguage(EntityUid ent) - { - if (HasComp(ent)) - return true; - - if (!TryComp(ent, out var comp)) - return true; - - if (comp != null && comp.CurrentLanguage == UniversalLanguage) - return true; - - if (comp != null && comp.LearnedLanguages.Contains(UniversalLanguage)) - return true; - - return false; - } - - /// - /// A method to get a prototype language from an entity. - /// If the entity does not have a language component, a universal language is assigned. - /// - public LanguagesPrototype? GetProto(EntityUid ent) - { - if (!TryComp(ent, out var comp)) - { - if (_proto.TryIndex(UniversalLanguage, out var universalProto)) - return universalProto; - } - - var languageID = GetCurrentLanguage(ent); - - if (languageID == null) - return null; - - if (_proto.TryIndex(languageID, out var proto)) - return proto; - - return null; - } - - public string? GetCurrentLanguage(EntityUid ent) - { - if (!TryComp(ent, out var comp)) - return null; - - return comp.CurrentLanguage; - } - - public void AddLanguages(EntityUid uid, List languages) - { - foreach (var language in languages) - { - AddLanguage(uid, language); - } - } - - public void AddLanguage(EntityUid uid, string languageId) - { - if (!TryComp(uid, out var comp)) - return; - - if (!_proto.TryIndex(languageId, out var proto)) - { - Log.Error($"Doesn't found a LanguagePrototype with id: {languageId}"); - return; - } - - if (!comp.LearnedLanguages.Contains(proto)) - comp.LearnedLanguages.Add(proto); - } - - /// - /// Sets the color of the prototype language to the message - /// - public string SetColor(string message, LanguagesPrototype proto) - { - if (proto.Color == null) - return message; - - var color = proto.Color.Value.ToHex(); - message = $"[color={color}]{message}[/color]"; - return message; - } - - public void AddLanguagesFromSource(EntityUid source, EntityUid target) - { - if (!TryComp(source, out var sourceComp)) - return; - - var targetComp = EnsureComp(target); - foreach (var language in sourceComp.LearnedLanguages) - { - if (!targetComp.LearnedLanguages.Contains(language)) - targetComp.LearnedLanguages.Add(language); - } - - Dirty(target, targetComp); - } -} diff --git a/Resources/Prototypes/SS220/Language/language.yml b/Resources/Prototypes/SS220/Language/language.yml index 9d028fff36c2..65354987827a 100644 --- a/Resources/Prototypes/SS220/Language/language.yml +++ b/Resources/Prototypes/SS220/Language/language.yml @@ -1,18 +1,18 @@ # Based on SS13 Paradise (https://github.com/ParadiseSS13/Paradise/blob/017a56f8080361f04c296c94859802aaddf25114/code/modules/mob/language.dm#L4) # Everyone understands you, you understand everyone, but there's no right to speak all languages -- type: languages +- type: language id: Universal # Galactic common lanaguges region: -- type: languages +- type: language id: Galactic name: "language-galacticcommon-name" description: "language-galacticcommon-desc" scrambleMethod: !type:RandomSyllablesScrambleMethod syllables: [бла, бла, бла, бле, мех, ньех, нах, ах, угу, увы] -- type: languages +- type: language id: SolCommon name: "language-solcommon-name" description: "language-solcommon-desc" @@ -20,7 +20,7 @@ scrambleMethod: !type:RandomSyllablesScrambleMethod syllables: [tao, shi, tzu, yi, com, be, is, i, op, vi, ed, lec, mo, cle, te, dis, e] -- type: languages +- type: language id: Tradeband name: "language-tradeband-name" description: "language-tradeband-desc" @@ -34,7 +34,7 @@ nulla, pariatur, excepteur, sint, occaecat, cupidatat, non, proident, sunt, in, culpa, qui, officia, deserunt, mollit, anim, id, est, laborum] -- type: languages +- type: language id: Gutter name: "language-gutter-name" description: "language-gutter-desc" @@ -43,7 +43,7 @@ spaceChance: 0.55 syllables: [gra, ba, ba, breh, bra, rah, dur, ra, ro, gro, go, ber, bar, geh, heh, gra] -- type: languages +- type: language id: Clownish name: "language-clownish-name" description: "language-clownish-desc" @@ -52,7 +52,7 @@ spaceChance: 0.6 syllables: [хонк, cкуик, ойк, бонк, тут, наф, пуп, ви, вуб, ниф] -- type: languages +- type: language id: NeoRusskiya name: "language-neorusskiya-name" description: "language-neorusskiya-desc" @@ -68,7 +68,7 @@ na, udi, litchki, casa, linka, toly, anatov, vich, vech, vuch, toi, ka, vod] # Race region: -- type: languages +- type: language id: Sintaunathi name: "language-unathi-name" description: "language-unathi-desc" @@ -81,7 +81,7 @@ ri, ir, ro, or, ru, ur, rs, sr, a, a, e, e, i, i, o, o, u, u, s, s] -- type: languages +- type: language id: Siiktajr name: "language-siiktajr-name" description: "language-siiktajr-desc" @@ -95,7 +95,7 @@ mah, sanu, dra, ii'r, ъka, aasi, far, mah, tul, ragh wa, baq, ara, qara, zir', sam, mak, cresh, khan] -- type: languages +- type: language id: VoxPidgin name: "language-voxpidgin-name" description: "language-voxpidgin-desc" @@ -106,7 +106,7 @@ SKRE, AHK, EHK, RAWK, KRA, AAA, EEE, KI, II, KRI, KA] -- type: languages +- type: language id: Rootspeak name: "language-rootspeak-name" description: "language-rootspeak-desc" @@ -115,7 +115,7 @@ spaceChance: 0.3 syllables: [hs, zt, kr, st, sh] -- type: languages +- type: language id: Bubblish name: "language-bobblish-name" description: "language-bobblish-desc" @@ -124,7 +124,7 @@ spaceChance: 0.6 syllables: [блоб, плап, поп, боп, буп, пламп, буб, баб, бламп] -- type: languages +- type: language id: Tkachi name: "language-tkachi-name" description: "language-tkachi-desc" @@ -137,7 +137,7 @@ int, tyc, om, när, två, må, dag, sjä, vii, vuo, eil, tun, käyt, teh, vä, hei, huo, suo, ää, ten, ja, heu, stu, uhr, kön, we, hön] -- type: languages +- type: language id: Eldwarf name: "language-eldwarf-name" description: "language-eldwarf-desc" @@ -148,7 +148,7 @@ рд, клыт, зм, эмээ, гнык, зрм, длк, брг, грд, скрын, вродд, бдар, глтх, скрр, трг, бртх, хыкл, тр, крг, рдм, грыж, мд, гхрм, клм, прк, кнур] -- type: languages +- type: language id: Arati name: "language-arati-name" description: "language-arati-desc" @@ -162,7 +162,7 @@ кар, харат, хш, харр, арш', ашан, шанн, хсар, ашат, хаа, хазт, рашта, зара, хаш, анн, аро', хат] -- type: languages +- type: language id: Canilunzt name: "language-canilunzt-name" description: "language-canilunzt-desc" @@ -176,7 +176,7 @@ einech, cresthz, azunein, ghzth] # Misc region: -- type: languages +- type: language id: Binary name: "language-binary-name" description: "language-binary-desc" From fb0b71c0cc752f93e4548e9fcee96f3c1f774b90 Mon Sep 17 00:00:00 2001 From: Kirus59 <145689588+Kirus59@users.noreply.github.com> Date: Wed, 26 Feb 2025 18:50:56 +0300 Subject: [PATCH 15/48] add manager --- Content.Server/Entry/EntryPoint.cs | 3 ++ Content.Server/IoC/ServerContentIoC.cs | 2 + .../SS220/Commands/LanguageCommands.cs | 3 +- .../SS220/Language/LanguageManager.cs | 46 +++++++++++++++++++ .../SS220/Language/LanguageSystem.Verbs.cs | 4 +- .../SS220/Language/LanguageSystem.cs | 7 +-- .../SS220/Language/LanguagesPrototype.cs | 3 ++ .../Prototypes/SS220/Language/language.yml | 17 +++++++ 8 files changed, 79 insertions(+), 6 deletions(-) create mode 100644 Content.Server/SS220/Language/LanguageManager.cs diff --git a/Content.Server/Entry/EntryPoint.cs b/Content.Server/Entry/EntryPoint.cs index b5153bc1f31d..e5b7f11103c0 100644 --- a/Content.Server/Entry/EntryPoint.cs +++ b/Content.Server/Entry/EntryPoint.cs @@ -39,6 +39,7 @@ using Robust.Shared.Timing; using Robust.Shared.Utility; using Content.Server.SS220.BackEndApi; +using Content.Server.SS220.Language; namespace Content.Server.Entry { @@ -168,6 +169,8 @@ public override void PostInit() IoCManager.Resolve().Initialize(); IoCManager.Resolve().PostInit(); IoCManager.Resolve().Initialize(); + + IoCManager.Resolve().Initialize(); // SS220 Languages } } diff --git a/Content.Server/IoC/ServerContentIoC.cs b/Content.Server/IoC/ServerContentIoC.cs index e64719fcc355..6b3b70df4975 100644 --- a/Content.Server/IoC/ServerContentIoC.cs +++ b/Content.Server/IoC/ServerContentIoC.cs @@ -35,6 +35,7 @@ using Content.Shared.Kitchen; using Content.Shared.Players.PlayTimeTracking; using Content.Shared.Players.RateLimiting; +using Content.Server.SS220.Language; namespace Content.Server.IoC { @@ -89,6 +90,7 @@ public static void Register() IoCManager.Register(); IoCManager.Register(); IoCManager.Register(); + IoCManager.Register(); // SS220 Languages } } } diff --git a/Content.Server/SS220/Commands/LanguageCommands.cs b/Content.Server/SS220/Commands/LanguageCommands.cs index d8c92bb0fb24..8384e05003ae 100644 --- a/Content.Server/SS220/Commands/LanguageCommands.cs +++ b/Content.Server/SS220/Commands/LanguageCommands.cs @@ -11,6 +11,7 @@ public sealed class AddLanguageCommand : IConsoleCommand { [Dependency] private readonly IEntityManager _entities = default!; [Dependency] private readonly IPrototypeManager _proto = default!; + [Dependency] private readonly LanguageManager _languageManager = default!; public string Command => "addlanguage"; public string Description => Loc.GetString("cmd-language-add-desc"); @@ -32,7 +33,7 @@ public void Execute(IConsoleShell shell, string argStr, string[] args) var languageId = args[1]; - if (!_proto.TryIndex(languageId, out var languageProto)) + if (_languageManager.TryGetLanguageById(languageId, out var language)) { shell.WriteError(Loc.GetString("cmd-language-proto-miss")); return; diff --git a/Content.Server/SS220/Language/LanguageManager.cs b/Content.Server/SS220/Language/LanguageManager.cs new file mode 100644 index 000000000000..07e54fce7691 --- /dev/null +++ b/Content.Server/SS220/Language/LanguageManager.cs @@ -0,0 +1,46 @@ +// © SS220, An EULA/CLA with a hosting restriction, full text: https://raw.githubusercontent.com/SerbiaStrong-220/space-station-14/master/CLA.txt +using Robust.Shared.Prototypes; +using System.Diagnostics.CodeAnalysis; + +namespace Content.Server.SS220.Language; + +public sealed class LanguageManager +{ + [Dependency] private readonly ILogManager _logManager = default!; + [Dependency] private readonly IPrototypeManager _prototype = default!; + + public List Languages { get; private set; } = new(); + + private ISawmill _sawmill = default!; + + public void Initialize() + { + Languages = new List(); + foreach (var language in _prototype.EnumeratePrototypes()) + { + Languages.Add(language); + } + + _sawmill = _logManager.GetSawmill("language.manager"); + } + + public bool TryGetLanguageById(string id, [NotNullWhen(true)] out LanguagePrototype? language) + { + language = Languages.Find(l => l.ID == id); + + if (language == null) + _sawmill.Error($"Doesn't found a language with id: {id}"); + + return language != null; + } + + public bool TryGetLanguageByKey(string key, [NotNullWhen(true)] out LanguagePrototype? language) + { + language = Languages.Find(l => l.Key == key); + + if (language == null) + _sawmill.Error($"Doesn't found a language with key: {key}"); + + return language != null; + } +} diff --git a/Content.Server/SS220/Language/LanguageSystem.Verbs.cs b/Content.Server/SS220/Language/LanguageSystem.Verbs.cs index deb71c018155..d36cd630ec05 100644 --- a/Content.Server/SS220/Language/LanguageSystem.Verbs.cs +++ b/Content.Server/SS220/Language/LanguageSystem.Verbs.cs @@ -54,7 +54,7 @@ private List CreateVerbs(EntityUid ent, List languages) public string GetName(string language) { - if (!_proto.TryIndex(language, out var proto)) + if (!_languageManager.TryGetLanguageById(language, out var proto)) return language; if (proto.Name == null) @@ -66,7 +66,7 @@ public string GetName(string language) public string? GetDescription(string language) { - if (!_proto.TryIndex(language, out var proto)) + if (!_languageManager.TryGetLanguageById(language, out var proto)) return null; if (proto.Description == null) diff --git a/Content.Server/SS220/Language/LanguageSystem.cs b/Content.Server/SS220/Language/LanguageSystem.cs index 43ca237a6b6e..cd1a77899785 100644 --- a/Content.Server/SS220/Language/LanguageSystem.cs +++ b/Content.Server/SS220/Language/LanguageSystem.cs @@ -11,6 +11,7 @@ namespace Content.Server.SS220.Language; public sealed partial class LanguageSystem : EntitySystem { [Dependency] private readonly IPrototypeManager _proto = default!; + [Dependency] private readonly LanguageManager _languageManager = default!; public readonly string UniversalLanguage = "Universal"; public readonly string GalacticLanguage = "Galactic"; @@ -152,7 +153,7 @@ public bool KnowsUniversalLanguage(EntityUid ent) { if (!TryComp(ent, out var comp)) { - if (_proto.TryIndex(UniversalLanguage, out var universalProto)) + if (_languageManager.TryGetLanguageById(UniversalLanguage, out var universalProto)) return universalProto; } @@ -161,7 +162,7 @@ public bool KnowsUniversalLanguage(EntityUid ent) if (languageID == null) return null; - if (_proto.TryIndex(languageID, out var proto)) + if (_languageManager.TryGetLanguageById(languageID, out var proto)) return proto; return null; @@ -188,7 +189,7 @@ public void AddLanguage(EntityUid uid, string languageId) if (!TryComp(uid, out var comp)) return; - if (!_proto.TryIndex(languageId, out var proto)) + if (!_languageManager.TryGetLanguageById(languageId, out var proto)) { Log.Error($"Doesn't found a LanguagePrototype with id: {languageId}"); return; diff --git a/Content.Server/SS220/Language/LanguagesPrototype.cs b/Content.Server/SS220/Language/LanguagesPrototype.cs index dde8030b48a5..68c0398f9fed 100644 --- a/Content.Server/SS220/Language/LanguagesPrototype.cs +++ b/Content.Server/SS220/Language/LanguagesPrototype.cs @@ -16,6 +16,9 @@ public sealed partial class LanguagePrototype : IPrototype [DataField] public string? Description { get; private set; } + [DataField(required: true)] + public string Key = string.Empty; + /// /// The color of the language in which messages will be recolored, /// an empty value will not be recolored diff --git a/Resources/Prototypes/SS220/Language/language.yml b/Resources/Prototypes/SS220/Language/language.yml index 65354987827a..5fb0373e85c1 100644 --- a/Resources/Prototypes/SS220/Language/language.yml +++ b/Resources/Prototypes/SS220/Language/language.yml @@ -3,10 +3,12 @@ # Everyone understands you, you understand everyone, but there's no right to speak all languages - type: language id: Universal + key: uni # Galactic common lanaguges region: - type: language id: Galactic + key: gal name: "language-galacticcommon-name" description: "language-galacticcommon-desc" scrambleMethod: !type:RandomSyllablesScrambleMethod @@ -14,6 +16,7 @@ - type: language id: SolCommon + key: sol name: "language-solcommon-name" description: "language-solcommon-desc" color: "#2f2fad" @@ -22,6 +25,7 @@ - type: language id: Tradeband + key: trade name: "language-tradeband-name" description: "language-tradeband-desc" color: "#87451c" @@ -36,6 +40,7 @@ - type: language id: Gutter + key: gut name: "language-gutter-name" description: "language-gutter-desc" color: "#7092BE" @@ -45,6 +50,7 @@ - type: language id: Clownish + key: clown name: "language-clownish-name" description: "language-clownish-desc" color: "#ff0000" @@ -54,6 +60,7 @@ - type: language id: NeoRusskiya + key: neoru name: "language-neorusskiya-name" description: "language-neorusskiya-desc" color: "#7c4848" @@ -70,6 +77,7 @@ # Race region: - type: language id: Sintaunathi + key: unathi name: "language-unathi-name" description: "language-unathi-desc" color: "#228B22" @@ -83,6 +91,7 @@ - type: language id: Siiktajr + key: tajr name: "language-siiktajr-name" description: "language-siiktajr-desc" color: "#803B56" @@ -97,6 +106,7 @@ - type: language id: VoxPidgin + key: vox name: "language-voxpidgin-name" description: "language-voxpidgin-desc" color: "#AA00AA" @@ -108,6 +118,7 @@ - type: language id: Rootspeak + key: root name: "language-rootspeak-name" description: "language-rootspeak-desc" color: "#804000" @@ -117,6 +128,7 @@ - type: language id: Bubblish + key: bubbl name: "language-bobblish-name" description: "language-bobblish-desc" color: "#0077AA" @@ -126,6 +138,7 @@ - type: language id: Tkachi + key: tch name: "language-tkachi-name" description: "language-tkachi-desc" color: "#869b29" @@ -139,6 +152,7 @@ - type: language id: Eldwarf + key: dwarf name: "language-eldwarf-name" description: "language-eldwarf-desc" color: "#515d63" @@ -150,6 +164,7 @@ - type: language id: Arati + key: arati name: "language-arati-name" description: "language-arati-desc" color: "#68477a" @@ -164,6 +179,7 @@ - type: language id: Canilunzt + key: cani name: "language-canilunzt-name" description: "language-canilunzt-desc" color: "#B97A57" @@ -178,6 +194,7 @@ # Misc region: - type: language id: Binary + key: bin name: "language-binary-name" description: "language-binary-desc" color: "#2cc2e8" From 14257adfff3d91c042ee686aef783337a856debf Mon Sep 17 00:00:00 2001 From: Kirus59 <145689588+Kirus59@users.noreply.github.com> Date: Wed, 26 Feb 2025 23:01:30 +0300 Subject: [PATCH 16/48] add multilanguage messages --- .../SS220/Language/LanguageManager.cs | 15 +-- .../SS220/Language/LanguageSystem.cs | 102 +++++++++++++++++- 2 files changed, 99 insertions(+), 18 deletions(-) diff --git a/Content.Server/SS220/Language/LanguageManager.cs b/Content.Server/SS220/Language/LanguageManager.cs index 07e54fce7691..7c1c5eff3eb2 100644 --- a/Content.Server/SS220/Language/LanguageManager.cs +++ b/Content.Server/SS220/Language/LanguageManager.cs @@ -6,12 +6,11 @@ namespace Content.Server.SS220.Language; public sealed class LanguageManager { - [Dependency] private readonly ILogManager _logManager = default!; [Dependency] private readonly IPrototypeManager _prototype = default!; public List Languages { get; private set; } = new(); - private ISawmill _sawmill = default!; + public readonly string KeyPrefix = ":"; public void Initialize() { @@ -20,27 +19,17 @@ public void Initialize() { Languages.Add(language); } - - _sawmill = _logManager.GetSawmill("language.manager"); } public bool TryGetLanguageById(string id, [NotNullWhen(true)] out LanguagePrototype? language) { language = Languages.Find(l => l.ID == id); - - if (language == null) - _sawmill.Error($"Doesn't found a language with id: {id}"); - return language != null; } public bool TryGetLanguageByKey(string key, [NotNullWhen(true)] out LanguagePrototype? language) { - language = Languages.Find(l => l.Key == key); - - if (language == null) - _sawmill.Error($"Doesn't found a language with key: {key}"); - + language = Languages.Find(l => KeyPrefix + l.Key == key); return language != null; } } diff --git a/Content.Server/SS220/Language/LanguageSystem.cs b/Content.Server/SS220/Language/LanguageSystem.cs index cd1a77899785..f04e57170340 100644 --- a/Content.Server/SS220/Language/LanguageSystem.cs +++ b/Content.Server/SS220/Language/LanguageSystem.cs @@ -3,14 +3,15 @@ using Content.Shared.Ghost; using Content.Shared.Verbs; using Robust.Shared.Prototypes; +using System.Diagnostics.CodeAnalysis; using System.Linq; +using System.Text; using System.Text.RegularExpressions; namespace Content.Server.SS220.Language; public sealed partial class LanguageSystem : EntitySystem { - [Dependency] private readonly IPrototypeManager _proto = default!; [Dependency] private readonly LanguageManager _languageManager = default!; public readonly string UniversalLanguage = "Universal"; @@ -50,6 +51,8 @@ private void OnMapInit(Entity ent, ref MapInitEvent args) /// public string ScrambleText(EntityUid? ent, string input, LanguagePrototype proto) { + var saveEndWhitespace = char.IsWhiteSpace(input[input.Length - 1]); + input = RemoveColorTags(input); var cacheKey = $"{proto.ID}:{input}"; @@ -72,6 +75,9 @@ public string ScrambleText(EntityUid? ent, string input, LanguagePrototype proto } } + if (saveEndWhitespace) + scrambledText += " "; + return scrambledText; } @@ -94,12 +100,98 @@ public string RemoveColorTags(string input) public string SanitizeMessage(EntityUid source, EntityUid listener, string message) { var languageProto = GetProto(source); - if (languageProto == null || CheckLanguage(listener, languageProto)) + if (languageProto == null) return message; - var newMessage = ScrambleText(source, message, languageProto); - newMessage = SetColor(newMessage, languageProto); - return newMessage; + var languageStrings = SplitStringByLanguages(source, message, languageProto); + var sanitizedMessage = new StringBuilder(); + foreach (var languageString in languageStrings) + { + if (CheckLanguage(listener, languageString.Item2)) + { + sanitizedMessage.Append(languageString.Item1); + } + else + { + var scrambledString = ScrambleText(listener, languageString.Item1, languageString.Item2); + scrambledString = SetColor(scrambledString, languageString.Item2); + sanitizedMessage.Append(scrambledString); + } + } + + return sanitizedMessage.ToString(); + } + + public List<(string, LanguagePrototype)> SplitStringByLanguages(EntityUid source, string message, LanguagePrototype defaultLanguage) + { + var list = new List<(string, LanguagePrototype)>(); + var textWithKeyPattern = @"^:(.*?)\s(?=:\w+\s)|(?<=\s):(.*?)\s(?=:\w+\s)|(?<=\s):(.*)|^:(.*)"; // pizdec + + var matches = Regex.Matches(message, textWithKeyPattern); + if (matches.Count <= 0) + { + list.Add((message, defaultLanguage)); + return list; + } + + var textBeforeFirstTag = message.Substring(0, matches[0].Index); + (string, LanguagePrototype?) buffer = (string.Empty, null); + if (textBeforeFirstTag != string.Empty) + buffer = (textBeforeFirstTag, defaultLanguage); + + foreach (Match m in matches) + { + if (!TryGetLanguageFromString(m.Value, out var messageWithoutTags, out var language) || + !CheckLanguage(source, language)) + { + if (buffer.Item2 == null) + { + buffer = (m.Value, defaultLanguage); + } + else + { + buffer.Item1 += m.Value; + } + + continue; + } + + if (buffer.Item2 == language) + { + buffer.Item1 += messageWithoutTags; + continue; + } + else if (buffer.Item2 != null) + { + list.Add((buffer.Item1, buffer.Item2)); + } + + buffer = (messageWithoutTags, language); + } + + if (buffer.Item2 != null) + { + list.Add((buffer.Item1, buffer.Item2)); + } + + return list; + } + + public bool TryGetLanguageFromString(string message, + [NotNullWhen(true)] out string? messageWithoutTags, + [NotNullWhen(true)] out LanguagePrototype? language) + { + messageWithoutTags = null; + language = null; + + var keyPatern = @":\w+\s+"; + + var m = Regex.Match(message, keyPatern); + if (m == null || !_languageManager.TryGetLanguageByKey(m.Value.Trim(), out language)) + return false; + + messageWithoutTags = Regex.Replace(message, keyPatern, string.Empty); + return messageWithoutTags != null && language != null; } /// From 81e7d9fae9323893361d5b54a56d62e3de82c2e7 Mon Sep 17 00:00:00 2001 From: Kirus59 <145689588+Kirus59@users.noreply.github.com> Date: Wed, 26 Feb 2025 23:07:18 +0300 Subject: [PATCH 17/48] add const prefix in regex pattern --- Content.Server/SS220/Language/LanguageSystem.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Content.Server/SS220/Language/LanguageSystem.cs b/Content.Server/SS220/Language/LanguageSystem.cs index f04e57170340..fa378e7f73d5 100644 --- a/Content.Server/SS220/Language/LanguageSystem.cs +++ b/Content.Server/SS220/Language/LanguageSystem.cs @@ -125,7 +125,8 @@ public string SanitizeMessage(EntityUid source, EntityUid listener, string messa public List<(string, LanguagePrototype)> SplitStringByLanguages(EntityUid source, string message, LanguagePrototype defaultLanguage) { var list = new List<(string, LanguagePrototype)>(); - var textWithKeyPattern = @"^:(.*?)\s(?=:\w+\s)|(?<=\s):(.*?)\s(?=:\w+\s)|(?<=\s):(.*)|^:(.*)"; // pizdec + var p = _languageManager.KeyPrefix; + var textWithKeyPattern = $@"^{p}(.*?)\s(?={p}\w+\s)|(?<=\s){p}(.*?)\s(?={p}\w+\s)|(?<=\s){p}(.*)|^{p}(.*)"; // pizdec var matches = Regex.Matches(message, textWithKeyPattern); if (matches.Count <= 0) @@ -184,7 +185,7 @@ public bool TryGetLanguageFromString(string message, messageWithoutTags = null; language = null; - var keyPatern = @":\w+\s+"; + var keyPatern = $@"{_languageManager.KeyPrefix}\w+\s+"; var m = Regex.Match(message, keyPatern); if (m == null || !_languageManager.TryGetLanguageByKey(m.Value.Trim(), out language)) From 66e412aa83d4205a750264e2d98e0eb829b99d8a Mon Sep 17 00:00:00 2001 From: Kirus59 <145689588+Kirus59@users.noreply.github.com> Date: Thu, 27 Feb 2025 18:33:00 +0300 Subject: [PATCH 18/48] add seeded scramble --- .../EncryptionMethods/BaseEncryptionMethod.cs | 2 +- .../RandomSyllablesMethod.cs | 65 +++++++++++++++++-- .../SS220/Language/LanguageSystem.cs | 33 +++++----- 3 files changed, 80 insertions(+), 20 deletions(-) diff --git a/Content.Server/SS220/Language/EncryptionMethods/BaseEncryptionMethod.cs b/Content.Server/SS220/Language/EncryptionMethods/BaseEncryptionMethod.cs index c47bece2ce04..49beef624aff 100644 --- a/Content.Server/SS220/Language/EncryptionMethods/BaseEncryptionMethod.cs +++ b/Content.Server/SS220/Language/EncryptionMethods/BaseEncryptionMethod.cs @@ -5,5 +5,5 @@ namespace Content.Server.SS220.Language.EncryptionMethods; [ImplicitDataDefinitionForInheritors] public abstract partial class ScrambleMethod { - public abstract string ScrambleMessage(string message); + public abstract string ScrambleMessage(string message, int? seed = null); } diff --git a/Content.Server/SS220/Language/EncryptionMethods/RandomSyllablesMethod.cs b/Content.Server/SS220/Language/EncryptionMethods/RandomSyllablesMethod.cs index 8e0c8084501d..3387b6d3c3bd 100644 --- a/Content.Server/SS220/Language/EncryptionMethods/RandomSyllablesMethod.cs +++ b/Content.Server/SS220/Language/EncryptionMethods/RandomSyllablesMethod.cs @@ -34,11 +34,34 @@ public sealed partial class RandomSyllablesScrambleMethod : ScrambleMethod [DataField] public string SpecialCharacter = string.Empty; - public override string ScrambleMessage(string message) + public override string ScrambleMessage(string message, int? seed = null) { if (Syllables.Count == 0) return message; + string result; + if (seed != null) + { + foreach (var c in message.ToCharArray()) + { + seed += c; + } + result = ScrambleWithSeed(message, seed.Value); + } + else + { + result = ScrambleWithoutSeed(message); + } + + var punctuation = ExtractPunctuation(message); + + result += punctuation; + + return result; + } + + private string ScrambleWithoutSeed(string message) + { var random = IoCManager.Resolve(); var encryptedMessage = new StringBuilder(); @@ -58,21 +81,55 @@ public override string ScrambleMessage(string message) { encryptedMessage.Append(SpecialCharacter); } + else if (random.Prob(DotChance)) + { + encryptedMessage.Append(". "); + capitalize = true; + } else if (random.Prob(SpaceChance)) { encryptedMessage.Append(' '); } + } + + var result = encryptedMessage.ToString().Trim(); + + return result; + } + + private string ScrambleWithSeed(string message, int seed) + { + var random = new Random(seed); + + var encryptedMessage = new StringBuilder(); + var capitalize = false; + while (encryptedMessage.Length < message.Length) + { + var curSyllable = random.Pick(Syllables); + + if (capitalize) + { + curSyllable = curSyllable.Substring(0, 1).ToUpper() + curSyllable.Substring(1); + capitalize = false; + } + encryptedMessage.Append(curSyllable); + + if (random.Prob(SpecialCharacterChance)) + { + encryptedMessage.Append(SpecialCharacter); + } else if (random.Prob(DotChance)) { encryptedMessage.Append(". "); capitalize = true; } + else if (random.Prob(SpaceChance)) + { + encryptedMessage.Append(' '); + } } var result = encryptedMessage.ToString().Trim(); - var punctuation = ExtractPunctuation(message); - - result += punctuation; return result; } diff --git a/Content.Server/SS220/Language/LanguageSystem.cs b/Content.Server/SS220/Language/LanguageSystem.cs index fa378e7f73d5..a37f45cc184d 100644 --- a/Content.Server/SS220/Language/LanguageSystem.cs +++ b/Content.Server/SS220/Language/LanguageSystem.cs @@ -2,7 +2,8 @@ using Content.Server.GameTicking.Events; using Content.Shared.Ghost; using Content.Shared.Verbs; -using Robust.Shared.Prototypes; +using Robust.Shared.Random; +using Robust.Shared.Timing; using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Text; @@ -12,11 +13,18 @@ namespace Content.Server.SS220.Language; public sealed partial class LanguageSystem : EntitySystem { + [Dependency] private readonly IRobustRandom _random = default!; + [Dependency] private readonly IGameTiming _timing = default!; [Dependency] private readonly LanguageManager _languageManager = default!; public readonly string UniversalLanguage = "Universal"; public readonly string GalacticLanguage = "Galactic"; + // Cached values for one tick + private static readonly Dictionary ScrambleCache = new Dictionary(); + + private static int Seed = 0; + public override void Initialize() { base.Initialize(); @@ -27,12 +35,16 @@ public override void Initialize() SubscribeLocalEvent>(OnVerb); } - private static readonly Dictionary ScrambleCache = new Dictionary(); - private const int SCRAMBLE_CACHE_LEN = 20; + public override void Update(float frameTime) + { + base.Update(frameTime); + + ScrambleCache.Clear(); + } private void OnRoundStart(RoundStartingEvent args) { - ScrambleCache.Clear(); + Seed = _random.Next(); } /// @@ -51,7 +63,7 @@ private void OnMapInit(Entity ent, ref MapInitEvent args) /// public string ScrambleText(EntityUid? ent, string input, LanguagePrototype proto) { - var saveEndWhitespace = char.IsWhiteSpace(input[input.Length - 1]); + var saveEndWhitespace = char.IsWhiteSpace(input[^0]); input = RemoveColorTags(input); var cacheKey = $"{proto.ID}:{input}"; @@ -62,18 +74,9 @@ public string ScrambleText(EntityUid? ent, string input, LanguagePrototype proto if (ScrambleCache.TryGetValue(cacheKey, out var cachedValue)) return cachedValue; - var scrambledText = proto.ScrambleMethod.ScrambleMessage(input); + var scrambledText = proto.ScrambleMethod.ScrambleMessage(input, Seed); ScrambleCache[cacheKey] = scrambledText; - // Removes the first message from the cache if it fills up - if (ScrambleCache.Count > SCRAMBLE_CACHE_LEN) - { - var keysToRemove = ScrambleCache.Keys.Take(ScrambleCache.Count - SCRAMBLE_CACHE_LEN).ToList(); - foreach (var key in keysToRemove) - { - ScrambleCache.Remove(key); - } - } if (saveEndWhitespace) scrambledText += " "; From d134b237d0e7b198cd33f29a1c2bd12dc0cd2205 Mon Sep 17 00:00:00 2001 From: Kirus59 <145689588+Kirus59@users.noreply.github.com> Date: Thu, 27 Feb 2025 22:26:27 +0300 Subject: [PATCH 19/48] rename comp fields & radio sys fixes --- Content.Server/Chat/Systems/ChatSystem.cs | 27 ++-- .../EntityEffects/Effects/MakeSentient.cs | 9 +- Content.Server/PAI/PAISystem.cs | 9 +- .../Radio/EntitySystems/HeadsetSystem.cs | 18 +-- .../Radio/EntitySystems/RadioDeviceSystem.cs | 3 +- .../Radio/EntitySystems/RadioSystem.cs | 100 ++++++++------- Content.Server/Radio/RadioEvent.cs | 6 +- .../SS220/Commands/LanguageCommands.cs | 9 +- .../{ => Components}/LanguageComponent.cs | 12 +- .../SS220/Language/LanguageSystem.Verbs.cs | 11 +- .../SS220/Language/LanguageSystem.cs | 116 ++++++++++-------- .../TapeRecorder/TapeRecorderSystem.cs | 2 +- Content.Server/Traits/TraitSystem.cs | 5 +- .../Zombies/ZombieSystem.Transform.cs | 3 +- .../Mobs/Cyborgs/base_borg_chassis.yml | 2 +- .../Entities/Mobs/Species/arachnid.yml | 2 +- .../Entities/Mobs/Species/diona.yml | 2 +- .../Entities/Mobs/Species/dwarf.yml | 2 +- .../Entities/Mobs/Species/human.yml | 2 +- .../Prototypes/Entities/Mobs/Species/moth.yml | 2 +- .../Entities/Mobs/Species/reptilian.yml | 2 +- .../Entities/Mobs/Species/slime.yml | 2 +- .../Prototypes/Entities/Mobs/Species/vox.yml | 2 +- .../Prototypes/Entities/Objects/Fun/pai.yml | 2 +- .../Objects/Specific/Robotics/mmi.yml | 4 +- .../SS220/Entities/Mobs/NPCs/animals.yml | 2 +- .../SS220/Entities/Mobs/Species/felinid.yml | 2 +- .../SS220/Entities/Mobs/Species/tajaran.yml | 2 +- .../SS220/Entities/Mobs/Species/vulpkanin.yml | 2 +- .../SS220/Entities/Objects/Fun/pai.yml | 4 +- Resources/Prototypes/SS220/Geras/slime.yml | 4 +- .../SS220/Traits/language_traits.yml | 10 +- 32 files changed, 200 insertions(+), 180 deletions(-) rename Content.Server/SS220/Language/{ => Components}/LanguageComponent.cs (71%) diff --git a/Content.Server/Chat/Systems/ChatSystem.cs b/Content.Server/Chat/Systems/ChatSystem.cs index 1c20ef910733..cc3ce7c1d125 100644 --- a/Content.Server/Chat/Systems/ChatSystem.cs +++ b/Content.Server/Chat/Systems/ChatSystem.cs @@ -588,18 +588,9 @@ private void SendEntityWhisper( name = nameEv.VoiceName; } name = FormattedMessage.EscapeText(name); - // SS220-Add-Languages begin - if (languageProto == null) - languageProto = _languageSystem.GetProto(source); - - 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", message /*SS220-Add-Languages*/)); + ("entityName", name), ("message", FormattedMessage.EscapeText(message))); var wrappedobfuscatedMessage = Loc.GetString("chat-manager-entity-whisper-wrap-message", ("entityName", nameIdentity), ("message", FormattedMessage.EscapeText(obfuscatedMessage))); @@ -607,7 +598,6 @@ private void SendEntityWhisper( var wrappedUnknownMessage = Loc.GetString("chat-manager-entity-whisper-unknown-wrap-message", ("message", FormattedMessage.EscapeText(obfuscatedMessage))); - foreach (var (session, data) in GetRecipients(source, WhisperMuffledRange)) { EntityUid listener; @@ -618,13 +608,14 @@ private void SendEntityWhisper( // SS220-Add-Languages begin var scrambledMessage = _languageSystem.SanitizeMessage(source, listener, message); - var obfuscatedScrambledMessage = _languageSystem.SanitizeMessage(source, listener, obfuscatedMessage); + var scrambledColorlessMessage = _languageSystem.RemoveColorTags(scrambledMessage); + var obfuscatedScrambledMessage = ObfuscateMessageReadability(scrambledColorlessMessage, 0.2f); - var wrappedScrambledMessage = Loc.GetString("chat-manager-entity-whisper-wrap-message", + wrappedMessage = Loc.GetString("chat-manager-entity-whisper-wrap-message", ("entityName", name), ("message", scrambledMessage)); - var wrappedObfuscatedScrambledMessage = Loc.GetString("chat-manager-entity-whisper-wrap-message", + wrappedobfuscatedMessage = Loc.GetString("chat-manager-entity-whisper-wrap-message", ("entityName", nameIdentity), ("message", FormattedMessage.EscapeText(obfuscatedScrambledMessage))); - var wrappedUnknownScrambledMessage = Loc.GetString("chat-manager-entity-whisper-unknown-wrap-message", + wrappedUnknownMessage = Loc.GetString("chat-manager-entity-whisper-unknown-wrap-message", ("message", FormattedMessage.EscapeText(obfuscatedScrambledMessage))); // SS220-Add-Languages end @@ -632,13 +623,13 @@ private void SendEntityWhisper( 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, scrambledMessage, wrappedScrambledMessage /*SS220-Add-Languages*/, source, false, session.Channel); + _chatManager.ChatMessageToOne(ChatChannel.Whisper, scrambledMessage, wrappedMessage, 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, obfuscatedScrambledMessage, wrappedObfuscatedScrambledMessage /*SS220-Add-Languages*/, source, false, session.Channel); + _chatManager.ChatMessageToOne(ChatChannel.Whisper, obfuscatedScrambledMessage, wrappedobfuscatedMessage, 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, obfuscatedScrambledMessage, wrappedUnknownScrambledMessage /*SS220-Add-Languages*/, source, false, session.Channel); + _chatManager.ChatMessageToOne(ChatChannel.Whisper, obfuscatedScrambledMessage, wrappedUnknownMessage, source, false, session.Channel); } _replay.RecordServerMessage(new ChatMessage(ChatChannel.Whisper, message, wrappedMessage, GetNetEntity(source), null, MessageRangeHideChatForReplay(range))); diff --git a/Content.Server/EntityEffects/Effects/MakeSentient.cs b/Content.Server/EntityEffects/Effects/MakeSentient.cs index 9029d0176480..704436245b71 100644 --- a/Content.Server/EntityEffects/Effects/MakeSentient.cs +++ b/Content.Server/EntityEffects/Effects/MakeSentient.cs @@ -1,6 +1,7 @@ using Content.Server.Ghost.Roles.Components; using Content.Server.Speech.Components; -using Content.Server.SS220.Language; +using Content.Server.SS220.Language; +using Content.Server.SS220.Language.Components; using Content.Shared.EntityEffects; using Content.Shared.Mind.Components; using Robust.Shared.Prototypes; @@ -27,10 +28,10 @@ public override void Effect(EntityEffectBaseArgs args) var language = entityManager.EnsureComponent(uid); var languageSystem = entityManager.System(); - if (!language.LearnedLanguages.Contains(languageSystem.GalacticLanguage)) - language.LearnedLanguages.Add(languageSystem.GalacticLanguage); + if (!language.AvailableLanguages.Contains(languageSystem.GalacticLanguage)) + language.AvailableLanguages.Add(languageSystem.GalacticLanguage); - language.CurrentLanguage = language.LearnedLanguages[0]; + language.SelectedLanguage = language.AvailableLanguages[0]; // SS220-Add-Languages end // Stops from adding a ghost role to things like people who already have a mind diff --git a/Content.Server/PAI/PAISystem.cs b/Content.Server/PAI/PAISystem.cs index 51238df6fceb..7f3bd0f50154 100644 --- a/Content.Server/PAI/PAISystem.cs +++ b/Content.Server/PAI/PAISystem.cs @@ -9,7 +9,8 @@ using Robust.Shared.Random; using System.Text; using Robust.Shared.Player; -using Content.Server.SS220.Language; // SS220-Add-Languages +using Content.Server.SS220.Language; +using Content.Server.SS220.Language.Components; // SS220-Add-Languages namespace Content.Server.PAI; @@ -123,9 +124,9 @@ public void PAITurningOff(EntityUid uid) // SS220-Add-Languages begin if (TryComp(uid, out var languages)) { - languages.LearnedLanguages.Clear(); - _language.AddLanguages(uid, [_language.UniversalLanguage, _language.UniversalLanguage]); - languages.CurrentLanguage = languages.LearnedLanguages[0]; + languages.AvailableLanguages.Clear(); + _language.AddLanguages(uid, [_language.UniversalLanguage, _language.GalacticLanguage]); + languages.SelectedLanguage = languages.AvailableLanguages[0]; } } // SS220-Add-Languages end diff --git a/Content.Server/Radio/EntitySystems/HeadsetSystem.cs b/Content.Server/Radio/EntitySystems/HeadsetSystem.cs index 1bccb4eadb79..9a16bc41801c 100644 --- a/Content.Server/Radio/EntitySystems/HeadsetSystem.cs +++ b/Content.Server/Radio/EntitySystems/HeadsetSystem.cs @@ -16,13 +16,13 @@ public sealed class HeadsetSystem : SharedHeadsetSystem { [Dependency] private readonly INetManager _netMan = default!; [Dependency] private readonly RadioSystem _radio = default!; - [Dependency] private readonly LanguageSystem _languageSystem = default!; // SS220-Add-Languages public override void Initialize() { base.Initialize(); SubscribeLocalEvent(OnHeadsetReceive); SubscribeLocalEvent(OnKeysChanged); + SubscribeLocalEvent(OnGetLanguage); // SS220 languages SubscribeLocalEvent(OnSpeak); @@ -106,12 +106,7 @@ private void OnHeadsetReceive(EntityUid uid, HeadsetComponent component, ref Rad var actorUid = Transform(uid).ParentUid; if (TryComp(actorUid, out ActorComponent? actor)) { - // SS220-Add-Languages begin - if (_languageSystem.CheckLanguage(actorUid, args.LanguageProto)) - _netMan.ServerSendMessage(args.ChatMsg, actor.PlayerSession.Channel); - else - _netMan.ServerSendMessage(args.ScrambledChatMsg, actor.PlayerSession.Channel); - // SS220-Add-Languages end + _netMan.ServerSendMessage(args.ChatMsg, actor.PlayerSession.Channel); if (actorUid != args.MessageSource && TryComp(args.MessageSource, out TTSComponent? _)) { args.Receivers.Add(new(actorUid)); @@ -128,4 +123,13 @@ private void OnEmpPulse(EntityUid uid, HeadsetComponent component, ref EmpPulseE args.Disabled = true; } } + + // SS220 languages begin + private void OnGetLanguage(Entity ent, ref GetLanguageCompEvent args) + { + var actorUid = Transform(ent).ParentUid; + if (HasComp(actorUid)) + RaiseLocalEvent(actorUid, ref args); + } + // SS220 languages end } diff --git a/Content.Server/Radio/EntitySystems/RadioDeviceSystem.cs b/Content.Server/Radio/EntitySystems/RadioDeviceSystem.cs index f2ed606b7a7b..b8b9e26a2bf6 100644 --- a/Content.Server/Radio/EntitySystems/RadioDeviceSystem.cs +++ b/Content.Server/Radio/EntitySystems/RadioDeviceSystem.cs @@ -237,8 +237,7 @@ private void OnReceiveRadio(EntityUid uid, RadioSpeakerComponent component, ref // log to chat so people can identity the speaker/source, but avoid clogging ghost chat if there are many radios _chat.TrySendInGameICMessage(uid, args.Message, InGameICChatType.Whisper, - ChatTransmitRange.GhostRangeLimit, nameOverride: name, checkRadioPrefix: false, - languageProto: args.LanguageProto); // SS220-Add-Languages + ChatTransmitRange.GhostRangeLimit, nameOverride: name, checkRadioPrefix: false); } private void OnIntercomEncryptionChannelsChanged(Entity ent, ref EncryptionChannelsChangedEvent args) diff --git a/Content.Server/Radio/EntitySystems/RadioSystem.cs b/Content.Server/Radio/EntitySystems/RadioSystem.cs index b95eb7842a2b..05d0c92f25b9 100644 --- a/Content.Server/Radio/EntitySystems/RadioSystem.cs +++ b/Content.Server/Radio/EntitySystems/RadioSystem.cs @@ -19,7 +19,8 @@ using Content.Shared.PDA; using System.Globalization; using Content.Server.Popups; -using Content.Server.SS220.Language; // SS220-Add-Languages +using Content.Server.SS220.Language; +using System.Diagnostics.CodeAnalysis; // SS220-Add-Languages namespace Content.Server.Radio.EntitySystems; @@ -70,12 +71,7 @@ private void OnIntrinsicSpeak(EntityUid uid, IntrinsicRadioTransmitterComponent private void OnIntrinsicReceive(EntityUid uid, IntrinsicRadioReceiverComponent component, ref RadioReceiveEvent args) { if (TryComp(uid, out ActorComponent? actor)) - // SS220-Add-Languages begin - if (_languageSystem.CheckLanguage(uid, args.LanguageProto)) - _netMan.ServerSendMessage(args.ChatMsg, actor.PlayerSession.Channel); - else - _netMan.ServerSendMessage(args.ScrambledChatMsg, actor.PlayerSession.Channel); - // SS220-Add-Languages end + _netMan.ServerSendMessage(args.ChatMsg, actor.PlayerSession.Channel); // SS220 Silicon TTS fix begin if (component.ReceiverEntityOverride is { } receiverOverride && !TerminatingOrDeleted(receiverOverride)) @@ -103,7 +99,6 @@ public void SendRadioMessage(EntityUid messageSource, string message, RadioChann // TODO if radios ever garble / modify messages, feedback-prevention needs to be handled better than this. if (!_messages.Add(message)) return; - message = _languageSystem.RemoveColorTags(message); // SS220-Add-Languages var evt = new TransformSpeakerNameEvent(messageSource, _chat.GetRadioName(messageSource)); //ss220 add identity concealment for chat and radio messages RaiseLocalEvent(messageSource, evt); @@ -123,42 +118,6 @@ public void SendRadioMessage(EntityUid messageSource, string message, RadioChann var content = escapeMarkup ? FormattedMessage.EscapeText(message) : message; - // SS220-Add-Languages begin - var languageProto = _languageSystem.GetProto(messageSource); - if (languageProto == null) - return; - - var scrambledMessage = _languageSystem.ScrambleText(messageSource, content, languageProto); - - if (GetIdCardIsBold(messageSource)) - { - content = $"[bold]{content}[/bold]"; - scrambledMessage = $"[bold]{scrambledMessage}[/bold]"; - } - - if (languageProto.Color != null) - { - content = _languageSystem.SetColor(content, languageProto); - scrambledMessage = _languageSystem.SetColor(scrambledMessage, languageProto); - } - - var wrappedScrambledMessage = Loc.GetString(speech.Bold ? "chat-radio-message-wrap-bold" : "chat-radio-message-wrap", - ("color", channel.Color), - ("fontType", speech.FontId), - ("fontSize", speech.FontSize), - ("verb", Loc.GetString(_random.Pick(speech.SpeechVerbStrings))), - ("channel", $"\\[{channel.LocalizedName}\\]"), - ("name", formattedName), - ("message", scrambledMessage)); - - var scrambledChat = new ChatMessage( - ChatChannel.Radio, - message, - wrappedScrambledMessage, - NetEntity.Invalid, - null); - var scrambledChatMsg = new MsgChatMessage { Message = scrambledChat }; - // SS220-Add-Languages end var wrappedMessage = Loc.GetString(speech.Bold ? "chat-radio-message-wrap-bold" : "chat-radio-message-wrap", ("color", channel.Color), @@ -177,8 +136,7 @@ public void SendRadioMessage(EntityUid messageSource, string message, RadioChann NetEntity.Invalid, null); var chatMsg = new MsgChatMessage { Message = chat }; - var ev = new RadioReceiveEvent(message, messageSource, channel, radioSource, - chatMsg, scrambledChatMsg, languageProto, new()); // SS220-Add-Languages + var ev = new RadioReceiveEvent(message, messageSource, channel, radioSource, chatMsg, new()); var sendAttemptEv = new RadioSendAttemptEvent(channel, radioSource); RaiseLocalEvent(ref sendAttemptEv); @@ -214,8 +172,20 @@ public void SendRadioMessage(EntityUid messageSource, string message, RadioChann if (attemptEv.Cancelled) continue; + // SS220 languages begin + if (TryGetScrambledChatMessage(messageSource, receiver, message, out var scrambledChatMsg)) + { + var scrabledEv = new RadioReceiveEvent(message, messageSource, channel, radioSource, scrambledChatMsg, new()); + RaiseLocalEvent(receiver, ref scrabledEv); + } + else + { + RaiseLocalEvent(receiver, ref ev); + } + // SS220 languages end + // send the message - RaiseLocalEvent(receiver, ref ev); + //RaiseLocalEvent(receiver, ref ev); } // Dispatch TTS radio speech event for every receiver @@ -228,6 +198,42 @@ public void SendRadioMessage(EntityUid messageSource, string message, RadioChann _replay.RecordServerMessage(chat); _messages.Remove(message); + + // SS220 languages begin + bool TryGetScrambledChatMessage(EntityUid source, EntityUid listener, string message, [NotNullWhen(true)] out MsgChatMessage? scrambledChatMsg) + { + scrambledChatMsg = null; + var languageProto = _languageSystem.GetSelectedLanguage(source); + if (languageProto == null) + return false; + + var scrambledMessage = _languageSystem.SanitizeMessage(source, listener, message); + if (GetIdCardIsBold(source)) + { + content = $"[bold]{content}[/bold]"; + scrambledMessage = $"[bold]{scrambledMessage}[/bold]"; + } + + var wrappedScrambledMessage = Loc.GetString(speech.Bold ? "chat-radio-message-wrap-bold" : "chat-radio-message-wrap", + ("color", channel.Color), + ("fontType", speech.FontId), + ("fontSize", speech.FontSize), + ("verb", Loc.GetString(_random.Pick(speech.SpeechVerbStrings))), + ("channel", $"\\[{channel.LocalizedName}\\]"), + ("name", formattedName), + ("message", scrambledMessage)); + + var scrambledChat = new ChatMessage( + ChatChannel.Radio, + scrambledMessage, + wrappedScrambledMessage, + NetEntity.Invalid, + null); + + scrambledChatMsg = new MsgChatMessage { Message = scrambledChat }; + return scrambledChatMsg != null; + } + // SS220 languages end } private IdCardComponent? GetIdCard(EntityUid senderUid) diff --git a/Content.Server/Radio/RadioEvent.cs b/Content.Server/Radio/RadioEvent.cs index b56d67e26173..20cfaed3f982 100644 --- a/Content.Server/Radio/RadioEvent.cs +++ b/Content.Server/Radio/RadioEvent.cs @@ -1,15 +1,11 @@ using Content.Server.Chat.Systems; using Content.Shared.Chat; using Content.Shared.Radio; -using Content.Server.SS220.Language; namespace Content.Server.Radio; [ByRefEvent] -public readonly record struct RadioReceiveEvent(string Message, EntityUid MessageSource, - RadioChannelPrototype Channel, EntityUid RadioSource, - MsgChatMessage ChatMsg, MsgChatMessage ScrambledChatMsg, - LanguagePrototype? LanguageProto, List Receivers); // SS220-Add-Languages +public readonly record struct RadioReceiveEvent(string Message, EntityUid MessageSource, RadioChannelPrototype Channel, EntityUid RadioSource, MsgChatMessage ChatMsg, List Receivers); /// /// Use this event to cancel sending message per receiver diff --git a/Content.Server/SS220/Commands/LanguageCommands.cs b/Content.Server/SS220/Commands/LanguageCommands.cs index 8384e05003ae..1ec1beb17a6c 100644 --- a/Content.Server/SS220/Commands/LanguageCommands.cs +++ b/Content.Server/SS220/Commands/LanguageCommands.cs @@ -1,5 +1,6 @@ using Content.Server.Administration; using Content.Server.SS220.Language; +using Content.Server.SS220.Language.Components; using Content.Shared.Administration; using Robust.Shared.Console; using Robust.Shared.Prototypes; @@ -45,9 +46,9 @@ public void Execute(IConsoleShell shell, string argStr, string[] args) return; } - if (!languageComp.LearnedLanguages.Contains(languageId)) + if (!languageComp.AvailableLanguages.Contains(languageId)) { - languageComp.LearnedLanguages.Add(languageId); + languageComp.AvailableLanguages.Add(languageId); shell.WriteLine(Loc.GetString("cmd-language-success-add")); } else @@ -88,7 +89,7 @@ public void Execute(IConsoleShell shell, string argStr, string[] args) return; } - if (languageComp.LearnedLanguages.Remove(languageId)) + if (languageComp.AvailableLanguages.Remove(languageId)) { shell.WriteLine(Loc.GetString("cmd-language-succes-remove")); } @@ -128,7 +129,7 @@ public void Execute(IConsoleShell shell, string argStr, string[] args) return; } - languageComp.LearnedLanguages.Clear(); + languageComp.AvailableLanguages.Clear(); shell.WriteLine(Loc.GetString("cmd-language-clear")); } } diff --git a/Content.Server/SS220/Language/LanguageComponent.cs b/Content.Server/SS220/Language/Components/LanguageComponent.cs similarity index 71% rename from Content.Server/SS220/Language/LanguageComponent.cs rename to Content.Server/SS220/Language/Components/LanguageComponent.cs index 01f33896f435..6ed2dfdd2a35 100644 --- a/Content.Server/SS220/Language/LanguageComponent.cs +++ b/Content.Server/SS220/Language/Components/LanguageComponent.cs @@ -1,9 +1,7 @@ // © SS220, An EULA/CLA with a hosting restriction, full text: https://raw.githubusercontent.com/SerbiaStrong-220/space-station-14/master/CLA.txt -using Robust.Shared.GameStates; using Robust.Shared.Prototypes; - -namespace Content.Server.SS220.Language; +namespace Content.Server.SS220.Language.Components; /// /// A component that allows an entity to speak and understand languages. @@ -16,12 +14,12 @@ public sealed partial class LanguageComponent : Component /// /// Selected language in which the entity will speak. /// - [DataField, ViewVariables(VVAccess.ReadWrite)] - public string? CurrentLanguage = default!; + [DataField] + public string? SelectedLanguage = default!; /// /// List of languages that the Entity speaks and understands. /// - [DataField("learnedLanguages")] - public List> LearnedLanguages { get; set; } = new(); + [DataField] + public List> AvailableLanguages { get; set; } = new(); } diff --git a/Content.Server/SS220/Language/LanguageSystem.Verbs.cs b/Content.Server/SS220/Language/LanguageSystem.Verbs.cs index d36cd630ec05..f229be05a9c8 100644 --- a/Content.Server/SS220/Language/LanguageSystem.Verbs.cs +++ b/Content.Server/SS220/Language/LanguageSystem.Verbs.cs @@ -1,4 +1,5 @@ // © SS220, An EULA/CLA with a hosting restriction, full text: https://raw.githubusercontent.com/SerbiaStrong-220/space-station-14/master/CLA.txt +using Content.Server.SS220.Language.Components; using Content.Shared.Verbs; using System.Linq; @@ -19,7 +20,7 @@ private void OnVerb(EntityUid ent, LanguageComponent comp, ref GetVerbsEvent lang.ToString()).ToList(); + var learnedLanguages = comp.AvailableLanguages.Select(lang => lang.ToString()).ToList(); var verbs = CreateVerbs(ent, learnedLanguages); foreach (var verb in verbs) { @@ -31,7 +32,7 @@ private List CreateVerbs(EntityUid ent, List languages) { var verbs = new List(); - if (!TryComp(ent, out var comp)) + if (!TryGetLanguageComponent(ent, out var comp)) return verbs; foreach (var language in languages) @@ -44,7 +45,7 @@ private List CreateVerbs(EntityUid ent, List languages) Text = GetName(language), Message = GetDescription(language), Category = VerbCategory.Languages, - Disabled = language == comp.CurrentLanguage, + Disabled = language == comp.SelectedLanguage, Act = () => ChangeLanguage(ent, language) }); } @@ -78,9 +79,9 @@ public string GetName(string language) private void ChangeLanguage(EntityUid ent, string language) { - if (!TryComp(ent, out var comp)) + if (!TryGetLanguageComponent(ent, out var comp)) return; - comp.CurrentLanguage = language; + comp.SelectedLanguage = language; } } diff --git a/Content.Server/SS220/Language/LanguageSystem.cs b/Content.Server/SS220/Language/LanguageSystem.cs index a37f45cc184d..8556db57bb93 100644 --- a/Content.Server/SS220/Language/LanguageSystem.cs +++ b/Content.Server/SS220/Language/LanguageSystem.cs @@ -1,9 +1,9 @@ // © SS220, An EULA/CLA with a hosting restriction, full text: https://raw.githubusercontent.com/SerbiaStrong-220/space-station-14/master/CLA.txt using Content.Server.GameTicking.Events; +using Content.Server.SS220.Language.Components; using Content.Shared.Ghost; using Content.Shared.Verbs; using Robust.Shared.Random; -using Robust.Shared.Timing; using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Text; @@ -14,7 +14,6 @@ namespace Content.Server.SS220.Language; public sealed partial class LanguageSystem : EntitySystem { [Dependency] private readonly IRobustRandom _random = default!; - [Dependency] private readonly IGameTiming _timing = default!; [Dependency] private readonly LanguageManager _languageManager = default!; public readonly string UniversalLanguage = "Universal"; @@ -30,6 +29,7 @@ public override void Initialize() base.Initialize(); SubscribeLocalEvent(OnRoundStart); SubscribeLocalEvent(OnMapInit); + SubscribeLocalEvent(OnGetLanguage); // Verbs SubscribeLocalEvent>(OnVerb); @@ -53,19 +53,25 @@ private void OnRoundStart(RoundStartingEvent args) /// private void OnMapInit(Entity ent, ref MapInitEvent args) { - if (ent.Comp.CurrentLanguage == null) - ent.Comp.CurrentLanguage = ent.Comp.LearnedLanguages.FirstOrDefault(UniversalLanguage); + if (ent.Comp.SelectedLanguage == null) + ent.Comp.SelectedLanguage = ent.Comp.AvailableLanguages.FirstOrDefault(UniversalLanguage); + } + + private void OnGetLanguage(Entity ent, ref GetLanguageCompEvent args) + { + args.Component = ent.Comp; + args.Handled = true; } /// /// A method of encrypting the original message into a message created /// from the syllables of prototypes languages /// - public string ScrambleText(EntityUid? ent, string input, LanguagePrototype proto) + public string ScrambleText(string input, LanguagePrototype proto) { - var saveEndWhitespace = char.IsWhiteSpace(input[^0]); + var saveEndWhitespace = char.IsWhiteSpace(input[^1]); - input = RemoveColorTags(input); + //input = RemoveColorTags(input); var cacheKey = $"{proto.ID}:{input}"; // If the original message is already there earlier encrypted, @@ -100,9 +106,27 @@ public string RemoveColorTags(string input) return cleanedText; } + public string SanitizeMessage(EntityUid source, string message) + { + var languageProto = GetSelectedLanguage(source); + if (languageProto == null) + return message; + + var languageStrings = SplitStringByLanguages(source, message, languageProto); + var sanitizedMessage = new StringBuilder(); + foreach (var languageString in languageStrings) + { + var scrambledString = ScrambleText(languageString.Item1, languageString.Item2); + scrambledString = SetColor(scrambledString, languageString.Item2); + sanitizedMessage.Append(scrambledString); + } + + return sanitizedMessage.ToString(); + } + public string SanitizeMessage(EntityUid source, EntityUid listener, string message) { - var languageProto = GetProto(source); + var languageProto = GetSelectedLanguage(source); if (languageProto == null) return message; @@ -116,7 +140,8 @@ public string SanitizeMessage(EntityUid source, EntityUid listener, string messa } else { - var scrambledString = ScrambleText(listener, languageString.Item1, languageString.Item2); + var colorlessMessage = RemoveColorTags(languageString.Item1); + var scrambledString = ScrambleText(colorlessMessage, languageString.Item2); scrambledString = SetColor(scrambledString, languageString.Item2); sanitizedMessage.Append(scrambledString); } @@ -207,7 +232,7 @@ public bool CheckLanguage(EntityUid ent, LanguagePrototype? proto) if (proto == null) return false; - if (KnowsUniversalLanguage(ent)) + if (KnowsAllLanguages(ent)) return true; return KnowsLanguages(ent, proto.ID); @@ -215,61 +240,50 @@ public bool CheckLanguage(EntityUid ent, LanguagePrototype? proto) public bool KnowsLanguages(EntityUid ent, string languageId) { - if (!TryComp(ent, out var comp)) - return false; - - if (comp.CurrentLanguage == languageId) + // All ents knows universal language + if (languageId == UniversalLanguage) return true; - return comp.LearnedLanguages.Contains(languageId); + if (!TryGetLanguageComponent(ent, out var comp)) + return false; + + return comp.AvailableLanguages.Contains(languageId); } - public bool KnowsUniversalLanguage(EntityUid ent) + public bool KnowsAllLanguages(EntityUid uid) { - if (HasComp(ent)) - return true; - - if (!TryComp(ent, out var comp)) - return true; - - if (comp != null && comp.CurrentLanguage == UniversalLanguage) - return true; - - if (comp != null && comp.LearnedLanguages.Contains(UniversalLanguage)) - return true; - - return false; + return HasComp(uid); } /// /// A method to get a prototype language from an entity. /// If the entity does not have a language component, a universal language is assigned. /// - public LanguagePrototype? GetProto(EntityUid ent) + public LanguagePrototype? GetSelectedLanguage(EntityUid ent) { - if (!TryComp(ent, out var comp)) + if (!TryGetLanguageComponent(ent, out var comp)) { if (_languageManager.TryGetLanguageById(UniversalLanguage, out var universalProto)) return universalProto; - } - var languageID = GetCurrentLanguage(ent); + return null; + } + var languageID = comp.SelectedLanguage; if (languageID == null) return null; - if (_languageManager.TryGetLanguageById(languageID, out var proto)) - return proto; - - return null; + _languageManager.TryGetLanguageById(languageID, out var proto); + return proto; } - public string? GetCurrentLanguage(EntityUid ent) + public bool TryGetLanguageComponent(EntityUid uid, [NotNullWhen(true)] out LanguageComponent? component) { - if (!TryComp(ent, out var comp)) - return null; + var ev = new GetLanguageCompEvent(); + RaiseLocalEvent(uid, ref ev); + component = ev.Component; - return comp.CurrentLanguage; + return component != null; } public void AddLanguages(EntityUid uid, List languages) @@ -282,7 +296,7 @@ public void AddLanguages(EntityUid uid, List languages) public void AddLanguage(EntityUid uid, string languageId) { - if (!TryComp(uid, out var comp)) + if (!TryGetLanguageComponent(uid, out var comp)) return; if (!_languageManager.TryGetLanguageById(languageId, out var proto)) @@ -291,8 +305,8 @@ public void AddLanguage(EntityUid uid, string languageId) return; } - if (!comp.LearnedLanguages.Contains(proto)) - comp.LearnedLanguages.Add(proto); + if (!comp.AvailableLanguages.Contains(proto)) + comp.AvailableLanguages.Add(proto); } /// @@ -310,15 +324,21 @@ public string SetColor(string message, LanguagePrototype proto) public void AddLanguagesFromSource(EntityUid source, EntityUid target) { - if (!TryComp(source, out var sourceComp)) + if (!TryGetLanguageComponent(source, out var sourceComp)) return; var targetComp = EnsureComp(target); - foreach (var language in sourceComp.LearnedLanguages) + foreach (var language in sourceComp.AvailableLanguages) { - if (!targetComp.LearnedLanguages.Contains(language)) - targetComp.LearnedLanguages.Add(language); + if (!targetComp.AvailableLanguages.Contains(language)) + targetComp.AvailableLanguages.Add(language); } } } +[ByRefEvent] +public sealed class GetLanguageCompEvent() : HandledEntityEventArgs +{ + public LanguageComponent? Component = null; +} + diff --git a/Content.Server/TapeRecorder/TapeRecorderSystem.cs b/Content.Server/TapeRecorder/TapeRecorderSystem.cs index d249507a5e42..63a9dc6dcd93 100644 --- a/Content.Server/TapeRecorder/TapeRecorderSystem.cs +++ b/Content.Server/TapeRecorder/TapeRecorderSystem.cs @@ -43,7 +43,7 @@ protected override void ReplayMessagesInSegment(Entity en { var voice = EnsureComp(ent); var speech = EnsureComp(ent); - var language = _languageSystem.GetProto(ent); // SS220 Add languages + var language = _languageSystem.GetSelectedLanguage(ent); // SS220 Add languages TryComp(ent, out var tts); // SS220 Tape recorder TTS foreach (var message in tape.RecordedData) diff --git a/Content.Server/Traits/TraitSystem.cs b/Content.Server/Traits/TraitSystem.cs index f817e657d6a7..8c9866aa569d 100644 --- a/Content.Server/Traits/TraitSystem.cs +++ b/Content.Server/Traits/TraitSystem.cs @@ -6,6 +6,7 @@ using Content.Shared.Whitelist; using Robust.Shared.Prototypes; using Content.Server.SS220.Language; +using Content.Server.SS220.Language.Components; namespace Content.Server.Traits; @@ -50,8 +51,8 @@ private void OnPlayerSpawnComplete(PlayerSpawnCompleteEvent args) // SS220-Add-Languages begin if (traitPrototype.LearnedLanguage != null) { - if (TryComp(args.Mob, out var language) && !language.LearnedLanguages.Contains(traitPrototype.LearnedLanguage)) - language.LearnedLanguages.Add(traitPrototype.LearnedLanguage); + if (TryComp(args.Mob, out var language) && !language.AvailableLanguages.Contains(traitPrototype.LearnedLanguage)) + language.AvailableLanguages.Add(traitPrototype.LearnedLanguage); } // SS220-Add-Languages end diff --git a/Content.Server/Zombies/ZombieSystem.Transform.cs b/Content.Server/Zombies/ZombieSystem.Transform.cs index 4e75780145b1..9c152cf1a247 100644 --- a/Content.Server/Zombies/ZombieSystem.Transform.cs +++ b/Content.Server/Zombies/ZombieSystem.Transform.cs @@ -40,7 +40,8 @@ using Content.Shared.Humanoid.Markings; using Robust.Server.Player; using Content.Shared.Ghost.Roles.Components; -using Content.Server.SS220.Language; // SS220-Add-Languages +using Content.Server.SS220.Language; +using Content.Server.SS220.Language.Components; // SS220-Add-Languages namespace Content.Server.Zombies; diff --git a/Resources/Prototypes/Entities/Mobs/Cyborgs/base_borg_chassis.yml b/Resources/Prototypes/Entities/Mobs/Cyborgs/base_borg_chassis.yml index ab693008f6b6..7c12bb8e6afb 100644 --- a/Resources/Prototypes/Entities/Mobs/Cyborgs/base_borg_chassis.yml +++ b/Resources/Prototypes/Entities/Mobs/Cyborgs/base_borg_chassis.yml @@ -254,7 +254,7 @@ Heat: 10 # capable of touching light bulbs and stoves without feeling pain! # SS220-Add-Languages begin - type: Language - learnedLanguages: + availableLanguages: - Galactic - Binary - Universal diff --git a/Resources/Prototypes/Entities/Mobs/Species/arachnid.yml b/Resources/Prototypes/Entities/Mobs/Species/arachnid.yml index 024f10bcb7d1..0bebfb7fed0b 100644 --- a/Resources/Prototypes/Entities/Mobs/Species/arachnid.yml +++ b/Resources/Prototypes/Entities/Mobs/Species/arachnid.yml @@ -82,7 +82,7 @@ allowedEmotes: ['Click', 'Chitter', 'Hiss'] #ss-220-emote-fix # SS220-Add-Languages begin - type: Language - learnedLanguages: + availableLanguages: - Galactic - Arati # SS220-Add-Languages end diff --git a/Resources/Prototypes/Entities/Mobs/Species/diona.yml b/Resources/Prototypes/Entities/Mobs/Species/diona.yml index 3e85c4aa0526..684a37851ab6 100644 --- a/Resources/Prototypes/Entities/Mobs/Species/diona.yml +++ b/Resources/Prototypes/Entities/Mobs/Species/diona.yml @@ -121,7 +121,7 @@ - Dead # SS220-Add-Languages begin - type: Language - learnedLanguages: + availableLanguages: - Galactic - Rootspeak # SS220-Add-Languages end diff --git a/Resources/Prototypes/Entities/Mobs/Species/dwarf.yml b/Resources/Prototypes/Entities/Mobs/Species/dwarf.yml index 7a7daa6b2e9c..4156b951616e 100644 --- a/Resources/Prototypes/Entities/Mobs/Species/dwarf.yml +++ b/Resources/Prototypes/Entities/Mobs/Species/dwarf.yml @@ -63,7 +63,7 @@ speechSounds: Bass # SS220-Add-Languages begin - type: Language - learnedLanguages: + availableLanguages: - Galactic - Eldwarf # SS220-Add-Languages end diff --git a/Resources/Prototypes/Entities/Mobs/Species/human.yml b/Resources/Prototypes/Entities/Mobs/Species/human.yml index 82d65b4c3eac..6ad66d3dd948 100644 --- a/Resources/Prototypes/Entities/Mobs/Species/human.yml +++ b/Resources/Prototypes/Entities/Mobs/Species/human.yml @@ -22,7 +22,7 @@ - Snout # SS220-Add-Languages begin - type: Language - learnedLanguages: + availableLanguages: - Galactic - SolCommon # SS220-Add-Languages end diff --git a/Resources/Prototypes/Entities/Mobs/Species/moth.yml b/Resources/Prototypes/Entities/Mobs/Species/moth.yml index 5ad75e1a4270..247528000fcb 100644 --- a/Resources/Prototypes/Entities/Mobs/Species/moth.yml +++ b/Resources/Prototypes/Entities/Mobs/Species/moth.yml @@ -142,7 +142,7 @@ visible: false # SS220-Add-Languages begin - type: Language - learnedLanguages: + availableLanguages: - Galactic - Tkachi # SS220-Add-Languages end diff --git a/Resources/Prototypes/Entities/Mobs/Species/reptilian.yml b/Resources/Prototypes/Entities/Mobs/Species/reptilian.yml index 092c700f07cc..7e55ff7d7c99 100644 --- a/Resources/Prototypes/Entities/Mobs/Species/reptilian.yml +++ b/Resources/Prototypes/Entities/Mobs/Species/reptilian.yml @@ -90,7 +90,7 @@ - type: Wagging # SS220-Add-Languages begin - type: Language - learnedLanguages: + availableLanguages: - Galactic - Sintaunathi # SS220-Add-Languages end diff --git a/Resources/Prototypes/Entities/Mobs/Species/slime.yml b/Resources/Prototypes/Entities/Mobs/Species/slime.yml index b2c7e53d3d95..88c8d0b5762e 100644 --- a/Resources/Prototypes/Entities/Mobs/Species/slime.yml +++ b/Resources/Prototypes/Entities/Mobs/Species/slime.yml @@ -143,7 +143,7 @@ maxSaturation: 15 # SS220-Add-Languages begin - type: Language - learnedLanguages: + availableLanguages: - Galactic - Bubblish # SS220-Add-Languages end diff --git a/Resources/Prototypes/Entities/Mobs/Species/vox.yml b/Resources/Prototypes/Entities/Mobs/Species/vox.yml index 8ef532b2b958..596eea502349 100644 --- a/Resources/Prototypes/Entities/Mobs/Species/vox.yml +++ b/Resources/Prototypes/Entities/Mobs/Species/vox.yml @@ -127,7 +127,7 @@ visible: false # SS220-Add-Languages begin - type: Language - learnedLanguages: + availableLanguages: - Galactic - VoxPidgin # SS220-Add-Languages end diff --git a/Resources/Prototypes/Entities/Objects/Fun/pai.yml b/Resources/Prototypes/Entities/Objects/Fun/pai.yml index 930bd5419156..dd6ca35af231 100644 --- a/Resources/Prototypes/Entities/Objects/Fun/pai.yml +++ b/Resources/Prototypes/Entities/Objects/Fun/pai.yml @@ -83,7 +83,7 @@ - SecretStash # SS220-Add-Languages begin - type: Language - learnedLanguages: + availableLanguages: - Galactic - Universal # SS220-Add-Languages end diff --git a/Resources/Prototypes/Entities/Objects/Specific/Robotics/mmi.yml b/Resources/Prototypes/Entities/Objects/Specific/Robotics/mmi.yml index 9860c5eab856..81f848567945 100644 --- a/Resources/Prototypes/Entities/Objects/Specific/Robotics/mmi.yml +++ b/Resources/Prototypes/Entities/Objects/Specific/Robotics/mmi.yml @@ -55,7 +55,7 @@ - SecretStash # SS220-Add-Languages begin - type: Language - learnedLanguages: + availableLanguages: - Galactic - Binary - Universal @@ -112,7 +112,7 @@ - Binary # SS220-Add-Languages begin - type: Language - learnedLanguages: + availableLanguages: - Galactic - Binary - Universal diff --git a/Resources/Prototypes/SS220/Entities/Mobs/NPCs/animals.yml b/Resources/Prototypes/SS220/Entities/Mobs/NPCs/animals.yml index 1eff038ef699..718483928784 100644 --- a/Resources/Prototypes/SS220/Entities/Mobs/NPCs/animals.yml +++ b/Resources/Prototypes/SS220/Entities/Mobs/NPCs/animals.yml @@ -271,7 +271,7 @@ radius: 2 netsync: false - type: Language - learnedLanguages: + availableLanguages: - Galactic - Binary - Universal diff --git a/Resources/Prototypes/SS220/Entities/Mobs/Species/felinid.yml b/Resources/Prototypes/SS220/Entities/Mobs/Species/felinid.yml index de349fdadf47..db8d531684c8 100644 --- a/Resources/Prototypes/SS220/Entities/Mobs/Species/felinid.yml +++ b/Resources/Prototypes/SS220/Entities/Mobs/Species/felinid.yml @@ -112,7 +112,7 @@ - type: Emoting chatEmoteCooldown: 5.0 - type: Language - learnedLanguages: + availableLanguages: - Galactic - type: entity diff --git a/Resources/Prototypes/SS220/Entities/Mobs/Species/tajaran.yml b/Resources/Prototypes/SS220/Entities/Mobs/Species/tajaran.yml index 72d99a3f25d2..fa43c62af229 100644 --- a/Resources/Prototypes/SS220/Entities/Mobs/Species/tajaran.yml +++ b/Resources/Prototypes/SS220/Entities/Mobs/Species/tajaran.yml @@ -108,7 +108,7 @@ highSensitiveVisionRadius: 2 addAction: true - type: Language - learnedLanguages: + availableLanguages: - Galactic - Siiktajr diff --git a/Resources/Prototypes/SS220/Entities/Mobs/Species/vulpkanin.yml b/Resources/Prototypes/SS220/Entities/Mobs/Species/vulpkanin.yml index 201d37b18eb9..55d5337505bd 100644 --- a/Resources/Prototypes/SS220/Entities/Mobs/Species/vulpkanin.yml +++ b/Resources/Prototypes/SS220/Entities/Mobs/Species/vulpkanin.yml @@ -70,7 +70,7 @@ types: Slash: 5.5 - type: Language - learnedLanguages: + availableLanguages: - Galactic - Canilunzt #если будет дальнейшее обсуждение и одобрение, займусь этой рассой для раундстартового состояния. Пока так diff --git a/Resources/Prototypes/SS220/Entities/Objects/Fun/pai.yml b/Resources/Prototypes/SS220/Entities/Objects/Fun/pai.yml index 9ac7631432ea..4a50c0b1a5ec 100644 --- a/Resources/Prototypes/SS220/Entities/Objects/Fun/pai.yml +++ b/Resources/Prototypes/SS220/Entities/Objects/Fun/pai.yml @@ -88,7 +88,7 @@ Unsexed: UnisexSilicon # SS220 borg emotes to PAI end # SS220-Add-Languages begin - type: Language - learnedLanguages: + availableLanguages: - Galactic - Universal - # SS220-Add-Languages end \ No newline at end of file + # SS220-Add-Languages end diff --git a/Resources/Prototypes/SS220/Geras/slime.yml b/Resources/Prototypes/SS220/Geras/slime.yml index 27cb6d444c89..cd9a9fc6f0f6 100644 --- a/Resources/Prototypes/SS220/Geras/slime.yml +++ b/Resources/Prototypes/SS220/Geras/slime.yml @@ -34,7 +34,7 @@ Base: blue_adult_slime_dead # SS220-Add-Languages begin - type: Language - learnedLanguages: + availableLanguages: - Galactic - Bubblish - # SS220-Add-Languages end \ No newline at end of file + # SS220-Add-Languages end diff --git a/Resources/Prototypes/SS220/Traits/language_traits.yml b/Resources/Prototypes/SS220/Traits/language_traits.yml index 85daa97d4525..d9a6b670141a 100644 --- a/Resources/Prototypes/SS220/Traits/language_traits.yml +++ b/Resources/Prototypes/SS220/Traits/language_traits.yml @@ -6,7 +6,7 @@ cost: 1 components: - type: Language - learnedLanguages: + availableLanguages: - Tradeband learnedLanguage: Tradeband @@ -18,7 +18,7 @@ cost: 1 components: - type: Language - learnedLanguages: + availableLanguages: - Gutter learnedLanguage: Gutter @@ -30,7 +30,7 @@ cost: 1 components: - type: Language - learnedLanguages: + availableLanguages: - Clownish learnedLanguage: Clownish @@ -42,6 +42,6 @@ cost: 1 components: - type: Language - learnedLanguages: + availableLanguages: - NeoRusskiya - learnedLanguage: NeoRusskiya \ No newline at end of file + learnedLanguage: NeoRusskiya From 59d0686e1597bf1a7c1f834b0cd2fa4f464a50b6 Mon Sep 17 00:00:00 2001 From: Kirus59 <145689588+Kirus59@users.noreply.github.com> Date: Fri, 28 Feb 2025 20:47:57 +0300 Subject: [PATCH 20/48] return 'Remember, no English' & other fixes --- .../Chat/Managers/ChatSanitizationManager.cs | 24 +++++++++++-------- Content.Server/Chat/Systems/ChatSystem.cs | 19 +++++++-------- .../SS220/Language/LanguageSystem.cs | 18 -------------- .../TapeRecorder/TapeRecorderSystem.cs | 2 +- 4 files changed, 23 insertions(+), 40 deletions(-) diff --git a/Content.Server/Chat/Managers/ChatSanitizationManager.cs b/Content.Server/Chat/Managers/ChatSanitizationManager.cs index ae5da290ab58..63c002be7454 100644 --- a/Content.Server/Chat/Managers/ChatSanitizationManager.cs +++ b/Content.Server/Chat/Managers/ChatSanitizationManager.cs @@ -1,6 +1,7 @@ using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Text.RegularExpressions; +using Content.Server.SS220.Language; using Content.Shared.CCVar; using Robust.Shared.Configuration; @@ -113,6 +114,7 @@ public sealed class ChatSanitizationManager : IChatSanitizationManager [Dependency] private readonly IConfigurationManager _configurationManager = default!; [Dependency] private readonly ILocalizationManager _loc = default!; + [Dependency] private readonly IEntityManager _entityManager = default!; // SS220 languages private bool _doSanitize; @@ -175,16 +177,18 @@ 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 language = _entityManager.System(); + var checkMessage = language.SanitizeMessage(speaker, speaker, sanitized); + var ntAllowed = checkMessage.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; + } // SS220 no English end sanitized = message.Trim(); diff --git a/Content.Server/Chat/Systems/ChatSystem.cs b/Content.Server/Chat/Systems/ChatSystem.cs index cc3ce7c1d125..2e540be8dc03 100644 --- a/Content.Server/Chat/Systems/ChatSystem.cs +++ b/Content.Server/Chat/Systems/ChatSystem.cs @@ -173,13 +173,10 @@ public void TrySendInGameICMessage( IConsoleShell? shell = null, ICommonSession? player = null, string? nameOverride = null, bool checkRadioPrefix = true, - bool ignoreActionBlocker = false, - LanguagePrototype? languageProto = null) // SS220-Add-Languages + bool ignoreActionBlocker = false + ) { - TrySendInGameICMessage(source, message, desiredType, - hideChat ? ChatTransmitRange.HideChat : ChatTransmitRange.Normal, - hideLog, shell, player, nameOverride, checkRadioPrefix, - ignoreActionBlocker, languageProto: languageProto); // SS220-Add-Languages + TrySendInGameICMessage(source, message, desiredType, hideChat ? ChatTransmitRange.HideChat : ChatTransmitRange.Normal, hideLog, shell, player, nameOverride, checkRadioPrefix, ignoreActionBlocker); } /// @@ -203,8 +200,8 @@ public void TrySendInGameICMessage( ICommonSession? player = null, string? nameOverride = null, bool checkRadioPrefix = true, - bool ignoreActionBlocker = false, - LanguagePrototype? languageProto = null) // SS220-Add-Languages + bool ignoreActionBlocker = false + ) { if (HasComp(source)) { @@ -301,7 +298,7 @@ public void TrySendInGameICMessage( SendEntitySpeak(source, message, range, nameOverride, hideLog, ignoreActionBlocker); break; case InGameICChatType.Whisper: - SendEntityWhisper(source, message, range, null, nameOverride, hideLog, ignoreActionBlocker, languageProto); // SS220-Add-Languages + SendEntityWhisper(source, message, range, null, nameOverride, hideLog, ignoreActionBlocker); break; case InGameICChatType.Emote: SendEntityEmote(source, message, range, nameOverride, hideLog: hideLog, ignoreActionBlocker: ignoreActionBlocker); @@ -561,8 +558,8 @@ private void SendEntityWhisper( RadioChannelPrototype? channel, string? nameOverride, bool hideLog = false, - bool ignoreActionBlocker = false, - LanguagePrototype? languageProto = null) // SS220-Add-Languages + bool ignoreActionBlocker = false + ) { if (!_actionBlocker.CanSpeak(source) && !ignoreActionBlocker) return; diff --git a/Content.Server/SS220/Language/LanguageSystem.cs b/Content.Server/SS220/Language/LanguageSystem.cs index 8556db57bb93..44cae8ea122f 100644 --- a/Content.Server/SS220/Language/LanguageSystem.cs +++ b/Content.Server/SS220/Language/LanguageSystem.cs @@ -106,24 +106,6 @@ public string RemoveColorTags(string input) return cleanedText; } - public string SanitizeMessage(EntityUid source, string message) - { - var languageProto = GetSelectedLanguage(source); - if (languageProto == null) - return message; - - var languageStrings = SplitStringByLanguages(source, message, languageProto); - var sanitizedMessage = new StringBuilder(); - foreach (var languageString in languageStrings) - { - var scrambledString = ScrambleText(languageString.Item1, languageString.Item2); - scrambledString = SetColor(scrambledString, languageString.Item2); - sanitizedMessage.Append(scrambledString); - } - - return sanitizedMessage.ToString(); - } - public string SanitizeMessage(EntityUid source, EntityUid listener, string message) { var languageProto = GetSelectedLanguage(source); diff --git a/Content.Server/TapeRecorder/TapeRecorderSystem.cs b/Content.Server/TapeRecorder/TapeRecorderSystem.cs index 63a9dc6dcd93..14f8fe5579ff 100644 --- a/Content.Server/TapeRecorder/TapeRecorderSystem.cs +++ b/Content.Server/TapeRecorder/TapeRecorderSystem.cs @@ -63,7 +63,7 @@ protected override void ReplayMessagesInSegment(Entity en } // SS220 Tape recorder TTS end //Play the message - _chat.TrySendInGameICMessage(ent, message.Message, InGameICChatType.Speak, false, languageProto: language); // SS220-Add-Languages + _chat.TrySendInGameICMessage(ent, message.Message, InGameICChatType.Speak, false); } } From d381c570509459c08595e0b9dd1ace5ed369c3e6 Mon Sep 17 00:00:00 2001 From: Kirus59 <145689588+Kirus59@users.noreply.github.com> Date: Fri, 28 Feb 2025 20:57:04 +0300 Subject: [PATCH 21/48] remove 'RemoveColorTags' --- Content.Server/Chat/Systems/ChatSystem.cs | 2 +- .../Radio/EntitySystems/RadioDeviceSystem.cs | 7 ++--- .../SS220/Language/LanguageSystem.cs | 28 ++++--------------- 3 files changed, 9 insertions(+), 28 deletions(-) diff --git a/Content.Server/Chat/Systems/ChatSystem.cs b/Content.Server/Chat/Systems/ChatSystem.cs index 2e540be8dc03..6c99e6366311 100644 --- a/Content.Server/Chat/Systems/ChatSystem.cs +++ b/Content.Server/Chat/Systems/ChatSystem.cs @@ -605,7 +605,7 @@ private void SendEntityWhisper( // SS220-Add-Languages begin var scrambledMessage = _languageSystem.SanitizeMessage(source, listener, message); - var scrambledColorlessMessage = _languageSystem.RemoveColorTags(scrambledMessage); + var scrambledColorlessMessage = _languageSystem.SanitizeMessage(source, listener, message, false); var obfuscatedScrambledMessage = ObfuscateMessageReadability(scrambledColorlessMessage, 0.2f); wrappedMessage = Loc.GetString("chat-manager-entity-whisper-wrap-message", diff --git a/Content.Server/Radio/EntitySystems/RadioDeviceSystem.cs b/Content.Server/Radio/EntitySystems/RadioDeviceSystem.cs index b8b9e26a2bf6..abb0a527dbc3 100644 --- a/Content.Server/Radio/EntitySystems/RadioDeviceSystem.cs +++ b/Content.Server/Radio/EntitySystems/RadioDeviceSystem.cs @@ -206,13 +206,10 @@ private void OnListen(EntityUid uid, RadioMicrophoneComponent component, ListenE if (HasComp(args.Source)) return; // no feedback loops please. - // SS220-Add-Languages begin - var message = _languageSystem.RemoveColorTags(args.Message); var channel = _protoMan.Index(component.BroadcastChannel)!; if (_recentlySent.Add((args.Message, args.Source, channel))) - _radio.SendRadioMessage(args.Source, message, channel, uid); - // SS220-Add-Languages end - } + _radio.SendRadioMessage(args.Source, args.Message, channel, uid); + } private void OnAttemptListen(EntityUid uid, RadioMicrophoneComponent component, ListenAttemptEvent args) { diff --git a/Content.Server/SS220/Language/LanguageSystem.cs b/Content.Server/SS220/Language/LanguageSystem.cs index 44cae8ea122f..edf260127219 100644 --- a/Content.Server/SS220/Language/LanguageSystem.cs +++ b/Content.Server/SS220/Language/LanguageSystem.cs @@ -20,7 +20,7 @@ public sealed partial class LanguageSystem : EntitySystem public readonly string GalacticLanguage = "Galactic"; // Cached values for one tick - private static readonly Dictionary ScrambleCache = new Dictionary(); + private static readonly Dictionary ScrambleCache = new(); private static int Seed = 0; @@ -71,7 +71,6 @@ public string ScrambleText(string input, LanguagePrototype proto) { var saveEndWhitespace = char.IsWhiteSpace(input[^1]); - //input = RemoveColorTags(input); var cacheKey = $"{proto.ID}:{input}"; // If the original message is already there earlier encrypted, @@ -90,23 +89,7 @@ public string ScrambleText(string input, LanguagePrototype proto) return scrambledText; } - /// - /// Workaround for some message transmissions. - /// Removes BBCodes colors leaving only the original message. - /// (I couldn't think of anything cleverer) - /// - public string RemoveColorTags(string input) - { - if (string.IsNullOrEmpty(input)) - return input; - - string pattern = @"\[color=#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{8})\](.*?)\[/color\]"; - string cleanedText = Regex.Replace(input, pattern, "$2"); - - return cleanedText; - } - - public string SanitizeMessage(EntityUid source, EntityUid listener, string message) + public string SanitizeMessage(EntityUid source, EntityUid listener, string message, bool setColor = true) { var languageProto = GetSelectedLanguage(source); if (languageProto == null) @@ -122,9 +105,10 @@ public string SanitizeMessage(EntityUid source, EntityUid listener, string messa } else { - var colorlessMessage = RemoveColorTags(languageString.Item1); - var scrambledString = ScrambleText(colorlessMessage, languageString.Item2); - scrambledString = SetColor(scrambledString, languageString.Item2); + var scrambledString = ScrambleText(message, languageString.Item2); + if (setColor) + scrambledString = SetColor(scrambledString, languageString.Item2); + sanitizedMessage.Append(scrambledString); } } From dc00d4b3d384ef0abaa40ee002272b86eb67fe56 Mon Sep 17 00:00:00 2001 From: Kirus59 <145689588+Kirus59@users.noreply.github.com> Date: Fri, 28 Feb 2025 22:57:31 +0300 Subject: [PATCH 22/48] some fixes, cleaning & optimization --- Content.Server/Chat/Systems/ChatSystem.cs | 13 +-- .../EntityEffects/Effects/MakeSentient.cs | 7 +- Content.Server/PAI/PAISystem.cs | 17 +-- .../Radio/EntitySystems/RadioDeviceSystem.cs | 6 +- .../SS220/Commands/LanguageCommands.cs | 11 +- .../Language/Components/LanguageComponent.cs | 102 +++++++++++++++++- .../EncryptionMethods/BaseEncryptionMethod.cs | 4 + .../EncryptionMethods/EmptyScrambleMethod.cs | 15 +++ .../RandomSyllablesMethod.cs | 3 + .../SS220/Language/LanguageManager.cs | 6 ++ .../SS220/Language/LanguageSystem.Verbs.cs | 2 +- .../SS220/Language/LanguageSystem.cs | 82 +++++++------- .../SS220/Language/LanguagesPrototype.cs | 3 + .../Language/Special/AddLanguageSpecial.cs | 7 +- .../TapeRecorder/TapeRecorderSystem.cs | 3 - Content.Server/Traits/TraitSystem.cs | 6 +- .../Prototypes/SS220/Language/language.yml | 1 + 17 files changed, 203 insertions(+), 85 deletions(-) create mode 100644 Content.Server/SS220/Language/EncryptionMethods/EmptyScrambleMethod.cs diff --git a/Content.Server/Chat/Systems/ChatSystem.cs b/Content.Server/Chat/Systems/ChatSystem.cs index 6c99e6366311..f058a8da65f5 100644 --- a/Content.Server/Chat/Systems/ChatSystem.cs +++ b/Content.Server/Chat/Systems/ChatSystem.cs @@ -44,6 +44,7 @@ using Robust.Shared.Timing; using Content.Server.SS220.Language; // SS220-Add-Languages-end using Robust.Shared.Map; +using Content.Shared.Speech; namespace Content.Server.Chat.Systems; @@ -173,8 +174,7 @@ public void TrySendInGameICMessage( IConsoleShell? shell = null, ICommonSession? player = null, string? nameOverride = null, bool checkRadioPrefix = true, - bool ignoreActionBlocker = false - ) + bool ignoreActionBlocker = false) { TrySendInGameICMessage(source, message, desiredType, hideChat ? ChatTransmitRange.HideChat : ChatTransmitRange.Normal, hideLog, shell, player, nameOverride, checkRadioPrefix, ignoreActionBlocker); } @@ -595,6 +595,7 @@ private void SendEntityWhisper( var wrappedUnknownMessage = Loc.GetString("chat-manager-entity-whisper-unknown-wrap-message", ("message", FormattedMessage.EscapeText(obfuscatedMessage))); + foreach (var (session, data) in GetRecipients(source, WhisperMuffledRange)) { EntityUid listener; @@ -619,14 +620,14 @@ private void SendEntityWhisper( 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, scrambledMessage, wrappedMessage, source, false, session.Channel); + if (data.Range <= WhisperClearRange || data.Observer) + _chatManager.ChatMessageToOne(ChatChannel.Whisper, scrambledMessage /* SS220 languages */, wrappedMessage, 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, obfuscatedScrambledMessage, wrappedobfuscatedMessage, source, false, session.Channel); + _chatManager.ChatMessageToOne(ChatChannel.Whisper, obfuscatedScrambledMessage /* SS220 languages */, wrappedobfuscatedMessage, 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, obfuscatedScrambledMessage, wrappedUnknownMessage, source, false, session.Channel); + _chatManager.ChatMessageToOne(ChatChannel.Whisper, obfuscatedScrambledMessage /* SS220 languages */, wrappedUnknownMessage, source, false, session.Channel); } _replay.RecordServerMessage(new ChatMessage(ChatChannel.Whisper, message, wrappedMessage, GetNetEntity(source), null, MessageRangeHideChatForReplay(range))); diff --git a/Content.Server/EntityEffects/Effects/MakeSentient.cs b/Content.Server/EntityEffects/Effects/MakeSentient.cs index 704436245b71..86a3598585b4 100644 --- a/Content.Server/EntityEffects/Effects/MakeSentient.cs +++ b/Content.Server/EntityEffects/Effects/MakeSentient.cs @@ -25,13 +25,10 @@ public override void Effect(EntityEffectBaseArgs args) entityManager.RemoveComponent(uid); // SS220-Add-Languages begin - var language = entityManager.EnsureComponent(uid); + var languageComp = entityManager.EnsureComponent(uid); var languageSystem = entityManager.System(); - if (!language.AvailableLanguages.Contains(languageSystem.GalacticLanguage)) - language.AvailableLanguages.Add(languageSystem.GalacticLanguage); - - language.SelectedLanguage = language.AvailableLanguages[0]; + languageComp.TryAddLanguage(languageSystem.GalacticLanguage); // SS220-Add-Languages end // Stops from adding a ghost role to things like people who already have a mind diff --git a/Content.Server/PAI/PAISystem.cs b/Content.Server/PAI/PAISystem.cs index 7f3bd0f50154..f5d976672c7e 100644 --- a/Content.Server/PAI/PAISystem.cs +++ b/Content.Server/PAI/PAISystem.cs @@ -58,7 +58,11 @@ private void OnMindAdded(EntityUid uid, PAIComponent component, MindAddedMessage // Cause then you could remotely figure out information about the owner's equipped items. _metaData.SetEntityName(uid, val); - _language.AddLanguagesFromSource(component.LastUser.Value, uid); // SS220-Add-Languages + + // SS220-Add-Languages begin + if (TryComp(component.LastUser.Value, out var languageComp)) + _language.AddLanguagesFromSource((component.LastUser.Value, languageComp), uid); + // SS220-Add-Languages end } private void OnMindRemoved(EntityUid uid, PAIComponent component, MindRemovedMessage args) @@ -121,13 +125,12 @@ public void PAITurningOff(EntityUid uid) if (proto != null) _metaData.SetEntityName(uid, proto.Name); } - // SS220-Add-Languages begin - if (TryComp(uid, out var languages)) + // SS220-Add-Languages begin + if (TryComp(uid, out var languageComp)) { - languages.AvailableLanguages.Clear(); - _language.AddLanguages(uid, [_language.UniversalLanguage, _language.GalacticLanguage]); - languages.SelectedLanguage = languages.AvailableLanguages[0]; + languageComp.ClearLanguages(); + languageComp.AddLanguages([_language.UniversalLanguage, _language.GalacticLanguage]); } + // SS220-Add-Languages end } - // SS220-Add-Languages end } diff --git a/Content.Server/Radio/EntitySystems/RadioDeviceSystem.cs b/Content.Server/Radio/EntitySystems/RadioDeviceSystem.cs index abb0a527dbc3..0c488f06ae95 100644 --- a/Content.Server/Radio/EntitySystems/RadioDeviceSystem.cs +++ b/Content.Server/Radio/EntitySystems/RadioDeviceSystem.cs @@ -19,8 +19,6 @@ using Content.Shared.Chat; using Content.Shared.UserInterface; using Robust.Server.GameObjects; -using Robust.Shared.Utility; -using Content.Server.SS220.Language; // SS220-Add-Languages namespace Content.Server.Radio.EntitySystems; @@ -36,7 +34,6 @@ public sealed class RadioDeviceSystem : EntitySystem [Dependency] private readonly InteractionSystem _interaction = default!; [Dependency] private readonly SharedAppearanceSystem _appearance = default!; [Dependency] private readonly UserInterfaceSystem _ui = default!; - [Dependency] private readonly LanguageSystem _languageSystem = default!; // SS220-Add-Languages // Used to prevent a shitter from using a bunch of radios to spam chat. private HashSet<(string, EntityUid, RadioChannelPrototype)> _recentlySent = new(); @@ -233,8 +230,7 @@ private void OnReceiveRadio(EntityUid uid, RadioSpeakerComponent component, ref ("originalName", nameEv.VoiceName)); // log to chat so people can identity the speaker/source, but avoid clogging ghost chat if there are many radios - _chat.TrySendInGameICMessage(uid, args.Message, InGameICChatType.Whisper, - ChatTransmitRange.GhostRangeLimit, nameOverride: name, checkRadioPrefix: false); + _chat.TrySendInGameICMessage(uid, args.Message, InGameICChatType.Whisper, ChatTransmitRange.GhostRangeLimit, nameOverride: name, checkRadioPrefix: false); } private void OnIntercomEncryptionChannelsChanged(Entity ent, ref EncryptionChannelsChangedEvent args) diff --git a/Content.Server/SS220/Commands/LanguageCommands.cs b/Content.Server/SS220/Commands/LanguageCommands.cs index 1ec1beb17a6c..c6d60d1bc019 100644 --- a/Content.Server/SS220/Commands/LanguageCommands.cs +++ b/Content.Server/SS220/Commands/LanguageCommands.cs @@ -3,7 +3,6 @@ using Content.Server.SS220.Language.Components; using Content.Shared.Administration; using Robust.Shared.Console; -using Robust.Shared.Prototypes; namespace Content.Server.SS220.Commands; @@ -11,7 +10,6 @@ namespace Content.Server.SS220.Commands; public sealed class AddLanguageCommand : IConsoleCommand { [Dependency] private readonly IEntityManager _entities = default!; - [Dependency] private readonly IPrototypeManager _proto = default!; [Dependency] private readonly LanguageManager _languageManager = default!; public string Command => "addlanguage"; @@ -34,7 +32,7 @@ public void Execute(IConsoleShell shell, string argStr, string[] args) var languageId = args[1]; - if (_languageManager.TryGetLanguageById(languageId, out var language)) + if (_languageManager.TryGetLanguageById(languageId, out _)) { shell.WriteError(Loc.GetString("cmd-language-proto-miss")); return; @@ -46,9 +44,8 @@ public void Execute(IConsoleShell shell, string argStr, string[] args) return; } - if (!languageComp.AvailableLanguages.Contains(languageId)) + if (languageComp.TryAddLanguage(languageId)) { - languageComp.AvailableLanguages.Add(languageId); shell.WriteLine(Loc.GetString("cmd-language-success-add")); } else @@ -89,7 +86,7 @@ public void Execute(IConsoleShell shell, string argStr, string[] args) return; } - if (languageComp.AvailableLanguages.Remove(languageId)) + if (languageComp.RemoveLanguage(languageId)) { shell.WriteLine(Loc.GetString("cmd-language-succes-remove")); } @@ -129,7 +126,7 @@ public void Execute(IConsoleShell shell, string argStr, string[] args) return; } - languageComp.AvailableLanguages.Clear(); + languageComp.ClearLanguages(); shell.WriteLine(Loc.GetString("cmd-language-clear")); } } diff --git a/Content.Server/SS220/Language/Components/LanguageComponent.cs b/Content.Server/SS220/Language/Components/LanguageComponent.cs index 6ed2dfdd2a35..55cc314be512 100644 --- a/Content.Server/SS220/Language/Components/LanguageComponent.cs +++ b/Content.Server/SS220/Language/Components/LanguageComponent.cs @@ -1,5 +1,6 @@ // © SS220, An EULA/CLA with a hosting restriction, full text: https://raw.githubusercontent.com/SerbiaStrong-220/space-station-14/master/CLA.txt using Robust.Shared.Prototypes; +using System.Linq; namespace Content.Server.SS220.Language.Components; @@ -15,11 +16,106 @@ public sealed partial class LanguageComponent : Component /// Selected language in which the entity will speak. /// [DataField] - public string? SelectedLanguage = default!; + public ProtoId? SelectedLanguage { get; private set; } /// /// List of languages that the Entity speaks and understands. /// - [DataField] - public List> AvailableLanguages { get; set; } = new(); + [DataField, Access(Other = AccessPermissions.Read)] + public List> AvailableLanguages { get; private set; } = new(); + + #region Utilites + /// + /// Adds languages from + /// + public void AddLanguages(List languages) + { + foreach (var language in languages) + { + TryAddLanguage(language); + } + } + + /// + /// Adds language to the + /// + /// if successful added + public bool TryAddLanguage(string languageId) + { + var languageManager = IoCManager.Resolve(); + if (!languageManager.TryGetLanguageById(languageId, out _) || + AvailableLanguages.Contains(languageId)) + return false; + + AvailableLanguages.Add(languageId); + SelectedLanguage ??= AvailableLanguages[0]; + return true; + } + + /// + /// Clears + /// + public void ClearLanguages() + { + AvailableLanguages.Clear(); + SelectedLanguage = null; + } + + /// + /// Removes language from + /// + /// if successful removed + public bool RemoveLanguage(string languageId) + { + if (AvailableLanguages.Remove(languageId)) + { + if (SelectedLanguage == languageId) + { + if (AvailableLanguages.Count > 0) + SelectedLanguage = AvailableLanguages.First(); + else + SelectedLanguage = null; + } + + return true; + } + + return false; + } + + /// + /// Checks if contains this + /// + /// + public bool HasLanguage(string languageId) + { + return AvailableLanguages.Contains(languageId); + } + + /// + /// Tries set by of + /// + /// + public bool TrySetLanguage(int index) + { + if (AvailableLanguages.Count < index - 1) + return false; + + SelectedLanguage = AvailableLanguages[index]; + return true; + } + + /// + /// Tries set by language id. + /// Doesn't set language if doesn't contain this + /// + public bool TrySetLanguage(string languageId) + { + if (!HasLanguage(languageId)) + return false; + + SelectedLanguage = languageId; + return true; + } + #endregion } diff --git a/Content.Server/SS220/Language/EncryptionMethods/BaseEncryptionMethod.cs b/Content.Server/SS220/Language/EncryptionMethods/BaseEncryptionMethod.cs index 49beef624aff..06aac2951b53 100644 --- a/Content.Server/SS220/Language/EncryptionMethods/BaseEncryptionMethod.cs +++ b/Content.Server/SS220/Language/EncryptionMethods/BaseEncryptionMethod.cs @@ -5,5 +5,9 @@ namespace Content.Server.SS220.Language.EncryptionMethods; [ImplicitDataDefinitionForInheritors] public abstract partial class ScrambleMethod { + /// + /// Scramble according to a specific algorithm. + /// It is acceptable to use a specific seed to get the same result if the message is the same + /// public abstract string ScrambleMessage(string message, int? seed = null); } diff --git a/Content.Server/SS220/Language/EncryptionMethods/EmptyScrambleMethod.cs b/Content.Server/SS220/Language/EncryptionMethods/EmptyScrambleMethod.cs new file mode 100644 index 000000000000..a1292d75c211 --- /dev/null +++ b/Content.Server/SS220/Language/EncryptionMethods/EmptyScrambleMethod.cs @@ -0,0 +1,15 @@ +// © SS220, An EULA/CLA with a hosting restriction, full text: https://raw.githubusercontent.com/SerbiaStrong-220/space-station-14/master/CLA.txt + +namespace Content.Server.SS220.Language.EncryptionMethods; + +/// +/// Returns the original message without scramble. +/// Used in the universal language +/// +public sealed partial class EmptyScrambleMethod : ScrambleMethod +{ + public override string ScrambleMessage(string message, int? seed = null) + { + return message; + } +} diff --git a/Content.Server/SS220/Language/EncryptionMethods/RandomSyllablesMethod.cs b/Content.Server/SS220/Language/EncryptionMethods/RandomSyllablesMethod.cs index 3387b6d3c3bd..add7259bc980 100644 --- a/Content.Server/SS220/Language/EncryptionMethods/RandomSyllablesMethod.cs +++ b/Content.Server/SS220/Language/EncryptionMethods/RandomSyllablesMethod.cs @@ -4,6 +4,9 @@ namespace Content.Server.SS220.Language.EncryptionMethods; +/// +/// Scramble a message depending on its length using a specific list of syllables +/// public sealed partial class RandomSyllablesScrambleMethod : ScrambleMethod { /// diff --git a/Content.Server/SS220/Language/LanguageManager.cs b/Content.Server/SS220/Language/LanguageManager.cs index 7c1c5eff3eb2..1811db789bda 100644 --- a/Content.Server/SS220/Language/LanguageManager.cs +++ b/Content.Server/SS220/Language/LanguageManager.cs @@ -21,12 +21,18 @@ public void Initialize() } } + /// + /// Tries get language prototipe by id + /// public bool TryGetLanguageById(string id, [NotNullWhen(true)] out LanguagePrototype? language) { language = Languages.Find(l => l.ID == id); return language != null; } + /// + /// Tries get language prototipe by language key + /// public bool TryGetLanguageByKey(string key, [NotNullWhen(true)] out LanguagePrototype? language) { language = Languages.Find(l => KeyPrefix + l.Key == key); diff --git a/Content.Server/SS220/Language/LanguageSystem.Verbs.cs b/Content.Server/SS220/Language/LanguageSystem.Verbs.cs index f229be05a9c8..e36ae47af7ea 100644 --- a/Content.Server/SS220/Language/LanguageSystem.Verbs.cs +++ b/Content.Server/SS220/Language/LanguageSystem.Verbs.cs @@ -82,6 +82,6 @@ private void ChangeLanguage(EntityUid ent, string language) if (!TryGetLanguageComponent(ent, out var comp)) return; - comp.SelectedLanguage = language; + comp.TrySetLanguage(language); } } diff --git a/Content.Server/SS220/Language/LanguageSystem.cs b/Content.Server/SS220/Language/LanguageSystem.cs index edf260127219..11709ffd7db0 100644 --- a/Content.Server/SS220/Language/LanguageSystem.cs +++ b/Content.Server/SS220/Language/LanguageSystem.cs @@ -53,8 +53,7 @@ private void OnRoundStart(RoundStartingEvent args) /// private void OnMapInit(Entity ent, ref MapInitEvent args) { - if (ent.Comp.SelectedLanguage == null) - ent.Comp.SelectedLanguage = ent.Comp.AvailableLanguages.FirstOrDefault(UniversalLanguage); + ent.Comp.TrySetLanguage(0); } private void OnGetLanguage(Entity ent, ref GetLanguageCompEvent args) @@ -67,11 +66,10 @@ private void OnGetLanguage(Entity ent, ref GetLanguageCompEve /// A method of encrypting the original message into a message created /// from the syllables of prototypes languages /// - public string ScrambleText(string input, LanguagePrototype proto) + public string ScrambleMessage(string message, LanguagePrototype proto) { - var saveEndWhitespace = char.IsWhiteSpace(input[^1]); - - var cacheKey = $"{proto.ID}:{input}"; + var saveEndWhitespace = char.IsWhiteSpace(message[^1]); + var cacheKey = $"{proto.ID}:{message}"; // If the original message is already there earlier encrypted, // it is taken from the cache, it is necessary for the correct display when sending in the radio, @@ -79,23 +77,26 @@ public string ScrambleText(string input, LanguagePrototype proto) if (ScrambleCache.TryGetValue(cacheKey, out var cachedValue)) return cachedValue; - var scrambledText = proto.ScrambleMethod.ScrambleMessage(input, Seed); + var scrambled = proto.ScrambleMethod.ScrambleMessage(message, Seed); - ScrambleCache[cacheKey] = scrambledText; + ScrambleCache[cacheKey] = scrambled; if (saveEndWhitespace) - scrambledText += " "; + scrambled += " "; - return scrambledText; + return scrambled; } + /// + /// Sanitize the by removing the language tags and scramble it (if necessary) for + /// public string SanitizeMessage(EntityUid source, EntityUid listener, string message, bool setColor = true) { var languageProto = GetSelectedLanguage(source); if (languageProto == null) return message; - var languageStrings = SplitStringByLanguages(source, message, languageProto); + var languageStrings = SplitMessageByLanguages(source, message, languageProto); var sanitizedMessage = new StringBuilder(); foreach (var languageString in languageStrings) { @@ -105,7 +106,7 @@ public string SanitizeMessage(EntityUid source, EntityUid listener, string messa } else { - var scrambledString = ScrambleText(message, languageString.Item2); + var scrambledString = ScrambleMessage(message, languageString.Item2); if (setColor) scrambledString = SetColor(scrambledString, languageString.Item2); @@ -116,7 +117,11 @@ public string SanitizeMessage(EntityUid source, EntityUid listener, string messa return sanitizedMessage.ToString(); } - public List<(string, LanguagePrototype)> SplitStringByLanguages(EntityUid source, string message, LanguagePrototype defaultLanguage) + /// + /// Split the message into parts by language tags. + /// will be used for the part of the message without the language tag. + /// + private List<(string, LanguagePrototype)> SplitMessageByLanguages(EntityUid source, string message, LanguagePrototype defaultLanguage) { var list = new List<(string, LanguagePrototype)>(); var p = _languageManager.KeyPrefix; @@ -172,6 +177,9 @@ public string SanitizeMessage(EntityUid source, EntityUid listener, string messa return list; } + /// + /// Tries to find the first language tag in the message and extracts it from the message + /// public bool TryGetLanguageFromString(string message, [NotNullWhen(true)] out string? messageWithoutTags, [NotNullWhen(true)] out LanguagePrototype? language) @@ -204,6 +212,9 @@ public bool CheckLanguage(EntityUid ent, LanguagePrototype? proto) return KnowsLanguages(ent, proto.ID); } + /// + /// Checks if the entity knows this language + /// public bool KnowsLanguages(EntityUid ent, string languageId) { // All ents knows universal language @@ -213,9 +224,12 @@ public bool KnowsLanguages(EntityUid ent, string languageId) if (!TryGetLanguageComponent(ent, out var comp)) return false; - return comp.AvailableLanguages.Contains(languageId); + return comp.HasLanguage(languageId); } + /// + /// Checks whether the entity knows all languages. + /// public bool KnowsAllLanguages(EntityUid uid) { return HasComp(uid); @@ -243,6 +257,10 @@ public bool KnowsAllLanguages(EntityUid uid) return proto; } + /// + /// Raises event to receive a language component. + /// This is done for the possibility of forwarding + /// public bool TryGetLanguageComponent(EntityUid uid, [NotNullWhen(true)] out LanguageComponent? component) { var ev = new GetLanguageCompEvent(); @@ -252,29 +270,6 @@ public bool TryGetLanguageComponent(EntityUid uid, [NotNullWhen(true)] out Langu return component != null; } - public void AddLanguages(EntityUid uid, List languages) - { - foreach (var language in languages) - { - AddLanguage(uid, language); - } - } - - public void AddLanguage(EntityUid uid, string languageId) - { - if (!TryGetLanguageComponent(uid, out var comp)) - return; - - if (!_languageManager.TryGetLanguageById(languageId, out var proto)) - { - Log.Error($"Doesn't found a LanguagePrototype with id: {languageId}"); - return; - } - - if (!comp.AvailableLanguages.Contains(proto)) - comp.AvailableLanguages.Add(proto); - } - /// /// Sets the color of the prototype language to the message /// @@ -288,16 +283,15 @@ public string SetColor(string message, LanguagePrototype proto) return message; } - public void AddLanguagesFromSource(EntityUid source, EntityUid target) + /// + /// Adds languages for from + /// + public void AddLanguagesFromSource(Entity ent, EntityUid target) { - if (!TryGetLanguageComponent(source, out var sourceComp)) - return; - var targetComp = EnsureComp(target); - foreach (var language in sourceComp.AvailableLanguages) + foreach (var language in ent.Comp.AvailableLanguages) { - if (!targetComp.AvailableLanguages.Contains(language)) - targetComp.AvailableLanguages.Add(language); + targetComp.TryAddLanguage(language); } } } diff --git a/Content.Server/SS220/Language/LanguagesPrototype.cs b/Content.Server/SS220/Language/LanguagesPrototype.cs index 68c0398f9fed..4e6fbe5e8fe0 100644 --- a/Content.Server/SS220/Language/LanguagesPrototype.cs +++ b/Content.Server/SS220/Language/LanguagesPrototype.cs @@ -26,6 +26,9 @@ public sealed partial class LanguagePrototype : IPrototype [DataField] public Color? Color; + /// + /// The method used to scramble the message + /// [DataField] public ScrambleMethod ScrambleMethod = new RandomSyllablesScrambleMethod(); } diff --git a/Content.Server/SS220/Language/Special/AddLanguageSpecial.cs b/Content.Server/SS220/Language/Special/AddLanguageSpecial.cs index 9b349813c47b..e0b10b954989 100644 --- a/Content.Server/SS220/Language/Special/AddLanguageSpecial.cs +++ b/Content.Server/SS220/Language/Special/AddLanguageSpecial.cs @@ -1,4 +1,6 @@ // © SS220, An EULA/CLA with a hosting restriction, full text: https://raw.githubusercontent.com/SerbiaStrong-220/space-station-14/master/CLA.txt +using Content.Server.SS220.Commands; +using Content.Server.SS220.Language.Components; using Content.Shared.Roles; using JetBrains.Annotations; @@ -12,10 +14,11 @@ public sealed partial class AddLanguageSpecial : JobSpecial [DataField] public List Languages { get; private set; } = new(); - public override void AfterEquip(EntityUid mob) + public override void AfterEquip(EntityUid uid) { var entMan = IoCManager.Resolve(); var languageSystem = entMan.System(); - languageSystem.AddLanguages(mob, Languages); + var languageComp = entMan.EnsureComponent(uid); + languageComp.AddLanguages(Languages); } } diff --git a/Content.Server/TapeRecorder/TapeRecorderSystem.cs b/Content.Server/TapeRecorder/TapeRecorderSystem.cs index 14f8fe5579ff..d40499a323b8 100644 --- a/Content.Server/TapeRecorder/TapeRecorderSystem.cs +++ b/Content.Server/TapeRecorder/TapeRecorderSystem.cs @@ -2,7 +2,6 @@ using Content.Server.Hands.Systems; using Content.Server.Speech; using Content.Server.Speech.Components; -using Content.Server.SS220.Language; // SS220-Add-Languages using Content.Server.SS220.TTS; // SS220 Tape recorder TTS using Content.Shared.Chat; using Content.Shared.Paper; @@ -25,7 +24,6 @@ public sealed class TapeRecorderSystem : SharedTapeRecorderSystem [Dependency] private readonly IPrototypeManager _proto = default!; [Dependency] private readonly PaperSystem _paper = default!; [Dependency] private readonly TTSSystem _ttsSystem = default!; // SS220 Tape recorder TTS - [Dependency] private readonly LanguageSystem _languageSystem = default!; // SS220-Add-Languages public override void Initialize() { @@ -43,7 +41,6 @@ protected override void ReplayMessagesInSegment(Entity en { var voice = EnsureComp(ent); var speech = EnsureComp(ent); - var language = _languageSystem.GetSelectedLanguage(ent); // SS220 Add languages TryComp(ent, out var tts); // SS220 Tape recorder TTS foreach (var message in tape.RecordedData) diff --git a/Content.Server/Traits/TraitSystem.cs b/Content.Server/Traits/TraitSystem.cs index 8c9866aa569d..d94cdc0da28e 100644 --- a/Content.Server/Traits/TraitSystem.cs +++ b/Content.Server/Traits/TraitSystem.cs @@ -51,8 +51,10 @@ private void OnPlayerSpawnComplete(PlayerSpawnCompleteEvent args) // SS220-Add-Languages begin if (traitPrototype.LearnedLanguage != null) { - if (TryComp(args.Mob, out var language) && !language.AvailableLanguages.Contains(traitPrototype.LearnedLanguage)) - language.AvailableLanguages.Add(traitPrototype.LearnedLanguage); + if (TryComp(args.Mob, out var language)) + { + language.TryAddLanguage(traitPrototype.LearnedLanguage); + } } // SS220-Add-Languages end diff --git a/Resources/Prototypes/SS220/Language/language.yml b/Resources/Prototypes/SS220/Language/language.yml index 5fb0373e85c1..3062e25fac11 100644 --- a/Resources/Prototypes/SS220/Language/language.yml +++ b/Resources/Prototypes/SS220/Language/language.yml @@ -4,6 +4,7 @@ - type: language id: Universal key: uni + scrambleMethod: !type:EmptyScrambleMethod # Doesn't scramble messages # Galactic common lanaguges region: - type: language From a60beabc1b85fa3016fabaeff0e624092493a581 Mon Sep 17 00:00:00 2001 From: Kirus59 <145689588+Kirus59@users.noreply.github.com> Date: Sun, 2 Mar 2025 17:38:26 +0300 Subject: [PATCH 23/48] add ui button --- Content.Client/Content.Client.csproj | 5 + Content.Client/Entry/EntryPoint.cs | 1 - .../SS220/Languages/LanguageSystem.cs | 19 +++ .../LanguageSettingsButton.cs | 38 ++++++ .../LanguageSettingsPopup.xaml | 10 ++ .../LanguageSettingsPopup.xaml.cs | 118 +++++++++++++++++ .../Chat/Controls/ChatInputBox.xaml.cs | 12 +- .../EntityEffects/Effects/MakeSentient.cs | 4 +- Content.Server/Entry/EntryPoint.cs | 3 - Content.Server/IoC/ServerContentIoC.cs | 2 - Content.Server/PAI/PAISystem.cs | 6 +- .../Radio/EntitySystems/HeadsetSystem.cs | 4 +- .../Radio/EntitySystems/RadioSystem.cs | 3 +- .../SS220/Commands/LanguageCommands.cs | 15 ++- .../Language/Components/LanguageComponent.cs | 121 ------------------ .../SS220/Language/LanguageSystem.Verbs.cs | 87 ------------- .../SS220/Language/LanguageSystem.cs | 100 ++++++++------- .../Language/Special/AddLanguageSpecial.cs | 4 +- Content.Server/Traits/TraitSystem.cs | 9 +- .../Zombies/ZombieSystem.Transform.cs | 2 +- Content.Shared/Entry/EntryPoint.cs | 2 + Content.Shared/IoC/SharedContentIoC.cs | 4 +- .../Language/Components/LanguageComponent.cs | 29 +++++ .../EncryptionMethods/BaseEncryptionMethod.cs | 2 +- .../EncryptionMethods/EmptyScrambleMethod.cs | 2 +- .../RandomSyllablesMethod.cs | 4 +- .../SS220/Language/LanguageManager.cs | 16 ++- .../SS220/Language/LanguageNetMessages.cs | 26 ++++ .../SS220/Language/LanguagesPrototype.cs | 8 +- .../Language/Systems/SharedLanguageSystem.cs | 101 +++++++++++++++ .../ru-RU/ss220/language/language-ui.ftl | 2 + .../SS220/Interface/Nano/language_icon.png | Bin 0 -> 297 bytes 32 files changed, 464 insertions(+), 295 deletions(-) create mode 100644 Content.Client/SS220/Languages/LanguageSystem.cs create mode 100644 Content.Client/SS220/UserInterface/System/Chat/Controls/LanguageSettings/LanguageSettingsButton.cs create mode 100644 Content.Client/SS220/UserInterface/System/Chat/Controls/LanguageSettings/LanguageSettingsPopup.xaml create mode 100644 Content.Client/SS220/UserInterface/System/Chat/Controls/LanguageSettings/LanguageSettingsPopup.xaml.cs delete mode 100644 Content.Server/SS220/Language/Components/LanguageComponent.cs delete mode 100644 Content.Server/SS220/Language/LanguageSystem.Verbs.cs create mode 100644 Content.Shared/SS220/Language/Components/LanguageComponent.cs rename {Content.Server => Content.Shared}/SS220/Language/EncryptionMethods/BaseEncryptionMethod.cs (89%) rename {Content.Server => Content.Shared}/SS220/Language/EncryptionMethods/EmptyScrambleMethod.cs (88%) rename {Content.Server => Content.Shared}/SS220/Language/EncryptionMethods/RandomSyllablesMethod.cs (97%) rename {Content.Server => Content.Shared}/SS220/Language/LanguageManager.cs (68%) create mode 100644 Content.Shared/SS220/Language/LanguageNetMessages.cs rename {Content.Server => Content.Shared}/SS220/Language/LanguagesPrototype.cs (81%) create mode 100644 Content.Shared/SS220/Language/Systems/SharedLanguageSystem.cs create mode 100644 Resources/Locale/ru-RU/ss220/language/language-ui.ftl create mode 100644 Resources/Textures/SS220/Interface/Nano/language_icon.png diff --git a/Content.Client/Content.Client.csproj b/Content.Client/Content.Client.csproj index 43fd8df2e19a..19901e24e588 100644 --- a/Content.Client/Content.Client.csproj +++ b/Content.Client/Content.Client.csproj @@ -25,4 +25,9 @@ + + + MSBuild:Compile + + diff --git a/Content.Client/Entry/EntryPoint.cs b/Content.Client/Entry/EntryPoint.cs index d0e207d0f494..acb98563b913 100644 --- a/Content.Client/Entry/EntryPoint.cs +++ b/Content.Client/Entry/EntryPoint.cs @@ -133,7 +133,6 @@ public override void Init() _prototypeManager.RegisterIgnore("nukeopsRole"); _prototypeManager.RegisterIgnore("stationGoal"); // Corvax-StationGoal _prototypeManager.RegisterIgnore("ghostRoleRaffleDecider"); - _prototypeManager.RegisterIgnore("language"); // SS220 languages _componentFactory.GenerateNetIds(); _adminManager.Initialize(); diff --git a/Content.Client/SS220/Languages/LanguageSystem.cs b/Content.Client/SS220/Languages/LanguageSystem.cs new file mode 100644 index 000000000000..2768b68d16b7 --- /dev/null +++ b/Content.Client/SS220/Languages/LanguageSystem.cs @@ -0,0 +1,19 @@ +// © 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.SS220.Language; +using Content.Shared.SS220.Language.Systems; +using Robust.Shared.Network; + +namespace Content.Client.SS220.Languages; + +public sealed partial class LanguageSystem : SharedLanguageSystem +{ + [Dependency] private readonly INetManager _net = default!; + + public override void Initialize() + { + base.Initialize(); + + _net.RegisterNetMessage(); + } +} + diff --git a/Content.Client/SS220/UserInterface/System/Chat/Controls/LanguageSettings/LanguageSettingsButton.cs b/Content.Client/SS220/UserInterface/System/Chat/Controls/LanguageSettings/LanguageSettingsButton.cs new file mode 100644 index 000000000000..f6c4b3ef7045 --- /dev/null +++ b/Content.Client/SS220/UserInterface/System/Chat/Controls/LanguageSettings/LanguageSettingsButton.cs @@ -0,0 +1,38 @@ +// © SS220, An EULA/CLA with a hosting restriction, full text: https://raw.githubusercontent.com/SerbiaStrong-220/space-station-14/master/CLA.txt +using Content.Client.Resources; +using Content.Client.UserInterface.Systems.Chat.Controls; +using Robust.Client.Player; +using Robust.Client.ResourceManagement; +using Robust.Client.UserInterface.Controls; +using System.Numerics; + +namespace Content.Client.SS220.UserInterface.System.Chat.Controls.LanguageSettings; + +public sealed class LanguageSettingsButton : ChatPopupButton +{ + public LanguageSettingsButton() + { + IoCManager.InjectDependencies(this); + + var texture = IoCManager.Resolve() + .GetTexture("/Textures/SS220/Interface/Nano/language_icon.png"); + + AddChild(new TextureRect + { + Texture = texture, + HorizontalAlignment = HAlignment.Center, + VerticalAlignment = VAlignment.Center, + }); + + OnPressed += _ => Popup.Update(); + } + + protected override UIBox2 GetPopupPosition() + { + var globalPos = GlobalPosition; + var (minX, minY) = Popup.MinSize; + return UIBox2.FromDimensions( + globalPos, + new Vector2(Math.Max(minX, Popup.MinWidth), minY)); + } +} diff --git a/Content.Client/SS220/UserInterface/System/Chat/Controls/LanguageSettings/LanguageSettingsPopup.xaml b/Content.Client/SS220/UserInterface/System/Chat/Controls/LanguageSettings/LanguageSettingsPopup.xaml new file mode 100644 index 000000000000..5567f8dfc313 --- /dev/null +++ b/Content.Client/SS220/UserInterface/System/Chat/Controls/LanguageSettings/LanguageSettingsPopup.xaml @@ -0,0 +1,10 @@ + + + + + diff --git a/Content.Client/SS220/UserInterface/System/Chat/Controls/LanguageSettings/LanguageSettingsPopup.xaml.cs b/Content.Client/SS220/UserInterface/System/Chat/Controls/LanguageSettings/LanguageSettingsPopup.xaml.cs new file mode 100644 index 000000000000..770d6f68d621 --- /dev/null +++ b/Content.Client/SS220/UserInterface/System/Chat/Controls/LanguageSettings/LanguageSettingsPopup.xaml.cs @@ -0,0 +1,118 @@ +// © 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.SS220.Language; +using Content.Shared.SS220.Language.Components; +using Robust.Client.AutoGenerated; +using Robust.Client.Player; +using Robust.Client.UserInterface.Controls; +using Robust.Client.UserInterface.CustomControls; +using Robust.Client.UserInterface.XAML; +using Robust.Shared.Network; +using Robust.Shared.Utility; + +namespace Content.Client.SS220.UserInterface.System.Chat.Controls.LanguageSettings; + +[GenerateTypedNameReferences] +public sealed partial class LanguageSettingsPopup : Popup +{ + [Dependency] private readonly IEntityManager _entityManager = default!; + [Dependency] private readonly INetManager _net = default!; + [Dependency] private readonly IPlayerManager _player = default!; + [Dependency] private readonly LanguageManager _language = default!; + + private Dictionary _buttonsDict = new(); + private Button? _selectedLanguage; + + public LanguageSettingsPopup() + { + IoCManager.InjectDependencies(this); + RobustXamlLoader.Load(this); + Update(); + } + + public void Update() + { + var uid = _player.LocalEntity; + if (uid == null || + !_entityManager.TryGetComponent(uid, out var comp)) + { + UpdateLanguageContainer(null); + UpdateSelectedLanguage(null); + return; + } + + var availableLanguages = new List(); + foreach (var id in comp.AvailableLanguages) + { + if (!_language.TryGetLanguageById(id, out var language)) + continue; + + availableLanguages.Add(language); + } + UpdateLanguageContainer(availableLanguages); + + _language.TryGetLanguageById(comp.SelectedLanguage, out var selectedLanguage); + UpdateSelectedLanguage(selectedLanguage); + } + + private void UpdateLanguageContainer(List? availableLanguages) + { + LanguageContainer.DisposeAllChildren(); + _buttonsDict.Clear(); + + if (availableLanguages == null || + availableLanguages.Count <= 0) + { + LanguageLabel.Text = Loc.GetString("language-settings-ui-no-languages"); + return; + } + + LanguageLabel.Text = Loc.GetString("language-settings-ui-select-default"); + foreach (var language in availableLanguages) + { + var name = $"{_language.KeyPrefix}{language.Key} {Loc.GetString(language.Name)}"; + var button = new Button() { Text = name }; + + if (language.Description is { } desc) + { + var tooltip = new Tooltip(); + tooltip.SetMessage(FormattedMessage.FromMarkupPermissive(Loc.GetString(language.Description))); + button.TooltipSupplier = _ => tooltip; + } + + _buttonsDict.Add(language, button); + button.OnPressed += _ => + { + UpdateSelectedLanguage(language); + var msg = new ClientSelectlanguageMessage + { + LanguageId = language.ID + }; + _net.ClientSendMessage(msg); + }; + LanguageContainer.AddChild(button); + } + } + + private void UpdateSelectedLanguage(LanguagePrototype? language) + { + if (language == null) + { + if (_selectedLanguage != null) + _selectedLanguage.Disabled = false; + + _selectedLanguage = null; + return; + } + + if (_buttonsDict.TryGetValue(language, out var button)) + { + if (_selectedLanguage != null) + _selectedLanguage.Disabled = false; + + button.Disabled = true; + _selectedLanguage = button; + } + } +} + + diff --git a/Content.Client/UserInterface/Systems/Chat/Controls/ChatInputBox.xaml.cs b/Content.Client/UserInterface/Systems/Chat/Controls/ChatInputBox.xaml.cs index 84bce10c93c4..aa664c823350 100644 --- a/Content.Client/UserInterface/Systems/Chat/Controls/ChatInputBox.xaml.cs +++ b/Content.Client/UserInterface/Systems/Chat/Controls/ChatInputBox.xaml.cs @@ -1,8 +1,9 @@ -using Content.Client.Stylesheets; +using Content.Client.Stylesheets; using Content.Client.SS220.UserInterface.System.Chat.Controls; using Content.Shared.Chat; using Content.Shared.Input; using Robust.Client.UserInterface.Controls; +using Content.Client.SS220.UserInterface.System.Chat.Controls.LanguageSettings; namespace Content.Client.UserInterface.Systems.Chat.Controls; @@ -13,6 +14,7 @@ public class ChatInputBox : PanelContainer public readonly HistoryLineEdit Input; public readonly ChannelFilterButton FilterButton; public readonly HighlightButton HighlightButton; //ss220 highlight words + public readonly LanguageSettingsButton LanguageSettings; protected readonly BoxContainer Container; protected ChatChannel ActiveChannel { get; private set; } = ChatChannel.Local; @@ -53,8 +55,16 @@ public ChatInputBox() StyleClasses = {"chatFilterOptionButton"} }; //ss220 highlight words end + // SS220 languages begin + LanguageSettings = new LanguageSettingsButton() + { + Name = "LanguageSettings", + StyleClasses = { "chatFilterOptionButton" } + }; + // SS220 languages end Container.AddChild(FilterButton); Container.AddChild(HighlightButton); //ss220 highlight words + Container.AddChild(LanguageSettings); // SS220 languages AddStyleClass(StyleNano.StyleClassChatSubPanel); ChannelSelector.OnChannelSelect += UpdateActiveChannel; } diff --git a/Content.Server/EntityEffects/Effects/MakeSentient.cs b/Content.Server/EntityEffects/Effects/MakeSentient.cs index 86a3598585b4..ea1730f195c1 100644 --- a/Content.Server/EntityEffects/Effects/MakeSentient.cs +++ b/Content.Server/EntityEffects/Effects/MakeSentient.cs @@ -1,9 +1,9 @@ using Content.Server.Ghost.Roles.Components; using Content.Server.Speech.Components; using Content.Server.SS220.Language; -using Content.Server.SS220.Language.Components; using Content.Shared.EntityEffects; using Content.Shared.Mind.Components; +using Content.Shared.SS220.Language.Components; using Robust.Shared.Prototypes; namespace Content.Server.EntityEffects.Effects; @@ -28,7 +28,7 @@ public override void Effect(EntityEffectBaseArgs args) var languageComp = entityManager.EnsureComponent(uid); var languageSystem = entityManager.System(); - languageComp.TryAddLanguage(languageSystem.GalacticLanguage); + languageSystem.AddLanguage((uid, languageComp), languageSystem.GalacticLanguage); // SS220-Add-Languages end // Stops from adding a ghost role to things like people who already have a mind diff --git a/Content.Server/Entry/EntryPoint.cs b/Content.Server/Entry/EntryPoint.cs index e5b7f11103c0..b5153bc1f31d 100644 --- a/Content.Server/Entry/EntryPoint.cs +++ b/Content.Server/Entry/EntryPoint.cs @@ -39,7 +39,6 @@ using Robust.Shared.Timing; using Robust.Shared.Utility; using Content.Server.SS220.BackEndApi; -using Content.Server.SS220.Language; namespace Content.Server.Entry { @@ -169,8 +168,6 @@ public override void PostInit() IoCManager.Resolve().Initialize(); IoCManager.Resolve().PostInit(); IoCManager.Resolve().Initialize(); - - IoCManager.Resolve().Initialize(); // SS220 Languages } } diff --git a/Content.Server/IoC/ServerContentIoC.cs b/Content.Server/IoC/ServerContentIoC.cs index 6b3b70df4975..e64719fcc355 100644 --- a/Content.Server/IoC/ServerContentIoC.cs +++ b/Content.Server/IoC/ServerContentIoC.cs @@ -35,7 +35,6 @@ using Content.Shared.Kitchen; using Content.Shared.Players.PlayTimeTracking; using Content.Shared.Players.RateLimiting; -using Content.Server.SS220.Language; namespace Content.Server.IoC { @@ -90,7 +89,6 @@ public static void Register() IoCManager.Register(); IoCManager.Register(); IoCManager.Register(); - IoCManager.Register(); // SS220 Languages } } } diff --git a/Content.Server/PAI/PAISystem.cs b/Content.Server/PAI/PAISystem.cs index f5d976672c7e..8b2b5b142ae1 100644 --- a/Content.Server/PAI/PAISystem.cs +++ b/Content.Server/PAI/PAISystem.cs @@ -10,7 +10,7 @@ using System.Text; using Robust.Shared.Player; using Content.Server.SS220.Language; -using Content.Server.SS220.Language.Components; // SS220-Add-Languages +using Content.Shared.SS220.Language.Components; // SS220-Add-Languages namespace Content.Server.PAI; @@ -128,8 +128,8 @@ public void PAITurningOff(EntityUid uid) // SS220-Add-Languages begin if (TryComp(uid, out var languageComp)) { - languageComp.ClearLanguages(); - languageComp.AddLanguages([_language.UniversalLanguage, _language.GalacticLanguage]); + _language.ClearLanguages((uid, languageComp)); + _language.AddLanguages((uid, languageComp), [_language.UniversalLanguage, _language.GalacticLanguage]); } // SS220-Add-Languages end } diff --git a/Content.Server/Radio/EntitySystems/HeadsetSystem.cs b/Content.Server/Radio/EntitySystems/HeadsetSystem.cs index 9a16bc41801c..7415c8cf389f 100644 --- a/Content.Server/Radio/EntitySystems/HeadsetSystem.cs +++ b/Content.Server/Radio/EntitySystems/HeadsetSystem.cs @@ -22,7 +22,7 @@ public override void Initialize() base.Initialize(); SubscribeLocalEvent(OnHeadsetReceive); SubscribeLocalEvent(OnKeysChanged); - SubscribeLocalEvent(OnGetLanguage); // SS220 languages + SubscribeLocalEvent(OnGetLanguage); // SS220 languages SubscribeLocalEvent(OnSpeak); @@ -125,7 +125,7 @@ private void OnEmpPulse(EntityUid uid, HeadsetComponent component, ref EmpPulseE } // SS220 languages begin - private void OnGetLanguage(Entity ent, ref GetLanguageCompEvent args) + private void OnGetLanguage(Entity ent, ref GetLanguageListenerEvent args) { var actorUid = Transform(ent).ParentUid; if (HasComp(actorUid)) diff --git a/Content.Server/Radio/EntitySystems/RadioSystem.cs b/Content.Server/Radio/EntitySystems/RadioSystem.cs index 05d0c92f25b9..78195eb030d9 100644 --- a/Content.Server/Radio/EntitySystems/RadioSystem.cs +++ b/Content.Server/Radio/EntitySystems/RadioSystem.cs @@ -173,7 +173,8 @@ public void SendRadioMessage(EntityUid messageSource, string message, RadioChann continue; // SS220 languages begin - if (TryGetScrambledChatMessage(messageSource, receiver, message, out var scrambledChatMsg)) + if (_languageSystem.TryGetLanguageListener(receiver, out var listener) && + TryGetScrambledChatMessage(messageSource, listener.Value, message, out var scrambledChatMsg)) { var scrabledEv = new RadioReceiveEvent(message, messageSource, channel, radioSource, scrambledChatMsg, new()); RaiseLocalEvent(receiver, ref scrabledEv); diff --git a/Content.Server/SS220/Commands/LanguageCommands.cs b/Content.Server/SS220/Commands/LanguageCommands.cs index c6d60d1bc019..dbdf59cbe0f7 100644 --- a/Content.Server/SS220/Commands/LanguageCommands.cs +++ b/Content.Server/SS220/Commands/LanguageCommands.cs @@ -1,7 +1,9 @@ +// © SS220, An EULA/CLA with a hosting restriction, full text: https://raw.githubusercontent.com/SerbiaStrong-220/space-station-14/master/CLA.txt using Content.Server.Administration; using Content.Server.SS220.Language; -using Content.Server.SS220.Language.Components; using Content.Shared.Administration; +using Content.Shared.SS220.Language; +using Content.Shared.SS220.Language.Components; using Robust.Shared.Console; namespace Content.Server.SS220.Commands; @@ -32,7 +34,7 @@ public void Execute(IConsoleShell shell, string argStr, string[] args) var languageId = args[1]; - if (_languageManager.TryGetLanguageById(languageId, out _)) + if (!_languageManager.TryGetLanguageById(languageId, out _)) { shell.WriteError(Loc.GetString("cmd-language-proto-miss")); return; @@ -44,7 +46,8 @@ public void Execute(IConsoleShell shell, string argStr, string[] args) return; } - if (languageComp.TryAddLanguage(languageId)) + var languageSystem = _entities.System(); + if (languageSystem.AddLanguage((entityId, languageComp), languageId)) { shell.WriteLine(Loc.GetString("cmd-language-success-add")); } @@ -86,7 +89,8 @@ public void Execute(IConsoleShell shell, string argStr, string[] args) return; } - if (languageComp.RemoveLanguage(languageId)) + var languageSystem = _entities.System(); + if (languageSystem.RemoveLanguage((entityId, languageComp), languageId)) { shell.WriteLine(Loc.GetString("cmd-language-succes-remove")); } @@ -126,7 +130,8 @@ public void Execute(IConsoleShell shell, string argStr, string[] args) return; } - languageComp.ClearLanguages(); + var languageSystem = _entities.System(); + languageSystem.ClearLanguages((entityId, languageComp)); shell.WriteLine(Loc.GetString("cmd-language-clear")); } } diff --git a/Content.Server/SS220/Language/Components/LanguageComponent.cs b/Content.Server/SS220/Language/Components/LanguageComponent.cs deleted file mode 100644 index 55cc314be512..000000000000 --- a/Content.Server/SS220/Language/Components/LanguageComponent.cs +++ /dev/null @@ -1,121 +0,0 @@ -// © SS220, An EULA/CLA with a hosting restriction, full text: https://raw.githubusercontent.com/SerbiaStrong-220/space-station-14/master/CLA.txt -using Robust.Shared.Prototypes; -using System.Linq; - -namespace Content.Server.SS220.Language.Components; - -/// -/// A component that allows an entity to speak and understand languages. -/// Language prototypes are taken from YML of -/// The absence of this component gives the entity “Universal” language -/// -[RegisterComponent] -public sealed partial class LanguageComponent : Component -{ - /// - /// Selected language in which the entity will speak. - /// - [DataField] - public ProtoId? SelectedLanguage { get; private set; } - - /// - /// List of languages that the Entity speaks and understands. - /// - [DataField, Access(Other = AccessPermissions.Read)] - public List> AvailableLanguages { get; private set; } = new(); - - #region Utilites - /// - /// Adds languages from - /// - public void AddLanguages(List languages) - { - foreach (var language in languages) - { - TryAddLanguage(language); - } - } - - /// - /// Adds language to the - /// - /// if successful added - public bool TryAddLanguage(string languageId) - { - var languageManager = IoCManager.Resolve(); - if (!languageManager.TryGetLanguageById(languageId, out _) || - AvailableLanguages.Contains(languageId)) - return false; - - AvailableLanguages.Add(languageId); - SelectedLanguage ??= AvailableLanguages[0]; - return true; - } - - /// - /// Clears - /// - public void ClearLanguages() - { - AvailableLanguages.Clear(); - SelectedLanguage = null; - } - - /// - /// Removes language from - /// - /// if successful removed - public bool RemoveLanguage(string languageId) - { - if (AvailableLanguages.Remove(languageId)) - { - if (SelectedLanguage == languageId) - { - if (AvailableLanguages.Count > 0) - SelectedLanguage = AvailableLanguages.First(); - else - SelectedLanguage = null; - } - - return true; - } - - return false; - } - - /// - /// Checks if contains this - /// - /// - public bool HasLanguage(string languageId) - { - return AvailableLanguages.Contains(languageId); - } - - /// - /// Tries set by of - /// - /// - public bool TrySetLanguage(int index) - { - if (AvailableLanguages.Count < index - 1) - return false; - - SelectedLanguage = AvailableLanguages[index]; - return true; - } - - /// - /// Tries set by language id. - /// Doesn't set language if doesn't contain this - /// - public bool TrySetLanguage(string languageId) - { - if (!HasLanguage(languageId)) - return false; - - SelectedLanguage = languageId; - return true; - } - #endregion -} diff --git a/Content.Server/SS220/Language/LanguageSystem.Verbs.cs b/Content.Server/SS220/Language/LanguageSystem.Verbs.cs deleted file mode 100644 index e36ae47af7ea..000000000000 --- a/Content.Server/SS220/Language/LanguageSystem.Verbs.cs +++ /dev/null @@ -1,87 +0,0 @@ -// © SS220, An EULA/CLA with a hosting restriction, full text: https://raw.githubusercontent.com/SerbiaStrong-220/space-station-14/master/CLA.txt -using Content.Server.SS220.Language.Components; -using Content.Shared.Verbs; -using System.Linq; - -namespace Content.Server.SS220.Language; - -/// -/// I was bored and lazy to understand the UI, -/// according to this language is selected with Verb at the entity -/// -// TODO: Make the language selection in the UI instead of this crap -public sealed partial class LanguageSystem : EntitySystem -{ - private void OnVerb(EntityUid ent, LanguageComponent comp, ref GetVerbsEvent args) - { - if (args.User != args.Target) - return; - - if (!args.CanAccess) - return; - - var learnedLanguages = comp.AvailableLanguages.Select(lang => lang.ToString()).ToList(); - var verbs = CreateVerbs(ent, learnedLanguages); - foreach (var verb in verbs) - { - args.Verbs.Add(verb); - } - } - - private List CreateVerbs(EntityUid ent, List languages) - { - var verbs = new List(); - - if (!TryGetLanguageComponent(ent, out var comp)) - return verbs; - - foreach (var language in languages) - { - if (language == UniversalLanguage) // no verb for a universal language is created - continue; - - verbs.Add(new Verb - { - Text = GetName(language), - Message = GetDescription(language), - Category = VerbCategory.Languages, - Disabled = language == comp.SelectedLanguage, - Act = () => ChangeLanguage(ent, language) - }); - } - - return verbs; - } - - public string GetName(string language) - { - if (!_languageManager.TryGetLanguageById(language, out var proto)) - return language; - - if (proto.Name == null) - return language; - - var name = Loc.GetString(proto.Name); - return name; - } - - public string? GetDescription(string language) - { - if (!_languageManager.TryGetLanguageById(language, out var proto)) - return null; - - if (proto.Description == null) - return null; - - var desc = Loc.GetString(proto.Description); - return desc; - } - - private void ChangeLanguage(EntityUid ent, string language) - { - if (!TryGetLanguageComponent(ent, out var comp)) - return; - - comp.TrySetLanguage(language); - } -} diff --git a/Content.Server/SS220/Language/LanguageSystem.cs b/Content.Server/SS220/Language/LanguageSystem.cs index 11709ffd7db0..1828731160a0 100644 --- a/Content.Server/SS220/Language/LanguageSystem.cs +++ b/Content.Server/SS220/Language/LanguageSystem.cs @@ -1,20 +1,24 @@ // © SS220, An EULA/CLA with a hosting restriction, full text: https://raw.githubusercontent.com/SerbiaStrong-220/space-station-14/master/CLA.txt using Content.Server.GameTicking.Events; -using Content.Server.SS220.Language.Components; +using Content.Shared.SS220.Language.Components; using Content.Shared.Ghost; -using Content.Shared.Verbs; +using Content.Shared.SS220.Language; +using Robust.Server.Player; using Robust.Shared.Random; using System.Diagnostics.CodeAnalysis; -using System.Linq; using System.Text; using System.Text.RegularExpressions; +using Content.Shared.SS220.Language.Systems; +using Robust.Shared.Network; namespace Content.Server.SS220.Language; -public sealed partial class LanguageSystem : EntitySystem +public sealed partial class LanguageSystem : SharedLanguageSystem { [Dependency] private readonly IRobustRandom _random = default!; - [Dependency] private readonly LanguageManager _languageManager = default!; + [Dependency] private readonly LanguageManager _language = default!; + [Dependency] private readonly IPlayerManager _player = default!; + [Dependency] private readonly INetManager _net = default!; public readonly string UniversalLanguage = "Universal"; public readonly string GalacticLanguage = "Galactic"; @@ -27,12 +31,13 @@ public sealed partial class LanguageSystem : EntitySystem public override void Initialize() { base.Initialize(); + SubscribeLocalEvent(OnRoundStart); SubscribeLocalEvent(OnMapInit); - SubscribeLocalEvent(OnGetLanguage); + SubscribeLocalEvent(OnGetLanguage); - // Verbs - SubscribeLocalEvent>(OnVerb); + // UI + _net.RegisterNetMessage(OnClientSelectLanguage); } public override void Update(float frameTime) @@ -53,15 +58,29 @@ private void OnRoundStart(RoundStartingEvent args) /// private void OnMapInit(Entity ent, ref MapInitEvent args) { - ent.Comp.TrySetLanguage(0); + TrySetLanguage(ent, 0); } - private void OnGetLanguage(Entity ent, ref GetLanguageCompEvent args) + private void OnGetLanguage(Entity ent, ref GetLanguageListenerEvent args) { - args.Component = ent.Comp; + args.Listener = ent; args.Handled = true; } + #region Client + private void OnClientSelectLanguage(ClientSelectlanguageMessage msg) + { + if (!_player.TryGetSessionByChannel(msg.MsgChannel, out var player)) + return; + + var entity = player.AttachedEntity; + if (entity == null || !TryComp(entity, out var comp)) + return; + + TrySetLanguage((entity.Value, comp), msg.LanguageId); + } + #endregion + /// /// A method of encrypting the original message into a message created /// from the syllables of prototypes languages @@ -100,7 +119,7 @@ public string SanitizeMessage(EntityUid source, EntityUid listener, string messa var sanitizedMessage = new StringBuilder(); foreach (var languageString in languageStrings) { - if (CheckLanguage(listener, languageString.Item2)) + if (CheckLanguage(listener, languageString.Item2.ID)) { sanitizedMessage.Append(languageString.Item1); } @@ -124,7 +143,7 @@ public string SanitizeMessage(EntityUid source, EntityUid listener, string messa private List<(string, LanguagePrototype)> SplitMessageByLanguages(EntityUid source, string message, LanguagePrototype defaultLanguage) { var list = new List<(string, LanguagePrototype)>(); - var p = _languageManager.KeyPrefix; + var p = _language.KeyPrefix; var textWithKeyPattern = $@"^{p}(.*?)\s(?={p}\w+\s)|(?<=\s){p}(.*?)\s(?={p}\w+\s)|(?<=\s){p}(.*)|^{p}(.*)"; // pizdec var matches = Regex.Matches(message, textWithKeyPattern); @@ -142,7 +161,7 @@ public string SanitizeMessage(EntityUid source, EntityUid listener, string messa foreach (Match m in matches) { if (!TryGetLanguageFromString(m.Value, out var messageWithoutTags, out var language) || - !CheckLanguage(source, language)) + !CheckLanguage(source, language.ID)) { if (buffer.Item2 == null) { @@ -187,10 +206,10 @@ public bool TryGetLanguageFromString(string message, messageWithoutTags = null; language = null; - var keyPatern = $@"{_languageManager.KeyPrefix}\w+\s+"; + var keyPatern = $@"{_language.KeyPrefix}\w+\s+"; var m = Regex.Match(message, keyPatern); - if (m == null || !_languageManager.TryGetLanguageByKey(m.Value.Trim(), out language)) + if (m == null || !_language.TryGetLanguageByKey(m.Value.Trim(), out language)) return false; messageWithoutTags = Regex.Replace(message, keyPatern, string.Empty); @@ -201,30 +220,17 @@ public bool TryGetLanguageFromString(string message, /// Method that checks an entity for the presence of a prototype language /// or for the presence of a universal language /// - public bool CheckLanguage(EntityUid ent, LanguagePrototype? proto) - { - if (proto == null) - return false; - - if (KnowsAllLanguages(ent)) - return true; - - return KnowsLanguages(ent, proto.ID); - } - - /// - /// Checks if the entity knows this language - /// - public bool KnowsLanguages(EntityUid ent, string languageId) + public bool CheckLanguage(EntityUid uid, string? languageId) { - // All ents knows universal language - if (languageId == UniversalLanguage) + if (KnowsAllLanguages(uid) || + languageId == UniversalLanguage) return true; - if (!TryGetLanguageComponent(ent, out var comp)) + if (languageId == null || + !TryComp(uid, out var comp)) return false; - return comp.HasLanguage(languageId); + return HasLanguage((uid, comp), languageId); } /// @@ -239,11 +245,11 @@ public bool KnowsAllLanguages(EntityUid uid) /// A method to get a prototype language from an entity. /// If the entity does not have a language component, a universal language is assigned. /// - public LanguagePrototype? GetSelectedLanguage(EntityUid ent) + public LanguagePrototype? GetSelectedLanguage(EntityUid uid) { - if (!TryGetLanguageComponent(ent, out var comp)) + if (!TryComp(uid, out var comp)) { - if (_languageManager.TryGetLanguageById(UniversalLanguage, out var universalProto)) + if (_language.TryGetLanguageById(UniversalLanguage, out var universalProto)) return universalProto; return null; @@ -253,21 +259,21 @@ public bool KnowsAllLanguages(EntityUid uid) if (languageID == null) return null; - _languageManager.TryGetLanguageById(languageID, out var proto); + _language.TryGetLanguageById(languageID, out var proto); return proto; } /// - /// Raises event to receive a language component. + /// Raises event to receive the listener entity. /// This is done for the possibility of forwarding /// - public bool TryGetLanguageComponent(EntityUid uid, [NotNullWhen(true)] out LanguageComponent? component) + public bool TryGetLanguageListener(EntityUid uid, [NotNullWhen(true)] out Entity? listener) { - var ev = new GetLanguageCompEvent(); + var ev = new GetLanguageListenerEvent(); RaiseLocalEvent(uid, ref ev); - component = ev.Component; + listener = ev.Listener; - return component != null; + return listener != null; } /// @@ -291,14 +297,14 @@ public void AddLanguagesFromSource(Entity ent, EntityUid targ var targetComp = EnsureComp(target); foreach (var language in ent.Comp.AvailableLanguages) { - targetComp.TryAddLanguage(language); + AddLanguage((target, targetComp), language); } } } [ByRefEvent] -public sealed class GetLanguageCompEvent() : HandledEntityEventArgs +public sealed class GetLanguageListenerEvent() : HandledEntityEventArgs { - public LanguageComponent? Component = null; + public Entity? Listener = null; } diff --git a/Content.Server/SS220/Language/Special/AddLanguageSpecial.cs b/Content.Server/SS220/Language/Special/AddLanguageSpecial.cs index e0b10b954989..b5dad4000c34 100644 --- a/Content.Server/SS220/Language/Special/AddLanguageSpecial.cs +++ b/Content.Server/SS220/Language/Special/AddLanguageSpecial.cs @@ -1,7 +1,7 @@ // © SS220, An EULA/CLA with a hosting restriction, full text: https://raw.githubusercontent.com/SerbiaStrong-220/space-station-14/master/CLA.txt using Content.Server.SS220.Commands; -using Content.Server.SS220.Language.Components; using Content.Shared.Roles; +using Content.Shared.SS220.Language.Components; using JetBrains.Annotations; namespace Content.Server.SS220.Language.Special; @@ -19,6 +19,6 @@ public override void AfterEquip(EntityUid uid) var entMan = IoCManager.Resolve(); var languageSystem = entMan.System(); var languageComp = entMan.EnsureComponent(uid); - languageComp.AddLanguages(Languages); + languageSystem.AddLanguages((uid, languageComp), Languages); } } diff --git a/Content.Server/Traits/TraitSystem.cs b/Content.Server/Traits/TraitSystem.cs index d94cdc0da28e..f84c23af7d85 100644 --- a/Content.Server/Traits/TraitSystem.cs +++ b/Content.Server/Traits/TraitSystem.cs @@ -6,7 +6,7 @@ using Content.Shared.Whitelist; using Robust.Shared.Prototypes; using Content.Server.SS220.Language; -using Content.Server.SS220.Language.Components; +using Content.Shared.SS220.Language.Components; namespace Content.Server.Traits; @@ -15,6 +15,7 @@ public sealed class TraitSystem : EntitySystem [Dependency] private readonly IPrototypeManager _prototypeManager = default!; [Dependency] private readonly SharedHandsSystem _sharedHandsSystem = default!; [Dependency] private readonly EntityWhitelistSystem _whitelistSystem = default!; + [Dependency] private readonly LanguageSystem _language = default!; public override void Initialize() { @@ -51,10 +52,8 @@ private void OnPlayerSpawnComplete(PlayerSpawnCompleteEvent args) // SS220-Add-Languages begin if (traitPrototype.LearnedLanguage != null) { - if (TryComp(args.Mob, out var language)) - { - language.TryAddLanguage(traitPrototype.LearnedLanguage); - } + var language = EnsureComp(args.Mob); + _language.AddLanguage((args.Mob, language), traitPrototype.LearnedLanguage); } // SS220-Add-Languages end diff --git a/Content.Server/Zombies/ZombieSystem.Transform.cs b/Content.Server/Zombies/ZombieSystem.Transform.cs index 9c152cf1a247..4fd220d1b503 100644 --- a/Content.Server/Zombies/ZombieSystem.Transform.cs +++ b/Content.Server/Zombies/ZombieSystem.Transform.cs @@ -41,7 +41,7 @@ using Robust.Server.Player; using Content.Shared.Ghost.Roles.Components; using Content.Server.SS220.Language; -using Content.Server.SS220.Language.Components; // SS220-Add-Languages +using Content.Shared.SS220.Language.Components; namespace Content.Server.Zombies; diff --git a/Content.Shared/Entry/EntryPoint.cs b/Content.Shared/Entry/EntryPoint.cs index df267b08cb11..761558dd737a 100644 --- a/Content.Shared/Entry/EntryPoint.cs +++ b/Content.Shared/Entry/EntryPoint.cs @@ -4,6 +4,7 @@ using Content.Shared.Humanoid.Markings; using Content.Shared.IoC; using Content.Shared.Maps; +using Content.Shared.SS220.Language; using Robust.Shared; using Robust.Shared.Configuration; using Robust.Shared.ContentPack; @@ -46,6 +47,7 @@ public override void PostInit() InitTileDefinitions(); IoCManager.Resolve().Initialize(); + IoCManager.Resolve().Initialize(); // SS220 languages #if DEBUG var configMan = IoCManager.Resolve(); diff --git a/Content.Shared/IoC/SharedContentIoC.cs b/Content.Shared/IoC/SharedContentIoC.cs index c20cdbc111e3..2bf0267df082 100644 --- a/Content.Shared/IoC/SharedContentIoC.cs +++ b/Content.Shared/IoC/SharedContentIoC.cs @@ -1,5 +1,6 @@ -using Content.Shared.Humanoid.Markings; +using Content.Shared.Humanoid.Markings; using Content.Shared.Localizations; +using Content.Shared.SS220.Language; namespace Content.Shared.IoC { @@ -9,6 +10,7 @@ public static void Register() { IoCManager.Register(); IoCManager.Register(); + IoCManager.Register(); // SS220 languages } } } diff --git a/Content.Shared/SS220/Language/Components/LanguageComponent.cs b/Content.Shared/SS220/Language/Components/LanguageComponent.cs new file mode 100644 index 000000000000..01fbff9a7e4d --- /dev/null +++ b/Content.Shared/SS220/Language/Components/LanguageComponent.cs @@ -0,0 +1,29 @@ +// © 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.SS220.Language.Systems; +using Robust.Shared.GameStates; +using Robust.Shared.Prototypes; +using Robust.Shared.Serialization; + +namespace Content.Shared.SS220.Language.Components; + +/// +/// A component that allows an entity to speak and understand languages. +/// Language prototypes are taken from YML of +/// The absence of this component gives the entity “Universal” language +/// +[RegisterComponent, Access(typeof(SharedLanguageSystem), Other = AccessPermissions.Read)] +[NetworkedComponent, AutoGenerateComponentState] +public sealed partial class LanguageComponent : Component +{ + /// + /// Selected language in which the entity will speak. + /// + [DataField, AutoNetworkedField] + public ProtoId? SelectedLanguage; + + /// + /// List of languages that the Entity speaks and understands. + /// + [DataField, AutoNetworkedField] + public List> AvailableLanguages = new(); +} diff --git a/Content.Server/SS220/Language/EncryptionMethods/BaseEncryptionMethod.cs b/Content.Shared/SS220/Language/EncryptionMethods/BaseEncryptionMethod.cs similarity index 89% rename from Content.Server/SS220/Language/EncryptionMethods/BaseEncryptionMethod.cs rename to Content.Shared/SS220/Language/EncryptionMethods/BaseEncryptionMethod.cs index 06aac2951b53..89a2c6b09765 100644 --- a/Content.Server/SS220/Language/EncryptionMethods/BaseEncryptionMethod.cs +++ b/Content.Shared/SS220/Language/EncryptionMethods/BaseEncryptionMethod.cs @@ -1,6 +1,6 @@ // © SS220, An EULA/CLA with a hosting restriction, full text: https://raw.githubusercontent.com/SerbiaStrong-220/space-station-14/master/CLA.txt -namespace Content.Server.SS220.Language.EncryptionMethods; +namespace Content.Shared.SS220.Language.EncryptionMethods; [ImplicitDataDefinitionForInheritors] public abstract partial class ScrambleMethod diff --git a/Content.Server/SS220/Language/EncryptionMethods/EmptyScrambleMethod.cs b/Content.Shared/SS220/Language/EncryptionMethods/EmptyScrambleMethod.cs similarity index 88% rename from Content.Server/SS220/Language/EncryptionMethods/EmptyScrambleMethod.cs rename to Content.Shared/SS220/Language/EncryptionMethods/EmptyScrambleMethod.cs index a1292d75c211..a839c68f4f36 100644 --- a/Content.Server/SS220/Language/EncryptionMethods/EmptyScrambleMethod.cs +++ b/Content.Shared/SS220/Language/EncryptionMethods/EmptyScrambleMethod.cs @@ -1,6 +1,6 @@ // © SS220, An EULA/CLA with a hosting restriction, full text: https://raw.githubusercontent.com/SerbiaStrong-220/space-station-14/master/CLA.txt -namespace Content.Server.SS220.Language.EncryptionMethods; +namespace Content.Shared.SS220.Language.EncryptionMethods; /// /// Returns the original message without scramble. diff --git a/Content.Server/SS220/Language/EncryptionMethods/RandomSyllablesMethod.cs b/Content.Shared/SS220/Language/EncryptionMethods/RandomSyllablesMethod.cs similarity index 97% rename from Content.Server/SS220/Language/EncryptionMethods/RandomSyllablesMethod.cs rename to Content.Shared/SS220/Language/EncryptionMethods/RandomSyllablesMethod.cs index add7259bc980..bd60db5bec4a 100644 --- a/Content.Server/SS220/Language/EncryptionMethods/RandomSyllablesMethod.cs +++ b/Content.Shared/SS220/Language/EncryptionMethods/RandomSyllablesMethod.cs @@ -2,7 +2,7 @@ using System.Text; using Robust.Shared.Random; -namespace Content.Server.SS220.Language.EncryptionMethods; +namespace Content.Shared.SS220.Language.EncryptionMethods; /// /// Scramble a message depending on its length using a specific list of syllables @@ -102,7 +102,7 @@ private string ScrambleWithoutSeed(string message) private string ScrambleWithSeed(string message, int seed) { - var random = new Random(seed); + var random = new System.Random(); var encryptedMessage = new StringBuilder(); var capitalize = false; diff --git a/Content.Server/SS220/Language/LanguageManager.cs b/Content.Shared/SS220/Language/LanguageManager.cs similarity index 68% rename from Content.Server/SS220/Language/LanguageManager.cs rename to Content.Shared/SS220/Language/LanguageManager.cs index 1811db789bda..47505863c103 100644 --- a/Content.Server/SS220/Language/LanguageManager.cs +++ b/Content.Shared/SS220/Language/LanguageManager.cs @@ -1,12 +1,14 @@ // © SS220, An EULA/CLA with a hosting restriction, full text: https://raw.githubusercontent.com/SerbiaStrong-220/space-station-14/master/CLA.txt +using Robust.Shared.Network; using Robust.Shared.Prototypes; using System.Diagnostics.CodeAnalysis; -namespace Content.Server.SS220.Language; +namespace Content.Shared.SS220.Language; public sealed class LanguageManager { [Dependency] private readonly IPrototypeManager _prototype = default!; + [Dependency] private readonly INetManager _net = default!; public List Languages { get; private set; } = new(); @@ -24,8 +26,12 @@ public void Initialize() /// /// Tries get language prototipe by id /// - public bool TryGetLanguageById(string id, [NotNullWhen(true)] out LanguagePrototype? language) + public bool TryGetLanguageById(string? id, [NotNullWhen(true)] out LanguagePrototype? language) { + language = null; + if (id == null) + return false; + language = Languages.Find(l => l.ID == id); return language != null; } @@ -33,8 +39,12 @@ public bool TryGetLanguageById(string id, [NotNullWhen(true)] out LanguageProtot /// /// Tries get language prototipe by language key /// - public bool TryGetLanguageByKey(string key, [NotNullWhen(true)] out LanguagePrototype? language) + public bool TryGetLanguageByKey(string? key, [NotNullWhen(true)] out LanguagePrototype? language) { + language = null; + if (key == null) + return false; + language = Languages.Find(l => KeyPrefix + l.Key == key); return language != null; } diff --git a/Content.Shared/SS220/Language/LanguageNetMessages.cs b/Content.Shared/SS220/Language/LanguageNetMessages.cs new file mode 100644 index 000000000000..89d1deec2071 --- /dev/null +++ b/Content.Shared/SS220/Language/LanguageNetMessages.cs @@ -0,0 +1,26 @@ +// © SS220, An EULA/CLA with a hosting restriction, full text: https://raw.githubusercontent.com/SerbiaStrong-220/space-station-14/master/CLA.txt +using Lidgren.Network; +using Robust.Shared.Network; +using Robust.Shared.Serialization; +using Robust.Shared.Utility; +using System.IO; + +namespace Content.Shared.SS220.Language; + +public sealed class ClientSelectlanguageMessage : NetMessage +{ + public string LanguageId = string.Empty; + + public override MsgGroups MsgGroup => MsgGroups.Entity; + + public override void ReadFromBuffer(NetIncomingMessage buffer, IRobustSerializer serializer) + { + LanguageId = buffer.ReadString(); + } + + public override void WriteToBuffer(NetOutgoingMessage buffer, IRobustSerializer serializer) + { + buffer.Write(LanguageId); + } +} + diff --git a/Content.Server/SS220/Language/LanguagesPrototype.cs b/Content.Shared/SS220/Language/LanguagesPrototype.cs similarity index 81% rename from Content.Server/SS220/Language/LanguagesPrototype.cs rename to Content.Shared/SS220/Language/LanguagesPrototype.cs index 4e6fbe5e8fe0..8249f1cf1c99 100644 --- a/Content.Server/SS220/Language/LanguagesPrototype.cs +++ b/Content.Shared/SS220/Language/LanguagesPrototype.cs @@ -1,8 +1,8 @@ // © SS220, An EULA/CLA with a hosting restriction, full text: https://raw.githubusercontent.com/SerbiaStrong-220/space-station-14/master/CLA.txt -using Content.Server.SS220.Language.EncryptionMethods; +using Content.Shared.SS220.Language.EncryptionMethods; using Robust.Shared.Prototypes; -namespace Content.Server.SS220.Language; +namespace Content.Shared.SS220.Language; [Prototype("language")] public sealed partial class LanguagePrototype : IPrototype @@ -11,10 +11,10 @@ public sealed partial class LanguagePrototype : IPrototype public string ID { get; private set; } = default!; [DataField] - public string? Name { get; private set; } + public string Name = string.Empty; [DataField] - public string? Description { get; private set; } + public string Description = string.Empty; [DataField(required: true)] public string Key = string.Empty; diff --git a/Content.Shared/SS220/Language/Systems/SharedLanguageSystem.cs b/Content.Shared/SS220/Language/Systems/SharedLanguageSystem.cs new file mode 100644 index 000000000000..fdc2e25344c7 --- /dev/null +++ b/Content.Shared/SS220/Language/Systems/SharedLanguageSystem.cs @@ -0,0 +1,101 @@ +// © 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.SS220.Language.Components; + +namespace Content.Shared.SS220.Language.Systems; + +public abstract class SharedLanguageSystem : EntitySystem +{ + [Dependency] private readonly LanguageManager _language = default!; + + #region Component + /// + /// Adds languages to from . + /// + public void AddLanguages(Entity ent, IEnumerable languageIds) + { + foreach (var language in languageIds) + { + AddLanguage(ent, language); + } + } + + /// + /// Adds language to the + /// + /// if successful added + public bool AddLanguage(Entity ent, string languageId) + { + if (ent.Comp.AvailableLanguages.Contains(languageId) || + !_language.TryGetLanguageById(languageId, out var language)) + return false; + + ent.Comp.AvailableLanguages.Add(languageId); + ent.Comp.SelectedLanguage ??= languageId; + Dirty(ent); + return true; + } + + /// + /// Clears + /// + public void ClearLanguages(Entity ent) + { + ent.Comp.AvailableLanguages.Clear(); + ent.Comp.SelectedLanguage = null; + Dirty(ent); + } + + /// + /// Removes language from + /// + /// if successful removed + public bool RemoveLanguage(Entity ent, string languageId) + { + if (ent.Comp.AvailableLanguages.Remove(languageId)) + { + if (ent.Comp.SelectedLanguage == languageId && !TrySetLanguage(ent, 0)) + ent.Comp.SelectedLanguage = null; + + Dirty(ent); + return true; + } + + return false; + } + + /// + /// Checks if contains this + /// + public static bool HasLanguage(Entity ent, string langageId) + { + return ent.Comp.AvailableLanguages.Contains(langageId); + } + + /// + /// Tries set by of + /// + public bool TrySetLanguage(Entity ent, int index) + { + if (ent.Comp.AvailableLanguages.Count <= index) + return false; + + ent.Comp.SelectedLanguage = ent.Comp.AvailableLanguages[index]; + Dirty(ent); + return true; + } + + /// + /// Tries set by language id. + /// Doesn't set language if doesn't contain this + /// + public bool TrySetLanguage(Entity ent, string languageId) + { + if (!HasLanguage(ent, languageId)) + return false; + + ent.Comp.SelectedLanguage = languageId; + Dirty(ent); + return true; + } + #endregion +} diff --git a/Resources/Locale/ru-RU/ss220/language/language-ui.ftl b/Resources/Locale/ru-RU/ss220/language/language-ui.ftl new file mode 100644 index 000000000000..f3afbdf8e75a --- /dev/null +++ b/Resources/Locale/ru-RU/ss220/language/language-ui.ftl @@ -0,0 +1,2 @@ +language-settings-ui-no-languages = Вы не знаете дополнительных языков. +language-settings-ui-select-default = Выберите язык по умолчанию: diff --git a/Resources/Textures/SS220/Interface/Nano/language_icon.png b/Resources/Textures/SS220/Interface/Nano/language_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..5a0dd86231259f4ab8415cec0d3807384c558736 GIT binary patch literal 297 zcmV+^0oMMBP)Px#<4Ht8R5*?8)G4VS?R2@Iz5_b^XupqUaP6Hi4~;sQ!83DPj#VErl02MH-0D5oQ;q z@C3^-&&+U%^P)C^odMD=p4wdE3b%O23J7sp2#_av)V9be-^e;bxK$a*gDf;&9o8E0c0*J5bK vRmaJCkm#@54EH!5AZ?Ejo Date: Sun, 2 Mar 2025 18:04:10 +0300 Subject: [PATCH 24/48] some fixes --- Content.Client/Content.Client.csproj | 5 ----- .../LanguageSettingsButton.cs | 1 - .../LanguageSettingsPopup.xaml.cs | 9 ++++++-- Content.Server/Chat/Systems/ChatSystem.cs | 1 - .../Radio/EntitySystems/RadioSystem.cs | 7 +++++- .../SS220/Language/LanguageSystem.cs | 4 ---- .../RandomSyllablesMethod.cs | 4 +++- .../SS220/Language/LanguageManager.cs | 20 ++++-------------- .../SS220/Language/LanguageNetMessages.cs | 2 -- Content.Shared/Verbs/VerbCategory.cs | 4 ---- .../ru-RU/ss220/language/language-desc.ftl | 6 +++--- .../Locale/ru-RU/ss220/verbs/verb-system.ftl | 3 --- .../Interface/VerbIcons/language_icon.svg | 7 ------ .../VerbIcons/language_icon.svg.192dpi.png | Bin 3213 -> 0 bytes .../VerbIcons/language_icon.svg.192dpi.yml | 2 -- 15 files changed, 23 insertions(+), 52 deletions(-) delete mode 100644 Resources/Textures/SS220/Interface/VerbIcons/language_icon.svg delete mode 100644 Resources/Textures/SS220/Interface/VerbIcons/language_icon.svg.192dpi.png delete mode 100644 Resources/Textures/SS220/Interface/VerbIcons/language_icon.svg.192dpi.yml diff --git a/Content.Client/Content.Client.csproj b/Content.Client/Content.Client.csproj index 19901e24e588..43fd8df2e19a 100644 --- a/Content.Client/Content.Client.csproj +++ b/Content.Client/Content.Client.csproj @@ -25,9 +25,4 @@ - - - MSBuild:Compile - - diff --git a/Content.Client/SS220/UserInterface/System/Chat/Controls/LanguageSettings/LanguageSettingsButton.cs b/Content.Client/SS220/UserInterface/System/Chat/Controls/LanguageSettings/LanguageSettingsButton.cs index f6c4b3ef7045..712a833e69c9 100644 --- a/Content.Client/SS220/UserInterface/System/Chat/Controls/LanguageSettings/LanguageSettingsButton.cs +++ b/Content.Client/SS220/UserInterface/System/Chat/Controls/LanguageSettings/LanguageSettingsButton.cs @@ -1,7 +1,6 @@ // © SS220, An EULA/CLA with a hosting restriction, full text: https://raw.githubusercontent.com/SerbiaStrong-220/space-station-14/master/CLA.txt using Content.Client.Resources; using Content.Client.UserInterface.Systems.Chat.Controls; -using Robust.Client.Player; using Robust.Client.ResourceManagement; using Robust.Client.UserInterface.Controls; using System.Numerics; diff --git a/Content.Client/SS220/UserInterface/System/Chat/Controls/LanguageSettings/LanguageSettingsPopup.xaml.cs b/Content.Client/SS220/UserInterface/System/Chat/Controls/LanguageSettings/LanguageSettingsPopup.xaml.cs index 770d6f68d621..d5ccb793706f 100644 --- a/Content.Client/SS220/UserInterface/System/Chat/Controls/LanguageSettings/LanguageSettingsPopup.xaml.cs +++ b/Content.Client/SS220/UserInterface/System/Chat/Controls/LanguageSettings/LanguageSettingsPopup.xaml.cs @@ -50,8 +50,13 @@ public void Update() } UpdateLanguageContainer(availableLanguages); - _language.TryGetLanguageById(comp.SelectedLanguage, out var selectedLanguage); - UpdateSelectedLanguage(selectedLanguage); + if (comp.SelectedLanguage is { } selectedLanguageId) + { + _language.TryGetLanguageById(comp.SelectedLanguage, out var selectedLanguage); + UpdateSelectedLanguage(selectedLanguage); + } + else + UpdateSelectedLanguage(null); } private void UpdateLanguageContainer(List? availableLanguages) diff --git a/Content.Server/Chat/Systems/ChatSystem.cs b/Content.Server/Chat/Systems/ChatSystem.cs index f058a8da65f5..eb03d0e475b6 100644 --- a/Content.Server/Chat/Systems/ChatSystem.cs +++ b/Content.Server/Chat/Systems/ChatSystem.cs @@ -44,7 +44,6 @@ using Robust.Shared.Timing; using Content.Server.SS220.Language; // SS220-Add-Languages-end using Robust.Shared.Map; -using Content.Shared.Speech; namespace Content.Server.Chat.Systems; diff --git a/Content.Server/Radio/EntitySystems/RadioSystem.cs b/Content.Server/Radio/EntitySystems/RadioSystem.cs index 78195eb030d9..f485387874af 100644 --- a/Content.Server/Radio/EntitySystems/RadioSystem.cs +++ b/Content.Server/Radio/EntitySystems/RadioSystem.cs @@ -119,6 +119,11 @@ public void SendRadioMessage(EntityUid messageSource, string message, RadioChann ? FormattedMessage.EscapeText(message) : message; + if (GetIdCardIsBold(messageSource)) + { + content = $"[bold]{content}[/bold]"; + } + var wrappedMessage = Loc.GetString(speech.Bold ? "chat-radio-message-wrap-bold" : "chat-radio-message-wrap", ("color", channel.Color), ("fontType", speech.FontId), @@ -183,10 +188,10 @@ public void SendRadioMessage(EntityUid messageSource, string message, RadioChann { RaiseLocalEvent(receiver, ref ev); } - // SS220 languages end // send the message //RaiseLocalEvent(receiver, ref ev); + // SS220 languages end } // Dispatch TTS radio speech event for every receiver diff --git a/Content.Server/SS220/Language/LanguageSystem.cs b/Content.Server/SS220/Language/LanguageSystem.cs index 1828731160a0..2a07721055d1 100644 --- a/Content.Server/SS220/Language/LanguageSystem.cs +++ b/Content.Server/SS220/Language/LanguageSystem.cs @@ -87,7 +87,6 @@ private void OnClientSelectLanguage(ClientSelectlanguageMessage msg) /// public string ScrambleMessage(string message, LanguagePrototype proto) { - var saveEndWhitespace = char.IsWhiteSpace(message[^1]); var cacheKey = $"{proto.ID}:{message}"; // If the original message is already there earlier encrypted, @@ -100,9 +99,6 @@ public string ScrambleMessage(string message, LanguagePrototype proto) ScrambleCache[cacheKey] = scrambled; - if (saveEndWhitespace) - scrambled += " "; - return scrambled; } diff --git a/Content.Shared/SS220/Language/EncryptionMethods/RandomSyllablesMethod.cs b/Content.Shared/SS220/Language/EncryptionMethods/RandomSyllablesMethod.cs index bd60db5bec4a..f70525f4e2cc 100644 --- a/Content.Shared/SS220/Language/EncryptionMethods/RandomSyllablesMethod.cs +++ b/Content.Shared/SS220/Language/EncryptionMethods/RandomSyllablesMethod.cs @@ -75,7 +75,7 @@ private string ScrambleWithoutSeed(string message) if (capitalize) { - curSyllable = curSyllable.Substring(0, 1).ToUpper() + curSyllable.Substring(1); + curSyllable = string.Concat(curSyllable.Substring(0, 1).ToUpper(), curSyllable.AsSpan(1)); capitalize = false; } encryptedMessage.Append(curSyllable); @@ -96,6 +96,7 @@ private string ScrambleWithoutSeed(string message) } var result = encryptedMessage.ToString().Trim(); + result += " "; // save whitespace before language tag return result; } @@ -133,6 +134,7 @@ private string ScrambleWithSeed(string message, int seed) } var result = encryptedMessage.ToString().Trim(); + result += " "; // save whitespace before language tag return result; } diff --git a/Content.Shared/SS220/Language/LanguageManager.cs b/Content.Shared/SS220/Language/LanguageManager.cs index 47505863c103..bab2f99e4ed7 100644 --- a/Content.Shared/SS220/Language/LanguageManager.cs +++ b/Content.Shared/SS220/Language/LanguageManager.cs @@ -12,26 +12,18 @@ public sealed class LanguageManager public List Languages { get; private set; } = new(); - public readonly string KeyPrefix = ":"; + public readonly string KeyPrefix = "%"; public void Initialize() { - Languages = new List(); - foreach (var language in _prototype.EnumeratePrototypes()) - { - Languages.Add(language); - } + Languages = [.. _prototype.EnumeratePrototypes()]; } /// /// Tries get language prototipe by id /// - public bool TryGetLanguageById(string? id, [NotNullWhen(true)] out LanguagePrototype? language) + public bool TryGetLanguageById(string id, [NotNullWhen(true)] out LanguagePrototype? language) { - language = null; - if (id == null) - return false; - language = Languages.Find(l => l.ID == id); return language != null; } @@ -39,12 +31,8 @@ public bool TryGetLanguageById(string? id, [NotNullWhen(true)] out LanguageProto /// /// Tries get language prototipe by language key /// - public bool TryGetLanguageByKey(string? key, [NotNullWhen(true)] out LanguagePrototype? language) + public bool TryGetLanguageByKey(string key, [NotNullWhen(true)] out LanguagePrototype? language) { - language = null; - if (key == null) - return false; - language = Languages.Find(l => KeyPrefix + l.Key == key); return language != null; } diff --git a/Content.Shared/SS220/Language/LanguageNetMessages.cs b/Content.Shared/SS220/Language/LanguageNetMessages.cs index 89d1deec2071..5bbebee9ebc2 100644 --- a/Content.Shared/SS220/Language/LanguageNetMessages.cs +++ b/Content.Shared/SS220/Language/LanguageNetMessages.cs @@ -2,8 +2,6 @@ using Lidgren.Network; using Robust.Shared.Network; using Robust.Shared.Serialization; -using Robust.Shared.Utility; -using System.IO; namespace Content.Shared.SS220.Language; diff --git a/Content.Shared/Verbs/VerbCategory.cs b/Content.Shared/Verbs/VerbCategory.cs index 6ed0a55a81ce..4647a921d545 100644 --- a/Content.Shared/Verbs/VerbCategory.cs +++ b/Content.Shared/Verbs/VerbCategory.cs @@ -95,9 +95,5 @@ public VerbCategory(string text, string? icon, bool iconsOnly = false) //SS220-SpecialSound-system end public static readonly VerbCategory PowerLevel = new("verb-categories-power-level", null); - - // SS220-Add-Languages begin - public static readonly VerbCategory Languages = new("verb-categories-languages-selector", "/Textures/SS220/Interface/VerbIcons/language_icon.svg.192dpi.png"); - // SS220-Add-Languages end } } diff --git a/Resources/Locale/ru-RU/ss220/language/language-desc.ftl b/Resources/Locale/ru-RU/ss220/language/language-desc.ftl index 46a4af084d93..a0f08487d5df 100644 --- a/Resources/Locale/ru-RU/ss220/language/language-desc.ftl +++ b/Resources/Locale/ru-RU/ss220/language/language-desc.ftl @@ -1,9 +1,9 @@ # Sources: https://wiki.ss220.club/index.php/Языки and https://wiki14.ss220.club/index.php?title=Лор # Galactic common languages -language-galacticcommon-desc = Дружелюбный для иных рас язык, введёный правительством ТСФ в связи с насплывом сектор иммигрантов представляющие многочисленное количества рас. +language-galacticcommon-desc = Дружелюбный для иных рас язык, введёный правительством ТСФ в связи с наслывом в сектор иммигрантов представляющие многочисленное количества рас. language-solcommon-desc = Родной язык людей. Убийственный гибрид неформального английского и элементов мандаринского китайского, общий язык Солнечной системы. -language-tradeband-desc = Это тщательно продуманная манера говорить с использованием множества слов из многих инопланетных языков, а также из ряда человеческих. +language-tradeband-desc = Это тщательно продуманная манера говорить с использованием множества слов из многих инопланетных языков, а также из ряда человеческих. language-gutter-desc = Используется в основном только гражданами НЕИЗВЕСТНОЙ забытой республики. Современный является продуктом смешения латинских языков, французского и итальянского. language-clownish-desc = Язык клоунской планеты. Родной язык клоунов по всей галактике. language-neorusskiya-desc = Смесь общесолнечного и славянских языков. Официальный язык СССП. @@ -18,4 +18,4 @@ language-eldwarf-desc = Грубый язык с малым количество language-arati-desc = Достаточно грубый язык, в котором большое количество шипящих звуков. language-canilunzt-desc = Гортанный язык, на котором говорят и используют жители системы Ваззенда, состоит из рычания, лая, тявканья и интенсивного использования ушей и движений хвоста. # Misc -language-binary-desc = Свободные протоколы связи и концентраторы маршрутизации для использования синтетиками. Большинство человеческих станций их поддерживают. \ No newline at end of file +language-binary-desc = Свободные протоколы связи и концентраторы маршрутизации для использования синтетиками. Большинство человеческих станций их поддерживают. diff --git a/Resources/Locale/ru-RU/ss220/verbs/verb-system.ftl b/Resources/Locale/ru-RU/ss220/verbs/verb-system.ftl index 096382fb0f5c..57559a90303e 100644 --- a/Resources/Locale/ru-RU/ss220/verbs/verb-system.ftl +++ b/Resources/Locale/ru-RU/ss220/verbs/verb-system.ftl @@ -1,7 +1,4 @@ verb-categories-attach-cart = Прикрепить verb-categories-deattach-cart = Открепить -verb-categories-languages-selector = Выбрать язык - - verb-shuffle-cards = Перемешать diff --git a/Resources/Textures/SS220/Interface/VerbIcons/language_icon.svg b/Resources/Textures/SS220/Interface/VerbIcons/language_icon.svg deleted file mode 100644 index 3a510738a2ec..000000000000 --- a/Resources/Textures/SS220/Interface/VerbIcons/language_icon.svg +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - \ No newline at end of file diff --git a/Resources/Textures/SS220/Interface/VerbIcons/language_icon.svg.192dpi.png b/Resources/Textures/SS220/Interface/VerbIcons/language_icon.svg.192dpi.png deleted file mode 100644 index ec625cd24a7d3e63fb6f2a56cb6a2a50369dcc52..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3213 zcmbVP2~-p37EXXb0tLak0%8a**pih%7KlIzOCCf)V_6i*kW5GfG9if&1cYc2L6Lw~ zun2X*wIa3nYOI36jVc8Z6&IF*N&zVp5d{Rb69mrdJ9aspGjrzuXTJO0<-2pwnXI4{ ze&(jurU(SWoa4`41>ZgO7upzsK( zSZ_!UVrc|2UO*y|urvk%6atheXOR<@LZXm~WcZ}w$rPqDiAkkkCl4I#PA(KNSFwF3 zoxwX6POMbQm_%Y?Vj>~YnE=V7iDU+YK_pR#6bc?j;1x+yC7{Af6%JDjY)~PPOJqt3 zB*p3(fhcIBl7)jqeV;>|Y?@Z8n5+|AF`^2P5y=FSKBozwP%w>?ZIs7OI2Q_tU@RC1 zN|g#2OPSH8Pz^rhQ7HGD)QOP%hjELO=<82uz_eot^&xhJ+GP(%(Xb0;UL(#{qDa zBym7ANR&yVC%kdFOpa8c1f&9x!)D>&Pze%=km)KCk)r^*3tm75o$&%16~F^@K!68H z00=k(bcTpdow8>`f{l6wr|gBWz0j3HqtHmscq#~p@DzYb!83$ZGG4@>gF-M009;AH zl>JJ%1pb78*niJ6tq{{2iiPA{NC;QiS>L}CeZ=&aC}6RYCclW)VEp7NR)U>q9VQ^q zcQ*?s(8~%6ag&cFAE?Yf%j`XEq8Nlp|3dEfFa;!1CIWKMD;loi-?kI+&w^I~34a~> zKNI!OL;pkb{hQDy%PJ59(r6H#l|-CA8KQouycdP||9VZl`=0?c1&61aemOl);m!0! z2Bk2y9GP8i9XF|APlS#48rEMQ7a#w@*XkYx6jVsD3`FRh_!k()^#DG1CDR|PSYt*Xk5BA^S z(Y9_19$qm18#=beD2(gAWRX=N=BH!sHWjwl>{~|OE;7)#ACB=shUUvoQwJ+{sxiDD z%EOB+TAa)76x<&fM6VPpE_%%|$UL6X^k%is@WS@M_Rw~*$uD>RgO%S~zHaE%H|6h2 z4n!IyB!9=!8AMiDjku*`R1@1BuUikiR0x>ms?pEQcU7Kho1g!P+iJY|O`iL#&yFQU z2XC>>k7T(-mOgZ>JF7KuH7K89sE%K}q^uyg%_uyg0oQ=DOq-d2w2}SXo>O9%hRiki z=2XLqD;RBJTE!VdE&b#Jf~xu5E{9}y`ew9|=u!4d&pdhep4qKBwY|nM!l9%xcGjl& zVBX0(QQa03^&O7sm5)yPu&wHmuA_qw*9_SiH+8fmH`I!P5{Aok*1P;T)pCfZDg+VetP?KSVR z+4a<)M+Yw(wJvBIm_Z&jerL0CIiplrot{_RS!;-iXy^hJIlqQ_mOr+>hdwp%@=z)3 z?RFBQdZ2Fo=8F3(Z#Ii?K|D$o#&Tp$BZ2dT*K;kp@@@KU?qX7NLGJaP4`W-p=cyO_ z9^;;_jde@*K2gz5X`$4Ghz5KLx7IeLn%f?AH%l<|dv3-yPSwrT`Rp-CmCPySUZGNl zA~a@BYG2TITOhyaUGXaKF^}HG{2Cob`|XK`576sua0mi6$)M2ZiQuw_dMv9mEBtE_ z-r)SlKc-s#lGBomh0fY)XzGi%<(_RugT5{%fvE2(?g52$?%%&o#^8EfR7(f6CoW|L z{MyG=hV*T3lAddyGrK4U)OwyX;8-|9ty^u<3%+8XwCTE=C&@PVBzE?>EndV`TOD0D z>~|~8$lb`2;iEJ5u6Kw6-a3H;Q|9D4lDixdC zaNO$KS&3IFwaZ?Z5d2a`E&E!1RoutG;R@@nAx)dO{f^Vz4Oh`xYZVjgfjJlV)RZ5R z<67`IUlEq9H6Jkw&1z;e8t>0P0#sTQqAqTDMjU&+sl~mxyEeq&(p~;JGg`K>j3!@p z?_8FhuB_T;?S{RhF~=M<$vM%xcPE&x{8IU#JJnut$Rn}flQUt`BRJ{dwH*s;#-4so z)igW2lX@<_yqr|z1Z(Mf+jTbp~3$5^N?C17THiQ^nR{Xzl9TIr!EjNJrZhty6A@gr?Cthv#rdZThLUf-+-h-z@_>0g$3)X zEQU=o13Nb2ExHG`bp>yp3nAwmJKKx0J8awEwqvdQ;hwvQb1uJO`f@T|Wg>^p~^9_FI&YFw@n#+#cB*0uY yx4(~sF8lJ}Ma Date: Sun, 2 Mar 2025 19:54:24 +0300 Subject: [PATCH 25/48] try fix tts --- Content.Server/Chat/Systems/ChatSystem.cs | 70 ++++++++-- .../Radio/EntitySystems/RadioSystem.cs | 42 +++--- Content.Server/SS220/TTS/TTSSystem.cs | 124 ++++++++++++------ 3 files changed, 170 insertions(+), 66 deletions(-) diff --git a/Content.Server/Chat/Systems/ChatSystem.cs b/Content.Server/Chat/Systems/ChatSystem.cs index eb03d0e475b6..2d7bc8f66930 100644 --- a/Content.Server/Chat/Systems/ChatSystem.cs +++ b/Content.Server/Chat/Systems/ChatSystem.cs @@ -511,7 +511,7 @@ private void SendEntitySpeak( continue; var listener = session.AttachedEntity.Value; - var currentMessage = _languageSystem.SanitizeMessage(source, listener, message); + var scrambledMessage = _languageSystem.SanitizeMessage(source, listener, message); // SS220-Add-Languages end var wrappedMessage = Loc.GetString(speech.Bold ? "chat-manager-entity-say-bold-wrap-message" : "chat-manager-entity-say-wrap-message", @@ -519,13 +519,30 @@ private void SendEntitySpeak( ("verb", Loc.GetString(_random.Pick(speech.SpeechVerbStrings))), ("fontType", speech.FontId), ("fontSize", speech.FontSize), - ("message", currentMessage /*SS220-Add-Languages*/)); + ("message", scrambledMessage /*SS220-Add-Languages*/)); + + //SS220-Add-Languages begin + _chatManager.ChatMessageToOne(ChatChannel.Local, scrambledMessage, wrappedMessage, source, false, session.Channel); - _chatManager.ChatMessageToOne(ChatChannel.Local, currentMessage, wrappedMessage, source, false, session.Channel); //SS220-Add-Languages + if (listener == source) + { + var ev = new EntitySpokeEvent(source, scrambledMessage, originalMessage, null, null); + RaiseLocalEvent(source, ev, true); + } + else + { + var scrambledEv = new EntitySpokeScrambledEvent(source, listener, scrambledMessage, originalMessage, null, false); + RaiseLocalEvent(scrambledEv); + } + //SS220-Add-Languages end } - //SendInVoiceRange(ChatChannel.Local, message, wrappedMessage, source, range); //SS220-Add-Languages - var ev = new EntitySpokeEvent(source, message, originalMessage, null, null); - RaiseLocalEvent(source, ev, true); + //SS220-Add-Languages begin + message = _languageSystem.SanitizeMessage(source, source, message); + + //SendInVoiceRange(ChatChannel.Local, message, wrappedMessage, source, range); + //var ev = new EntitySpokeEvent(source, message, originalMessage, null, null); + //RaiseLocalEvent(source, ev, true); + //SS220-Add-Languages end // To avoid logging any messages sent by entities that are not players, like vendors, cloning, etc. // Also doesn't log if hideLog is true. @@ -594,7 +611,6 @@ private void SendEntityWhisper( var wrappedUnknownMessage = Loc.GetString("chat-manager-entity-whisper-unknown-wrap-message", ("message", FormattedMessage.EscapeText(obfuscatedMessage))); - foreach (var (session, data) in GetRecipients(source, WhisperMuffledRange)) { EntityUid listener; @@ -627,12 +643,27 @@ private void SendEntityWhisper( //If listener is too far and has no line of sight, they can't identify the whisperer's identity else _chatManager.ChatMessageToOne(ChatChannel.Whisper, obfuscatedScrambledMessage /* SS220 languages */, wrappedUnknownMessage, source, false, session.Channel); + + // SS220-Add-Languages begin + if (listener == source) + { + var ev = new EntitySpokeEvent(source, scrambledMessage, originalMessage, channel, obfuscatedMessage); + RaiseLocalEvent(source, ev, true); + } + else + { + var scrambledEv = new EntitySpokeScrambledEvent(source, listener, scrambledMessage, originalMessage, obfuscatedMessage, channel != null); + RaiseLocalEvent(scrambledEv); + } + // SS220-Add-Languages end } _replay.RecordServerMessage(new ChatMessage(ChatChannel.Whisper, message, wrappedMessage, GetNetEntity(source), null, MessageRangeHideChatForReplay(range))); - var ev = new EntitySpokeEvent(source, message, originalMessage, channel, obfuscatedMessage); - RaiseLocalEvent(source, ev, true); + // SS220 languages begin + //var ev = new EntitySpokeEvent(source, message, originalMessage, channel, obfuscatedMessage); + //RaiseLocalEvent(source, ev, true); + // SS220 languages end if (!hideLog) if (originalMessage == message) { @@ -1209,3 +1240,24 @@ public RadioEventReceiver(EntityUid actor, EntityCoordinates playTarget) } // SS220 Silicon TTS fix end +// SS220 languages begin +public sealed class EntitySpokeScrambledEvent : EntityEventArgs +{ + public readonly EntityUid Source; + public readonly EntityUid Listener; + public readonly string Message; + public readonly string OriginalMessage; + public readonly string? ObfuscatedMessage; // not null if this was a whisper + public readonly bool IsRadio; // radio message is always a whisper + + public EntitySpokeScrambledEvent(EntityUid source, EntityUid listener, string message, string originalMessage, string? obfuscatedMessage, bool isRadio) + { + Source = source; + Listener = listener; + Message = message; + OriginalMessage = originalMessage; + ObfuscatedMessage = obfuscatedMessage; + IsRadio = isRadio; + } +} +// SS220 languages end diff --git a/Content.Server/Radio/EntitySystems/RadioSystem.cs b/Content.Server/Radio/EntitySystems/RadioSystem.cs index f485387874af..dd7792e5babf 100644 --- a/Content.Server/Radio/EntitySystems/RadioSystem.cs +++ b/Content.Server/Radio/EntitySystems/RadioSystem.cs @@ -153,6 +153,7 @@ public void SendRadioMessage(EntityUid messageSource, string message, RadioChann var sourceServerExempt = _exemptQuery.HasComp(radioSource); var radioQuery = EntityQueryEnumerator(); + var messageListenerDict = new Dictionary>(); // SS220 languages while (canSend && radioQuery.MoveNext(out var receiver, out var radio, out var transform)) { if (!radio.ReceiveAllChannels) @@ -178,11 +179,13 @@ public void SendRadioMessage(EntityUid messageSource, string message, RadioChann continue; // SS220 languages begin - if (_languageSystem.TryGetLanguageListener(receiver, out var listener) && - TryGetScrambledChatMessage(messageSource, listener.Value, message, out var scrambledChatMsg)) + if (_languageSystem.TryGetLanguageListener(receiver, out var listener)) { - var scrabledEv = new RadioReceiveEvent(message, messageSource, channel, radioSource, scrambledChatMsg, new()); - RaiseLocalEvent(receiver, ref scrabledEv); + var scrambledMessage = _languageSystem.SanitizeMessage(messageSource, listener.Value, message); + if (messageListenerDict.TryGetValue(scrambledMessage, out var lisneners)) + lisneners.Add(receiver); + else + messageListenerDict[scrambledMessage] = [receiver]; } else { @@ -194,6 +197,20 @@ public void SendRadioMessage(EntityUid messageSource, string message, RadioChann // SS220 languages end } + // SS220 languages begin + foreach (var (scrambledMessage, listeners) in messageListenerDict) + { + var newChatMsg = GetMsgChatMessage(messageSource, scrambledMessage); + var newEv = new RadioReceiveEvent(message, messageSource, channel, radioSource, newChatMsg, new()); + foreach (var listener in listeners) + { + RaiseLocalEvent(listener, ref newEv); + } + + RaiseLocalEvent(new RadioSpokeEvent(messageSource, scrambledMessage, newEv.Receivers.ToArray())); + } + // SS220 languages end + // Dispatch TTS radio speech event for every receiver RaiseLocalEvent(new RadioSpokeEvent(messageSource, message, ev.Receivers.ToArray())); @@ -206,18 +223,12 @@ public void SendRadioMessage(EntityUid messageSource, string message, RadioChann _messages.Remove(message); // SS220 languages begin - bool TryGetScrambledChatMessage(EntityUid source, EntityUid listener, string message, [NotNullWhen(true)] out MsgChatMessage? scrambledChatMsg) + MsgChatMessage GetMsgChatMessage(EntityUid source, string message) { - scrambledChatMsg = null; - var languageProto = _languageSystem.GetSelectedLanguage(source); - if (languageProto == null) - return false; - - var scrambledMessage = _languageSystem.SanitizeMessage(source, listener, message); if (GetIdCardIsBold(source)) { content = $"[bold]{content}[/bold]"; - scrambledMessage = $"[bold]{scrambledMessage}[/bold]"; + message = $"[bold]{message}[/bold]"; } var wrappedScrambledMessage = Loc.GetString(speech.Bold ? "chat-radio-message-wrap-bold" : "chat-radio-message-wrap", @@ -227,17 +238,16 @@ bool TryGetScrambledChatMessage(EntityUid source, EntityUid listener, string mes ("verb", Loc.GetString(_random.Pick(speech.SpeechVerbStrings))), ("channel", $"\\[{channel.LocalizedName}\\]"), ("name", formattedName), - ("message", scrambledMessage)); + ("message", message)); var scrambledChat = new ChatMessage( ChatChannel.Radio, - scrambledMessage, + message, wrappedScrambledMessage, NetEntity.Invalid, null); - scrambledChatMsg = new MsgChatMessage { Message = scrambledChat }; - return scrambledChatMsg != null; + return new MsgChatMessage { Message = scrambledChat }; } // SS220 languages end } diff --git a/Content.Server/SS220/TTS/TTSSystem.cs b/Content.Server/SS220/TTS/TTSSystem.cs index 61034fa4ac30..8cc30cfad686 100644 --- a/Content.Server/SS220/TTS/TTSSystem.cs +++ b/Content.Server/SS220/TTS/TTSSystem.cs @@ -14,6 +14,7 @@ using Robust.Shared.Random; using Robust.Shared.Network; using Robust.Server.Player; +using Robust.Shared.GameObjects; namespace Content.Server.SS220.TTS; @@ -46,6 +47,7 @@ public override void Initialize() SubscribeLocalEvent(OnTransformSpeech); SubscribeLocalEvent(OnEntitySpoke); + SubscribeLocalEvent(OnEntitySpokeScrambled); SubscribeLocalEvent(OnRadioReceiveEvent); SubscribeLocalEvent(OnAnnouncementSpoke); SubscribeLocalEvent(OnRoundRestartCleanup); @@ -190,12 +192,23 @@ private async void OnRequestGlobalTTS(RequestGlobalTTSEvent ev, EntitySessionEve private async void OnEntitySpoke(EntityUid uid, TTSComponent component, EntitySpokeEvent args) { - var voiceId = component.VoicePrototypeId; + HandleEntitySpoke(uid, uid, args.Message, args.ObfuscatedMessage, args.IsRadio); + } + + private async void OnEntitySpokeScrambled(EntitySpokeScrambledEvent args) + { + HandleEntitySpoke(args.Source, args.Listener, args.Message, args.ObfuscatedMessage, args.IsRadio); + } + + private async void HandleEntitySpoke(EntityUid uid, EntityUid listener, string message, string? obfuscatedMessage, bool isRadio) + { if (!_isEnabled || - args.Message.Length > MaxMessageChars || - voiceId == null) + message.Length > MaxMessageChars || + !TryComp(uid, out var component) || + component.VoicePrototypeId == null) return; + var voiceId = component.VoicePrototypeId; if (TryGetVoiceMaskUid(uid, out var maskUid)) { var voiceEv = new TransformSpeakerVoiceEvent(maskUid.Value, voiceId); @@ -208,16 +221,16 @@ private async void OnEntitySpoke(EntityUid uid, TTSComponent component, EntitySp return; } - if (args.ObfuscatedMessage != null) + if (obfuscatedMessage != null) { - HandleWhisper(uid, args.Message, args.ObfuscatedMessage, protoVoice.Speaker, args.IsRadio); + HandleWhisperToOne(uid, listener, message, obfuscatedMessage, protoVoice.Speaker, isRadio); return; } - HandleSay(uid, args.Message, protoVoice.Speaker); + HandleSayToOne(uid, listener, message, protoVoice.Speaker); } - private async void HandleSay(EntityUid uid, string message, string speaker) + private async void HandleSayToMany(EntityUid uid, string message, string speaker) { using var ttsResponse = await GenerateTts(message, speaker, TtsKind.Default); if (!ttsResponse.TryGetValue(out var audioData)) return; @@ -228,56 +241,85 @@ private async void HandleSay(EntityUid uid, string message, string speaker) }; foreach (var receiver in Filter.Pvs(uid).Recipients) { - _netManager.ServerSendMessage(playTtsMessage, receiver.Channel); + HandleSayToOne(uid, receiver, message, speaker, playTtsMessage); } } - private async void HandleWhisper(EntityUid uid, string message, string obfMessage, string speaker, bool isRadio) + private async void HandleSayToOne(EntityUid source, EntityUid target, string message, string speaker, MsgPlayTts? msgPlayTts = null) { - // If it's a whisper into a radio, generate speech without whisper - // attributes to prevent an additional speech synthesis event - using var ttsResponse = await GenerateTts(message, speaker, TtsKind.Whisper); - if (!ttsResponse.TryGetValue(out var audioData)) + if (!_playerManager.TryGetSessionByEntity(target, out var receiver)) return; - using var obfTtsResponse = await GenerateTts(obfMessage, speaker, TtsKind.Whisper); - if (!obfTtsResponse.TryGetValue(out var obfAudioData)) + HandleSayToOne(source, receiver, message, speaker, msgPlayTts); + } + + private async void HandleSayToOne(EntityUid source, ICommonSession receiver, string message, string speaker, MsgPlayTts? msgPlayTts = null) + { + if (msgPlayTts == null) + { + using var ttsResponse = await GenerateTts(message, speaker, TtsKind.Default); + if (!ttsResponse.TryGetValue(out var audioData)) return; + msgPlayTts = new MsgPlayTts + { + Data = audioData, + SourceUid = GetNetEntity(source), + }; + } + + _netManager.ServerSendMessage(msgPlayTts, receiver.Channel); + } + + private async void HandleWhisperToOne(EntityUid uid, EntityUid target, string message, string obfMessage, string speaker, bool isRadio) + { + if (!_playerManager.TryGetSessionByEntity(target, out var receiver)) return; - // TODO: Check obstacles - var xformQuery = GetEntityQuery(); - var sourcePos = _xforms.GetWorldPosition(xformQuery.GetComponent(uid), xformQuery); - var receptions = Filter.Pvs(uid).Recipients; + HandleWhisperToOne(uid, receiver, message, obfMessage, speaker, isRadio); + } - var fullTtsMessage = new MsgPlayTts - { - Data = audioData, - SourceUid = GetNetEntity(uid), - Kind = TtsKind.Whisper, - }; + private async void HandleWhisperToOne(EntityUid source, ICommonSession receiver, string message, string obfMessage, string speaker, bool isRadio) + { + if (!receiver.AttachedEntity.HasValue) + return; - var obfuscatedTtsMessage = new MsgPlayTts - { - Data = obfAudioData, - SourceUid = GetNetEntity(uid), - Kind = TtsKind.Whisper, - }; + MsgPlayTts ttsMessage; + var xformQuery = GetEntityQuery(); + var sourcePos = _xforms.GetWorldPosition(xformQuery.GetComponent(source), xformQuery); - foreach (var session in receptions) - { - if (!session.AttachedEntity.HasValue) - continue; + var xform = xformQuery.GetComponent(receiver.AttachedEntity.Value); + var distance = (sourcePos - _xforms.GetWorldPosition(xform, xformQuery)).Length(); - var xform = xformQuery.GetComponent(session.AttachedEntity.Value); - var distance = (sourcePos - _xforms.GetWorldPosition(xform, xformQuery)).Length(); + if (distance > ChatSystem.WhisperMuffledRange) + return; - if (distance > ChatSystem.WhisperMuffledRange) - continue; + if (distance > ChatSystem.WhisperClearRange) + { + using var ttsResponse = await GenerateTts(message, speaker, TtsKind.Whisper); + if (!ttsResponse.TryGetValue(out var audioData)) + return; - var netMessageToSend = distance > ChatSystem.WhisperClearRange ? obfuscatedTtsMessage : fullTtsMessage; + ttsMessage = new MsgPlayTts + { + Data = audioData, + SourceUid = GetNetEntity(source), + Kind = TtsKind.Whisper, + }; + } + else + { + using var obfTtsResponse = await GenerateTts(obfMessage, speaker, TtsKind.Whisper); + if (!obfTtsResponse.TryGetValue(out var obfAudioData)) + return; - _netManager.ServerSendMessage(netMessageToSend, session.Channel); + ttsMessage = new MsgPlayTts + { + Data = obfAudioData, + SourceUid = GetNetEntity(source), + Kind = TtsKind.Whisper, + }; } + + _netManager.ServerSendMessage(ttsMessage, receiver.Channel); } private async void HandleRadio(RadioEventReceiver[] receivers, string message, string speaker) From 30799f1cc8440cc0a477ccdaa5d41cfeb4b59e8d Mon Sep 17 00:00:00 2001 From: Kirus59 <145689588+Kirus59@users.noreply.github.com> Date: Sun, 2 Mar 2025 20:58:26 +0300 Subject: [PATCH 26/48] fix tts & add seeded scrambled words --- .../Chat/Managers/ChatSanitizationManager.cs | 2 +- Content.Server/Chat/Systems/ChatSystem.cs | 16 ++++---- .../Radio/EntitySystems/RadioSystem.cs | 12 +++--- .../SS220/Language/LanguageSystem.cs | 6 ++- .../RandomSyllablesMethod.cs | 41 +++++++++++-------- 5 files changed, 45 insertions(+), 32 deletions(-) diff --git a/Content.Server/Chat/Managers/ChatSanitizationManager.cs b/Content.Server/Chat/Managers/ChatSanitizationManager.cs index 63c002be7454..c5bc3a8d02af 100644 --- a/Content.Server/Chat/Managers/ChatSanitizationManager.cs +++ b/Content.Server/Chat/Managers/ChatSanitizationManager.cs @@ -178,7 +178,7 @@ public bool TrySanitizeEmoteShorthands(string message, // SS220 no English begin var language = _entityManager.System(); - var checkMessage = language.SanitizeMessage(speaker, speaker, sanitized); + var checkMessage = language.SanitizeMessage(speaker, speaker, sanitized, out _); var ntAllowed = checkMessage.Replace("NanoTrasen", string.Empty, StringComparison.OrdinalIgnoreCase); ntAllowed = ntAllowed.Replace("nt", string.Empty, StringComparison.OrdinalIgnoreCase); diff --git a/Content.Server/Chat/Systems/ChatSystem.cs b/Content.Server/Chat/Systems/ChatSystem.cs index 2d7bc8f66930..234fda698e78 100644 --- a/Content.Server/Chat/Systems/ChatSystem.cs +++ b/Content.Server/Chat/Systems/ChatSystem.cs @@ -44,6 +44,7 @@ using Robust.Shared.Timing; using Content.Server.SS220.Language; // SS220-Add-Languages-end using Robust.Shared.Map; +using JetBrains.Annotations; namespace Content.Server.Chat.Systems; @@ -511,7 +512,7 @@ private void SendEntitySpeak( continue; var listener = session.AttachedEntity.Value; - var scrambledMessage = _languageSystem.SanitizeMessage(source, listener, message); + var scrambledMessage = _languageSystem.SanitizeMessage(source, listener, message, out var scrambledColorlessMessage); // SS220-Add-Languages end var wrappedMessage = Loc.GetString(speech.Bold ? "chat-manager-entity-say-bold-wrap-message" : "chat-manager-entity-say-wrap-message", @@ -531,13 +532,13 @@ private void SendEntitySpeak( } else { - var scrambledEv = new EntitySpokeScrambledEvent(source, listener, scrambledMessage, originalMessage, null, false); + var scrambledEv = new EntitySpokeScrambledEvent(source, listener, scrambledMessage, scrambledColorlessMessage, originalMessage, null, false); RaiseLocalEvent(scrambledEv); } //SS220-Add-Languages end } //SS220-Add-Languages begin - message = _languageSystem.SanitizeMessage(source, source, message); + message = _languageSystem.SanitizeMessage(source, source, message, out _); //SendInVoiceRange(ChatChannel.Local, message, wrappedMessage, source, range); //var ev = new EntitySpokeEvent(source, message, originalMessage, null, null); @@ -620,8 +621,7 @@ private void SendEntityWhisper( listener = session.AttachedEntity.Value; // SS220-Add-Languages begin - var scrambledMessage = _languageSystem.SanitizeMessage(source, listener, message); - var scrambledColorlessMessage = _languageSystem.SanitizeMessage(source, listener, message, false); + var scrambledMessage = _languageSystem.SanitizeMessage(source, listener, message, out var scrambledColorlessMessage); var obfuscatedScrambledMessage = ObfuscateMessageReadability(scrambledColorlessMessage, 0.2f); wrappedMessage = Loc.GetString("chat-manager-entity-whisper-wrap-message", @@ -652,7 +652,7 @@ private void SendEntityWhisper( } else { - var scrambledEv = new EntitySpokeScrambledEvent(source, listener, scrambledMessage, originalMessage, obfuscatedMessage, channel != null); + var scrambledEv = new EntitySpokeScrambledEvent(source, listener, scrambledMessage, scrambledColorlessMessage, originalMessage, obfuscatedMessage, channel != null); RaiseLocalEvent(scrambledEv); } // SS220-Add-Languages end @@ -1246,15 +1246,17 @@ public sealed class EntitySpokeScrambledEvent : EntityEventArgs public readonly EntityUid Source; public readonly EntityUid Listener; public readonly string Message; + public readonly string ColorlessMessage; public readonly string OriginalMessage; public readonly string? ObfuscatedMessage; // not null if this was a whisper public readonly bool IsRadio; // radio message is always a whisper - public EntitySpokeScrambledEvent(EntityUid source, EntityUid listener, string message, string originalMessage, string? obfuscatedMessage, bool isRadio) + public EntitySpokeScrambledEvent(EntityUid source, EntityUid listener, string message, string colorlessMessage, string originalMessage, string? obfuscatedMessage, bool isRadio) { Source = source; Listener = listener; Message = message; + ColorlessMessage = colorlessMessage; OriginalMessage = originalMessage; ObfuscatedMessage = obfuscatedMessage; IsRadio = isRadio; diff --git a/Content.Server/Radio/EntitySystems/RadioSystem.cs b/Content.Server/Radio/EntitySystems/RadioSystem.cs index dd7792e5babf..b3b2fa91686f 100644 --- a/Content.Server/Radio/EntitySystems/RadioSystem.cs +++ b/Content.Server/Radio/EntitySystems/RadioSystem.cs @@ -153,7 +153,7 @@ public void SendRadioMessage(EntityUid messageSource, string message, RadioChann var sourceServerExempt = _exemptQuery.HasComp(radioSource); var radioQuery = EntityQueryEnumerator(); - var messageListenerDict = new Dictionary>(); // SS220 languages + var messageListenerDict = new Dictionary<(string, string), HashSet>(); // SS220 languages while (canSend && radioQuery.MoveNext(out var receiver, out var radio, out var transform)) { if (!radio.ReceiveAllChannels) @@ -181,11 +181,11 @@ public void SendRadioMessage(EntityUid messageSource, string message, RadioChann // SS220 languages begin if (_languageSystem.TryGetLanguageListener(receiver, out var listener)) { - var scrambledMessage = _languageSystem.SanitizeMessage(messageSource, listener.Value, message); - if (messageListenerDict.TryGetValue(scrambledMessage, out var lisneners)) + var scrambledMessage = _languageSystem.SanitizeMessage(messageSource, listener.Value, message, out var colorlessMessage); + if (messageListenerDict.TryGetValue((scrambledMessage, colorlessMessage), out var lisneners)) lisneners.Add(receiver); else - messageListenerDict[scrambledMessage] = [receiver]; + messageListenerDict[(scrambledMessage, colorlessMessage)] = [receiver]; } else { @@ -198,7 +198,7 @@ public void SendRadioMessage(EntityUid messageSource, string message, RadioChann } // SS220 languages begin - foreach (var (scrambledMessage, listeners) in messageListenerDict) + foreach (var ((scrambledMessage, colorlessMessage), listeners) in messageListenerDict) { var newChatMsg = GetMsgChatMessage(messageSource, scrambledMessage); var newEv = new RadioReceiveEvent(message, messageSource, channel, radioSource, newChatMsg, new()); @@ -207,7 +207,7 @@ public void SendRadioMessage(EntityUid messageSource, string message, RadioChann RaiseLocalEvent(listener, ref newEv); } - RaiseLocalEvent(new RadioSpokeEvent(messageSource, scrambledMessage, newEv.Receivers.ToArray())); + RaiseLocalEvent(new RadioSpokeEvent(messageSource, colorlessMessage, newEv.Receivers.ToArray())); } // SS220 languages end diff --git a/Content.Server/SS220/Language/LanguageSystem.cs b/Content.Server/SS220/Language/LanguageSystem.cs index 2a07721055d1..7396a6511230 100644 --- a/Content.Server/SS220/Language/LanguageSystem.cs +++ b/Content.Server/SS220/Language/LanguageSystem.cs @@ -105,8 +105,9 @@ public string ScrambleMessage(string message, LanguagePrototype proto) /// /// Sanitize the by removing the language tags and scramble it (if necessary) for /// - public string SanitizeMessage(EntityUid source, EntityUid listener, string message, bool setColor = true) + public string SanitizeMessage(EntityUid source, EntityUid listener, string message, out string colorlessMessage, bool setColor = true) { + colorlessMessage = message; var languageProto = GetSelectedLanguage(source); if (languageProto == null) return message; @@ -122,6 +123,7 @@ public string SanitizeMessage(EntityUid source, EntityUid listener, string messa else { var scrambledString = ScrambleMessage(message, languageString.Item2); + colorlessMessage = scrambledString; if (setColor) scrambledString = SetColor(scrambledString, languageString.Item2); @@ -129,7 +131,7 @@ public string SanitizeMessage(EntityUid source, EntityUid listener, string messa } } - return sanitizedMessage.ToString(); + return sanitizedMessage.ToString().Trim(); } /// diff --git a/Content.Shared/SS220/Language/EncryptionMethods/RandomSyllablesMethod.cs b/Content.Shared/SS220/Language/EncryptionMethods/RandomSyllablesMethod.cs index f70525f4e2cc..4375e9eddf91 100644 --- a/Content.Shared/SS220/Language/EncryptionMethods/RandomSyllablesMethod.cs +++ b/Content.Shared/SS220/Language/EncryptionMethods/RandomSyllablesMethod.cs @@ -1,5 +1,6 @@ // © SS220, An EULA/CLA with a hosting restriction, full text: https://raw.githubusercontent.com/SerbiaStrong-220/space-station-14/master/CLA.txt using System.Text; +using System.Text.RegularExpressions; using Robust.Shared.Random; namespace Content.Shared.SS220.Language.EncryptionMethods; @@ -42,25 +43,35 @@ public override string ScrambleMessage(string message, int? seed = null) if (Syllables.Count == 0) return message; - string result; - if (seed != null) + var wordRegex = @"\S+"; + var matches = Regex.Matches(message, wordRegex); + if (matches.Count <= 0) + return message; + + var result = new StringBuilder(); + foreach (Match m in matches) { - foreach (var c in message.ToCharArray()) + string scrambledWord; + if (seed != null) { - seed += c; + foreach (var c in m.Value.ToCharArray()) + { + seed += c; + } + scrambledWord = ScrambleWithSeed(m.Value, seed.Value); } - result = ScrambleWithSeed(message, seed.Value); - } - else - { - result = ScrambleWithoutSeed(message); + else + { + scrambledWord = ScrambleWithoutSeed(message); + } + + result.Append(scrambledWord); } var punctuation = ExtractPunctuation(message); + result.Append(punctuation); - result += punctuation; - - return result; + return result.ToString(); } private string ScrambleWithoutSeed(string message) @@ -96,8 +107,6 @@ private string ScrambleWithoutSeed(string message) } var result = encryptedMessage.ToString().Trim(); - result += " "; // save whitespace before language tag - return result; } @@ -134,8 +143,6 @@ private string ScrambleWithSeed(string message, int seed) } var result = encryptedMessage.ToString().Trim(); - result += " "; // save whitespace before language tag - return result; } @@ -153,6 +160,8 @@ private static string ExtractPunctuation(string input) else break; } + punctuationBuilder.Append(' '); // save whitespace before language tag + return punctuationBuilder.ToString(); } } From a65833c78cc99179306cdd14e72c0e10c6fe0201 Mon Sep 17 00:00:00 2001 From: Kirus59 <145689588+Kirus59@users.noreply.github.com> Date: Sun, 2 Mar 2025 21:16:18 +0300 Subject: [PATCH 27/48] fix tts color --- Content.Server/SS220/TTS/TTSSystem.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Content.Server/SS220/TTS/TTSSystem.cs b/Content.Server/SS220/TTS/TTSSystem.cs index 8cc30cfad686..66f1f4365e38 100644 --- a/Content.Server/SS220/TTS/TTSSystem.cs +++ b/Content.Server/SS220/TTS/TTSSystem.cs @@ -197,7 +197,7 @@ private async void OnEntitySpoke(EntityUid uid, TTSComponent component, EntitySp private async void OnEntitySpokeScrambled(EntitySpokeScrambledEvent args) { - HandleEntitySpoke(args.Source, args.Listener, args.Message, args.ObfuscatedMessage, args.IsRadio); + HandleEntitySpoke(args.Source, args.Listener, args.ColorlessMessage, args.ObfuscatedMessage, args.IsRadio); } private async void HandleEntitySpoke(EntityUid uid, EntityUid listener, string message, string? obfuscatedMessage, bool isRadio) From 7448ee037bb0b20e79c6b5426c0d537756a3c28e Mon Sep 17 00:00:00 2001 From: Kirus59 <145689588+Kirus59@users.noreply.github.com> Date: Sun, 2 Mar 2025 22:28:43 +0300 Subject: [PATCH 28/48] RandomSyllablesMethod fixes --- .../Chat/Controls/ChatInputBox.xaml.cs | 4 +- .../SS220/Language/LanguageSystem.cs | 20 +++++++--- .../RandomSyllablesMethod.cs | 38 +++++++++++-------- 3 files changed, 39 insertions(+), 23 deletions(-) diff --git a/Content.Client/UserInterface/Systems/Chat/Controls/ChatInputBox.xaml.cs b/Content.Client/UserInterface/Systems/Chat/Controls/ChatInputBox.xaml.cs index aa664c823350..d59d050d7ce0 100644 --- a/Content.Client/UserInterface/Systems/Chat/Controls/ChatInputBox.xaml.cs +++ b/Content.Client/UserInterface/Systems/Chat/Controls/ChatInputBox.xaml.cs @@ -1,4 +1,4 @@ -using Content.Client.Stylesheets; +using Content.Client.Stylesheets; using Content.Client.SS220.UserInterface.System.Chat.Controls; using Content.Shared.Chat; using Content.Shared.Input; @@ -14,7 +14,7 @@ public class ChatInputBox : PanelContainer public readonly HistoryLineEdit Input; public readonly ChannelFilterButton FilterButton; public readonly HighlightButton HighlightButton; //ss220 highlight words - public readonly LanguageSettingsButton LanguageSettings; + public readonly LanguageSettingsButton LanguageSettings; // SS220 languages protected readonly BoxContainer Container; protected ChatChannel ActiveChannel { get; private set; } = ChatChannel.Local; diff --git a/Content.Server/SS220/Language/LanguageSystem.cs b/Content.Server/SS220/Language/LanguageSystem.cs index 7396a6511230..3dce04d5f3d9 100644 --- a/Content.Server/SS220/Language/LanguageSystem.cs +++ b/Content.Server/SS220/Language/LanguageSystem.cs @@ -114,23 +114,31 @@ public string SanitizeMessage(EntityUid source, EntityUid listener, string messa var languageStrings = SplitMessageByLanguages(source, message, languageProto); var sanitizedMessage = new StringBuilder(); - foreach (var languageString in languageStrings) + var sanitizedColorlessMessage = new StringBuilder(); + for (var i = 0; i < languageStrings.Count; i++) { - if (CheckLanguage(listener, languageString.Item2.ID)) + var curString = languageStrings[i]; + if (CheckLanguage(listener, curString.Item2.ID)) { - sanitizedMessage.Append(languageString.Item1); + sanitizedMessage.Append(curString.Item1); + sanitizedColorlessMessage.Append(curString.Item1); } else { - var scrambledString = ScrambleMessage(message, languageString.Item2); - colorlessMessage = scrambledString; + var scrambledString = ScrambleMessage(message, curString.Item2); + sanitizedColorlessMessage.Append(scrambledString); if (setColor) - scrambledString = SetColor(scrambledString, languageString.Item2); + { + if (i + 1 == languageStrings.Count) + scrambledString = scrambledString.Trim(); + scrambledString = SetColor(scrambledString, curString.Item2); + } sanitizedMessage.Append(scrambledString); } } + colorlessMessage = sanitizedColorlessMessage.ToString().Trim(); return sanitizedMessage.ToString().Trim(); } diff --git a/Content.Shared/SS220/Language/EncryptionMethods/RandomSyllablesMethod.cs b/Content.Shared/SS220/Language/EncryptionMethods/RandomSyllablesMethod.cs index 4375e9eddf91..ec3cded07806 100644 --- a/Content.Shared/SS220/Language/EncryptionMethods/RandomSyllablesMethod.cs +++ b/Content.Shared/SS220/Language/EncryptionMethods/RandomSyllablesMethod.cs @@ -38,9 +38,14 @@ public sealed partial class RandomSyllablesScrambleMethod : ScrambleMethod [DataField] public string SpecialCharacter = string.Empty; + private int? _inputSeed; + + private bool _capitalize = false; + public override string ScrambleMessage(string message, int? seed = null) { - if (Syllables.Count == 0) + if (message == string.Empty || + Syllables.Count == 0) return message; var wordRegex = @"\S+"; @@ -48,13 +53,17 @@ public override string ScrambleMessage(string message, int? seed = null) if (matches.Count <= 0) return message; + _inputSeed = seed; + _capitalize = char.IsUpper(message[0]); var result = new StringBuilder(); foreach (Match m in matches) { string scrambledWord; + seed = _inputSeed; + var word = m.Value.ToLower(); if (seed != null) { - foreach (var c in m.Value.ToCharArray()) + foreach (var c in word.ToCharArray()) { seed += c; } @@ -62,7 +71,7 @@ public override string ScrambleMessage(string message, int? seed = null) } else { - scrambledWord = ScrambleWithoutSeed(message); + scrambledWord = ScrambleWithoutSeed(m.Value); } result.Append(scrambledWord); @@ -71,6 +80,7 @@ public override string ScrambleMessage(string message, int? seed = null) var punctuation = ExtractPunctuation(message); result.Append(punctuation); + _capitalize = false; return result.ToString(); } @@ -79,15 +89,14 @@ private string ScrambleWithoutSeed(string message) var random = IoCManager.Resolve(); var encryptedMessage = new StringBuilder(); - var capitalize = false; while (encryptedMessage.Length < message.Length) { var curSyllable = random.Pick(Syllables); - if (capitalize) + if (_capitalize) { - curSyllable = string.Concat(curSyllable.Substring(0, 1).ToUpper(), curSyllable.AsSpan(1)); - capitalize = false; + curSyllable = curSyllable.Substring(0, 1).ToUpper() + curSyllable.Substring(1); + _capitalize = false; } encryptedMessage.Append(curSyllable); @@ -98,7 +107,7 @@ private string ScrambleWithoutSeed(string message) else if (random.Prob(DotChance)) { encryptedMessage.Append(". "); - capitalize = true; + _capitalize = true; } else if (random.Prob(SpaceChance)) { @@ -106,24 +115,23 @@ private string ScrambleWithoutSeed(string message) } } - var result = encryptedMessage.ToString().Trim(); + var result = encryptedMessage.ToString(); return result; } private string ScrambleWithSeed(string message, int seed) { - var random = new System.Random(); + var random = new System.Random(seed); var encryptedMessage = new StringBuilder(); - var capitalize = false; while (encryptedMessage.Length < message.Length) { var curSyllable = random.Pick(Syllables); - if (capitalize) + if (_capitalize) { curSyllable = curSyllable.Substring(0, 1).ToUpper() + curSyllable.Substring(1); - capitalize = false; + _capitalize = false; } encryptedMessage.Append(curSyllable); @@ -134,7 +142,7 @@ private string ScrambleWithSeed(string message, int seed) else if (random.Prob(DotChance)) { encryptedMessage.Append(". "); - capitalize = true; + _capitalize = true; } else if (random.Prob(SpaceChance)) { @@ -142,7 +150,7 @@ private string ScrambleWithSeed(string message, int seed) } } - var result = encryptedMessage.ToString().Trim(); + var result = encryptedMessage.ToString(); return result; } From a24839b1644409a71fe750ef7bc8f1a026c7470c Mon Sep 17 00:00:00 2001 From: Kirus59 <145689588+Kirus59@users.noreply.github.com> Date: Sun, 2 Mar 2025 22:33:19 +0300 Subject: [PATCH 29/48] change icon --- .../LanguageSettings/LanguageSettingsButton.cs | 2 +- .../SS220/Interface/Nano/language_icon.png | Bin 297 -> 0 bytes .../Interface/Nano/language_settings-button.png | Bin 0 -> 307 bytes 3 files changed, 1 insertion(+), 1 deletion(-) delete mode 100644 Resources/Textures/SS220/Interface/Nano/language_icon.png create mode 100644 Resources/Textures/SS220/Interface/Nano/language_settings-button.png diff --git a/Content.Client/SS220/UserInterface/System/Chat/Controls/LanguageSettings/LanguageSettingsButton.cs b/Content.Client/SS220/UserInterface/System/Chat/Controls/LanguageSettings/LanguageSettingsButton.cs index 712a833e69c9..10bace4be990 100644 --- a/Content.Client/SS220/UserInterface/System/Chat/Controls/LanguageSettings/LanguageSettingsButton.cs +++ b/Content.Client/SS220/UserInterface/System/Chat/Controls/LanguageSettings/LanguageSettingsButton.cs @@ -14,7 +14,7 @@ public LanguageSettingsButton() IoCManager.InjectDependencies(this); var texture = IoCManager.Resolve() - .GetTexture("/Textures/SS220/Interface/Nano/language_icon.png"); + .GetTexture("/Textures/SS220/Interface/Nano/language_settings-button.png"); AddChild(new TextureRect { diff --git a/Resources/Textures/SS220/Interface/Nano/language_icon.png b/Resources/Textures/SS220/Interface/Nano/language_icon.png deleted file mode 100644 index 5a0dd86231259f4ab8415cec0d3807384c558736..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 297 zcmV+^0oMMBP)Px#<4Ht8R5*?8)G4VS?R2@Iz5_b^XupqUaP6Hi4~;sQ!83DPj#VErl02MH-0D5oQ;q z@C3^-&&+U%^P)C^odMD=p4wdE3b%O23J7sp2#_av)V9be-^e;bxK$a*gDf;&9o8E0c0*J5bK vRmaJCkm#@54EH!5AZ?EjoZRztA3?P2)4`FXs|uz3eI_CaCoESsRIs< zMTf;iEO?Ji-E-mS#8|Fk-Kq-@e2)KM*mZrSlt>FhF7LN5Ul#5<*uw(^8;oW~E!e5p tDai2NAbH!nY9kAv_xMsHJkxxA8MJ_G4j=}BOTm*tl&7no%Q~loCIIMUaSi|g literal 0 HcmV?d00001 From 5a375d639d9fa8912270991ac4c625ca42e3f57e Mon Sep 17 00:00:00 2001 From: Kirus59 <145689588+Kirus59@users.noreply.github.com> Date: Tue, 4 Mar 2025 19:41:04 +0300 Subject: [PATCH 30/48] syllables method changes --- ...esMethod.cs => SyllablesScrambleMethod.cs} | 122 ++++++--------- .../SS220/Language/LanguagesPrototype.cs | 2 +- .../Prototypes/SS220/Language/language.yml | 141 ++++++++++++++---- 3 files changed, 155 insertions(+), 110 deletions(-) rename Content.Shared/SS220/Language/EncryptionMethods/{RandomSyllablesMethod.cs => SyllablesScrambleMethod.cs} (54%) diff --git a/Content.Shared/SS220/Language/EncryptionMethods/RandomSyllablesMethod.cs b/Content.Shared/SS220/Language/EncryptionMethods/SyllablesScrambleMethod.cs similarity index 54% rename from Content.Shared/SS220/Language/EncryptionMethods/RandomSyllablesMethod.cs rename to Content.Shared/SS220/Language/EncryptionMethods/SyllablesScrambleMethod.cs index ec3cded07806..7b7ddef3f320 100644 --- a/Content.Shared/SS220/Language/EncryptionMethods/RandomSyllablesMethod.cs +++ b/Content.Shared/SS220/Language/EncryptionMethods/SyllablesScrambleMethod.cs @@ -1,6 +1,8 @@ // © SS220, An EULA/CLA with a hosting restriction, full text: https://raw.githubusercontent.com/SerbiaStrong-220/space-station-14/master/CLA.txt +using System.Linq; using System.Text; using System.Text.RegularExpressions; +using Content.Shared.Random.Helpers; using Robust.Shared.Random; namespace Content.Shared.SS220.Language.EncryptionMethods; @@ -8,7 +10,7 @@ namespace Content.Shared.SS220.Language.EncryptionMethods; /// /// Scramble a message depending on its length using a specific list of syllables /// -public sealed partial class RandomSyllablesScrambleMethod : ScrambleMethod +public sealed partial class SyllablesScrambleMethod : ScrambleMethod { /// /// List of syllables from which the original message will be encrypted @@ -18,28 +20,18 @@ public sealed partial class RandomSyllablesScrambleMethod : ScrambleMethod public List Syllables = new(); /// - /// Chance of space between scrambled syllables + /// Chance of the after a scrambled syllable /// [DataField] - public float SpaceChance = 0.5f; + public float SpecialCharacterChance = 0.5f; /// - /// Chance for a dot after a scrambled syllable. + /// Special characters that can be inserted after a scrambled syllable /// [DataField] - public float DotChance = 0.3f; - - /// - /// Chance of the after a scrambled syllable - /// - [DataField] - public float SpecialCharacterChance = 0.3f; - - [DataField] - public string SpecialCharacter = string.Empty; - - private int? _inputSeed; + public List SpecialCharacters = new(); + private int _inputSeed; private bool _capitalize = false; public override string ScrambleMessage(string message, int? seed = null) @@ -53,27 +45,21 @@ public override string ScrambleMessage(string message, int? seed = null) if (matches.Count <= 0) return message; - _inputSeed = seed; + var random = IoCManager.Resolve(); + _inputSeed = seed ?? random.Next(); _capitalize = char.IsUpper(message[0]); + var result = new StringBuilder(); foreach (Match m in matches) { - string scrambledWord; seed = _inputSeed; var word = m.Value.ToLower(); - if (seed != null) + foreach (var c in word.ToCharArray()) { - foreach (var c in word.ToCharArray()) - { - seed += c; - } - scrambledWord = ScrambleWithSeed(m.Value, seed.Value); - } - else - { - scrambledWord = ScrambleWithoutSeed(m.Value); + seed += c; } + var scrambledWord = ScrambleWord(m.Value, seed.Value); result.Append(scrambledWord); } @@ -84,69 +70,29 @@ public override string ScrambleMessage(string message, int? seed = null) return result.ToString(); } - private string ScrambleWithoutSeed(string message) - { - var random = IoCManager.Resolve(); - - var encryptedMessage = new StringBuilder(); - while (encryptedMessage.Length < message.Length) - { - var curSyllable = random.Pick(Syllables); - - if (_capitalize) - { - curSyllable = curSyllable.Substring(0, 1).ToUpper() + curSyllable.Substring(1); - _capitalize = false; - } - encryptedMessage.Append(curSyllable); - - if (random.Prob(SpecialCharacterChance)) - { - encryptedMessage.Append(SpecialCharacter); - } - else if (random.Prob(DotChance)) - { - encryptedMessage.Append(". "); - _capitalize = true; - } - else if (random.Prob(SpaceChance)) - { - encryptedMessage.Append(' '); - } - } - - var result = encryptedMessage.ToString(); - return result; - } - - private string ScrambleWithSeed(string message, int seed) + private string ScrambleWord(string word, int seed) { var random = new System.Random(seed); - var encryptedMessage = new StringBuilder(); - while (encryptedMessage.Length < message.Length) + while (encryptedMessage.Length < word.Length) { var curSyllable = random.Pick(Syllables); if (_capitalize) { - curSyllable = curSyllable.Substring(0, 1).ToUpper() + curSyllable.Substring(1); + curSyllable = string.Concat(curSyllable.Substring(0, 1).ToUpper(), curSyllable.AsSpan(1)); _capitalize = false; } encryptedMessage.Append(curSyllable); if (random.Prob(SpecialCharacterChance)) { - encryptedMessage.Append(SpecialCharacter); - } - else if (random.Prob(DotChance)) - { - encryptedMessage.Append(". "); - _capitalize = true; - } - else if (random.Prob(SpaceChance)) - { - encryptedMessage.Append(' '); + var character = GetSpecialCharacter(random); + if (character != null) + { + encryptedMessage.Append(character.Character); + _capitalize = character.Capitalize; + } } } @@ -172,4 +118,26 @@ private static string ExtractPunctuation(string input) return punctuationBuilder.ToString(); } + + private SyllablesSpecialCharacter? GetSpecialCharacter(System.Random random) + { + var weights = SpecialCharacters.ToDictionary(s => s, s => s.Weight); + if (weights == null || weights.Count <= 0) + return null; + + return SharedRandomExtensions.Pick(weights, random); + } +} + +[DataDefinition] +public sealed partial class SyllablesSpecialCharacter +{ + [DataField(required: true)] + public string Character; + + [DataField] + public float Weight = 1f; + + [DataField] + public bool Capitalize = false; } diff --git a/Content.Shared/SS220/Language/LanguagesPrototype.cs b/Content.Shared/SS220/Language/LanguagesPrototype.cs index 8249f1cf1c99..e700c8b39039 100644 --- a/Content.Shared/SS220/Language/LanguagesPrototype.cs +++ b/Content.Shared/SS220/Language/LanguagesPrototype.cs @@ -30,5 +30,5 @@ public sealed partial class LanguagePrototype : IPrototype /// The method used to scramble the message /// [DataField] - public ScrambleMethod ScrambleMethod = new RandomSyllablesScrambleMethod(); + public ScrambleMethod ScrambleMethod = new SyllablesScrambleMethod(); } diff --git a/Resources/Prototypes/SS220/Language/language.yml b/Resources/Prototypes/SS220/Language/language.yml index 3062e25fac11..741df0e929b8 100644 --- a/Resources/Prototypes/SS220/Language/language.yml +++ b/Resources/Prototypes/SS220/Language/language.yml @@ -12,7 +12,12 @@ key: gal name: "language-galacticcommon-name" description: "language-galacticcommon-desc" - scrambleMethod: !type:RandomSyllablesScrambleMethod + scrambleMethod: !type:SyllablesScrambleMethod + specialCharacters: + - character: " " + - character: ". " + capitalize: true + weight: 0.3 syllables: [бла, бла, бла, бле, мех, ньех, нах, ах, угу, увы] - type: language @@ -21,7 +26,12 @@ name: "language-solcommon-name" description: "language-solcommon-desc" color: "#2f2fad" - scrambleMethod: !type:RandomSyllablesScrambleMethod + scrambleMethod: !type:SyllablesScrambleMethod + specialCharacters: + - character: " " + - character: ". " + capitalize: true + weight: 0.3 syllables: [tao, shi, tzu, yi, com, be, is, i, op, vi, ed, lec, mo, cle, te, dis, e] - type: language @@ -30,8 +40,13 @@ name: "language-tradeband-name" description: "language-tradeband-desc" color: "#87451c" - scrambleMethod: !type:RandomSyllablesScrambleMethod - spaceChance: 1 + scrambleMethod: !type:SyllablesScrambleMethod + specialCharacterChance: 1 + specialCharacters: + - character: " " + - character: ". " + capitalize: true + weight: 0.3 syllables: [lorem, ipsum, dolor, sit, amet, consectetur, adipiscing, elit, sed, do, eiusmod, tempor, incididunt, ut, labore, et, dolore, magna, aliqua, ut, enim, ad, minim, veniam, quis, nostrud, exercitation, ullamco, laboris, nisi, ut, aliquip, ex, ea, commodo, consequat, duis, aute, irure, @@ -45,8 +60,13 @@ name: "language-gutter-name" description: "language-gutter-desc" color: "#7092BE" - scrambleMethod: !type:RandomSyllablesScrambleMethod - spaceChance: 0.55 + scrambleMethod: !type:SyllablesScrambleMethod + specialCharacterChance: 0.55 + specialCharacters: + - character: " " + - character: ". " + capitalize: true + weight: 0.3 syllables: [gra, ba, ba, breh, bra, rah, dur, ra, ro, gro, go, ber, bar, geh, heh, gra] - type: language @@ -55,8 +75,13 @@ name: "language-clownish-name" description: "language-clownish-desc" color: "#ff0000" - scrambleMethod: !type:RandomSyllablesScrambleMethod - spaceChance: 0.6 + scrambleMethod: !type:SyllablesScrambleMethod + specialCharacterChance: 0.6 + specialCharacters: + - character: " " + - character: ". " + capitalize: true + weight: 0.3 syllables: [хонк, cкуик, ойк, бонк, тут, наф, пуп, ви, вуб, ниф] - type: language @@ -65,8 +90,13 @@ name: "language-neorusskiya-name" description: "language-neorusskiya-desc" color: "#7c4848" - scrambleMethod: !type:RandomSyllablesScrambleMethod - spaceChance: 0.65 + scrambleMethod: !type:SyllablesScrambleMethod + specialCharacterChance: 0.65 + specialCharacters: + - character: " " + - character: ". " + capitalize: true + weight: 0.3 syllables: [dyen, bar, bota, vyek, tvo, slov, slav, syen, doup, vah, laz, gloz, yet, nyet, da, sky, glav, glaz, netz, doomat, zat, moch, boz, comy, vrad, vrade, tay, bli, ay, nov, livn, tolv, glaz, gliz, ouy, zet, yevt, dat, botat, nev, novy, vzy, @@ -82,7 +112,12 @@ name: "language-unathi-name" description: "language-unathi-desc" color: "#228B22" - scrambleMethod: !type:RandomSyllablesScrambleMethod + scrambleMethod: !type:SyllablesScrambleMethod + specialCharacters: + - character: " " + - character: ". " + capitalize: true + weight: 0.3 syllables: [za, az, ze, ez, zi, iz, zo, oz, zu, uz, zs, sz, ha, ah, he, eh, hi, ih, ho, oh, hu, uh, hs, sh, la, al, le, el, li, il, lo, ol, lu, ul, ls, sl, ka, ak, ke, ek, ki, ik, ko, ok, ku, uk, ks, sk, @@ -96,8 +131,13 @@ name: "language-siiktajr-name" description: "language-siiktajr-desc" color: "#803B56" - scrambleMethod: !type:RandomSyllablesScrambleMethod - spaceChance: 0.4 + scrambleMethod: !type:SyllablesScrambleMethod + specialCharacterChance: 0.4 + specialCharacters: + - character: " " + - character: ". " + capitalize: true + weight: 0.3 syllables: [rr, rrr, taj'r, kir, raj, kii, mir, kah, hrar, jun, kra, ahkъ, nal, vah, khaz, jri, ran, hal, nja, dar, darr, mi, jr'i, dynh, manq', rhe, zar, ketъ, rir, rik, @@ -111,7 +151,12 @@ name: "language-voxpidgin-name" description: "language-voxpidgin-desc" color: "#AA00AA" - scrambleMethod: !type:RandomSyllablesScrambleMethod + scrambleMethod: !type:SyllablesScrambleMethod + specialCharacters: + - character: " " + - character: ". " + capitalize: true + weight: 0.3 syllables: [ti, ti, ti, hi, hi, ki, ki, ki, ki, ya, ta, ha, ka, ya, yi, chi, cha, kah, SKRE, AHK, EHK, RAWK, KRA, AAA, EEE, KI, @@ -123,8 +168,13 @@ name: "language-rootspeak-name" description: "language-rootspeak-desc" color: "#804000" - scrambleMethod: !type:RandomSyllablesScrambleMethod - spaceChance: 0.3 + scrambleMethod: !type:SyllablesScrambleMethod + specialCharacterChance: 0.3 + specialCharacters: + - character: " " + - character: ". " + capitalize: true + weight: 0.3 syllables: [hs, zt, kr, st, sh] - type: language @@ -133,8 +183,13 @@ name: "language-bobblish-name" description: "language-bobblish-desc" color: "#0077AA" - scrambleMethod: !type:RandomSyllablesScrambleMethod - spaceChance: 0.6 + scrambleMethod: !type:SyllablesScrambleMethod + specialCharacterChance: 0.6 + specialCharacters: + - character: " " + - character: ". " + capitalize: true + weight: 0.3 syllables: [блоб, плап, поп, боп, буп, пламп, буб, баб, бламп] - type: language @@ -143,9 +198,15 @@ name: "language-tkachi-name" description: "language-tkachi-desc" color: "#869b29" - scrambleMethod: !type:RandomSyllablesScrambleMethod - spaceChance: 0.55 - specialCharacter: "-" + scrambleMethod: !type:SyllablesScrambleMethod + specialCharacterChance: 0.55 + specialCharacters: + - character: " " + - character: ". " + capitalize: true + weight: 0.3 + - character: "-" + weight: 0.5 syllables: [år, i, går, sek, mo, ff, ok, gj, ø, gå, la, le, lit, ygg, van, dår, næ, møt, idd, hvo, ja, på, han, så, ån, det, att, nå, gö, bra, int, tyc, om, när, två, må, dag, sjä, vii, vuo, eil, tun, käyt, teh, @@ -157,8 +218,13 @@ name: "language-eldwarf-name" description: "language-eldwarf-desc" color: "#515d63" - scrambleMethod: !type:RandomSyllablesScrambleMethod - spaceChance: 0.55 + scrambleMethod: !type:SyllablesScrambleMethod + specialCharacterChance: 0.55 + specialCharacters: + - character: " " + - character: ". " + capitalize: true + weight: 0.3 syllables: [вр, врон, рон, крон, друк, трым, бд, шкж, брм, рыт, грн, драш, клм, трк, врг, хрм, рд, клыт, зм, эмээ, гнык, зрм, длк, брг, грд, скрын, вродд, бдар, глтх, скрр, трг, бртх, хыкл, тр, крг, рдм, грыж, мд, гхрм, клм, прк, кнур] @@ -169,10 +235,15 @@ name: "language-arati-name" description: "language-arati-desc" color: "#68477a" - scrambleMethod: !type:RandomSyllablesScrambleMethod - spaceChance: 0.52 - specialCharacter: "'" - specialCharacterChance: 0.4 + scrambleMethod: !type:SyllablesScrambleMethod + specialCharacterChance: 0.52 + specialCharacters: + - character: " " + - character: ". " + capitalize: true + weight: 0.3 + - character: "'" + weight: 0.7 syllables: [шаш, хаш, раш, шар, хра, хашт, шара, шкар, храк, тар, хар, схр, карш, аш, шр, зз, ср, хаз, рашк, харш, рашн, шан, харз, шах, шарз, рашар, кар, харат, хш, харр, арш', ашан, шанн, хсар, ашат, хаа, хазт, рашта, зара, @@ -184,8 +255,13 @@ name: "language-canilunzt-name" description: "language-canilunzt-desc" color: "#B97A57" - scrambleMethod: !type:RandomSyllablesScrambleMethod - spaceChance: 0.45 + scrambleMethod: !type:SyllablesScrambleMethod + specialCharacterChance: 0.45 + specialCharacters: + - character: " " + - character: ". " + capitalize: true + weight: 0.3 syllables: [rur, ya, cen, rawr, bar, kuk, tek, qat, uk, wu, vuh, tah, tch, schz, auch, ist, ein, entch, zwichs, tut, mir, wo, bis, es, vor, nic, gro, lll, enem, zandt, tzch, noch, hel, ischt, far, wa, baram, iereng, tech, lach, @@ -199,8 +275,9 @@ name: "language-binary-name" description: "language-binary-desc" color: "#2cc2e8" - scrambleMethod: !type:RandomSyllablesScrambleMethod - spaceChance: 0.8 - dotChance: 0 + scrambleMethod: !type:SyllablesScrambleMethod + specialCharacterChance: 0.8 + specialCharacters: + - character: " " syllables: [1, 0, 01, 10, 11, 100, 101, 110, 111, 1000, 1001, 1010, 1011, 1100, 1110, 1111, 10000, 10001, 10010, 10011, 10100, 10101] From 2063f24f0fc219194c77d06a8840e9555cb48a8e Mon Sep 17 00:00:00 2001 From: Kirus59 <145689588+Kirus59@users.noreply.github.com> Date: Tue, 4 Mar 2025 19:47:57 +0300 Subject: [PATCH 31/48] change buttons text --- .../Controls/LanguageSettings/LanguageSettingsPopup.xaml.cs | 6 ++++-- Resources/Locale/ru-RU/ss220/language/language-ui.ftl | 1 + 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/Content.Client/SS220/UserInterface/System/Chat/Controls/LanguageSettings/LanguageSettingsPopup.xaml.cs b/Content.Client/SS220/UserInterface/System/Chat/Controls/LanguageSettings/LanguageSettingsPopup.xaml.cs index d5ccb793706f..f37cd8d9eb50 100644 --- a/Content.Client/SS220/UserInterface/System/Chat/Controls/LanguageSettings/LanguageSettingsPopup.xaml.cs +++ b/Content.Client/SS220/UserInterface/System/Chat/Controls/LanguageSettings/LanguageSettingsPopup.xaml.cs @@ -74,8 +74,10 @@ private void UpdateLanguageContainer(List? availableLanguages LanguageLabel.Text = Loc.GetString("language-settings-ui-select-default"); foreach (var language in availableLanguages) { - var name = $"{_language.KeyPrefix}{language.Key} {Loc.GetString(language.Name)}"; - var button = new Button() { Text = name }; + var languageKey = $"{_language.KeyPrefix}{language.Key}"; + var text = Loc.GetString("language-settings-ui-field-name", + ("name", Loc.GetString(language.Name)), ("key", languageKey)); + var button = new Button() { Text = text }; if (language.Description is { } desc) { diff --git a/Resources/Locale/ru-RU/ss220/language/language-ui.ftl b/Resources/Locale/ru-RU/ss220/language/language-ui.ftl index f3afbdf8e75a..9e847f92e2f1 100644 --- a/Resources/Locale/ru-RU/ss220/language/language-ui.ftl +++ b/Resources/Locale/ru-RU/ss220/language/language-ui.ftl @@ -1,2 +1,3 @@ language-settings-ui-no-languages = Вы не знаете дополнительных языков. language-settings-ui-select-default = Выберите язык по умолчанию: +language-settings-ui-field-name = { $name } (ключ { $key }) From a1c629c24894334b51f0bf94d5012cea448c2cd9 Mon Sep 17 00:00:00 2001 From: Kirus59 <145689588+Kirus59@users.noreply.github.com> Date: Tue, 4 Mar 2025 21:10:22 +0300 Subject: [PATCH 32/48] add canSpeak param --- .../LanguageSettingsPopup.xaml.cs | 7 +- .../EntityEffects/Effects/MakeSentient.cs | 2 +- Content.Server/PAI/PAISystem.cs | 2 +- .../SS220/Commands/LanguageCommands.cs | 13 ++- .../SS220/Language/LanguageSystem.cs | 32 +----- .../Language/Special/AddLanguageSpecial.cs | 2 +- Content.Server/Traits/TraitSystem.cs | 4 +- .../Language/Components/LanguageComponent.cs | 22 +++- .../Language/Systems/SharedLanguageSystem.cs | 102 +++++++++++++++--- Content.Shared/Traits/TraitPrototype.cs | 3 +- .../Mobs/Cyborgs/base_borg_chassis.yml | 6 +- .../Entities/Mobs/Species/arachnid.yml | 4 +- .../Entities/Mobs/Species/diona.yml | 4 +- .../Entities/Mobs/Species/dwarf.yml | 4 +- .../Entities/Mobs/Species/human.yml | 4 +- .../Prototypes/Entities/Mobs/Species/moth.yml | 4 +- .../Entities/Mobs/Species/reptilian.yml | 4 +- .../Entities/Mobs/Species/slime.yml | 4 +- .../Prototypes/Entities/Mobs/Species/vox.yml | 4 +- .../Prototypes/Entities/Objects/Fun/pai.yml | 4 +- .../Objects/Specific/Robotics/mmi.yml | 12 +-- .../SS220/Entities/Mobs/NPCs/animals.yml | 6 +- .../SS220/Entities/Mobs/Species/felinid.yml | 2 +- .../SS220/Entities/Mobs/Species/tajaran.yml | 4 +- .../SS220/Entities/Mobs/Species/vulpkanin.yml | 4 +- .../SS220/Entities/Objects/Fun/pai.yml | 4 +- Resources/Prototypes/SS220/Geras/slime.yml | 4 +- .../SS220/Traits/language_traits.yml | 28 ++--- 28 files changed, 177 insertions(+), 118 deletions(-) diff --git a/Content.Client/SS220/UserInterface/System/Chat/Controls/LanguageSettings/LanguageSettingsPopup.xaml.cs b/Content.Client/SS220/UserInterface/System/Chat/Controls/LanguageSettings/LanguageSettingsPopup.xaml.cs index f37cd8d9eb50..08b6bebd1c9d 100644 --- a/Content.Client/SS220/UserInterface/System/Chat/Controls/LanguageSettings/LanguageSettingsPopup.xaml.cs +++ b/Content.Client/SS220/UserInterface/System/Chat/Controls/LanguageSettings/LanguageSettingsPopup.xaml.cs @@ -41,9 +41,10 @@ public void Update() } var availableLanguages = new List(); - foreach (var id in comp.AvailableLanguages) + foreach (var def in comp.AvailableLanguages) { - if (!_language.TryGetLanguageById(id, out var language)) + if (!def.CanSpeak || + !_language.TryGetLanguageById(def.Id, out var language)) continue; availableLanguages.Add(language); @@ -52,7 +53,7 @@ public void Update() if (comp.SelectedLanguage is { } selectedLanguageId) { - _language.TryGetLanguageById(comp.SelectedLanguage, out var selectedLanguage); + _language.TryGetLanguageById(selectedLanguageId, out var selectedLanguage); UpdateSelectedLanguage(selectedLanguage); } else diff --git a/Content.Server/EntityEffects/Effects/MakeSentient.cs b/Content.Server/EntityEffects/Effects/MakeSentient.cs index ea1730f195c1..3e9897c995e9 100644 --- a/Content.Server/EntityEffects/Effects/MakeSentient.cs +++ b/Content.Server/EntityEffects/Effects/MakeSentient.cs @@ -28,7 +28,7 @@ public override void Effect(EntityEffectBaseArgs args) var languageComp = entityManager.EnsureComponent(uid); var languageSystem = entityManager.System(); - languageSystem.AddLanguage((uid, languageComp), languageSystem.GalacticLanguage); + languageSystem.AddLanguage((uid, languageComp), languageSystem.GalacticLanguage, true); // SS220-Add-Languages end // Stops from adding a ghost role to things like people who already have a mind diff --git a/Content.Server/PAI/PAISystem.cs b/Content.Server/PAI/PAISystem.cs index 8b2b5b142ae1..7683585e8e22 100644 --- a/Content.Server/PAI/PAISystem.cs +++ b/Content.Server/PAI/PAISystem.cs @@ -129,7 +129,7 @@ public void PAITurningOff(EntityUid uid) if (TryComp(uid, out var languageComp)) { _language.ClearLanguages((uid, languageComp)); - _language.AddLanguages((uid, languageComp), [_language.UniversalLanguage, _language.GalacticLanguage]); + _language.AddLanguages((uid, languageComp), [_language.UniversalLanguage, _language.GalacticLanguage], true); } // SS220-Add-Languages end } diff --git a/Content.Server/SS220/Commands/LanguageCommands.cs b/Content.Server/SS220/Commands/LanguageCommands.cs index dbdf59cbe0f7..57cfdcb90c8f 100644 --- a/Content.Server/SS220/Commands/LanguageCommands.cs +++ b/Content.Server/SS220/Commands/LanguageCommands.cs @@ -16,13 +16,13 @@ public sealed class AddLanguageCommand : IConsoleCommand public string Command => "addlanguage"; public string Description => Loc.GetString("cmd-language-add-desc"); - public string Help => "addlanguage "; + public string Help => "addlanguage "; public void Execute(IConsoleShell shell, string argStr, string[] args) { - if (args.Length != 2) + if (args.Length != 3) { - shell.WriteError("addlanguage "); + shell.WriteError("addlanguage "); return; } @@ -32,6 +32,11 @@ public void Execute(IConsoleShell shell, string argStr, string[] args) return; } + if (!bool.TryParse(args[2], out var canSpeak)) + { + return; + } + var languageId = args[1]; if (!_languageManager.TryGetLanguageById(languageId, out _)) @@ -47,7 +52,7 @@ public void Execute(IConsoleShell shell, string argStr, string[] args) } var languageSystem = _entities.System(); - if (languageSystem.AddLanguage((entityId, languageComp), languageId)) + if (languageSystem.AddLanguage((entityId, languageComp), languageId, canSpeak)) { shell.WriteLine(Loc.GetString("cmd-language-success-add")); } diff --git a/Content.Server/SS220/Language/LanguageSystem.cs b/Content.Server/SS220/Language/LanguageSystem.cs index 3dce04d5f3d9..184d39f69df6 100644 --- a/Content.Server/SS220/Language/LanguageSystem.cs +++ b/Content.Server/SS220/Language/LanguageSystem.cs @@ -20,9 +20,6 @@ public sealed partial class LanguageSystem : SharedLanguageSystem [Dependency] private readonly IPlayerManager _player = default!; [Dependency] private readonly INetManager _net = default!; - public readonly string UniversalLanguage = "Universal"; - public readonly string GalacticLanguage = "Galactic"; - // Cached values for one tick private static readonly Dictionary ScrambleCache = new(); @@ -118,7 +115,7 @@ public string SanitizeMessage(EntityUid source, EntityUid listener, string messa for (var i = 0; i < languageStrings.Count; i++) { var curString = languageStrings[i]; - if (CheckLanguage(listener, curString.Item2.ID)) + if (CanUnderstand(listener, curString.Item2.ID)) { sanitizedMessage.Append(curString.Item1); sanitizedColorlessMessage.Append(curString.Item1); @@ -167,7 +164,7 @@ public string SanitizeMessage(EntityUid source, EntityUid listener, string messa foreach (Match m in matches) { if (!TryGetLanguageFromString(m.Value, out var messageWithoutTags, out var language) || - !CheckLanguage(source, language.ID)) + !CanSpeak(source, language.ID)) { if (buffer.Item2 == null) { @@ -222,31 +219,6 @@ public bool TryGetLanguageFromString(string message, return messageWithoutTags != null && language != null; } - /// - /// Method that checks an entity for the presence of a prototype language - /// or for the presence of a universal language - /// - public bool CheckLanguage(EntityUid uid, string? languageId) - { - if (KnowsAllLanguages(uid) || - languageId == UniversalLanguage) - return true; - - if (languageId == null || - !TryComp(uid, out var comp)) - return false; - - return HasLanguage((uid, comp), languageId); - } - - /// - /// Checks whether the entity knows all languages. - /// - public bool KnowsAllLanguages(EntityUid uid) - { - return HasComp(uid); - } - /// /// A method to get a prototype language from an entity. /// If the entity does not have a language component, a universal language is assigned. diff --git a/Content.Server/SS220/Language/Special/AddLanguageSpecial.cs b/Content.Server/SS220/Language/Special/AddLanguageSpecial.cs index b5dad4000c34..3ac3590fa67f 100644 --- a/Content.Server/SS220/Language/Special/AddLanguageSpecial.cs +++ b/Content.Server/SS220/Language/Special/AddLanguageSpecial.cs @@ -19,6 +19,6 @@ public override void AfterEquip(EntityUid uid) var entMan = IoCManager.Resolve(); var languageSystem = entMan.System(); var languageComp = entMan.EnsureComponent(uid); - languageSystem.AddLanguages((uid, languageComp), Languages); + languageSystem.AddLanguages((uid, languageComp), Languages, true); } } diff --git a/Content.Server/Traits/TraitSystem.cs b/Content.Server/Traits/TraitSystem.cs index f84c23af7d85..321434d6438a 100644 --- a/Content.Server/Traits/TraitSystem.cs +++ b/Content.Server/Traits/TraitSystem.cs @@ -50,10 +50,10 @@ private void OnPlayerSpawnComplete(PlayerSpawnCompleteEvent args) // Add all components required by the prototype EntityManager.AddComponents(args.Mob, traitPrototype.Components, false); // SS220-Add-Languages begin - if (traitPrototype.LearnedLanguage != null) + if (traitPrototype.LearnedLanguages.Count > 0) { var language = EnsureComp(args.Mob); - _language.AddLanguage((args.Mob, language), traitPrototype.LearnedLanguage); + _language.AddLanguages((args.Mob, language), traitPrototype.LearnedLanguages); } // SS220-Add-Languages end diff --git a/Content.Shared/SS220/Language/Components/LanguageComponent.cs b/Content.Shared/SS220/Language/Components/LanguageComponent.cs index 01fbff9a7e4d..5f25c3868a97 100644 --- a/Content.Shared/SS220/Language/Components/LanguageComponent.cs +++ b/Content.Shared/SS220/Language/Components/LanguageComponent.cs @@ -17,13 +17,31 @@ public sealed partial class LanguageComponent : Component { /// /// Selected language in which the entity will speak. + /// If null, the universal language will be used. /// [DataField, AutoNetworkedField] public ProtoId? SelectedLanguage; /// - /// List of languages that the Entity speaks and understands. + /// List of languages that the Entity can speak. /// [DataField, AutoNetworkedField] - public List> AvailableLanguages = new(); + public List AvailableLanguages = new(); +} + +[DataDefinition] +[Serializable, NetSerializable] +public sealed partial class LanguageDefinition +{ + [DataField(required: true)] + public ProtoId Id; + + [DataField] + public bool CanSpeak = true; + + public LanguageDefinition(ProtoId id, bool canSpeak) + { + Id = id; + CanSpeak = canSpeak; + } } diff --git a/Content.Shared/SS220/Language/Systems/SharedLanguageSystem.cs b/Content.Shared/SS220/Language/Systems/SharedLanguageSystem.cs index fdc2e25344c7..172f19549401 100644 --- a/Content.Shared/SS220/Language/Systems/SharedLanguageSystem.cs +++ b/Content.Shared/SS220/Language/Systems/SharedLanguageSystem.cs @@ -1,4 +1,5 @@ // © 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.Ghost; using Content.Shared.SS220.Language.Components; namespace Content.Shared.SS220.Language.Systems; @@ -7,34 +8,59 @@ public abstract class SharedLanguageSystem : EntitySystem { [Dependency] private readonly LanguageManager _language = default!; + public readonly string UniversalLanguage = "Universal"; + public readonly string GalacticLanguage = "Galactic"; + #region Component /// /// Adds languages to from . /// - public void AddLanguages(Entity ent, IEnumerable languageIds) + /// Will entity be able to speak this language + public void AddLanguages(Entity ent, IEnumerable languageIds, bool canSpeak = false) { foreach (var language in languageIds) { - AddLanguage(ent, language); + AddLanguage(ent, language, canSpeak); + } + } + + /// + /// Adds a from list to + /// + public void AddLanguages(Entity ent, List definitions) + { + foreach (var def in definitions) + { + AddLanguage(ent, def); } } /// /// Adds language to the /// + /// Will entity be able to speak this language /// if successful added - public bool AddLanguage(Entity ent, string languageId) + public bool AddLanguage(Entity ent, string languageId, bool canSpeak = false) { - if (ent.Comp.AvailableLanguages.Contains(languageId) || - !_language.TryGetLanguageById(languageId, out var language)) + if (GetDefinition(ent, languageId) != null || + !_language.TryGetLanguageById(languageId, out _)) return false; - ent.Comp.AvailableLanguages.Add(languageId); - ent.Comp.SelectedLanguage ??= languageId; - Dirty(ent); + var newDef = new LanguageDefinition(languageId, canSpeak); + AddLanguage(ent, newDef); return true; } + /// + /// Adds a to the + /// + public void AddLanguage(Entity ent, LanguageDefinition definition) + { + ent.Comp.AvailableLanguages.Add(definition); + ent.Comp.SelectedLanguage ??= definition.Id; + Dirty(ent); + } + /// /// Clears /// @@ -51,7 +77,11 @@ public void ClearLanguages(Entity ent) /// if successful removed public bool RemoveLanguage(Entity ent, string languageId) { - if (ent.Comp.AvailableLanguages.Remove(languageId)) + var def = GetDefinition(ent, languageId); + if (def == null) + return false; + + if (ent.Comp.AvailableLanguages.Remove(def)) { if (ent.Comp.SelectedLanguage == languageId && !TrySetLanguage(ent, 0)) ent.Comp.SelectedLanguage = null; @@ -64,11 +94,21 @@ public bool RemoveLanguage(Entity ent, string languageId) } /// - /// Checks if contains this + /// Does the contain this language. /// - public static bool HasLanguage(Entity ent, string langageId) + public bool ContainsLanguage(Entity ent, string languageId, bool withCanSpeak = false) + { + var def = GetDefinition(ent, languageId); + if (def == null || + (withCanSpeak && !def.CanSpeak)) + return false; + + return true; + } + + public static LanguageDefinition? GetDefinition(Entity ent, string languageId) { - return ent.Comp.AvailableLanguages.Contains(langageId); + return ent.Comp.AvailableLanguages.Find(l => l.Id == languageId); } /// @@ -79,7 +119,7 @@ public bool TrySetLanguage(Entity ent, int index) if (ent.Comp.AvailableLanguages.Count <= index) return false; - ent.Comp.SelectedLanguage = ent.Comp.AvailableLanguages[index]; + ent.Comp.SelectedLanguage = ent.Comp.AvailableLanguages[index].Id; Dirty(ent); return true; } @@ -90,7 +130,7 @@ public bool TrySetLanguage(Entity ent, int index) /// public bool TrySetLanguage(Entity ent, string languageId) { - if (!HasLanguage(ent, languageId)) + if (!CanSpeak(ent, languageId)) return false; ent.Comp.SelectedLanguage = languageId; @@ -98,4 +138,38 @@ public bool TrySetLanguage(Entity ent, string languageId) return true; } #endregion + + /// + /// Checks whether the entity can speak this language. + /// + public bool CanSpeak(EntityUid uid, string languageId) + { + if (!TryComp(uid, out var comp)) + return false; + + return ContainsLanguage((uid, comp), languageId, true); + } + + /// + /// Checks whether the entity understands this language. + /// + public bool CanUnderstand(EntityUid uid, string languageId) + { + if (KnowsAllLanguages(uid) || + languageId == UniversalLanguage) + return true; + + if (!TryComp(uid, out var comp)) + return false; + + return ContainsLanguage((uid, comp), languageId); + } + + /// + /// Checks whether the entity knows all languages. + /// + public bool KnowsAllLanguages(EntityUid uid) + { + return HasComp(uid); + } } diff --git a/Content.Shared/Traits/TraitPrototype.cs b/Content.Shared/Traits/TraitPrototype.cs index f6198a8d14c5..b3d2a5ee85e2 100644 --- a/Content.Shared/Traits/TraitPrototype.cs +++ b/Content.Shared/Traits/TraitPrototype.cs @@ -1,3 +1,4 @@ +using Content.Shared.SS220.Language.Components; using Content.Shared.Whitelist; using Robust.Shared.Prototypes; @@ -62,5 +63,5 @@ public sealed partial class TraitPrototype : IPrototype public ProtoId? Category; [DataField] - public string? LearnedLanguage { get; private set; } // SS220-Add-Languages + public List LearnedLanguages = new(); // SS220-Add-Languages } diff --git a/Resources/Prototypes/Entities/Mobs/Cyborgs/base_borg_chassis.yml b/Resources/Prototypes/Entities/Mobs/Cyborgs/base_borg_chassis.yml index 7c12bb8e6afb..1e81bb0847ae 100644 --- a/Resources/Prototypes/Entities/Mobs/Cyborgs/base_borg_chassis.yml +++ b/Resources/Prototypes/Entities/Mobs/Cyborgs/base_borg_chassis.yml @@ -255,9 +255,9 @@ # SS220-Add-Languages begin - type: Language availableLanguages: - - Galactic - - Binary - - Universal + - id: Galactic + - id: Binary + - id: Universal # SS220-Add-Languages end - type: entity diff --git a/Resources/Prototypes/Entities/Mobs/Species/arachnid.yml b/Resources/Prototypes/Entities/Mobs/Species/arachnid.yml index 0bebfb7fed0b..049e94315c30 100644 --- a/Resources/Prototypes/Entities/Mobs/Species/arachnid.yml +++ b/Resources/Prototypes/Entities/Mobs/Species/arachnid.yml @@ -83,8 +83,8 @@ # SS220-Add-Languages begin - type: Language availableLanguages: - - Galactic - - Arati + - id: Galactic + - id: Arati # SS220-Add-Languages end - type: Vocal sounds: diff --git a/Resources/Prototypes/Entities/Mobs/Species/diona.yml b/Resources/Prototypes/Entities/Mobs/Species/diona.yml index 684a37851ab6..16478f7972ef 100644 --- a/Resources/Prototypes/Entities/Mobs/Species/diona.yml +++ b/Resources/Prototypes/Entities/Mobs/Species/diona.yml @@ -122,8 +122,8 @@ # SS220-Add-Languages begin - type: Language availableLanguages: - - Galactic - - Rootspeak + - id: Galactic + - id: Rootspeak # SS220-Add-Languages end - type: Inventory templateId: diona diff --git a/Resources/Prototypes/Entities/Mobs/Species/dwarf.yml b/Resources/Prototypes/Entities/Mobs/Species/dwarf.yml index 4156b951616e..8173b928cd4a 100644 --- a/Resources/Prototypes/Entities/Mobs/Species/dwarf.yml +++ b/Resources/Prototypes/Entities/Mobs/Species/dwarf.yml @@ -64,8 +64,8 @@ # SS220-Add-Languages begin - type: Language availableLanguages: - - Galactic - - Eldwarf + - id: Galactic + - id: Eldwarf # SS220-Add-Languages end - type: HumanoidAppearance species: Human diff --git a/Resources/Prototypes/Entities/Mobs/Species/human.yml b/Resources/Prototypes/Entities/Mobs/Species/human.yml index 6ad66d3dd948..eba08bb4afb0 100644 --- a/Resources/Prototypes/Entities/Mobs/Species/human.yml +++ b/Resources/Prototypes/Entities/Mobs/Species/human.yml @@ -23,8 +23,8 @@ # SS220-Add-Languages begin - type: Language availableLanguages: - - Galactic - - SolCommon + - id: Galactic + - id: SolCommon # SS220-Add-Languages end - type: Inventory femaleDisplacements: diff --git a/Resources/Prototypes/Entities/Mobs/Species/moth.yml b/Resources/Prototypes/Entities/Mobs/Species/moth.yml index 247528000fcb..08f07e56b751 100644 --- a/Resources/Prototypes/Entities/Mobs/Species/moth.yml +++ b/Resources/Prototypes/Entities/Mobs/Species/moth.yml @@ -143,8 +143,8 @@ # SS220-Add-Languages begin - type: Language availableLanguages: - - Galactic - - Tkachi + - id: Galactic + - id: Tkachi # SS220-Add-Languages end - type: Inventory femaleDisplacements: diff --git a/Resources/Prototypes/Entities/Mobs/Species/reptilian.yml b/Resources/Prototypes/Entities/Mobs/Species/reptilian.yml index 7e55ff7d7c99..ea49a81c7112 100644 --- a/Resources/Prototypes/Entities/Mobs/Species/reptilian.yml +++ b/Resources/Prototypes/Entities/Mobs/Species/reptilian.yml @@ -91,8 +91,8 @@ # SS220-Add-Languages begin - type: Language availableLanguages: - - Galactic - - Sintaunathi + - id: Galactic + - id: Sintaunathi # SS220-Add-Languages end - type: Inventory speciesId: reptilian diff --git a/Resources/Prototypes/Entities/Mobs/Species/slime.yml b/Resources/Prototypes/Entities/Mobs/Species/slime.yml index 88c8d0b5762e..50588a84cc31 100644 --- a/Resources/Prototypes/Entities/Mobs/Species/slime.yml +++ b/Resources/Prototypes/Entities/Mobs/Species/slime.yml @@ -144,8 +144,8 @@ # SS220-Add-Languages begin - type: Language availableLanguages: - - Galactic - - Bubblish + - id: Galactic + - id: Bubblish # SS220-Add-Languages end - type: Inventory femaleDisplacements: diff --git a/Resources/Prototypes/Entities/Mobs/Species/vox.yml b/Resources/Prototypes/Entities/Mobs/Species/vox.yml index 596eea502349..96a7a67ca039 100644 --- a/Resources/Prototypes/Entities/Mobs/Species/vox.yml +++ b/Resources/Prototypes/Entities/Mobs/Species/vox.yml @@ -128,8 +128,8 @@ # SS220-Add-Languages begin - type: Language availableLanguages: - - Galactic - - VoxPidgin + - id: Galactic + - id: VoxPidgin # SS220-Add-Languages end - type: Inventory speciesId: vox diff --git a/Resources/Prototypes/Entities/Objects/Fun/pai.yml b/Resources/Prototypes/Entities/Objects/Fun/pai.yml index dd6ca35af231..71f80451909f 100644 --- a/Resources/Prototypes/Entities/Objects/Fun/pai.yml +++ b/Resources/Prototypes/Entities/Objects/Fun/pai.yml @@ -84,8 +84,8 @@ # SS220-Add-Languages begin - type: Language availableLanguages: - - Galactic - - Universal + - id: Galactic + - id: Universal # SS220-Add-Languages end - type: entity diff --git a/Resources/Prototypes/Entities/Objects/Specific/Robotics/mmi.yml b/Resources/Prototypes/Entities/Objects/Specific/Robotics/mmi.yml index 81f848567945..4adf376a95c0 100644 --- a/Resources/Prototypes/Entities/Objects/Specific/Robotics/mmi.yml +++ b/Resources/Prototypes/Entities/Objects/Specific/Robotics/mmi.yml @@ -56,9 +56,9 @@ # SS220-Add-Languages begin - type: Language availableLanguages: - - Galactic - - Binary - - Universal + - id: Galactic + - id: Binary + - id: Universal # SS220-Add-Languages end - type: entity @@ -113,9 +113,9 @@ # SS220-Add-Languages begin - type: Language availableLanguages: - - Galactic - - Binary - - Universal + - id: Galactic + - id: Binary + - id: Universal # SS220-Add-Languages end - type: ActiveRadio channels: diff --git a/Resources/Prototypes/SS220/Entities/Mobs/NPCs/animals.yml b/Resources/Prototypes/SS220/Entities/Mobs/NPCs/animals.yml index 718483928784..f35fc411b8c5 100644 --- a/Resources/Prototypes/SS220/Entities/Mobs/NPCs/animals.yml +++ b/Resources/Prototypes/SS220/Entities/Mobs/NPCs/animals.yml @@ -272,9 +272,9 @@ netsync: false - type: Language availableLanguages: - - Galactic - - Binary - - Universal + - id: Galactic + - id: Binary + - id: Universal - type: entity name: крокодил diff --git a/Resources/Prototypes/SS220/Entities/Mobs/Species/felinid.yml b/Resources/Prototypes/SS220/Entities/Mobs/Species/felinid.yml index db8d531684c8..7bfd9d7badb4 100644 --- a/Resources/Prototypes/SS220/Entities/Mobs/Species/felinid.yml +++ b/Resources/Prototypes/SS220/Entities/Mobs/Species/felinid.yml @@ -113,7 +113,7 @@ chatEmoteCooldown: 5.0 - type: Language availableLanguages: - - Galactic + - id: Galactic - type: entity save: false diff --git a/Resources/Prototypes/SS220/Entities/Mobs/Species/tajaran.yml b/Resources/Prototypes/SS220/Entities/Mobs/Species/tajaran.yml index fa43c62af229..2e62048385b0 100644 --- a/Resources/Prototypes/SS220/Entities/Mobs/Species/tajaran.yml +++ b/Resources/Prototypes/SS220/Entities/Mobs/Species/tajaran.yml @@ -109,8 +109,8 @@ addAction: true - type: Language availableLanguages: - - Galactic - - Siiktajr + - id: Galactic + - id: Siiktajr - type: entity id: MobTajaranDummy diff --git a/Resources/Prototypes/SS220/Entities/Mobs/Species/vulpkanin.yml b/Resources/Prototypes/SS220/Entities/Mobs/Species/vulpkanin.yml index 55d5337505bd..9fbdff8a147f 100644 --- a/Resources/Prototypes/SS220/Entities/Mobs/Species/vulpkanin.yml +++ b/Resources/Prototypes/SS220/Entities/Mobs/Species/vulpkanin.yml @@ -71,8 +71,8 @@ Slash: 5.5 - type: Language availableLanguages: - - Galactic - - Canilunzt + - id: Galactic + - id: Canilunzt #если будет дальнейшее обсуждение и одобрение, займусь этой рассой для раундстартового состояния. Пока так diff --git a/Resources/Prototypes/SS220/Entities/Objects/Fun/pai.yml b/Resources/Prototypes/SS220/Entities/Objects/Fun/pai.yml index 4a50c0b1a5ec..ec3c16067d88 100644 --- a/Resources/Prototypes/SS220/Entities/Objects/Fun/pai.yml +++ b/Resources/Prototypes/SS220/Entities/Objects/Fun/pai.yml @@ -89,6 +89,6 @@ # SS220-Add-Languages begin - type: Language availableLanguages: - - Galactic - - Universal + - id: Galactic + - id: Universal # SS220-Add-Languages end diff --git a/Resources/Prototypes/SS220/Geras/slime.yml b/Resources/Prototypes/SS220/Geras/slime.yml index cd9a9fc6f0f6..d3c5d2c40168 100644 --- a/Resources/Prototypes/SS220/Geras/slime.yml +++ b/Resources/Prototypes/SS220/Geras/slime.yml @@ -35,6 +35,6 @@ # SS220-Add-Languages begin - type: Language availableLanguages: - - Galactic - - Bubblish + - id: Galactic + - id: Bubblish # SS220-Add-Languages end diff --git a/Resources/Prototypes/SS220/Traits/language_traits.yml b/Resources/Prototypes/SS220/Traits/language_traits.yml index d9a6b670141a..ce1b8e73cb13 100644 --- a/Resources/Prototypes/SS220/Traits/language_traits.yml +++ b/Resources/Prototypes/SS220/Traits/language_traits.yml @@ -4,11 +4,8 @@ description: "language-tradeband-desc" category: Languages cost: 1 - components: - - type: Language - availableLanguages: - - Tradeband - learnedLanguage: Tradeband + learnedLanguages: + - id: Gutter - type: trait id: GutterLanguage @@ -16,11 +13,8 @@ description: "language-gutter-desc" category: Languages cost: 1 - components: - - type: Language - availableLanguages: - - Gutter - learnedLanguage: Gutter + learnedLanguages: + - id: Gutter - type: trait id: ClownishLanguage @@ -28,11 +22,8 @@ description: "language-clownish-desc" category: Languages cost: 1 - components: - - type: Language - availableLanguages: - - Clownish - learnedLanguage: Clownish + learnedLanguages: + - id: Gutter - type: trait id: NeoRusskiyaLanguage @@ -40,8 +31,5 @@ description: "language-neorusskiya-desc" category: Languages cost: 1 - components: - - type: Language - availableLanguages: - - NeoRusskiya - learnedLanguage: NeoRusskiya + learnedLanguages: + - id: Gutter From 458d39fd126f98d30fc62394aa27243b1db43a6f Mon Sep 17 00:00:00 2001 From: Kirus59 <145689588+Kirus59@users.noreply.github.com> Date: Tue, 4 Mar 2025 21:34:22 +0300 Subject: [PATCH 33/48] add ScrambledLengthCoefficient --- .../SyllablesScrambleMethod.cs | 18 +++++++++++++----- .../Prototypes/SS220/Language/language.yml | 1 + 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/Content.Shared/SS220/Language/EncryptionMethods/SyllablesScrambleMethod.cs b/Content.Shared/SS220/Language/EncryptionMethods/SyllablesScrambleMethod.cs index 7b7ddef3f320..efd03bc674ea 100644 --- a/Content.Shared/SS220/Language/EncryptionMethods/SyllablesScrambleMethod.cs +++ b/Content.Shared/SS220/Language/EncryptionMethods/SyllablesScrambleMethod.cs @@ -25,6 +25,13 @@ public sealed partial class SyllablesScrambleMethod : ScrambleMethod [DataField] public float SpecialCharacterChance = 0.5f; + /// + /// Coefficient of how much the length of the scrambled message will differ from the original. + /// The shorter the syllables length, the higher the accuracy. + /// + [DataField] + public float ScrambledLengthCoefficient = 1f; + /// /// Special characters that can be inserted after a scrambled syllable /// @@ -73,8 +80,9 @@ public override string ScrambleMessage(string message, int? seed = null) private string ScrambleWord(string word, int seed) { var random = new System.Random(seed); - var encryptedMessage = new StringBuilder(); - while (encryptedMessage.Length < word.Length) + var scrambledMessage = new StringBuilder(); + var scrambledLength = word.Length * ScrambledLengthCoefficient; + while (scrambledMessage.Length < scrambledLength) { var curSyllable = random.Pick(Syllables); @@ -83,20 +91,20 @@ private string ScrambleWord(string word, int seed) curSyllable = string.Concat(curSyllable.Substring(0, 1).ToUpper(), curSyllable.AsSpan(1)); _capitalize = false; } - encryptedMessage.Append(curSyllable); + scrambledMessage.Append(curSyllable); if (random.Prob(SpecialCharacterChance)) { var character = GetSpecialCharacter(random); if (character != null) { - encryptedMessage.Append(character.Character); + scrambledMessage.Append(character.Character); _capitalize = character.Capitalize; } } } - var result = encryptedMessage.ToString(); + var result = scrambledMessage.ToString(); return result; } diff --git a/Resources/Prototypes/SS220/Language/language.yml b/Resources/Prototypes/SS220/Language/language.yml index 741df0e929b8..4b5b7da103ca 100644 --- a/Resources/Prototypes/SS220/Language/language.yml +++ b/Resources/Prototypes/SS220/Language/language.yml @@ -276,6 +276,7 @@ description: "language-binary-desc" color: "#2cc2e8" scrambleMethod: !type:SyllablesScrambleMethod + scrambledLengthCoefficient: 0.5 specialCharacterChance: 0.8 specialCharacters: - character: " " From 9c1f9e0a37fbde17752594aee1becc501e828c0d Mon Sep 17 00:00:00 2001 From: Bomjojuk Date: Wed, 5 Mar 2025 01:10:37 +0300 Subject: [PATCH 34/48] Pets languages, shorter keys --- .../Prototypes/Entities/Mobs/NPCs/pets.yml | 168 ++++++++++++++++++ .../Prototypes/SS220/Language/language.yml | 24 +-- .../Prototypes/SS220/Mobs/PetParrots.yml | 5 + 3 files changed, 185 insertions(+), 12 deletions(-) diff --git a/Resources/Prototypes/Entities/Mobs/NPCs/pets.yml b/Resources/Prototypes/Entities/Mobs/NPCs/pets.yml index 8532867a401e..0bbb2db8be2a 100644 --- a/Resources/Prototypes/Entities/Mobs/NPCs/pets.yml +++ b/Resources/Prototypes/Entities/Mobs/NPCs/pets.yml @@ -7,6 +7,13 @@ id: MobCorgiIan description: Favorite pet corgi. components: + #SS220 languages revive begin + - type: Language + availableLanguages: + - id: Galactic + - id: SolCommon + canSpeak: false + #SS220 languages revive end - type: Sprite drawdepth: Mobs sprite: Mobs/Pets/corgi.rsi @@ -43,6 +50,13 @@ id: MobCorgiIanOld description: Still the favorite pet corgi. Love his wheels. components: + #SS220 languages revive begin + - type: Language + availableLanguages: + - id: Galactic + - id: SolCommon + canSpeak: false + #SS220 languages revive end - type: Sprite layers: - map: ["enum.DamageStateVisualLayers.Base"] @@ -68,6 +82,13 @@ id: MobCorgiLisa description: Ian's favorite corgi. components: + #SS220 languages revive begin + - type: Language + availableLanguages: + - id: Galactic + - id: SolCommon + canSpeak: false + #SS220 languages revive end - type: Sprite layers: - map: ["enum.DamageStateVisualLayers.Base"] @@ -118,6 +139,13 @@ attributes: proper: true gender: male + #SS220 languages revive begin + - type: Language + availableLanguages: + - id: Galactic + - id: SolCommon + canSpeak: false + #SS220 languages revive end - type: Butcherable # A puppy? You monster... spawned: - id: FoodMeatCorgi @@ -155,6 +183,13 @@ - type: HTN rootTask: task: SimpleHostileCompound + #SS220 languages revive begin + - type: Language + availableLanguages: + - id: Galactic + - id: Siiktajr + canSpeak: false + #SS220 languages revive end - type: Grammar attributes: proper: true @@ -176,6 +211,13 @@ factions: - PetsNT - type: Grammar + #SS220 languages revive begin + - type: Language + availableLanguages: + - id: Galactic + - id: Siiktajr + canSpeak: false + #SS220 languages revive end attributes: proper: true gender: male @@ -206,6 +248,13 @@ - type: Grammar attributes: gender: male + #SS220 languages revive begin + - type: Language + availableLanguages: + - id: Galactic + - id: Siiktajr + canSpeak: false + #SS220 languages revive end - type: Tag tags: - CannotSuicide @@ -223,6 +272,13 @@ attributes: proper: true gender: male + #SS220 languages revive begin + - type: Language + availableLanguages: + - id: Galactic + - id: SolCommon + canSpeak: false + #SS220 languages revive end - type: Tag tags: - CannotSuicide @@ -247,6 +303,13 @@ - type: LyingDownOnBuckledEntity offset: -0.1, 0 #SS220 Add lying down on entity end + #SS220 languages revive begin + - type: Language + availableLanguages: + - id: Galactic + - id: Siiktajr + canSpeak: false + #SS220 languages revive end - type: Physics # 220 cat-emotes start - type: Speech @@ -318,6 +381,13 @@ layers: - map: ["enum.DamageStateVisualLayers.Base"] state: mcgriff + #SS220 languages revive begin + - type: Language + availableLanguages: + - id: Galactic + - id: SolCommon + canSpeak: false + #SS220 languages revive end - type: Physics - type: Fixtures fixtures: @@ -385,6 +455,13 @@ Base: paperwork_dead Dead: Base: paperwork_dead + #SS220 languages revive begin + - type: Language + availableLanguages: + - id: Galactic + - id: SolCommon + canSpeak: false + #SS220 languages revive end - type: Butcherable spawned: - id: FoodMeat @@ -411,6 +488,13 @@ layers: - map: ["enum.DamageStateVisualLayers.Base"] state: walter + #SS220 languages revive begin + - type: Language + availableLanguages: + - id: Galactic + - id: SolCommon + canSpeak: false + #SS220 languages revive end - type: Physics - type: Fixtures fixtures: @@ -475,6 +559,13 @@ attributes: proper: true gender: male + #SS220 languages revive begin + - type: Language + availableLanguages: + - id: Galactic + - id: SolCommon + canSpeak: false + #SS220 languages revive end - type: Tag tags: - CannotSuicide @@ -511,6 +602,13 @@ attributes: proper: true gender: female + #SS220 languages revive begin + - type: Language + availableLanguages: + - id: Galactic + - id: SolCommon + canSpeak: false + #SS220 languages revive end - type: Sprite drawdepth: Mobs sprite: Mobs/Animals/possum.rsi @@ -541,6 +639,13 @@ attributes: proper: true gender: female + #SS220 languages revive begin + - type: Language + availableLanguages: + - id: Galactic + - id: Tradeband #Cause cargo dep + canSpeak: false + #SS220 languages revive end - type: Tag tags: - CannotSuicide @@ -563,6 +668,13 @@ attributes: proper: true gender: male + #SS220 languages revive begin + - type: Language + availableLanguages: + - id: Galactic + - id: SolCommon + canSpeak: false + #SS220 languages revive end - type: Tag tags: - CannotSuicide @@ -587,6 +699,13 @@ amount: 3 - id: Telecrystal5 amount: 1 + #SS220 languages revive begin + - type: Language + availableLanguages: + - id: Galactic + - id: Canilunzt #Vulp gagaga + canSpeak: false + #SS220 languages revive end - type: Grammar attributes: proper: true @@ -617,6 +736,13 @@ noMovementLayers: movement: state: hamster-0 + #SS220 languages revive begin + - type: Language + availableLanguages: + - id: Galactic + - id: SolCommon + canSpeak: false + #SS220 languages revive end - type: GhostRole makeSentient: true allowSpeech: true @@ -664,6 +790,13 @@ interactSuccessSpawn: EffectHearts interactSuccessSound: path: /Audio/Animals/snake_hiss.ogg + #SS220 languages revive begin + - type: Language + availableLanguages: + - id: Galactic + - id: Arati + canSpeak: false + #SS220 languages revive end - type: NpcFactionMember factions: - PetsNT @@ -733,6 +866,13 @@ attributes: proper: true gender: female + #SS220 languages revive begin + - type: Language + availableLanguages: + - id: Galactic + - id: SolCommon + canSpeak: false + #SS220 languages revive end - type: Tag tags: - CannotSuicide @@ -761,6 +901,13 @@ state: aslime-_3 shader: unshaded - map: [ "head" ] + #SS220 languages revive begin + - type: Language + availableLanguages: + - id: Galactic + - id: Bubblish + canSpeak: false + #SS220 languages revive end - type: Inventory speciesId: slime templateId: head @@ -846,6 +993,13 @@ description: ghost-role-information-punpun-description rules: ghost-role-information-nonantagonist-rules - type: GhostTakeoverAvailable + #SS220 languages revive begin + - type: Language + availableLanguages: + - id: Galactic + - id: SolCommon + canSpeak: false + #SS220 languages revive end - type: Butcherable butcheringType: Spike spawned: @@ -887,6 +1041,13 @@ tags: - VimPilot - CannotSuicide + #SS220 languages revive begin + - type: Language + availableLanguages: + - id: Galactic + - id: SolCommon + canSpeak: false + #SS220 languages revive end - type: Grammar attributes: proper: true @@ -913,6 +1074,13 @@ - MobMask layer: - MobLayer + #SS220 languages revive begin + - type: Language + availableLanguages: + - id: Galactic + - id: Siiktajr + canSpeak: false + #SS220 languages revive end - type: Grammar attributes: gender: male diff --git a/Resources/Prototypes/SS220/Language/language.yml b/Resources/Prototypes/SS220/Language/language.yml index 4b5b7da103ca..7ced1cba52a3 100644 --- a/Resources/Prototypes/SS220/Language/language.yml +++ b/Resources/Prototypes/SS220/Language/language.yml @@ -9,7 +9,7 @@ # Galactic common lanaguges region: - type: language id: Galactic - key: gal + key: gl name: "language-galacticcommon-name" description: "language-galacticcommon-desc" scrambleMethod: !type:SyllablesScrambleMethod @@ -22,7 +22,7 @@ - type: language id: SolCommon - key: sol + key: sl name: "language-solcommon-name" description: "language-solcommon-desc" color: "#2f2fad" @@ -36,7 +36,7 @@ - type: language id: Tradeband - key: trade + key: trd name: "language-tradeband-name" description: "language-tradeband-desc" color: "#87451c" @@ -56,7 +56,7 @@ - type: language id: Gutter - key: gut + key: gt name: "language-gutter-name" description: "language-gutter-desc" color: "#7092BE" @@ -71,7 +71,7 @@ - type: language id: Clownish - key: clown + key: clw name: "language-clownish-name" description: "language-clownish-desc" color: "#ff0000" @@ -86,7 +86,7 @@ - type: language id: NeoRusskiya - key: neoru + key: ru name: "language-neorusskiya-name" description: "language-neorusskiya-desc" color: "#7c4848" @@ -108,7 +108,7 @@ # Race region: - type: language id: Sintaunathi - key: unathi + key: Sin name: "language-unathi-name" description: "language-unathi-desc" color: "#228B22" @@ -127,7 +127,7 @@ - type: language id: Siiktajr - key: tajr + key: Sii name: "language-siiktajr-name" description: "language-siiktajr-desc" color: "#803B56" @@ -164,7 +164,7 @@ - type: language id: Rootspeak - key: root + key: rt name: "language-rootspeak-name" description: "language-rootspeak-desc" color: "#804000" @@ -179,7 +179,7 @@ - type: language id: Bubblish - key: bubbl + key: bbl name: "language-bobblish-name" description: "language-bobblish-desc" color: "#0077AA" @@ -214,7 +214,7 @@ - type: language id: Eldwarf - key: dwarf + key: El name: "language-eldwarf-name" description: "language-eldwarf-desc" color: "#515d63" @@ -231,7 +231,7 @@ - type: language id: Arati - key: arati + key: ara name: "language-arati-name" description: "language-arati-desc" color: "#68477a" diff --git a/Resources/Prototypes/SS220/Mobs/PetParrots.yml b/Resources/Prototypes/SS220/Mobs/PetParrots.yml index 91a72778314b..8bfbf15b99d3 100644 --- a/Resources/Prototypes/SS220/Mobs/PetParrots.yml +++ b/Resources/Prototypes/SS220/Mobs/PetParrots.yml @@ -58,6 +58,11 @@ sprite: SS220/Mobs/Animals/cuckadoo.rsi - type: InteractionPopup successChance: 1 + - type: Language + availableLanguages: + - id: Galactic + - id: SolCommon + canSpeak: false - type: Grammar attributes: proper: true From c096c1b7c5ef8d4a30a010d43e688cd7710e8bf1 Mon Sep 17 00:00:00 2001 From: Bomjojuk Date: Wed, 5 Mar 2025 12:59:57 +0300 Subject: [PATCH 35/48] Codespeak, dwarf desc --- .../ru-RU/ss220/language/language-desc.ftl | 3 ++- .../ru-RU/ss220/language/language-name.ftl | 3 ++- .../Prototypes/SS220/Language/language.yml | 20 +++++++++++++++++-- 3 files changed, 22 insertions(+), 4 deletions(-) diff --git a/Resources/Locale/ru-RU/ss220/language/language-desc.ftl b/Resources/Locale/ru-RU/ss220/language/language-desc.ftl index a0f08487d5df..e1ca69e403d8 100644 --- a/Resources/Locale/ru-RU/ss220/language/language-desc.ftl +++ b/Resources/Locale/ru-RU/ss220/language/language-desc.ftl @@ -14,8 +14,9 @@ language-voxpidgin-desc = Общий язык различных воксов, language-rootspeak-desc = Скрипучий субголосый язык, на котором инстинктивно говорят дионы. Из-за уникального состава средней дионы фразы песни корней могут представлять собой комбинацию от одного до двенадцати отдельных голосов и нот. language-bobblish-desc = Произносится с помощью определенной комбинации хлопающих звуков, легко понимаемых другими слаймами. language-tkachi-desc = В основе языка лежат жужжащие звуки. Для построения речи используется ритмичность, длительность издаваемых звуков, интервал, интонация. -language-eldwarf-desc = Грубый язык с малым количеством гласных. +language-eldwarf-desc = Грубый язык с малым количеством гласных. Традиционно является языком, на котором дворфы разговаривают исключительно в окружении других цвергов, как метод скрытия от гнета республики. language-arati-desc = Достаточно грубый язык, в котором большое количество шипящих звуков. language-canilunzt-desc = Гортанный язык, на котором говорят и используют жители системы Ваззенда, состоит из рычания, лая, тявканья и интенсивного использования ушей и движений хвоста. # Misc language-binary-desc = Свободные протоколы связи и концентраторы маршрутизации для использования синтетиками. Большинство человеческих станций их поддерживают. +language-codespeak-desc = Кодовый язык, используемый агентами и ядерными оперативниками синдиката. Структурно представляет из себя сложнейший шифр, который для внешнего слушателя звучик как случайный набор напитков. diff --git a/Resources/Locale/ru-RU/ss220/language/language-name.ftl b/Resources/Locale/ru-RU/ss220/language/language-name.ftl index 029c6c1a2202..f5e4956d416c 100644 --- a/Resources/Locale/ru-RU/ss220/language/language-name.ftl +++ b/Resources/Locale/ru-RU/ss220/language/language-name.ftl @@ -16,4 +16,5 @@ language-eldwarf-name = Эл’Дварф language-arati-name = Арати language-canilunzt-name = Канилунц # Misc -language-binary-name = Бинарный канал \ No newline at end of file +language-binary-name = Бинарный канал +language-codespeak-name = Кодспик diff --git a/Resources/Prototypes/SS220/Language/language.yml b/Resources/Prototypes/SS220/Language/language.yml index 7ced1cba52a3..37c414e8c27c 100644 --- a/Resources/Prototypes/SS220/Language/language.yml +++ b/Resources/Prototypes/SS220/Language/language.yml @@ -54,6 +54,22 @@ nulla, pariatur, excepteur, sint, occaecat, cupidatat, non, proident, sunt, in, culpa, qui, officia, deserunt, mollit, anim, id, est, laborum] +- type: language + id: Codespeak + key: cod + name: "language-codespeak-name" + description: "language-codespeak-desc" + color: "#8f4a4b" + scrambleMethod: !type:SyllablesScrambleMethod + scrambleMethod: !type:SyllablesScrambleMethod + specialCharacterChance: 1 + specialCharacters: + - character: " " + - character: ". " + capitalize: true + weight: 0.3 + syllables: [виски, кола, тоник, водка, эхо, лима, альфа, дельта, русский, черный, белый, капитан] + - type: language id: Gutter key: gt @@ -108,7 +124,7 @@ # Race region: - type: language id: Sintaunathi - key: Sin + key: sin name: "language-unathi-name" description: "language-unathi-desc" color: "#228B22" @@ -127,7 +143,7 @@ - type: language id: Siiktajr - key: Sii + key: sii name: "language-siiktajr-name" description: "language-siiktajr-desc" color: "#803B56" From fe6b7ec49900f54a1b2c645e2e64b046792a0368 Mon Sep 17 00:00:00 2001 From: Bomjojuk Date: Wed, 5 Mar 2025 13:02:57 +0300 Subject: [PATCH 36/48] Fix scramble codespeak --- Resources/Prototypes/SS220/Language/language.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/Resources/Prototypes/SS220/Language/language.yml b/Resources/Prototypes/SS220/Language/language.yml index 37c414e8c27c..69c62d145db7 100644 --- a/Resources/Prototypes/SS220/Language/language.yml +++ b/Resources/Prototypes/SS220/Language/language.yml @@ -60,7 +60,6 @@ name: "language-codespeak-name" description: "language-codespeak-desc" color: "#8f4a4b" - scrambleMethod: !type:SyllablesScrambleMethod scrambleMethod: !type:SyllablesScrambleMethod specialCharacterChance: 1 specialCharacters: From 75d95957b7bf270aed12b565eca30401f585ebb6 Mon Sep 17 00:00:00 2001 From: Bomjojuk Date: Thu, 6 Mar 2025 12:48:41 +0300 Subject: [PATCH 37/48] codespeak, pets fix --- .../Prototypes/Entities/Mobs/NPCs/pets.yml | 23 +++++++++++++++++++ .../Prototypes/SS220/Language/language.yml | 6 ++--- 2 files changed, 26 insertions(+), 3 deletions(-) diff --git a/Resources/Prototypes/Entities/Mobs/NPCs/pets.yml b/Resources/Prototypes/Entities/Mobs/NPCs/pets.yml index 0bbb2db8be2a..108b0382dcb3 100644 --- a/Resources/Prototypes/Entities/Mobs/NPCs/pets.yml +++ b/Resources/Prototypes/Entities/Mobs/NPCs/pets.yml @@ -11,6 +11,7 @@ - type: Language availableLanguages: - id: Galactic + canSpeak: false - id: SolCommon canSpeak: false #SS220 languages revive end @@ -86,6 +87,7 @@ - type: Language availableLanguages: - id: Galactic + canSpeak: false - id: SolCommon canSpeak: false #SS220 languages revive end @@ -143,6 +145,7 @@ - type: Language availableLanguages: - id: Galactic + canSpeak: false - id: SolCommon canSpeak: false #SS220 languages revive end @@ -187,6 +190,7 @@ - type: Language availableLanguages: - id: Galactic + canSpeak: false - id: Siiktajr canSpeak: false #SS220 languages revive end @@ -215,6 +219,7 @@ - type: Language availableLanguages: - id: Galactic + canSpeak: false - id: Siiktajr canSpeak: false #SS220 languages revive end @@ -252,6 +257,7 @@ - type: Language availableLanguages: - id: Galactic + canSpeak: false - id: Siiktajr canSpeak: false #SS220 languages revive end @@ -276,6 +282,7 @@ - type: Language availableLanguages: - id: Galactic + canSpeak: false - id: SolCommon canSpeak: false #SS220 languages revive end @@ -307,6 +314,7 @@ - type: Language availableLanguages: - id: Galactic + canSpeak: false - id: Siiktajr canSpeak: false #SS220 languages revive end @@ -385,6 +393,7 @@ - type: Language availableLanguages: - id: Galactic + canSpeak: false - id: SolCommon canSpeak: false #SS220 languages revive end @@ -459,6 +468,7 @@ - type: Language availableLanguages: - id: Galactic + canSpeak: false - id: SolCommon canSpeak: false #SS220 languages revive end @@ -492,6 +502,7 @@ - type: Language availableLanguages: - id: Galactic + canSpeak: false - id: SolCommon canSpeak: false #SS220 languages revive end @@ -563,6 +574,7 @@ - type: Language availableLanguages: - id: Galactic + canSpeak: false - id: SolCommon canSpeak: false #SS220 languages revive end @@ -606,6 +618,7 @@ - type: Language availableLanguages: - id: Galactic + canSpeak: false - id: SolCommon canSpeak: false #SS220 languages revive end @@ -643,6 +656,7 @@ - type: Language availableLanguages: - id: Galactic + canSpeak: false - id: Tradeband #Cause cargo dep canSpeak: false #SS220 languages revive end @@ -672,6 +686,7 @@ - type: Language availableLanguages: - id: Galactic + canSpeak: false - id: SolCommon canSpeak: false #SS220 languages revive end @@ -703,6 +718,7 @@ - type: Language availableLanguages: - id: Galactic + canSpeak: false - id: Canilunzt #Vulp gagaga canSpeak: false #SS220 languages revive end @@ -740,6 +756,7 @@ - type: Language availableLanguages: - id: Galactic + canSpeak: false - id: SolCommon canSpeak: false #SS220 languages revive end @@ -794,6 +811,7 @@ - type: Language availableLanguages: - id: Galactic + canSpeak: false - id: Arati canSpeak: false #SS220 languages revive end @@ -870,6 +888,7 @@ - type: Language availableLanguages: - id: Galactic + canSpeak: false - id: SolCommon canSpeak: false #SS220 languages revive end @@ -905,6 +924,7 @@ - type: Language availableLanguages: - id: Galactic + canSpeak: false - id: Bubblish canSpeak: false #SS220 languages revive end @@ -997,6 +1017,7 @@ - type: Language availableLanguages: - id: Galactic + canSpeak: false - id: SolCommon canSpeak: false #SS220 languages revive end @@ -1045,6 +1066,7 @@ - type: Language availableLanguages: - id: Galactic + canSpeak: false - id: SolCommon canSpeak: false #SS220 languages revive end @@ -1078,6 +1100,7 @@ - type: Language availableLanguages: - id: Galactic + canSpeak: false - id: Siiktajr canSpeak: false #SS220 languages revive end diff --git a/Resources/Prototypes/SS220/Language/language.yml b/Resources/Prototypes/SS220/Language/language.yml index 69c62d145db7..39460ffda0d1 100644 --- a/Resources/Prototypes/SS220/Language/language.yml +++ b/Resources/Prototypes/SS220/Language/language.yml @@ -64,10 +64,10 @@ specialCharacterChance: 1 specialCharacters: - character: " " - - character: ". " - capitalize: true + - character: ", " + capitalize: false weight: 0.3 - syllables: [виски, кола, тоник, водка, эхо, лима, альфа, дельта, русский, черный, белый, капитан] + syllables: [виски, кола, тоник, водка, вермут, ром, эхо, лима, альфа, дельта, гамма, сигма, чарли, зомби, шлюз, бармен, повар, грузчик, учёный, инженер, карп, ИИ, борг, смена, цель, русский, перчатки, адвокат, пьяный, бипски, иан, морти, черный, белый, капитан, и] - type: language id: Gutter From c6e28cd74b632ae1e379689c5f91c29298a03255 Mon Sep 17 00:00:00 2001 From: Kirus59 <145689588+Kirus59@users.noreply.github.com> Date: Fri, 7 Mar 2025 19:13:44 +0300 Subject: [PATCH 38/48] logs fixes & tweaks --- Content.Server/Chat/Systems/ChatSystem.cs | 56 +++++++--- Content.Server/SS220/TTS/TTSSystem.cs | 121 ++++++++++++++++------ 2 files changed, 129 insertions(+), 48 deletions(-) diff --git a/Content.Server/Chat/Systems/ChatSystem.cs b/Content.Server/Chat/Systems/ChatSystem.cs index 234fda698e78..0dfb78f2ce87 100644 --- a/Content.Server/Chat/Systems/ChatSystem.cs +++ b/Content.Server/Chat/Systems/ChatSystem.cs @@ -506,6 +506,7 @@ private void SendEntitySpeak( name = FormattedMessage.EscapeText(name); // SS220-Add-Languages begin + Dictionary)> scrambledMsgReceiversDict = new(); foreach (var (session, data) in GetRecipients(source, VoiceRange)) { if (session.AttachedEntity is not { Valid: true } playerEntity) @@ -532,12 +533,20 @@ private void SendEntitySpeak( } else { - var scrambledEv = new EntitySpokeScrambledEvent(source, listener, scrambledMessage, scrambledColorlessMessage, originalMessage, null, false); - RaiseLocalEvent(scrambledEv); + if (scrambledMsgReceiversDict.TryGetValue(scrambledMessage, out var entities)) + entities.Item2.Add(listener); + else + scrambledMsgReceiversDict[scrambledMessage] = (scrambledColorlessMessage, [listener]); } //SS220-Add-Languages end } //SS220-Add-Languages begin + foreach (var (scrambledMsg, (colorlessMsg, reseivers)) in scrambledMsgReceiversDict) + { + var scrambledEv = new EntitySpokeScrambledEvent(source, reseivers, scrambledMsg, colorlessMsg, originalMessage, null, false); + RaiseLocalEvent(scrambledEv); + } + message = _languageSystem.SanitizeMessage(source, source, message, out _); //SendInVoiceRange(ChatChannel.Local, message, wrappedMessage, source, range); @@ -550,21 +559,22 @@ private void SendEntitySpeak( if (!HasComp(source) || hideLog) return; + var defaultLanguageName = _languageSystem.GetSelectedLanguage(source)?.Name ?? "none"; // SS220 languages if (originalMessage == message) { if (name != Name(source)) - _adminLogger.Add(LogType.Chat, LogImpact.Low, $"Say from {ToPrettyString(source):user} as {name}: {originalMessage}."); + _adminLogger.Add(LogType.Chat, LogImpact.Low, $"Say from {ToPrettyString(source):user} as {name}: {originalMessage}, defaultLanguage: {defaultLanguageName}."); // SS220 languages else - _adminLogger.Add(LogType.Chat, LogImpact.Low, $"Say from {ToPrettyString(source):user}: {originalMessage}."); + _adminLogger.Add(LogType.Chat, LogImpact.Low, $"Say from {ToPrettyString(source):user}: {originalMessage}, defaultLanguage: {defaultLanguageName}."); // SS220 languages } else { if (name != Name(source)) _adminLogger.Add(LogType.Chat, LogImpact.Low, - $"Say from {ToPrettyString(source):user} as {name}, original: {originalMessage}, transformed: {message}."); + $"Say from {ToPrettyString(source):user} as {name}, original: {originalMessage}, transformed: {message}, defaultLanguage: {defaultLanguageName}."); // SS220 languages else _adminLogger.Add(LogType.Chat, LogImpact.Low, - $"Say from {ToPrettyString(source):user}, original: {originalMessage}, transformed: {message}."); + $"Say from {ToPrettyString(source):user}, original: {originalMessage}, transformed: {message}, defaultLanguage: {defaultLanguageName}."); // SS220 languages } } @@ -585,6 +595,11 @@ private void SendEntityWhisper( if (message.Length == 0) return; + // SS220 languages begin + var transformedMessage = message; + message = _languageSystem.SanitizeMessage(source, source, message, out _); + // SS220 languages end + var obfuscatedMessage = ObfuscateMessageReadability(message, 0.2f); // get the entity's name by visual identity (if no override provided). @@ -612,6 +627,7 @@ private void SendEntityWhisper( var wrappedUnknownMessage = Loc.GetString("chat-manager-entity-whisper-unknown-wrap-message", ("message", FormattedMessage.EscapeText(obfuscatedMessage))); + Dictionary)> scrambledMsgReceiversDict = new(); // SS220 languages foreach (var (session, data) in GetRecipients(source, WhisperMuffledRange)) { EntityUid listener; @@ -652,8 +668,10 @@ private void SendEntityWhisper( } else { - var scrambledEv = new EntitySpokeScrambledEvent(source, listener, scrambledMessage, scrambledColorlessMessage, originalMessage, obfuscatedMessage, channel != null); - RaiseLocalEvent(scrambledEv); + if (scrambledMsgReceiversDict.TryGetValue(scrambledMessage, out var entities)) + entities.Item2.Add(listener); + else + scrambledMsgReceiversDict[scrambledMessage] = (scrambledColorlessMessage, [listener]); } // SS220-Add-Languages end } @@ -661,25 +679,33 @@ private void SendEntityWhisper( _replay.RecordServerMessage(new ChatMessage(ChatChannel.Whisper, message, wrappedMessage, GetNetEntity(source), null, MessageRangeHideChatForReplay(range))); // SS220 languages begin + foreach (var (scrambledMsg, (colorlessMsg, reseivers)) in scrambledMsgReceiversDict) + { + var scrambledEv = new EntitySpokeScrambledEvent(source, reseivers, scrambledMsg, colorlessMsg, originalMessage, obfuscatedMessage, channel != null); + RaiseLocalEvent(scrambledEv); + } + //var ev = new EntitySpokeEvent(source, message, originalMessage, channel, obfuscatedMessage); //RaiseLocalEvent(source, ev, true); + + var defaultLanguageName = _languageSystem.GetSelectedLanguage(source)?.Name ?? "none"; // SS220 languages end if (!hideLog) if (originalMessage == message) { if (name != Name(source)) - _adminLogger.Add(LogType.Chat, LogImpact.Low, $"Whisper from {ToPrettyString(source):user} as {name}: {originalMessage}."); + _adminLogger.Add(LogType.Chat, LogImpact.Low, $"Whisper from {ToPrettyString(source):user} as {name}: {originalMessage}, defaultLanguage: {defaultLanguageName}."); // SS220 languages else - _adminLogger.Add(LogType.Chat, LogImpact.Low, $"Whisper from {ToPrettyString(source):user}: {originalMessage}."); + _adminLogger.Add(LogType.Chat, LogImpact.Low, $"Whisper from {ToPrettyString(source):user}: {originalMessage}, defaultLanguage: {defaultLanguageName}."); // SS220 languages } else { if (name != Name(source)) _adminLogger.Add(LogType.Chat, LogImpact.Low, - $"Whisper from {ToPrettyString(source):user} as {name}, original: {originalMessage}, transformed: {message}."); + $"Whisper from {ToPrettyString(source):user} as {name}, original: {originalMessage}, transformed: {message}, defaultLanguage: {defaultLanguageName}."); // SS220 languages else _adminLogger.Add(LogType.Chat, LogImpact.Low, - $"Whisper from {ToPrettyString(source):user}, original: {originalMessage}, transformed: {message}."); + $"Whisper from {ToPrettyString(source):user}, original: {originalMessage}, transformed: {message}, defaultLanguage: {defaultLanguageName}."); // SS220 languages } } @@ -1244,17 +1270,17 @@ public RadioEventReceiver(EntityUid actor, EntityCoordinates playTarget) public sealed class EntitySpokeScrambledEvent : EntityEventArgs { public readonly EntityUid Source; - public readonly EntityUid Listener; + public readonly List Listeners; public readonly string Message; public readonly string ColorlessMessage; public readonly string OriginalMessage; public readonly string? ObfuscatedMessage; // not null if this was a whisper public readonly bool IsRadio; // radio message is always a whisper - public EntitySpokeScrambledEvent(EntityUid source, EntityUid listener, string message, string colorlessMessage, string originalMessage, string? obfuscatedMessage, bool isRadio) + public EntitySpokeScrambledEvent(EntityUid source, List listeners, string message, string colorlessMessage, string originalMessage, string? obfuscatedMessage, bool isRadio) { Source = source; - Listener = listener; + Listeners = listeners; Message = message; ColorlessMessage = colorlessMessage; OriginalMessage = originalMessage; diff --git a/Content.Server/SS220/TTS/TTSSystem.cs b/Content.Server/SS220/TTS/TTSSystem.cs index 66f1f4365e38..b8a5546fbd72 100644 --- a/Content.Server/SS220/TTS/TTSSystem.cs +++ b/Content.Server/SS220/TTS/TTSSystem.cs @@ -15,6 +15,7 @@ using Robust.Shared.Network; using Robust.Server.Player; using Robust.Shared.GameObjects; +using System.Linq; namespace Content.Server.SS220.TTS; @@ -192,24 +193,29 @@ private async void OnRequestGlobalTTS(RequestGlobalTTSEvent ev, EntitySessionEve private async void OnEntitySpoke(EntityUid uid, TTSComponent component, EntitySpokeEvent args) { - HandleEntitySpoke(uid, uid, args.Message, args.ObfuscatedMessage, args.IsRadio); + HandleEntitySpoke(uid, uid, args.Message, args.IsRadio, args.ObfuscatedMessage); } private async void OnEntitySpokeScrambled(EntitySpokeScrambledEvent args) { - HandleEntitySpoke(args.Source, args.Listener, args.ColorlessMessage, args.ObfuscatedMessage, args.IsRadio); + HandleEntitySpoke(args.Source, args.Listeners, args.ColorlessMessage, args.IsRadio, args.ObfuscatedMessage); } - private async void HandleEntitySpoke(EntityUid uid, EntityUid listener, string message, string? obfuscatedMessage, bool isRadio) + private async void HandleEntitySpoke(EntityUid source, EntityUid listener, string message, bool isRadio, string? obfuscatedMessage = null) + { + HandleEntitySpoke(source, [listener], message, isRadio, obfuscatedMessage); + } + + private async void HandleEntitySpoke(EntityUid source, IEnumerable receivers, string message, bool isRadio, string? obfuscatedMessage = null) { if (!_isEnabled || message.Length > MaxMessageChars || - !TryComp(uid, out var component) || + !TryComp(source, out var component) || component.VoicePrototypeId == null) return; var voiceId = component.VoicePrototypeId; - if (TryGetVoiceMaskUid(uid, out var maskUid)) + if (TryGetVoiceMaskUid(source, out var maskUid)) { var voiceEv = new TransformSpeakerVoiceEvent(maskUid.Value, voiceId); RaiseLocalEvent(maskUid.Value, voiceEv); @@ -223,25 +229,43 @@ private async void HandleEntitySpoke(EntityUid uid, EntityUid listener, string m if (obfuscatedMessage != null) { - HandleWhisperToOne(uid, listener, message, obfuscatedMessage, protoVoice.Speaker, isRadio); + HandleWhisperToMany(source, receivers, message, obfuscatedMessage, protoVoice.Speaker, isRadio); return; } - HandleSayToOne(uid, listener, message, protoVoice.Speaker); + HandleSayToMany(source, receivers, message, protoVoice.Speaker); + } + + private async void HandleSayToMany(EntityUid source, string message, string speaker) + { + var receivers = Filter.Pvs(source).Recipients; + HandleSayToMany(source, receivers, message, speaker); } - private async void HandleSayToMany(EntityUid uid, string message, string speaker) + private async void HandleSayToMany(EntityUid source, IEnumerable entities, string message, string speaker) + { + List receivers = new(); + foreach (var entity in entities) + { + if (_playerManager.TryGetSessionByEntity(entity, out var receiver) && receiver != null) + receivers.Add(receiver); + } + + HandleSayToMany(source, receivers, message, speaker); + } + + private async void HandleSayToMany(EntityUid source, IEnumerable receivers, string message, string speaker) { using var ttsResponse = await GenerateTts(message, speaker, TtsKind.Default); if (!ttsResponse.TryGetValue(out var audioData)) return; var playTtsMessage = new MsgPlayTts { Data = audioData, - SourceUid = GetNetEntity(uid), + SourceUid = GetNetEntity(source), }; - foreach (var receiver in Filter.Pvs(uid).Recipients) + foreach (var receiver in receivers) { - HandleSayToOne(uid, receiver, message, speaker, playTtsMessage); + HandleSayToOne(source, receiver, message, speaker, playTtsMessage); } } @@ -269,6 +293,31 @@ private async void HandleSayToOne(EntityUid source, ICommonSession receiver, str _netManager.ServerSendMessage(msgPlayTts, receiver.Channel); } + private async void HandleWhisperToMany(EntityUid source, IEnumerable entities, string message, string obfMessage, string speaker, bool isRadio) + { + List receivers = new(); + foreach (var entity in entities) + { + if (_playerManager.TryGetSessionByEntity(entity, out var receiver) && receiver != null) + receivers.Add(receiver); + } + + HandleWhisperToMany(source, receivers, message, obfMessage, speaker, isRadio); + } + + private async void HandleWhisperToMany(EntityUid source, IEnumerable receivers, string message, string obfMessage, string speaker, bool isRadio) + { + var ttsMessage = await GetMsgPlayTts(source, message, speaker, TtsKind.Whisper); + var obfTtsMessage = await GetMsgPlayTts(source, obfMessage, speaker, TtsKind.Whisper); + if (ttsMessage == null || obfTtsMessage == null) + return; + + foreach (var receiver in receivers) + { + HandleWhisperToOne(source, receiver, message, obfMessage, speaker, isRadio, ttsMessage, obfTtsMessage); + } + } + private async void HandleWhisperToOne(EntityUid uid, EntityUid target, string message, string obfMessage, string speaker, bool isRadio) { if (!_playerManager.TryGetSessionByEntity(target, out var receiver)) @@ -277,12 +326,18 @@ private async void HandleWhisperToOne(EntityUid uid, EntityUid target, string me HandleWhisperToOne(uid, receiver, message, obfMessage, speaker, isRadio); } - private async void HandleWhisperToOne(EntityUid source, ICommonSession receiver, string message, string obfMessage, string speaker, bool isRadio) + private async void HandleWhisperToOne(EntityUid source, + ICommonSession receiver, + string message, + string obfMessage, + string speaker, + bool isRadio, + MsgPlayTts? ttsMessage = null, + MsgPlayTts? obfTtsMessage = null) { if (!receiver.AttachedEntity.HasValue) return; - MsgPlayTts ttsMessage; var xformQuery = GetEntityQuery(); var sourcePos = _xforms.GetWorldPosition(xformQuery.GetComponent(source), xformQuery); @@ -294,32 +349,18 @@ private async void HandleWhisperToOne(EntityUid source, ICommonSession receiver, if (distance > ChatSystem.WhisperClearRange) { - using var ttsResponse = await GenerateTts(message, speaker, TtsKind.Whisper); - if (!ttsResponse.TryGetValue(out var audioData)) - return; + ttsMessage ??= await GetMsgPlayTts(source, message, speaker, TtsKind.Whisper); + if (ttsMessage == null) return; - ttsMessage = new MsgPlayTts - { - Data = audioData, - SourceUid = GetNetEntity(source), - Kind = TtsKind.Whisper, - }; + _netManager.ServerSendMessage(ttsMessage, receiver.Channel); } else { - using var obfTtsResponse = await GenerateTts(obfMessage, speaker, TtsKind.Whisper); - if (!obfTtsResponse.TryGetValue(out var obfAudioData)) - return; + obfTtsMessage ??= await GetMsgPlayTts(source, obfMessage, speaker, TtsKind.Whisper); + if (obfTtsMessage == null) return; - ttsMessage = new MsgPlayTts - { - Data = obfAudioData, - SourceUid = GetNetEntity(source), - Kind = TtsKind.Whisper, - }; + _netManager.ServerSendMessage(obfTtsMessage, receiver.Channel); } - - _netManager.ServerSendMessage(ttsMessage, receiver.Channel); } private async void HandleRadio(RadioEventReceiver[] receivers, string message, string speaker) @@ -371,6 +412,20 @@ private async void HandleRadio(RadioEventReceiver[] receivers, string message, s return default; } + + private async Task GetMsgPlayTts(EntityUid source, string message, string speaker, TtsKind kind = TtsKind.Default) + { + using var ttsResponse = await GenerateTts(message, speaker, TtsKind.Whisper); + if (!ttsResponse.TryGetValue(out var obfAudioData)) + return null; + + return new MsgPlayTts + { + Data = obfAudioData, + SourceUid = GetNetEntity(source), + Kind = TtsKind.Whisper, + }; + } } public sealed class TransformSpeakerVoiceEvent : EntityEventArgs From a3bfec2bf7a98ead5c9a467895c4648aee443129 Mon Sep 17 00:00:00 2001 From: Kirus59 <145689588+Kirus59@users.noreply.github.com> Date: Fri, 7 Mar 2025 20:25:14 +0300 Subject: [PATCH 39/48] commands fix --- .../SS220/Commands/LanguageCommands.cs | 129 +++++++++++------- .../ru-RU/ss220/language/language-cmd.ftl | 36 +++-- 2 files changed, 106 insertions(+), 59 deletions(-) diff --git a/Content.Server/SS220/Commands/LanguageCommands.cs b/Content.Server/SS220/Commands/LanguageCommands.cs index 57cfdcb90c8f..66beef9d64fc 100644 --- a/Content.Server/SS220/Commands/LanguageCommands.cs +++ b/Content.Server/SS220/Commands/LanguageCommands.cs @@ -9,135 +9,170 @@ namespace Content.Server.SS220.Commands; [AdminCommand(AdminFlags.Admin)] -public sealed class AddLanguageCommand : IConsoleCommand +public sealed class AddLanguageCommand : LocalizedCommands { - [Dependency] private readonly IEntityManager _entities = default!; + [Dependency] private readonly IEntityManager _entManager = default!; [Dependency] private readonly LanguageManager _languageManager = default!; - public string Command => "addlanguage"; - public string Description => Loc.GetString("cmd-language-add-desc"); - public string Help => "addlanguage "; + public override string Command => "addlanguage"; - public void Execute(IConsoleShell shell, string argStr, string[] args) + public override void Execute(IConsoleShell shell, string argStr, string[] args) { if (args.Length != 3) { - shell.WriteError("addlanguage "); + shell.WriteError(Loc.GetString("shell-wrong-arguments-number")); return; } - if (!EntityUid.TryParse(args[0], out var entityId)) + if (!NetEntity.TryParse(args[0], out var netEntity)) { - shell.WriteError(Loc.GetString("cmd-language-invalid-id")); + shell.WriteError(Loc.GetString("shell-entity-uid-must-be-number")); return; } - if (!bool.TryParse(args[2], out var canSpeak)) + if (!_entManager.TryGetEntity(netEntity, out var uid)) { + shell.WriteError(Loc.GetString("cmd-language-invalid-entity", ("uid", args[0]))); return; } var languageId = args[1]; - if (!_languageManager.TryGetLanguageById(languageId, out _)) { - shell.WriteError(Loc.GetString("cmd-language-proto-miss")); + shell.WriteError(Loc.GetString("cmd-language-proto-miss", ("id", languageId))); return; } - if (!_entities.TryGetComponent(entityId, out var languageComp)) + if (!bool.TryParse(args[2], out var canSpeak)) { - shell.WriteError(Loc.GetString("cmd-language-comp-miss")); + shell.WriteError(Loc.GetString("cmd-addlanguage-can-speak-not-bool")); return; } - var languageSystem = _entities.System(); - if (languageSystem.AddLanguage((entityId, languageComp), languageId, canSpeak)) + var languageComp = _entManager.EnsureComponent(uid.Value); + var languageSystem = _entManager.System(); + if (languageSystem.AddLanguage((uid.Value, languageComp), languageId, canSpeak)) { - shell.WriteLine(Loc.GetString("cmd-language-success-add")); + shell.WriteLine(Loc.GetString("cmd-addlanguage-success-add")); } else { - shell.WriteLine(Loc.GetString("cmd-language-already-have")); + shell.WriteLine(Loc.GetString("cmd-addlanguage-already-have")); } } + + public override CompletionResult GetCompletion(IConsoleShell shell, string[] args) + { + return args.Length switch + { + 1 => CompletionResult.FromHint("cmd-language-entity-uid"), + 2 => CompletionResult.FromHintOptions(CompletionHelper.PrototypeIDs(), Loc.GetString("cmd-language-id-list")), + 3 => CompletionResult.FromHintOptions(CompletionHelper.Booleans, Loc.GetString("cmd-addlanguage-can-speak")), + _ => CompletionResult.Empty + }; + } } [AdminCommand(AdminFlags.Admin)] -public sealed class RemoveLanguageCommand : IConsoleCommand +public sealed class RemoveLanguageCommand : LocalizedCommands { - [Dependency] private readonly IEntityManager _entities = default!; + [Dependency] private readonly IEntityManager _entManager = default!; - public string Command => "removelanguage"; - public string Description => Loc.GetString("cmd-language-remove-desc"); - public string Help => "removelanguage "; + public override string Command => "removelanguage"; - public void Execute(IConsoleShell shell, string argStr, string[] args) + public override void Execute(IConsoleShell shell, string argStr, string[] args) { if (args.Length != 2) { - shell.WriteError("removelanguage "); + shell.WriteError(Loc.GetString("shell-wrong-arguments-number")); return; } - if (!EntityUid.TryParse(args[0], out var entityId)) + if (!NetEntity.TryParse(args[0], out var netEntity)) { - shell.WriteError(Loc.GetString("cmd-language-invalid-id")); + shell.WriteError(Loc.GetString("shell-entity-uid-must-be-number")); return; } - var languageId = args[1]; + if (!_entManager.TryGetEntity(netEntity, out var uid)) + { + shell.WriteError(Loc.GetString("cmd-language-invalid-entity", ("uid", args[0]))); + return; + } - if (!_entities.TryGetComponent(entityId, out var languageComp)) + var languageId = args[1]; + if (!_entManager.TryGetComponent(uid, out var languageComp)) { shell.WriteError(Loc.GetString("cmd-language-comp-miss")); return; } - var languageSystem = _entities.System(); - if (languageSystem.RemoveLanguage((entityId, languageComp), languageId)) + var languageSystem = _entManager.System(); + if (languageSystem.RemoveLanguage((uid.Value, languageComp), languageId)) { - shell.WriteLine(Loc.GetString("cmd-language-succes-remove")); + shell.WriteLine(Loc.GetString("cmd-removelanguage-success")); } else { - shell.WriteLine(Loc.GetString("cmd-language-fail-remove")); + shell.WriteLine(Loc.GetString("cmd-removelanguage-fail")); } } + + public override CompletionResult GetCompletion(IConsoleShell shell, string[] args) + { + return args.Length switch + { + 1 => CompletionResult.FromHint("cmd-language-entity-uid"), + 2 => CompletionResult.FromHintOptions(CompletionHelper.PrototypeIDs(), Loc.GetString("cmd-language-id-list")), + _ => CompletionResult.Empty + }; + } } [AdminCommand(AdminFlags.Admin)] -public sealed class ClearLanguagesCommand : IConsoleCommand +public sealed class ClearLanguagesCommand : LocalizedCommands { - [Dependency] private readonly IEntityManager _entities = default!; + [Dependency] private readonly IEntityManager _entManager = default!; - public string Command => "clearlanguages"; - public string Description => Loc.GetString("cmd-language-clear-desc"); - public string Help => "clearlanguages "; + public override string Command => "clearlanguages"; - public void Execute(IConsoleShell shell, string argStr, string[] args) + public override void Execute(IConsoleShell shell, string argStr, string[] args) { if (args.Length != 1) { - shell.WriteError("clearlanguages "); + shell.WriteError(Loc.GetString("shell-wrong-arguments-number")); return; } - if (!EntityUid.TryParse(args[0], out var entityId)) + if (!NetEntity.TryParse(args[0], out var netEntity)) { - shell.WriteError(Loc.GetString("cmd-language-invalid-id")); + shell.WriteError(Loc.GetString("shell-entity-uid-must-be-number")); return; } - if (!_entities.TryGetComponent(entityId, out var languageComp)) + if (!_entManager.TryGetEntity(netEntity, out var uid)) + { + shell.WriteError(Loc.GetString("cmd-language-invalid-entity", ("uid", args[0]))); + return; + } + + if (!_entManager.TryGetComponent(uid, out var languageComp)) { shell.WriteError(Loc.GetString("cmd-language-comp-miss")); return; } - var languageSystem = _entities.System(); - languageSystem.ClearLanguages((entityId, languageComp)); - shell.WriteLine(Loc.GetString("cmd-language-clear")); + var languageSystem = _entManager.System(); + languageSystem.ClearLanguages((uid.Value, languageComp)); + shell.WriteLine(Loc.GetString("cmd-clearlanguages-success")); } -} + public override CompletionResult GetCompletion(IConsoleShell shell, string[] args) + { + return args.Length switch + { + 1 => CompletionResult.FromHint("cmd-language-entity-uid"), + _ => CompletionResult.Empty + }; + } +} diff --git a/Resources/Locale/ru-RU/ss220/language/language-cmd.ftl b/Resources/Locale/ru-RU/ss220/language/language-cmd.ftl index ceec4fdcbc71..83c3f5cbfd28 100644 --- a/Resources/Locale/ru-RU/ss220/language/language-cmd.ftl +++ b/Resources/Locale/ru-RU/ss220/language/language-cmd.ftl @@ -1,13 +1,25 @@ -# Desc -cmd-language-add-desc = Добавляет язык в LanguageComponent энтити -cmd-language-remove-desc = Удаляет язык из LanguageComponent энтити -cmd-language-clear-desc = Удаляет все языки из LanguageComponent энтити -# Message -cmd-language-invalid-id = Некорректный энтити ID +cmd-language-invalid-arguments = Неверное количество аргументов +cmd-language-proto-miss = Не найден прототип языка с id: { $id } +cmd-language-invalid-entity = Не найден энтити с id: { $uid } +cmd-language-entity-uid = [id энтити] +cmd-language-id-list = [id языка] cmd-language-comp-miss = У энтити отсутсвует LanguageComponent -cmd-language-proto-miss = Некорректный прототип языка -cmd-language-success-add = Язык успешно добавлен -cmd-language-succes-remove = Язык удален -cmd-language-fail-remove = Энтити не обладает таким языком -cmd-language-already-have = Энтити уже знает этот язык -cmd-language-clear = Все языки энтити - удалены \ No newline at end of file + +# Add +cmd-addlanguage-desc = Добавляет язык в LanguageComponent энтити +cmd-addlanguage-help = Использование: addlanguage +cmd-addlanguage-can-speak = [Может говорить] +cmd-addlanguage-can-speak-not-bool = должно быть true или false +cmd-addlanguage-success-add = Язык успешно добавлен +cmd-addlanguage-already-have = Энтити уже знает этот язык + +# Remove +cmd-removelanguage-desc = Удаляет язык из LanguageComponent энтити +cmd-removelanguage-help = Использование: removelanguage +cmd-removelanguage-success = Язык удален +cmd-removelanguage-fail = Энтити не обладает таким языком + +# Clear +cmd-clearlanguages-desc = Удаляет все языки из LanguageComponent энтити +cmd-clearlanguages-help = Использование: clearlanguages +cmd-clearlanguages-success = Все языки энтити - удалены From a610e60f788d22157a23a08d77dbe494f2986d20 Mon Sep 17 00:00:00 2001 From: Bomjojuk Date: Sun, 9 Mar 2025 00:50:12 +0300 Subject: [PATCH 40/48] Borgs languages --- .../Mobs/Cyborgs/base_borg_chassis.yml | 30 +++++++++++++++++ .../Entities/Mobs/Cyborgs/borg_chassis.yml | 33 ++++++++++++++++++- .../Entities/Mobs/Player/silicon.yml | 17 ++++++++++ 3 files changed, 79 insertions(+), 1 deletion(-) diff --git a/Resources/Prototypes/Entities/Mobs/Cyborgs/base_borg_chassis.yml b/Resources/Prototypes/Entities/Mobs/Cyborgs/base_borg_chassis.yml index 1e81bb0847ae..f0e2bdb8fd82 100644 --- a/Resources/Prototypes/Entities/Mobs/Cyborgs/base_borg_chassis.yml +++ b/Resources/Prototypes/Entities/Mobs/Cyborgs/base_borg_chassis.yml @@ -359,6 +359,36 @@ - AllAccess #Randomized access would be fun. AllAccess is the best i can think of right now that does make it too hard for it to enter the station or navigate it.. - type: AccessReader access: [["Command"], ["Research"]] + - type: Language + availableLanguages: + - id: Galactic + - id: SolCommon + canSpeak: false + - id: Tradeband + canSpeak: false + - id: Gutter + canSpeak: false + - id: Clownish + canSpeak: false + - id: NeoRusskiya + canSpeak: false + - id: Sintaunathi + canSpeak: false + - id: Siiktajr + canSpeak: false + - id: VoxPidgin + canSpeak: false + - id: Rootspeak + canSpeak: false + - id: Bubblish + canSpeak: false + - id: Tkachi + canSpeak: false + - id: Arati + canSpeak: false + - id: Canilunzt + canSpeak: false + - id: Binary - type: StartIonStormed ionStormAmount: 3 - type: IonStormTarget diff --git a/Resources/Prototypes/Entities/Mobs/Cyborgs/borg_chassis.yml b/Resources/Prototypes/Entities/Mobs/Cyborgs/borg_chassis.yml index 87b8d54a9773..8a2c8e50ed6a 100644 --- a/Resources/Prototypes/Entities/Mobs/Cyborgs/borg_chassis.yml +++ b/Resources/Prototypes/Entities/Mobs/Cyborgs/borg_chassis.yml @@ -87,6 +87,37 @@ name: syndicate assault cyborg description: A lean, mean killing machine with access to a variety of deadly modules. components: + - type: Language + availableLanguages: + - id: Galactic + - id: SolCommon + canSpeak: false + - id: Tradeband + canSpeak: false + - id: Gutter + canSpeak: false + - id: Clownish + canSpeak: false + - id: NeoRusskiya + canSpeak: false + - id: Sintaunathi + canSpeak: false + - id: Siiktajr + canSpeak: false + - id: VoxPidgin + canSpeak: false + - id: Rootspeak + canSpeak: false + - id: Bubblish + canSpeak: false + - id: Tkachi + canSpeak: false + - id: Arati + canSpeak: false + - id: Canilunzt + canSpeak: false + - id: Binary + - id: Codespeak - type: Sprite layers: - state: synd_sec @@ -218,4 +249,4 @@ interactSuccessString: petting-success-derelict-cyborg interactFailureString: petting-failure-derelict-cyborg interactSuccessSound: - path: /Audio/Ambience/Objects/periodic_beep.ogg \ No newline at end of file + path: /Audio/Ambience/Objects/periodic_beep.ogg diff --git a/Resources/Prototypes/Entities/Mobs/Player/silicon.yml b/Resources/Prototypes/Entities/Mobs/Player/silicon.yml index a2b76cafbdd3..9e738b37dcce 100644 --- a/Resources/Prototypes/Entities/Mobs/Player/silicon.yml +++ b/Resources/Prototypes/Entities/Mobs/Player/silicon.yml @@ -486,6 +486,23 @@ visible: false - type: BlockMovement blockInteraction: false + - type: Language + availableLanguages: + - id: Galactic + - id: SolCommon + - id: Tradeband + - id: Gutter + - id: Clownish + - id: NeoRusskiya + - id: Sintaunathi + - id: Siiktajr + - id: VoxPidgin + - id: Rootspeak + - id: Bubblish + - id: Tkachi + - id: Arati + - id: Canilunzt + - id: Binary - type: SiliconLawProvider laws: Crewsimov - type: SiliconLawBound From e2196e1e4e36d9af2813682583227ee6c8581b49 Mon Sep 17 00:00:00 2001 From: Bomjojuk Date: Sun, 9 Mar 2025 01:01:23 +0300 Subject: [PATCH 41/48] Add comments --- .../Prototypes/Entities/Mobs/Cyborgs/base_borg_chassis.yml | 2 ++ Resources/Prototypes/Entities/Mobs/Cyborgs/borg_chassis.yml | 2 ++ Resources/Prototypes/Entities/Mobs/Player/silicon.yml | 2 ++ 3 files changed, 6 insertions(+) diff --git a/Resources/Prototypes/Entities/Mobs/Cyborgs/base_borg_chassis.yml b/Resources/Prototypes/Entities/Mobs/Cyborgs/base_borg_chassis.yml index f0e2bdb8fd82..bfd004075b46 100644 --- a/Resources/Prototypes/Entities/Mobs/Cyborgs/base_borg_chassis.yml +++ b/Resources/Prototypes/Entities/Mobs/Cyborgs/base_borg_chassis.yml @@ -359,6 +359,7 @@ - AllAccess #Randomized access would be fun. AllAccess is the best i can think of right now that does make it too hard for it to enter the station or navigate it.. - type: AccessReader access: [["Command"], ["Research"]] +#SS220 languages revive begin - type: Language availableLanguages: - id: Galactic @@ -389,6 +390,7 @@ - id: Canilunzt canSpeak: false - id: Binary +#SS220 languages revive end - type: StartIonStormed ionStormAmount: 3 - type: IonStormTarget diff --git a/Resources/Prototypes/Entities/Mobs/Cyborgs/borg_chassis.yml b/Resources/Prototypes/Entities/Mobs/Cyborgs/borg_chassis.yml index 8a2c8e50ed6a..7b640144eea4 100644 --- a/Resources/Prototypes/Entities/Mobs/Cyborgs/borg_chassis.yml +++ b/Resources/Prototypes/Entities/Mobs/Cyborgs/borg_chassis.yml @@ -87,6 +87,7 @@ name: syndicate assault cyborg description: A lean, mean killing machine with access to a variety of deadly modules. components: +#SS220 languages revive begin - type: Language availableLanguages: - id: Galactic @@ -118,6 +119,7 @@ canSpeak: false - id: Binary - id: Codespeak +#SS220 languages revive end - type: Sprite layers: - state: synd_sec diff --git a/Resources/Prototypes/Entities/Mobs/Player/silicon.yml b/Resources/Prototypes/Entities/Mobs/Player/silicon.yml index 9e738b37dcce..dfd3067a87a2 100644 --- a/Resources/Prototypes/Entities/Mobs/Player/silicon.yml +++ b/Resources/Prototypes/Entities/Mobs/Player/silicon.yml @@ -486,6 +486,7 @@ visible: false - type: BlockMovement blockInteraction: false +#SS220 languages revive begin - type: Language availableLanguages: - id: Galactic @@ -503,6 +504,7 @@ - id: Arati - id: Canilunzt - id: Binary +#SS220 languages revive end - type: SiliconLawProvider laws: Crewsimov - type: SiliconLawBound From 272c998a227fc1de72913f7a5f4aaa8ba4d5c360 Mon Sep 17 00:00:00 2001 From: Kirus59 <145689588+Kirus59@users.noreply.github.com> Date: Sun, 9 Mar 2025 10:04:53 +0300 Subject: [PATCH 42/48] fix traits --- Content.Server/Traits/TraitSystem.cs | 7 ++++++- Resources/Prototypes/SS220/Traits/language_traits.yml | 6 +++--- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/Content.Server/Traits/TraitSystem.cs b/Content.Server/Traits/TraitSystem.cs index 321434d6438a..de48b7239216 100644 --- a/Content.Server/Traits/TraitSystem.cs +++ b/Content.Server/Traits/TraitSystem.cs @@ -48,7 +48,12 @@ private void OnPlayerSpawnComplete(PlayerSpawnCompleteEvent args) continue; // Add all components required by the prototype - EntityManager.AddComponents(args.Mob, traitPrototype.Components, false); + // SS220 fix null components begin + if (traitPrototype.Components is { } components) + EntityManager.AddComponents(args.Mob, components, false); + + // EntityManager.AddComponents(args.Mob, traitPrototype.Components, false); + // SS220 fix null components end // SS220-Add-Languages begin if (traitPrototype.LearnedLanguages.Count > 0) { diff --git a/Resources/Prototypes/SS220/Traits/language_traits.yml b/Resources/Prototypes/SS220/Traits/language_traits.yml index ce1b8e73cb13..1b6b70f180fc 100644 --- a/Resources/Prototypes/SS220/Traits/language_traits.yml +++ b/Resources/Prototypes/SS220/Traits/language_traits.yml @@ -5,7 +5,7 @@ category: Languages cost: 1 learnedLanguages: - - id: Gutter + - id: Tradeband - type: trait id: GutterLanguage @@ -23,7 +23,7 @@ category: Languages cost: 1 learnedLanguages: - - id: Gutter + - id: Clownish - type: trait id: NeoRusskiyaLanguage @@ -32,4 +32,4 @@ category: Languages cost: 1 learnedLanguages: - - id: Gutter + - id: NeoRusskiya From 78d8bc799ba83668562d248ca1552567b3d31a1c Mon Sep 17 00:00:00 2001 From: Kirus59 <145689588+Kirus59@users.noreply.github.com> Date: Sun, 9 Mar 2025 10:50:59 +0300 Subject: [PATCH 43/48] add languages limit --- Content.Server/Chat/Systems/ChatSystem.cs | 8 ++++++ .../SS220/Language/LanguageSystem.cs | 25 ++++++++++++++++++- Content.Shared/SS220/CCVars/CCVars220.cs | 6 +++++ .../ru-RU/ss220/language/language-system.ftl | 1 + 4 files changed, 39 insertions(+), 1 deletion(-) create mode 100644 Resources/Locale/ru-RU/ss220/language/language-system.ftl diff --git a/Content.Server/Chat/Systems/ChatSystem.cs b/Content.Server/Chat/Systems/ChatSystem.cs index 0dfb78f2ce87..c55ecec548cf 100644 --- a/Content.Server/Chat/Systems/ChatSystem.cs +++ b/Content.Server/Chat/Systems/ChatSystem.cs @@ -888,6 +888,14 @@ private bool CanSendInGame(string message, IConsoleShell? shell = null, ICommonS return false; } + // SS220 languages begin + if (_languageSystem.MessageLanguagesLimit(player.AttachedEntity.Value, message, out var reason)) + { + _chatManager.DispatchServerMessage(player, reason); + return false; + } + // SS220 languages end + return !_chatManager.MessageCharacterLimit(player, message); } diff --git a/Content.Server/SS220/Language/LanguageSystem.cs b/Content.Server/SS220/Language/LanguageSystem.cs index 184d39f69df6..9e44b8973391 100644 --- a/Content.Server/SS220/Language/LanguageSystem.cs +++ b/Content.Server/SS220/Language/LanguageSystem.cs @@ -1,7 +1,6 @@ // © SS220, An EULA/CLA with a hosting restriction, full text: https://raw.githubusercontent.com/SerbiaStrong-220/space-station-14/master/CLA.txt using Content.Server.GameTicking.Events; using Content.Shared.SS220.Language.Components; -using Content.Shared.Ghost; using Content.Shared.SS220.Language; using Robust.Server.Player; using Robust.Shared.Random; @@ -10,6 +9,8 @@ using System.Text.RegularExpressions; using Content.Shared.SS220.Language.Systems; using Robust.Shared.Network; +using Robust.Shared.Configuration; +using Content.Shared.SS220.CCVars; namespace Content.Server.SS220.Language; @@ -19,6 +20,7 @@ public sealed partial class LanguageSystem : SharedLanguageSystem [Dependency] private readonly LanguageManager _language = default!; [Dependency] private readonly IPlayerManager _player = default!; [Dependency] private readonly INetManager _net = default!; + [Dependency] private readonly IConfigurationManager _config = default!; // Cached values for one tick private static readonly Dictionary ScrambleCache = new(); @@ -278,6 +280,27 @@ public void AddLanguagesFromSource(Entity ent, EntityUid targ AddLanguage((target, targetComp), language); } } + + public bool MessageLanguagesLimit(EntityUid source, string message, [NotNullWhen(true)] out string? reason) + { + reason = null; + if (!HasComp(source)) + return false; + + var defaultLanguage = GetSelectedLanguage(source); + if (defaultLanguage == null) + return false; + + var languagesLimit = _config.GetCVar(CCVars220.MaxLanguagesInOneMessage); + var languagesStrings = SplitMessageByLanguages(source, message, defaultLanguage); + if (languagesStrings.Count > languagesLimit) + { + reason = Loc.GetString("language-message-languages-limit", ("limit", languagesLimit)); + return true; + } + + return false; + } } [ByRefEvent] diff --git a/Content.Shared/SS220/CCVars/CCVars220.cs b/Content.Shared/SS220/CCVars/CCVars220.cs index 3f5db5566325..e5aadc70ae02 100644 --- a/Content.Shared/SS220/CCVars/CCVars220.cs +++ b/Content.Shared/SS220/CCVars/CCVars220.cs @@ -124,4 +124,10 @@ public sealed partial class CCVars220 /// public static readonly CVarDef MaxSponsorsBypass = CVarDef.Create("game.max_sponsors_bypass", 10, CVar.SERVER); + + /// + /// How many languages can be used in one message + /// + public static readonly CVarDef MaxLanguagesInOneMessage = + CVarDef.Create("chat.max_languages_in_one_message", 3, CVar.SERVER); } diff --git a/Resources/Locale/ru-RU/ss220/language/language-system.ftl b/Resources/Locale/ru-RU/ss220/language/language-system.ftl new file mode 100644 index 000000000000..c1c5ed75c03a --- /dev/null +++ b/Resources/Locale/ru-RU/ss220/language/language-system.ftl @@ -0,0 +1 @@ +language-message-languages-limit = Допускается использование не более { $limit } языков в одном сообщении From d46d396e52ebfd8bf4f65d9cde5fdd89bf236d03 Mon Sep 17 00:00:00 2001 From: Kirus59 <145689588+Kirus59@users.noreply.github.com> Date: Sun, 9 Mar 2025 10:58:09 +0300 Subject: [PATCH 44/48] fix yaml linter --- Resources/Prototypes/Entities/Mobs/NPCs/pets.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Resources/Prototypes/Entities/Mobs/NPCs/pets.yml b/Resources/Prototypes/Entities/Mobs/NPCs/pets.yml index 108b0382dcb3..a5a55d2b9e12 100644 --- a/Resources/Prototypes/Entities/Mobs/NPCs/pets.yml +++ b/Resources/Prototypes/Entities/Mobs/NPCs/pets.yml @@ -215,6 +215,9 @@ factions: - PetsNT - type: Grammar + attributes: + proper: true + gender: male #SS220 languages revive begin - type: Language availableLanguages: @@ -223,9 +226,6 @@ - id: Siiktajr canSpeak: false #SS220 languages revive end - attributes: - proper: true - gender: male - type: Tag tags: - CannotSuicide From e088e16db275e05add507df4bc8a1b855f10b88f Mon Sep 17 00:00:00 2001 From: Kirus59 <145689588+Kirus59@users.noreply.github.com> Date: Sun, 9 Mar 2025 11:03:49 +0300 Subject: [PATCH 45/48] fix yaml linter 2 --- Resources/Prototypes/Entities/Mobs/NPCs/pets.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Resources/Prototypes/Entities/Mobs/NPCs/pets.yml b/Resources/Prototypes/Entities/Mobs/NPCs/pets.yml index a5a55d2b9e12..a0adbc09e25d 100644 --- a/Resources/Prototypes/Entities/Mobs/NPCs/pets.yml +++ b/Resources/Prototypes/Entities/Mobs/NPCs/pets.yml @@ -216,8 +216,8 @@ - PetsNT - type: Grammar attributes: - proper: true - gender: male + proper: true + gender: male #SS220 languages revive begin - type: Language availableLanguages: From cb38b25e2066087b4df93cc0ec31c8e60ba4f4aa Mon Sep 17 00:00:00 2001 From: Kirus59 <145689588+Kirus59@users.noreply.github.com> Date: Sun, 9 Mar 2025 12:56:44 +0300 Subject: [PATCH 46/48] try fix --- Content.Shared/Traits/TraitPrototype.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Content.Shared/Traits/TraitPrototype.cs b/Content.Shared/Traits/TraitPrototype.cs index b3d2a5ee85e2..679ed6f6b47e 100644 --- a/Content.Shared/Traits/TraitPrototype.cs +++ b/Content.Shared/Traits/TraitPrototype.cs @@ -42,7 +42,7 @@ public sealed partial class TraitPrototype : IPrototype /// The components that get added to the player, when they pick this trait. /// [DataField] - public ComponentRegistry Components { get; private set; } = default!; + public ComponentRegistry? Components { get; private set; } = default!; // SS220 Add nullable /// /// Gear that is given to the player, when they pick this trait. From 762c6cfd628a15472db6925e3d2b517f42c46026 Mon Sep 17 00:00:00 2001 From: Bomjojuk Date: Sun, 9 Mar 2025 21:27:55 +0300 Subject: [PATCH 47/48] binary opt --- Resources/Prototypes/SS220/Language/language.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Resources/Prototypes/SS220/Language/language.yml b/Resources/Prototypes/SS220/Language/language.yml index 39460ffda0d1..d93b7cdbb57a 100644 --- a/Resources/Prototypes/SS220/Language/language.yml +++ b/Resources/Prototypes/SS220/Language/language.yml @@ -295,5 +295,4 @@ specialCharacterChance: 0.8 specialCharacters: - character: " " - syllables: [1, 0, 01, 10, 11, 100, 101, 110, 111, 1000, 1001, 1010, 1011, - 1100, 1110, 1111, 10000, 10001, 10010, 10011, 10100, 10101] + syllables: [1, 0] From f694fdacc67d0fc635254859c14965f0d8a4da68 Mon Sep 17 00:00:00 2001 From: Bomjojuk Date: Mon, 10 Mar 2025 18:05:48 +0300 Subject: [PATCH 48/48] comment codespeak --- Resources/Prototypes/Entities/Mobs/Cyborgs/borg_chassis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Resources/Prototypes/Entities/Mobs/Cyborgs/borg_chassis.yml b/Resources/Prototypes/Entities/Mobs/Cyborgs/borg_chassis.yml index 7b640144eea4..cbb98c161a88 100644 --- a/Resources/Prototypes/Entities/Mobs/Cyborgs/borg_chassis.yml +++ b/Resources/Prototypes/Entities/Mobs/Cyborgs/borg_chassis.yml @@ -118,7 +118,7 @@ - id: Canilunzt canSpeak: false - id: Binary - - id: Codespeak +# - id: Codespeak #SS220 languages revive end - type: Sprite layers: