Acaba la migració dels std::cout/cerr a Log::*:
- core/locale, core/ui/ui_config, core/rendering/{screen,text,gif,
surface, sprite/animated_sprite, sdl3gpu/*}.
- game/{options, debug_config, editor/editor_config, levels/level_manager,
map/{map,tilemap,paint_layer}, entities/entity_manager_loadlevel}.
Severitats coherents: warns per a configs absents amb fallback,
errors per a YAML malformat o E/S fallida, infos per a estats.
Resultat:
- 0 occurrences de std::cout/std::cerr a source/.
- Cap #include <iostream> orfà (eliminat de surface.cpp).
- Output funcional idèntic al històric; AEE_LOG filtra (ex.
`AEE_LOG=warn` només mostra warnings, `AEE_LOG=*:warn,Tag:info`
combina globals i overrides).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
180 lines
7.0 KiB
C++
180 lines
7.0 KiB
C++
#include "game/debug_config.hpp"
|
|
|
|
#include <exception>
|
|
#include <filesystem>
|
|
#include <fstream>
|
|
#include <sstream>
|
|
#include <string>
|
|
|
|
#include "external/fkyaml_node.hpp"
|
|
#include "utils/log.hpp"
|
|
|
|
namespace DebugConfig {
|
|
|
|
namespace {
|
|
|
|
auto readFile(const std::string& path) -> std::string {
|
|
std::ifstream file(path);
|
|
if (!file) { return {}; }
|
|
std::stringstream buffer;
|
|
buffer << file.rdbuf();
|
|
return buffer.str();
|
|
}
|
|
|
|
auto fromName(const std::string& name) -> StartScene {
|
|
if (name == "LOGO") { return StartScene::LOGO; }
|
|
if (name == "TITLE") { return StartScene::TITLE; }
|
|
if (name == "INTRO") { return StartScene::INTRO; }
|
|
if (name == "GAME") { return StartScene::GAME; }
|
|
return StartScene::GAME;
|
|
}
|
|
|
|
auto isKnown(const std::string& name) -> bool {
|
|
return name == "LOGO" || name == "TITLE" || name == "INTRO" || name == "GAME";
|
|
}
|
|
|
|
auto playersFromName(const std::string& name) -> StartingPlayers {
|
|
if (name == "P1") { return StartingPlayers::P1; }
|
|
if (name == "P2") { return StartingPlayers::P2; }
|
|
if (name == "BOTH") { return StartingPlayers::BOTH; }
|
|
return StartingPlayers::BOTH;
|
|
}
|
|
|
|
auto isKnownPlayers(const std::string& name) -> bool {
|
|
return name == "P1" || name == "P2" || name == "BOTH";
|
|
}
|
|
|
|
} // namespace
|
|
|
|
auto parseStartScene(const std::string& yaml_content) -> StartScene {
|
|
if (yaml_content.empty()) { return StartScene::GAME; }
|
|
try {
|
|
auto yaml = fkyaml::node::deserialize(yaml_content);
|
|
if (!yaml.contains("start_scene")) { return StartScene::GAME; }
|
|
const auto RAW = yaml["start_scene"].get_value<std::string>();
|
|
if (!isKnown(RAW)) {
|
|
Log::warn("debug.yaml", "start_scene \"{}\" invàlid, arrancant a GAME", RAW);
|
|
return StartScene::GAME;
|
|
}
|
|
return fromName(RAW);
|
|
} catch (const std::exception& e) {
|
|
Log::error("debug.yaml", "error parsejant: {} — arrancant a GAME", e.what());
|
|
return StartScene::GAME;
|
|
}
|
|
}
|
|
|
|
auto resolveStartScene(const std::string& file_path) -> StartScene {
|
|
std::error_code error;
|
|
if (!std::filesystem::exists(file_path, error)) {
|
|
// Silenciós: la no-existència és el cas per defecte en una màquina
|
|
// neta, no un error. L'usuari crea el fitxer quan el necessita.
|
|
return StartScene::GAME;
|
|
}
|
|
const auto CONTENT = readFile(file_path);
|
|
if (CONTENT.empty()) {
|
|
Log::warn("debug.yaml", "fitxer buit a {}, arrancant a GAME", file_path);
|
|
return StartScene::GAME;
|
|
}
|
|
return parseStartScene(CONTENT);
|
|
}
|
|
|
|
auto parseStartingPlayers(const std::string& yaml_content) -> StartingPlayers {
|
|
if (yaml_content.empty()) { return StartingPlayers::BOTH; }
|
|
try {
|
|
auto yaml = fkyaml::node::deserialize(yaml_content);
|
|
if (!yaml.contains("starting_players")) { return StartingPlayers::BOTH; }
|
|
const auto RAW = yaml["starting_players"].get_value<std::string>();
|
|
if (!isKnownPlayers(RAW)) {
|
|
Log::warn("debug.yaml", "starting_players \"{}\" invàlid, arrancant amb BOTH", RAW);
|
|
return StartingPlayers::BOTH;
|
|
}
|
|
return playersFromName(RAW);
|
|
} catch (const std::exception& e) {
|
|
Log::error("debug.yaml", "error parsejant starting_players: {} — arrancant amb BOTH", e.what());
|
|
return StartingPlayers::BOTH;
|
|
}
|
|
}
|
|
|
|
auto resolveStartingPlayers(const std::string& file_path) -> StartingPlayers {
|
|
std::error_code error;
|
|
if (!std::filesystem::exists(file_path, error)) { return StartingPlayers::BOTH; }
|
|
const auto CONTENT = readFile(file_path);
|
|
if (CONTENT.empty()) { return StartingPlayers::BOTH; }
|
|
return parseStartingPlayers(CONTENT);
|
|
}
|
|
|
|
auto parseStartingLevel(const std::string& yaml_content) -> std::optional<StartingLevel> {
|
|
if (yaml_content.empty()) { return std::nullopt; }
|
|
try {
|
|
auto yaml = fkyaml::node::deserialize(yaml_content);
|
|
if (!yaml.contains("starting_level")) { return std::nullopt; }
|
|
const auto& sl = yaml["starting_level"];
|
|
if (!sl.contains("pyramid") || !sl.contains("room")) {
|
|
Log::warn("debug.yaml", "starting_level necessita els camps `pyramid` i `room` — ignorat");
|
|
return std::nullopt;
|
|
}
|
|
return StartingLevel{
|
|
.pyramid = sl["pyramid"].get_value<int>(),
|
|
.room = sl["room"].get_value<int>(),
|
|
};
|
|
} catch (const std::exception& e) {
|
|
Log::error("debug.yaml", "error parsejant starting_level: {} — ignorat", e.what());
|
|
return std::nullopt;
|
|
}
|
|
}
|
|
|
|
auto resolveStartingLevel(const std::string& file_path) -> std::optional<StartingLevel> {
|
|
std::error_code error;
|
|
if (!std::filesystem::exists(file_path, error)) { return std::nullopt; }
|
|
const auto CONTENT = readFile(file_path);
|
|
if (CONTENT.empty()) { return std::nullopt; }
|
|
return parseStartingLevel(CONTENT);
|
|
}
|
|
|
|
auto toString(StartScene scene) -> const char* {
|
|
switch (scene) {
|
|
case StartScene::LOGO:
|
|
return "LOGO";
|
|
case StartScene::TITLE:
|
|
return "TITLE";
|
|
case StartScene::INTRO:
|
|
return "INTRO";
|
|
case StartScene::GAME:
|
|
return "GAME";
|
|
}
|
|
return "GAME";
|
|
}
|
|
|
|
auto toString(StartingPlayers players) -> const char* {
|
|
switch (players) {
|
|
case StartingPlayers::P1:
|
|
return "P1";
|
|
case StartingPlayers::P2:
|
|
return "P2";
|
|
case StartingPlayers::BOTH:
|
|
return "BOTH";
|
|
}
|
|
return "BOTH";
|
|
}
|
|
|
|
void createDefaultIfMissing(const std::string& file_path) {
|
|
std::error_code error;
|
|
if (std::filesystem::exists(file_path, error)) { return; }
|
|
std::ofstream file(file_path);
|
|
if (!file) {
|
|
Log::error("debug.yaml", "no s'ha pogut crear {}", file_path);
|
|
return;
|
|
}
|
|
file << "# debug.yaml — ajust personal de dev (no versionat).\n";
|
|
file << "# start_scene: LOGO | TITLE | INTRO | GAME\n";
|
|
file << "# starting_players: P1 | P2 | BOTH\n";
|
|
file << "# starting_level (opcional): { pyramid: N, room: M } — salta a la sala\n";
|
|
file << "# corresponent del levels.yaml. Sense la\n";
|
|
file << "# clau, comença a la primera (P1-R1).\n";
|
|
file << "start_scene: GAME\n";
|
|
file << "starting_players: BOTH\n";
|
|
Log::info("debug.yaml", "creat a {} amb start_scene=GAME starting_players=BOTH", file_path);
|
|
}
|
|
|
|
} // namespace DebugConfig
|