Geekid812 / TrackmaniaBingo

An Openplanet plugin to race against your friends to be the first team to complete a Bingo board!
https://openplanet.dev/plugin/trackmaniabingo
15 stars 5 forks source link

Change maps when the in-game menu is open. #45

Closed XertroV closed 1 year ago

Geekid812 commented 1 year ago

We had this implemented before and it was reported that it didn't prevent any crashes, so we had to revert it and put up the warning in commit eb9d3dc. Are you certain this prevents all crashes?

XertroV commented 1 year ago

Are you certain this prevents all crashes?

No. However, it does close the in-game menu.

it was reported that it didn't prevent any crashes

It fixes my crash. My implementation: https://github.com/XertroV/tm-cgf-library/blob/5f6616350488c84263b0ba10beb02f870fa7cb7e/src/Maps.as#L32

Note: even tho app.Network.PlaygroundInterfaceScriptHandler and app.CurrentPlayground.Interface.ManialinkScriptHandler might be of the same type, they might not be the same instance. DataFileManager is one example -- different ghosts exist in each instance.

This matters because the same method on one instance can cause a crash where it doesn't on other instances. It's weird, but basically my rule of thumb is that you need to check each instance, rather than just the method in general.

Maybe you could put it behind a test flag? Then some ppl can enable it and report back, but it's not enabled by default.

Edit: my note doesn't seem so relevant anymore after testing. Still good to know, but mb not a factor here.

XertroV commented 1 year ago

I did some testing, both work for me (at both ~60fps at ~120fps).

void Main() {
}

void ReturnToMenu1() {
    auto app = cast<CGameManiaPlanet>(GetApp());
    if (app.Network.PlaygroundClientScriptAPI.IsInGameMenuDisplayed) {
        app.Network.PlaygroundInterfaceScriptHandler.CloseInGameMenu(CGameScriptHandlerPlaygroundInterface::EInGameMenuResult::Resume);
    }
    app.BackToMainMenu();
}

void ReturnToMenu2() {
    auto app = cast<CGameManiaPlanet>(GetApp());
    if (app.ManiaPlanetScriptAPI.ActiveContext_InGameMenuDisplayed) {
        cast<CSmArenaClient>(app.CurrentPlayground).Interface.ManialinkScriptHandler.CloseInGameMenu(CGameScriptHandlerPlaygroundInterface::EInGameMenuResult::Resume);
    }
    app.BackToMainMenu();
}

[Setting hidden]
bool S_ShowWindow = true;

void Render() {
    if (!S_ShowWindow) return;
    if (UI::Begin("return-to-menu crash helper", S_ShowWindow)) {
        if (UI::Button("Try method 1 (app.Network.PlaygroundInterfaceScriptHandler)")) {
            ReturnToMenu1();
        }
        if (UI::Button("Try method 2 (app.CurrentPlayground.Interface.ManialinkScriptHandler)")) {
            ReturnToMenu2();
        }
    }
    UI::End();
}

/** Render function called every frame intended only for menu items in `UI`.
*/
void RenderMenu() {
    if (UI::MenuItem("return to menu crash helper", "", S_ShowWindow)) {
        S_ShowWindow = !S_ShowWindow;
    }
}
XertroV commented 1 year ago

Also note: I don't actually get a crash, I get a UI hang. I can still activate the top-bar and quit via that, for example, but I lose all game inputs and can't control the in-game menu.

XertroV commented 1 year ago

You could also try using EInGameMenuResult::Quit and/or yield()ing after calling it. IDK if you tried that, but those would be what I'd try next. Will update if I learn more.

XertroV commented 1 year ago

Okay, I think I have a better way to do the fix, and works well for me. If the in-game menu is open, close it with quit to get back to the main menu, otherwise use get back to main menu.

XertroV commented 1 year ago

NOTE: the code in the PR is not the code I tested -- I just tested the method with a little utility plugin.

Geekid812 commented 1 year ago

That seems to resolve the problem on my end too. Thanks for sharing your insight to help fix that problem.

XertroV commented 1 year ago

yw