extract MainWindow::reloadConfig
The three restart paths each repeated the same config + visuals reload with its own try/catch and error dialog. Only that shared part is extracted; each site keeps its own follow-up (ResetCommand vs. direct Simulation::reset) and its own error-path cleanup. Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GH8ZMRY3vhxxXcaUxBqxkk
This commit is contained in:
@@ -201,19 +201,9 @@ void MainWindow::handleEvent(std::shared_ptr<const EscapeMenuRequestedEvent> /*e
|
||||
QAbstractButton* clicked = box.clickedButton();
|
||||
if (clicked == restartBtn)
|
||||
{
|
||||
std::shared_ptr<GameConfig> newConfig;
|
||||
try
|
||||
std::optional<GameConfig> newConfig = reloadConfig();
|
||||
if (!newConfig.has_value())
|
||||
{
|
||||
newConfig = std::make_shared<GameConfig>(
|
||||
ConfigLoader::loadFromDirectory(m_configDir));
|
||||
VisualsConfig newVisuals = VisualsLoader::load(m_configDir + "/visuals.toml");
|
||||
m_visuals = std::move(newVisuals);
|
||||
m_dimOverlay->setDimColor(m_visuals.overlays.modalDim);
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
QMessageBox::critical(this, tr("Config Error"),
|
||||
tr("Failed to reload config:\n%1").arg(e.what()));
|
||||
m_gameWorldView->setGameSpeed(prevSpeed);
|
||||
m_gameWorldView->resetFrameTimer();
|
||||
return;
|
||||
@@ -221,7 +211,7 @@ void MainWindow::handleEvent(std::shared_ptr<const EscapeMenuRequestedEvent> /*e
|
||||
// Restart is a command boundary; the view resets when the drain applies
|
||||
// it (see GameWorldView::onFrame). A fresh random seed starts a new run.
|
||||
std::shared_ptr<ResetCommand> command = std::make_shared<ResetCommand>();
|
||||
command->config = std::move(newConfig);
|
||||
command->config = std::make_shared<GameConfig>(std::move(*newConfig));
|
||||
command->seed = std::random_device{}();
|
||||
EventManager::getInstance()->sendEventImmediately(
|
||||
std::make_shared<CommandRequestedEvent>(command));
|
||||
@@ -237,6 +227,27 @@ void MainWindow::handleEvent(std::shared_ptr<const EscapeMenuRequestedEvent> /*e
|
||||
}
|
||||
}
|
||||
|
||||
std::optional<GameConfig> MainWindow::reloadConfig()
|
||||
{
|
||||
// Config is reloaded from disk on every restart (REQ-CFG-RELOAD); a malformed
|
||||
// file must not leave the window half-updated, so the visuals are only applied
|
||||
// once both files have parsed.
|
||||
try
|
||||
{
|
||||
GameConfig newConfig = ConfigLoader::loadFromDirectory(m_configDir);
|
||||
VisualsConfig newVisuals = VisualsLoader::load(m_configDir + "/visuals.toml");
|
||||
m_visuals = std::move(newVisuals);
|
||||
m_dimOverlay->setDimColor(m_visuals.overlays.modalDim);
|
||||
return newConfig;
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
QMessageBox::critical(this, tr("Config Error"),
|
||||
tr("Failed to reload config:\n%1").arg(e.what()));
|
||||
return std::nullopt;
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::openShipLayoutDialog(BuildingId shipyardId,
|
||||
const std::string& schematicId,
|
||||
const ShipLayoutConfig& currentLayout)
|
||||
@@ -382,24 +393,14 @@ void MainWindow::handleEvent(std::shared_ptr<const GameOverEvent> /*event*/)
|
||||
|
||||
if (box.clickedButton() == restartBtn)
|
||||
{
|
||||
std::shared_ptr<GameConfig> newConfig;
|
||||
try
|
||||
std::optional<GameConfig> newConfig = reloadConfig();
|
||||
if (!newConfig.has_value())
|
||||
{
|
||||
newConfig = std::make_shared<GameConfig>(
|
||||
ConfigLoader::loadFromDirectory(m_configDir));
|
||||
VisualsConfig newVisuals = VisualsLoader::load(m_configDir + "/visuals.toml");
|
||||
m_visuals = std::move(newVisuals);
|
||||
m_dimOverlay->setDimColor(m_visuals.overlays.modalDim);
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
QMessageBox::critical(this, tr("Config Error"),
|
||||
tr("Failed to reload config:\n%1").arg(e.what()));
|
||||
return;
|
||||
}
|
||||
// Restart is a command boundary; the view resets when the drain applies it.
|
||||
std::shared_ptr<ResetCommand> command = std::make_shared<ResetCommand>();
|
||||
command->config = std::move(newConfig);
|
||||
command->config = std::make_shared<GameConfig>(std::move(*newConfig));
|
||||
command->seed = std::random_device{}();
|
||||
EventManager::getInstance()->sendEventImmediately(
|
||||
std::make_shared<CommandRequestedEvent>(command));
|
||||
@@ -429,20 +430,14 @@ void MainWindow::handleEvent(std::shared_ptr<const WinEvent> /*event*/)
|
||||
|
||||
if (box.clickedButton() == restartBtn)
|
||||
{
|
||||
try
|
||||
std::optional<GameConfig> newConfig = reloadConfig();
|
||||
if (!newConfig.has_value())
|
||||
{
|
||||
GameConfig newConfig = ConfigLoader::loadFromDirectory(m_configDir);
|
||||
VisualsConfig newVisuals = VisualsLoader::load(m_configDir + "/visuals.toml");
|
||||
m_visuals = std::move(newVisuals);
|
||||
m_dimOverlay->setDimColor(m_visuals.overlays.modalDim);
|
||||
m_sim->reset(std::move(newConfig));
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
QMessageBox::critical(this, tr("Config Error"),
|
||||
tr("Failed to reload config:\n%1").arg(e.what()));
|
||||
return;
|
||||
}
|
||||
// Unlike the other two restart paths this one resets the simulation
|
||||
// directly instead of enqueueing a ResetCommand; kept as-is.
|
||||
m_sim->reset(std::move(*newConfig));
|
||||
m_gameWorldView->resetForNewGame();
|
||||
}
|
||||
else
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
@@ -9,6 +10,7 @@
|
||||
#include "BuildingId.h"
|
||||
#include "EscapeMenuRequestedEvent.h"
|
||||
#include "EventHandler.h"
|
||||
#include "GameConfig.h"
|
||||
#include "GameOverEvent.h"
|
||||
#include "LayoutDialogRequestedEvent.h"
|
||||
#include "ModalDimOverlay.h"
|
||||
@@ -58,6 +60,12 @@ private:
|
||||
void handleEvent(std::shared_ptr<const LayoutDialogRequestedEvent> event) override;
|
||||
void handleEvent(std::shared_ptr<const RecipeSelectionRequestedEvent> event) override;
|
||||
|
||||
// Reloads the game config and visuals.toml from disk (REQ-CFG-RELOAD), shared
|
||||
// by every restart path. On success the reloaded visuals are applied to this
|
||||
// window and the fresh GameConfig is returned; on failure a modal error dialog
|
||||
// is shown and std::nullopt is returned, leaving the window state untouched.
|
||||
std::optional<GameConfig> reloadConfig();
|
||||
|
||||
// Opens the shipyard layout configuration dialog for the given schematic and
|
||||
// current layout, applying the result via SetShipLayoutCommand (REQ-MOD-UI-DIALOG).
|
||||
void openShipLayoutDialog(BuildingId shipyardId,
|
||||
|
||||
Reference in New Issue
Block a user