public IngameMenuLogic(Widget widget, ModData modData, World world, Action onExit, WorldRenderer worldRenderer,
                               IngameInfoPanel initialPanel, Dictionary <string, MiniYaml> logicArgs)
        {
            this.modData       = modData;
            this.world         = world;
            this.worldRenderer = worldRenderer;
            this.onExit        = onExit;

            var buttonHandlers = new Dictionary <string, Action>
            {
                { "ABORT_MISSION", CreateAbortMissionButton },
                { "RESTART", CreateRestartButton },
                { "SURRENDER", CreateSurrenderButton },
                { "LOAD_GAME", CreateLoadGameButton },
                { "SAVE_GAME", CreateSaveGameButton },
                { "MUSIC", CreateMusicButton },
                { "SETTINGS", CreateSettingsButton },
                { "RESUME", CreateResumeButton },
                { "SAVE_MAP", CreateSaveMapButton },
                { "EXIT_EDITOR", CreateExitEditorButton }
            };

            isSinglePlayer = !world.LobbyInfo.GlobalSettings.Dedicated && world.LobbyInfo.NonBotClients.Count() == 1;

            menu = widget.Get("INGAME_MENU");
            mpe  = world.WorldActor.TraitOrDefault <MenuPaletteEffect>();
            mpe?.Fade(mpe.Info.MenuEffect);

            menu.Get <LabelWidget>("VERSION_LABEL").Text = modData.Manifest.Metadata.Version;

            buttonContainer = menu.Get("MENU_BUTTONS");
            buttonTemplate  = buttonContainer.Get <ButtonWidget>("BUTTON_TEMPLATE");
            buttonContainer.RemoveChild(buttonTemplate);
            buttonContainer.IsVisible = () => !hideMenu;

            if (logicArgs.TryGetValue("ButtonStride", out var buttonStrideNode))
            {
                buttonStride = FieldLoader.GetValue <int2>("ButtonStride", buttonStrideNode.Value);
            }

            var scriptContext = world.WorldActor.TraitOrDefault <LuaScript>();

            hasError = scriptContext != null && scriptContext.FatalErrorOccurred;

            if (logicArgs.TryGetValue("Buttons", out var buttonsNode))
            {
                var buttonIds = FieldLoader.GetValue <string[]>("Buttons", buttonsNode.Value);
                foreach (var button in buttonIds)
                {
                    if (buttonHandlers.TryGetValue(button, out var createHandler))
                    {
                        createHandler();
                    }
                }
            }

            // Recenter the button container
            if (buttons.Count > 0)
            {
                var expand = (buttons.Count - 1) * buttonStride;
                buttonContainer.Bounds.X      -= expand.X / 2;
                buttonContainer.Bounds.Y      -= expand.Y / 2;
                buttonContainer.Bounds.Width  += expand.X;
                buttonContainer.Bounds.Height += expand.Y;
            }

            var panelRoot = widget.GetOrNull("PANEL_ROOT");

            if (panelRoot != null && world.Type != WorldType.Editor)
            {
                Action <bool> requestHideMenu = h => hideMenu = h;
                var           gameInfoPanel   = Game.LoadWidget(world, "GAME_INFO_PANEL", panelRoot, new WidgetArgs()
                {
                    { "initialPanel", initialPanel },
                    { "hideMenu", requestHideMenu }
                });

                gameInfoPanel.IsVisible = () => !hideMenu;
            }
        }