Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Languages #43

Merged
merged 92 commits into from
Jun 10, 2024
Merged

Languages #43

merged 92 commits into from
Jun 10, 2024

Conversation

FoxxoTrystan
Copy link
Member

@FoxxoTrystan FoxxoTrystan commented Mar 24, 2024

Resolves #37

Description

This PR adds languages. Every entity who can speak now speaks a specific language (or Universal, for entities that are not supposed to speak, which is understood by everyone). Other entities who do not understand this language will see gibberish (it's possible to learn how certain induvidual words are spelled. But the spelling changes between rounds). This means that certain creatures, like xenos, cats, vulps, can communicate within their species in their own languages. Similarly, it means that xenos, cats and other things cannot understand GalacticCommon speakers without a translator or cognization.

An entity may be able to speak multiple languages, or understand a language but be unable to speak it.

Thi PR was orignally made for Frontier but is now being ported and will be maintain here.
Orignal PR: new-frontiers-14/frontier-station-14#671

This PR was made orignally by Mnemotechnician and FoxxoTrystan.


TODO

  • Language System. (Check Frontier PR for all the compleated todo list)
  • Port PR from Frontier.
  • QOL Changes.
  • Missing Default Languages. (Missing default langauges for some roundstart species)
  • Animals Languages.

Media

image
image
image


Changelog

🆑 FoxxoTrystan / Mnemotechnician

  • add: All species can now bring their own cultures and languages

@github-actions github-actions bot added the Changes: C# Changes any cs files label Mar 24, 2024
@github-actions github-actions bot removed the Changes: C# Changes any cs files label Mar 24, 2024
@github-actions github-actions bot added Changes: C# Changes any cs files Changes: Localization Changes any ftl files Changes: Sprite Changes any png or json in an RSI Changes: UI Changes any XAML files Changes: YML Changes any yml files labels Mar 24, 2024
Copy link
Contributor

github-actions bot commented Mar 24, 2024

RSI Diff Bot; head commit 7581981 merging into 310e3ae
This PR makes changes to 1 or more RSIs. Here is a summary of all changes:

Resources/Textures/Objects/Devices/translator.rsi

State Old New Status
icon Added
translator Added

Edit: diff updated after 7581981

@FoxxoTrystan FoxxoTrystan marked this pull request as ready for review March 25, 2024 14:10
Copy link
Member

@Pspritechologist Pspritechologist left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Whoooo boy, that's a big one. Lots of thoughts after the fact...

First off, I think it would be suitable to move the collection of language information (spoken, understood, required, requiresall, the stuff you were defining more than once) and move it into a serializable struct or class object that can be plonked into any instance that requires defining languages in YAML. This allows for the definitions to be reused, and means you can easily extend the functionality. You don't end up with the awkward situation where implementation X supports one feature, but implementation Y doesn't.

Finally, this whole thing needs to be cvar'd out the butt. I'd recommend a few cvars by default, one for the if languages are enabled at all, one for if animals can understand each other (personal preference, you'd probably want an 'animalistic' tag in the animals language), one for if animals can be translated at at all, and perhaps one for the fallback language ID? These all need to react to the cvars being updated mid game.
I know this seems like a huge amount to implement, but really it's just amazing practice for encapsulating your code and ensuring that vital functionality isn't strewn about multiple functions and systems. You shouldn't need to check the values of these cvars more than a couple times, everything should kinda 'funnel down' into your main functions.

@@ -183,6 +183,9 @@ binds:
- function: OpenCharacterMenu
type: State
key: C
- function: OpenLanguageMenu
type: State
key: M
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

'M' personally feels like an odd choice to me. I'd align that more with maps, or other such stuff. As a random offer, I'd probably go with 'L'.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
key: M
key: L

Comment on lines +10 to +15
{
"name": "icon"
},
{
"name": "translator"
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These should probably have better names than 'icon' and 'translator,' especially considering 'icon' isn't wholly accurate as it appears to be the base sprite and translator appears to only be the unshaded portion.

Resources/Prototypes/Recipes/Lathes/language.yml Outdated Show resolved Hide resolved
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These should probably be changed to inline lists, just to make the file a little more digestible.

Also this is super cool, I was hoping replacements would be per-language! :P

if (Transform(args.Target).ParentUid is { Valid: true } holder && EntityManager.HasComponent<LanguageSpeakerComponent>(holder))
{
// This translator is held by a language speaker and thus has an intrinsic counterpart bound to it. Make sure it's up-to-date.
var intrinsic = EntityManager.EnsureComponent<HoldsTranslatorComponent>(holder);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

EnsureComp

UpdatedLanguages(holder);
}

private void OnTranslatorToggle(EntityUid translator, HandheldTranslatorComponent component, ActivateInWorldEvent args)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Make this function call a generic, public ToggleTranslator function to allow for interoperability

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
private void OnTranslatorToggle(EntityUid translator, HandheldTranslatorComponent component, ActivateInWorldEvent args)
private void OnTranslatorToggle(EntityUid translator, HandheldTranslatorComponent component,
ActivateInWorldEvent args)

intrinsic.Issuer = comp;
}

private static void AddIfNotExists(List<string> list, string item)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not in an IDE right now, but if this is not used more than I'd say remove it :P

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sadly no, it's used above in two places and I hate it

@@ -45,6 +48,7 @@ namespace Content.Server.Chat.Systems;
/// </summary>
public sealed partial class ChatSystem : SharedChatSystem
{
public const float DefaultObfuscationFactor = 0.2f;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should absolutely not live where it is right now

{
//If listener is too far and has no line of sight, they can't identify the whisperer's identity
var result = ObfuscateMessageReadability(finalMessage);
var wrappedResult = Loc.GetString("chat-manager-entity-whisper-unknown-wrap-message",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please try not to include 'magic strings' in your code like this. Any strings being accessed in code should generally be defined as consts at the top of the script to make debugging for others not a nightmare.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's not even our code, just a part of reorganized upstream code- 😭

How would you recommend to do it?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Eh, honestly leave it in that case. Refactors can happen later. The only point here then would be to try and reorganize less upstream code without refactoring it.

For reference, the correct way to hardcode a value is to not hardcode a value, but to leave it as a DataField in a Component somewhere. The second best way to hardcode a value is to do it as a 'private const string = ;` at the very top of the file, to make these values clear and collected.

Resources/Locale/en-US/language/languages.ftl Outdated Show resolved Hide resolved
@Pspritechologist
Copy link
Member

By the way, totally forgot to mention in the review-
Although I must say I really like the chosen language names, I would personally like to see the IDs for the languages made generic, with the in-world names only used in the locales. It makes it quite hard to understand what some of them are intended for by reading code, and will also make searching for them as keywords very difficult. I'd recommend boiling them down to their use, such as 'LanguageSlime' rather than 'Bubblish' or some such thing similar. This should be quite trivial to do with a good find-and-replace, but if you find it troublesome I'm more than happy to help (don't want to assume your experience with find-and-replace :P)

- CanilunztTranslatorImplanter
- SolCommonTranslatorImplanter
- RootSpeakTranslatorImplanter
#- AnimalTranslator
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

uncomment this

Comment on lines 52 to 60
var builder = new StringBuilder();
if (language.ObfuscateSyllables)
{
ObfuscateSyllables(builder, message, language);
}
else
{
ObfuscatePhrases(builder, message, language);
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I had a terrific idea. This should take a generic 'LanguageObfuscator' Class with children for each method of obfuscation. Instead of a binary boolean here, it would simply take the Obfuscator from the Language Prototype and execute the 'Obfuscate' function on it, using whatever is returned. This allows languages to implement custom obfuscation logic, for instance binary could be obfuscated based on actually being converted to binary (a stupid but funny suggestion), or Shadowkin could use whatever absurd system Death made.

The replacement portion of the YAML would be moved to the default obfuscator, since not every one would them.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a good idea!
But that could be made in the future and not planned for the base code.

Copy link
Contributor

@DangerRevolution DangerRevolution left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would nice to have things localised when this is finished as a QOL thing.

@Mnemotechnician
Copy link
Contributor

I went through most of the requested changes and implemented them.

But the more time I spend on this, the more I feel my sanity depleting, so I could not handle all, ask @FoxxoTrystan for the rest (mainly yml in the end of the list of changes) or something-

Some comments on some things in the reviews above:

  • Translators are split into 3 components exactly because of interoperability issues. I cannot think of a system that would allow to SAFELY handle multiple language knowledge sources without simply using different components for each (otherwise we would have situations where an entity could hold an active translator, deactivate it, and forget the language it used to know due to some other effect, e.g. translator implant)
  • I hate bloat, which is why all 4 translator comps (base + 3 impls) are in a simple file... It makes no sense to have 3 files each 5 lines long.
  • Chat and headset systems are a mess, and so are their modified versions... I don't believe much can be done without upstream rewriting them (there was a pr for it, but... this is a hard fork...)

@Pspritechologist
Copy link
Member

Pspritechologist commented Apr 2, 2024

I went through most of the requested changes and implemented them.

But the more time I spend on this, the more I feel my sanity depleting, so I could not handle all, ask @FoxxoTrystan for the rest (mainly yml in the end of the list of changes) or something-

Some comments on some things in the reviews above:

  • Translators are split into 3 components exactly because of interoperability issues. I cannot think of a system that would allow to SAFELY handle multiple language knowledge sources without simply using different components for each (otherwise we would have situations where an entity could hold an active translator, deactivate it, and forget the language it used to know due to some other effect, e.g. translator implant)
  • I hate bloat, which is why all 4 translator comps (base + 3 impls) are in a simple file... It makes no sense to have 3 files each 5 lines long.
  • Chat and headset systems are a mess, and so are their modified versions... I don't believe much can be done without upstream rewriting them (there was a pr for it, but... this is a hard fork...)
  • This is a fundamental issue with the Component system at the moment, which the StatusEffect system was meant to aid with. Perhaps the temporary understanding of a language could be done in that way? Otherwise, keeping a log of the sources of different languages and removing them only when you're out of sources is a way to handle it. Another option, perhaps the best one, is to simply make languages event-based, where a 'GetLanguagesEvent' is raised and Components can all respond to it individually. This way, you don't need to modify the data in a Component at all. This is the primary way information is gathered and relayed in SpaceStation and allows for the most expansion down the line.
  • Components are per-file by convention, breaking it is not permissible. Each file refers to one Component, and each Component has its own file. This makes finding anything in the repo a breeze, at the cost of having a large number of files. At the end of the day, any solution is a compromise and the only correct one is the one that is already established.
  • This is understandable. Not changing the file at all would be nice pending a rework, but I know that isn't doable not just with the pr here, but lots of other planned features. Let's just try to keep the changes compacted to certain areas, and to annotate then where you can.

Copy link
Member

@VMSolidus VMSolidus left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've discovered through testing that this apparently breaks Telepathy, which lives in the same code as Server Chatsystem. Players can HEAR telepathy when spoken by the Oracle, but cannot SAY telepathy. Telepathy works as a 4th method of chat, like Say, and Whisper, but wasn't updated like those two. Telepathy needs to be updated to use languages, and such that it must work again.

@Mnemotechnician
Copy link
Contributor

Mnemotechnician commented Jun 4, 2024

List of currently known issues:

  • Telepatic speech does not work (explained above)-
  • Reconnecting causes the language menu to glitch out (fixed by changing the list of languages your entity speaks, e.g. using a translator)
  • Some animalistic languages look ugly due to mixing of lower and upper case (might wanna introduce properties to control min/max syllables per word per language)
  • Ghosting does not update the language menu (Currently nivellated by re-opening the language window, but we may need to think of a proper solution later)
  • Taking on a ghost role sometimes does not update the language menu (see above)
  • Implant code is trash and is pending a total rewrite (using the real implant/implanter system)

@FoxxoTrystan
Copy link
Member Author

FoxxoTrystan commented Jun 4, 2024

List of currently known issues:

  • Telepatic speech does not work (explained above)-
  • Reconnecting causes the language menu to glitch out (fixed by changing the list of languages your entity speaks, e.g. using a translator)
  • Some animalistic languages look ugly due to mixing of lower and upper case (might wanna introduce properties to control min/max syllables per word per language)
  • Ghosting does not update the language menu (Currently nivellated by re-opening the language window, but we may need to think of a proper solution later)
  • Taking on a ghost role sometimes does not update the language menu (see above)
  • Implant code is trash and is pending a total rewrite (using the real implant/implanter system)

Nice to aee the assistance tho i think the "Animals Langauges/Implant code" should not be done on this list and later when the "Base" of languages are done so its avoid keeping this on limbo.

For animals im gona gives langauges a bunch of new properties like how many spaces, ect...

@DEATHB4DEFEAT
Copy link
Member

Mark review comments as resolved when you resolve them please.

@Mnemotechnician
Copy link
Contributor

Mark review comments as resolved when you resolve them please.

sadly I cannot do that, because this PR is owned by trystan

@DEATHB4DEFEAT
Copy link
Member

Mark review comments as resolved when you resolve them please.

sadly I cannot do that, because this PR is owned by trystan

Steal their account 🙂

@FoxxoTrystan
Copy link
Member Author

Mark review comments as resolved when you resolve them please.

sadly I cannot do that, because this PR is owned by trystan

Steal their account 🙂

How dare you!

Co-authored-by: DEATHB4DEFEAT <[email protected]>
Signed-off-by: FoxxoTrystan <[email protected]>
@FoxxoTrystan
Copy link
Member Author

Outated/Updated Suggestions has been commented.

@DangerRevolution
Copy link
Contributor

Not sure if an issue on latest version but... closing the language menu with the M button stops the M button glowing green. But closing it with Escape keeps it green.

image

@FoxxoTrystan
Copy link
Member Author

Not sure if an issue on latest version but... closing the language menu with the M button stops the M button glowing green. But closing it with Escape keeps it green.

image

This is not a huge issue and some tiny changes regarding the button has already been done.

Copy link
Member

@VMSolidus VMSolidus left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As far as I'm concerned this is sufficiently "Feature Complete" and free of major bugs that we can justify merging it in this exact state, and have any future updates to it be a separate PR.

@DangerRevolution DangerRevolution enabled auto-merge (squash) June 9, 2024 12:10
@DangerRevolution
Copy link
Contributor

ready to merge, just need a brave soul to dismiss reviews

@DangerRevolution DangerRevolution merged commit 82edb60 into Simple-Station:master Jun 10, 2024
12 checks passed
SimpleStation14 added a commit that referenced this pull request Jun 10, 2024
@FoxxoTrystan FoxxoTrystan mentioned this pull request Jun 10, 2024
dasprino007 pushed a commit to dasprino007/Einstein-Engines that referenced this pull request Jul 20, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Changes: C# Changes any cs files Changes: Localization Changes any ftl files Changes: Sprite Changes any png or json in an RSI Changes: UI Changes any XAML files Changes: YML Changes any yml files Holy Shit Priority: 2-High Needs to be resolved as soon as possible Size: 2-Large For large issues/PRs Status: Needs Review Someone please review this Type: Rework Large changes to a system, like a mix between the Balancing, Codebase, and Respace labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Languages from Frontier
9 participants