Adventure Game Studio

AGS Development => Engine Development => Topic started by: Monsieur OUXX on Sun 24/05/2020 11:07:30

Title: Bug in Game.ChangeTranslation("") ?
Post by: Monsieur OUXX on Sun 24/05/2020 11:07:30
With 3.5.0.24

Scenario (5 minutes to reproduce) :


- Create an empty AGS game (game1.ags)
- Create another empty AGS game (game2.ags)
- Copy game1.ags into the Compiled folder of game2.
- In game2, create one translation file : "whatever.tra". Just translate one line and compile that language, for test's sake.
- in game_start of game2.ags, Add this instruction : Game.ChangeTranslation("whatever");
   Now we know that no matter what language was chosen in winsetup.exe, it then immediately changes to "whatever"
- in room_AfterFadeIn() of game2's first room, add these instructions :
Code (ags) Select

    bool result = Game.ChangeTranslation(""); //As per documentation, reset to default language
    if (!result) {
      Display("Cannot revert to default language."));
    }
    if (Game.TranslationFilename != "") {
      Display(String.Format(The current translation should be (empty string), instead it's '%s'."), Game.TranslationFilename));
    }
    RunAGSGame("game1.ags", 0, 0);

    Now we know that regardless of what language was chosen as default language in winsetup.exe, and regardless of which language is set programmatically at startup, the language should still be "" just before the call to RunAGSGame

Now the core of the scenario :

- Build the EXE. Go to Compiled. Run game2.exe
  => This is the first execution. The selected language in winsetup.exe is "Default language". The call to RunAGSGame succeeds because when game1 starts, it detects that the current language is "".
- exit the game.
  => Now you will notice that if you start winsetup.exe, the startup language has changed to "whatever" because the engine remembers. OK, why not.
- Start game2.exe again.
  => The game starts with "whatever" (because of winsetup.exe) and immediately switches to "whatever" programmatically (because of game_start). => OK
  => In AfterFadeIn, Game.ChangeTranslation("") succeeds. => OK
  => The game does not enter if (Game.TranslationFilename != "") {. => OK
  => RunAGSGame call happens => OK
  => game1's startup crashes with error message "Failed to read translation file 'whatever.tra'". Why is it trying to read whatever.tra even though we just switched to "" ?

The issue lies in the fact that the engine "remembers" the language that was selected the last time the game exited as the "default language".
In this situation, I don't know how to switch from one game to another if they don't share mutual translation files (same names, same strings, same set of languages)
In other words: I don't know how to revert to "default language" which was supposed to remain "" and be a common, neutral language (i.e. a language that tells the game to use its own strings instead of reading them from any .tra file)
Title: Re: Bug in Game.ChangeTranslation("") ?
Post by: Crimson Wizard on Sun 24/05/2020 15:03:14
This is not a bug in Game.ChangeTranslation as it is merely switching current runtime language. This may be an issue with how engine writes last chosen language in config, and whether it does at all when calling RunAGSGame.
Also, there may be an issue of engine lacking a safe fallback on startup in case current tra is missing (guess it must switch to default language).

I will have to build the test case and see what's going on there.

PS. Of course, the general problem may be that both games share same config file to the last option. RunAGSGame mechanic is very old and may need a redesign too, as well as other related things (for example, IIRC you cannot have separate *.vox files for each game if they are in a bundle).
Title: Re: Bug in Game.ChangeTranslation("") ?
Post by: Monsieur OUXX on Sun 24/05/2020 15:22:11
Everything you wrote is correct.

The weird thing (to me) is really that Game.ChangeTranslation("") succeeds, but a moment later the engine is still looking for whatever.tra.
I think there's an overlap between "current translation", "defaut language" and "last saved language".
Title: Re: Bug in Game.ChangeTranslation("") ?
Post by: Crimson Wizard on Sun 24/05/2020 15:31:38
Quote from: Monsieur OUXX on Sun 24/05/2020 15:22:11
The weird thing (to me) is really that Game.ChangeTranslation("") succeeds, but a moment later the engine is still looking for whatever.tra.

That's because engine ChangeTranslation was called in one game, and engine runs next one, which does its own initialization at startup. These are unrelated steps.
EDIT: actually, I am not sure this is exactly what happens, need to double check everything.

Quote from: Monsieur OUXX on Sun 24/05/2020 15:22:11
I think there's an overlap between "current translation", "defaut language" and "last saved language".

I don't know what you mean by this. Default is always same default (no TRA).

Also, I am not sure I understand how does not it find "whatever.tra" if it lies in same folder. This may be a separate problem. I will have to built this test case first.
Title: Re: Bug in Game.ChangeTranslation("") ?
Post by: Monsieur OUXX on Sun 24/05/2020 15:59:22
Quote from: Crimson Wizard on Sun 24/05/2020 15:31:38
I am not sure I understand how does not it find "whatever.tra" if it lies in same folder.

The engine finds it, but has a mechanism to detect that it was generated for the other game. So it finds it but rejects it.

Quote from: Crimson Wizard on Sun 24/05/2020 15:31:38
ChangeTranslation was called in game2, but then game1 does its own initialization at startup.
Yes but it means that game1 reads which language it should boot with from acsetup.cfg. And that's problematic because:
- I can change the current language with an instruction. That happens instantaneously,
- but the language in acsetup.cfg gets changed against my will, and with a delay (at exit time). I have no control over that. The language selected in a previous session of game2 determines what language game1 will try to start with in the current session.

As always, thanks a lot for taking the time of answering. Now you have all the facts.
Title: Re: Bug in Game.ChangeTranslation("") ?
Post by: Crimson Wizard on Sun 24/05/2020 17:08:54
Quote from: Monsieur OUXX on Sun 24/05/2020 15:59:22
Yes but it means that game1 reads which language it should boot with from acsetup.cfg. And that's problematic because:
- I can change the current language with an instruction. That happens instantaneously,
- but the language in acsetup.cfg gets changed against my will, and with a delay (at exit time). I have no control over that. The language selected in a previous session of game2 determines what language game1 will try to start with in the current session.

At exit it should write down whatever you set ChangeTranslation to last. More likely, on contrary, config is not modified on RunAGSGame at all, and then config has what was set at last normal exit.
If this is so, then this is merely a matter of saving current user config before running a different game.

EDIT: it's turned out to be different, neither config is saved nor last translation set at runtime is applied when running next game, instead it applies translation setting loaded from config when the engine just started up. Maybe this was broken during many iterations of the engine and never noticed until now.
Title: Re: Bug in Game.ChangeTranslation("") ?
Post by: Crimson Wizard on Sun 24/05/2020 23:54:19
Here's the patched engine: https://www.dropbox.com/s/yyxbt7h2x97460p/acwin-3.5.0-p3--runagsgame-trs.zip?dl=1

Please tell if it works for you now.
Title: Re: Bug in Game.ChangeTranslation("") ?
Post by: Monsieur OUXX on Mon 25/05/2020 08:13:47
Quote from: Crimson Wizard on Sun 24/05/2020 23:54:19
Here's the patched engine: https://www.dropbox.com/s/yyxbt7h2x97460p/acwin-3.5.0-p3--runagsgame-trs.zip?dl=1

Please tell if it works for you now.

Wow, thanks!
I will try asap
Title: Re: Bug in Game.ChangeTranslation("") ?
Post by: Crimson Wizard on Mon 25/05/2020 11:16:37
No, on second thought something is not right here.

Like you say, game A cannot read translation files made for game B and vice versa.
While game B is running you won't be able to set any translation for game A, because game B will refuse to initialize them. Default translation ("") works simply because there's "default" in any game.

But this means that neither ChangeTranslation neither config from game B should be applied for game A at all. What's the point if you must run ChangeTranslation("") before RunAGSGame to simply make it run? Perhaps, better make RunAGSGame reset translation to default on its own?

How translation setting is supposed to work anyway in case there are two games bundled together? I'd rather find old developers who used RunAGSGame earlier to know what was the expected behavior in this case.
Title: Re: Bug in Game.ChangeTranslation("") ?
Post by: Monsieur OUXX on Mon 25/05/2020 12:18:45
I need to test more but I'm 90% sure that your patch fixed my issue.

Quote from: Crimson Wizard on Mon 25/05/2020 11:16:37
Default translation ("") works simply because there's "default" in any game.
Well that's what I was hoping and that's the scenario I indentified as the only one that could possible work. I wasn't hoping for more.

Quote from: Crimson Wizard on Mon 25/05/2020 11:16:37
But this means that neither ChangeTranslation neither config from game B should be applied for game A at all. What's the point if you must run ChangeTranslation("") before RunAGSGame to simply make it run? Perhaps, better make RunAGSGame reset translation to default on its own?
How translation setting is supposed to work anyway in case there are two games bundled together? I'd rather find old developers who used RunAGSGame earlier to know what was the expected behavior in this case.
I think that you're entering a dangerous realm here; Indeed the language setting should be even more restrictive, but do we really want that? It increases the risk of you making a mistake on engine-development end, and the risk of the game maker making a mistake on their end.
That being said, you just made me realize that it's unclear to me what ends up in acsetup.cfg after I quit the embedded game. But my code now works with your patched engine.


Here is how I do it (this is currently implemented in my game, and works) :

Quote
Solution for a normal game (no "RunAGSGame") :


- Make the end-user use winsetup.exe if they know about it
  => If they don't, then at first startup "game default" is selected
  => If they do, then at first startup the language is the one they selected
- When the game quits the language hasn't changed and remains the same in acsetup.cfg until next startup


Quote
Solution for a normal game (no "RunAGSGame") that lets the payer choose the language in-game :

- in game_start, the game tests the value of the current translation. If it's "" it means that the player didn't explicitly pick a language.
- Depending on that value and how much we want the player to choose, then :
   => No matter what the player has selected in winsetup.exe, the game immediately does a Game.ChangeTranslation("") at startup
   => The game displays a custom GUI asking to pick a language
   => If the user picks English, then we do Game.ChangeTranslation("English") to be able to tell the difference with "".
         Note: One extra benefit of having an explicit "English" .tra file is that the Tumbleweed and 9verb modules rely on a GUI_LANGUAGE entry that must be translated to "en" in English.tra.
- When the game quits the language is remembered in acsetup.cfg until next startup, so we can decide not to display the languageselection GUI at next startup


Quote
Solution for a game containing another game (uses "RunAGSGame"):

- we forbid the access to winsetup.exe. A game that starts for the first time with something else than "game default" is considered corrupt.
  The reason for that is that winsetup.exe displays the list of .TRA files for both games. If the parent game has "English" and the child game has "EN", then you will see both in the list.
  If the player is a smart arse and tries to force-pick a .TRA entry belonging to the child game, then the game will crash at startup anyways (built-in AGS engine check).

- As an extra safety, we do Game.ChangeTranslation("") in game_start but I'm not even sure that's needed.
- in game_start, the game reads the value of the language in a custom .ini file.
  => If the value does not exist or is not recognized as a correct value for the parent game, then the game displays the "select language" custom GUI
  => We update that value in the .ini file
  => We go Game.ChangeTranslation based on that value.
- Just before calling RunAGSGame, we do Game.ChangeTranslation(""). Thanks to your patch, the child game knows to start with "" and doesn't get confused with the parent's .TRA files.
   => For convenience, in the child game we display the custom language seection screen every time, but we could totally save it into a .ini file too.
- When any of these games exit, then some value is saved in acsetup.cfg
  => I don't care what the value is because the mechanisms described above help me work around it.
Title: Re: Bug in Game.ChangeTranslation("") ?
Post by: Crimson Wizard on Mon 25/05/2020 12:36:14
Quote from: Monsieur OUXX on Mon 25/05/2020 12:18:45
I need to test more but I'm 90% sure that your patch fixed my issue.

I maybe fixed it for your private case, but I doubt if that's good for a general solution, so I am probably goind to cancel it.


Quote from: Monsieur OUXX on Mon 25/05/2020 12:18:45I think that you're entering a dangerous realm here; Indeed the language setting should be even more restrictive, but do we really want that? It increases the risk of you making a mistake on engine-development end, and the risk of the game maker making a mistake on their end.

I am not sure we understand each other.

What I am saying is: right now - with my "fix" - for the next game to start successfully game developer is required to call ChangeTranslation before RunAGSGame. With my current fix it increases the risk of game maker making a mistake (what you were fearing) instead of decreasing it.
If next game cannot have same translation set, and parent game cannot tell it which to set beforehand, so it's only logical that the engine should reset translation to default before running the next game, not requiring user to script ChangeTranslation("").
At least in current situation, when both games are destined to use same config, because of how limited this feature is.



Quote from: Monsieur OUXX on Mon 25/05/2020 12:18:45
- we forbid the access to winsetup.exe. A game that starts for the first time with something else than "game default" is considered corrupt.
  The reason for that is that winsetup.exe displays the list of .TRA files for both games. If the parent game has "English" and the child game has "EN", then you will see both in the list.

This means there's a mistake in winsetup that should be fixed: it should test whether TRA belongs to the current game.
Title: Re: Bug in Game.ChangeTranslation("") ?
Post by: Monsieur OUXX on Mon 25/05/2020 14:25:55
Quote from: Monsieur OUXX on Mon 25/05/2020 12:18:45
This means there's a mistake in winsetup that should be fixed: it should test whether TRA belongs to the current game.

Yes.
A more general fix would be for winsetup to know what exe it targets, what .cfg file it uses, and what .tra entries it offers. The central issue is that winsetup is a generic program that's meant to autodetect everything in the same folder. If you start making winsetup specific to one game, then you create new constraints.
Title: Re: Bug in Game.ChangeTranslation("") ?
Post by: Crimson Wizard on Mon 25/05/2020 15:04:47
Quote from: Monsieur OUXX on Mon 25/05/2020 14:25:55
A more general fix would be for winsetup to know what exe it targets, what .cfg file it uses,...

But it does know that.
Winsetup.exe is simply a shell executor. It does not detect anything, the game exe name is written into it. It calls "game.exe --setup", and it is engine inside game.exe that detects the game data, and then knowing the game it finds its configs according to certain rules, and so forth.
At the moment when setup dialog opens, it already knows everything about the game, it's name, and most of its general settings.

Unless I misunderstood what you mean, in which case please elaborate...

Quote from: Monsieur OUXX on Mon 25/05/2020 14:25:55
The central issue is that winsetup is a generic program that's meant to autodetect everything in the same folder. If you start making winsetup specific to one game, then you create new constraints.

Not sure I understand this, are you saying that generic winsetup is good or bad?
Title: Re: Bug in Game.ChangeTranslation("") ?
Post by: Cassiebsg on Mon 25/05/2020 19:26:00
I don't like the "we forbid the access to winsetup.exe" option...  :-\ That's the first thing I run in any AGS game! And I will not play any game that doesn't provide it.

Quote
This means there's a mistake in winsetup that should be fixed: it should test whether TRA belongs to the current game.

(nod) This would be a very good fix. Specially since the TRA provides the game name to which it belongs.
Maybe if this was fixed then it would be possible to run  RunAGSGame, with it's own translation set as well...  ???  :-D Would be cool to be able to do something like RunAGSGame(game.exe, english);  ;)
Title: Re: Bug in Game.ChangeTranslation("") ?
Post by: Crimson Wizard on Mon 25/05/2020 19:43:52
Quote from: Cassiebsg on Mon 25/05/2020 19:26:00
I don't like the "we forbid the access to winsetup.exe" option...  :-\ That's the first thing I run in any AGS game! And I will not play any game that doesn't provide it.

Monsieur OUXX probably means they have custom setup/launcher program. Number of games had in the past.


Quote from: Cassiebsg on Mon 25/05/2020 19:26:00
This would be a very good fix. Specially since the TRA provides the game name to which it belongs.
Maybe if this was fixed then it would be possible to run  RunAGSGame, with it's own translation set as well... 

But there's no relation between these two.  ???
Title: Re: Bug in Game.ChangeTranslation("") ?
Post by: Cassiebsg on Mon 25/05/2020 21:43:33
I don't understand "there's no relation between these two"... what do you mean?

Right now you can't run a game (game B) inside another game with translation (game A), because game B will try and load the TRA from game A and then crash.
If I had a file called GameA_Eng.TRA and GameB_Eng.TRA and  RunAGSGame would not go and pick GameA_Eng for game B translation file; then there's a chance that one could run GameB with it's own translation, no? Right now, the only option is to set the language to default at then launch Game B.

And apparently  RunAGSGame already have a setting to carry GlobalInt from game A to game B... so telling it to carry also what language to use when running, should be in the realm of possibilities, no?
Title: Re: Bug in Game.ChangeTranslation("") ?
Post by: Crimson Wizard on Mon 25/05/2020 21:52:30
Quote from: Cassiebsg on Mon 25/05/2020 21:43:33
I don't understand "there's no relation between these two"... what do you mean?

I mean that there is no relation between proposed winsetup fix and RunAGSGame (telling next game what language it should use). Fixing first is not required to do second.
Title: Re: Bug in Game.ChangeTranslation("") ?
Post by: Cassiebsg on Mon 25/05/2020 22:22:50
Oh, that. I know.  (nod)

But fixing first, allows for second possibility.  ;)
Title: Re: Bug in Game.ChangeTranslation("") ?
Post by: Crimson Wizard on Tue 26/05/2020 01:51:41
I don't know if there's any reason to pass language to RunAGSGame, or whether that's a good thing to pass extra variables at all. Currently it's possible to do through a custom file, and that way you can pass any amount of data you need, then initialize it at startup in the called game.
Title: Re: Bug in Game.ChangeTranslation("") ?
Post by: Monsieur OUXX on Tue 26/05/2020 13:43:43
Quote from: Crimson Wizard on Mon 25/05/2020 15:04:47
Quote from: Monsieur OUXX on Mon 25/05/2020 14:25:55
A more general fix would be for winsetup to know what exe it targets, what .cfg file it uses,...

But it does know that.
It knows the .exe but it doesn't know which .cfg and which .tra to use. Or at least I thought so.

Quote from: Crimson Wizard on Mon 25/05/2020 15:04:47
Not sure I understand this, are you saying that generic winsetup is good or bad?
It's good! But it becomes bad if it gets confused with the settings (again: because it can't tell which .tra files are meant for it and just displays all of them).


Quote from: Cassiebsg on Mon 25/05/2020 19:26:00
I don't like the "we forbid the access to winsetup.exe" option...  :-\ That's the first thing I run in any AGS game! And I will not play any game that doesn't provide it.
The only reason we do that is because of this issue with the translations. Cassiebsg you didn't see that but that's already how it worked in Relic of the Viking 1.0 : All the translations (both for the parent game and the embedded game) appear in the list, that's an issue.
Of course we don't really "forbid" the access to winsetup.exe. We just hide it a little bit to not encourage people who have no idea what they're doing to mess up their settings and be locked out of the game.

Like everyone has said before, there are two ways out of this :
1) Fix the TRA issue in winsetup.exe -- that one I'm not demanding because this is a very specific scenario (very few people have an embedded game and translations!).
OR
2) Use a custom setup programs. That's on my TODO list anyways so I'm OK with it (I'll use eeri0o's program).
Title: Re: Bug in Game.ChangeTranslation("") ?
Post by: Crimson Wizard on Tue 26/05/2020 13:51:47
Quote from: Monsieur OUXX on Tue 26/05/2020 13:43:43
It knows the .exe but it doesn't know which .cfg and which .tra to use. Or at least I thought so.

I can't understand what do you mean. How would it work if it did not know which cfg to use... and what are options to choose from if there can be only one acsetup.cfg in game folder?... maybe we are talking about different things here, but I am very much confused.

It does not distinct tra files mostly because no one thought about doing this. That's an oversight that has to be corrected.
Title: Re: Bug in Game.ChangeTranslation("") ?
Post by: Monsieur OUXX on Tue 26/05/2020 16:22:42
Quote from: Crimson Wizard on Tue 26/05/2020 13:51:47
Quote from: Monsieur OUXX on Tue 26/05/2020 13:43:43
It knows the .exe but it doesn't know which .cfg and which .tra to use. Or at least I thought so.

I can't understand what do you mean. How would it work if it did not know which cfg to use...

Well I thought it took acsetup.cfg no matter what. Which means that two games in the same folder would share the same config file. I'm realizing it's not a big issue because if one of those two games is a .ags then there's only one .exe, which means we need only one .cfg.
Yeah the real issue really only lies in listing all the .tra for both games in winsetup.
Title: Re: Bug in Game.ChangeTranslation("") ?
Post by: Cassiebsg on Tue 26/05/2020 19:09:29
Oh, I wasn't actually passing the "english" to Game B. I was passing it to the config setting, or whatever flags one has to run gameb.ags with to choose a language at run time.

Now I'm thinking in the case of Relic of the Viking in particular, that runs the old demo.
The old demo does have some translations available, but right now, as far as I know, there's no way to run that demo with the translation (is there one?).

Now if the player choose to play Relic in Italian, and then went and run the old demo, it would be nice to be able run it with the Italian translation, if available. That would be the expected result from the players side, and not be meet with the English Demo instead (and no way to change the language, as I don't recall the old demo having an option to change translation in game).
Title: Re: Bug in Game.ChangeTranslation("") ?
Post by: Monsieur OUXX on Mon 08/06/2020 12:02:42
Quote from: Cassiebsg on Tue 26/05/2020 19:09:29
The old demo does have some translations available, but right now, as far as I know, there's no way to run that demo with the translation (is there one?).
You haven't had an opportunity to see how it's implemented yet. I'd need to send you the latest sources. You pick the language of the "parent" game and the language f the "embedded" game inside of the games, on a special welcome screen. Which means, we work around the problems with winsetup.exe and the .cfg. The only issue was that we couldn't reset the language while jumping from one game to the other (because of the "bug" that CW has fixed here). Now it works like a charm.
Title: Re: Bug in Game.ChangeTranslation("") ?
Post by: Cassiebsg on Mon 08/06/2020 17:10:22
Oh, but that means you had to change the old demo source and compile a new version... Of course that's always an option... except if you don't have the source anymore (or don't want to bother to change the old demo).  ;)
Title: Re: Bug in Game.ChangeTranslation("") ?
Post by: Crimson Wizard on Mon 08/06/2020 19:42:44
That would require a redesign of how running other games work, for example make each game actually read its own config when run from another, because they don't read config again with the current implementation.
One of the hypothetical possibilities that comes to mind is to pass a new Dictionary struct with config into RunAGSGame (rather than a single option).