#ifdef _DEBUG #include "game/editor/room_saver.hpp" #include // Para std::round #include // Para ifstream, ofstream, istreambuf_iterator #include // Para cout, cerr #include // Para ostringstream #include "utils/defines.hpp" // Para Tile::SIZE // Carga el YAML original directamente del filesystem (no del resource pack) auto RoomSaver::loadYAML(const std::string& file_path) -> fkyaml::node { std::ifstream file(file_path); if (!file.is_open()) { std::cerr << "RoomSaver: Cannot open " << file_path << "\n"; return {}; } std::string content((std::istreambuf_iterator(file)), std::istreambuf_iterator()); file.close(); return fkyaml::node::deserialize(content); } // Convierte una room connection al formato YAML auto RoomSaver::roomConnectionToYAML(const std::string& connection) -> std::string { if (connection == "0" || connection.empty()) { return "null"; } return connection; } // Convierte la dirección del conveyor belt a string auto RoomSaver::conveyorBeltToString(int direction) -> std::string { if (direction < 0) { return "left"; } if (direction > 0) { return "right"; } return "none"; } // Genera el YAML completo como texto con formato compacto auto RoomSaver::buildYAML(const fkyaml::node& original_yaml, const Room::Data& room_data) -> std::string { std::ostringstream out; // --- Cabecera: nombre como comentario --- out << "# " << room_data.name << "\n"; // --- Sección room --- out << "room:\n"; // Escribir todos los campos name_* del YAML original (preserva name_ca, name_en, etc.) if (original_yaml.contains("room")) { const auto& room_node = original_yaml["room"]; for (auto it = room_node.begin(); it != room_node.end(); ++it) { const std::string key = it.key().get_value(); if (key.substr(0, 5) == "name_") { out << " " << key << ": \"" << it.value().get_value() << "\"\n"; } } } out << " bgColor: " << room_data.bg_color << "\n"; out << " border: " << room_data.border_color << "\n"; out << " tileSetFile: " << room_data.tile_set_file << "\n"; // Conexiones out << "\n"; out << " # Conexiones de la habitación (null = sin conexión)\n"; out << " connections:\n"; out << " up: " << roomConnectionToYAML(room_data.upper_room) << "\n"; out << " down: " << roomConnectionToYAML(room_data.lower_room) << "\n"; out << " left: " << roomConnectionToYAML(room_data.left_room) << "\n"; out << " right: " << roomConnectionToYAML(room_data.right_room) << "\n"; // Colores de items out << "\n"; out << " # Colores de los objetos\n"; out << " itemColor1: " << (room_data.item_color1.empty() ? "yellow" : room_data.item_color1) << "\n"; out << " itemColor2: " << (room_data.item_color2.empty() ? "magenta" : room_data.item_color2) << "\n"; // Conveyor belt out << "\n"; out << " # Dirección de la cinta transportadora: left, none, right\n"; out << " conveyorBelt: " << conveyorBeltToString(room_data.conveyor_belt_direction) << "\n"; // --- Tilemap (16 filas × 32 columnas, formato flow) --- out << "\n"; out << "# Tilemap: 16 filas × 32 columnas (256×192 píxeles @ 8px/tile)\n"; out << "# Índices de tiles (-1 = vacío)\n"; out << "tilemap:\n"; constexpr int MAP_WIDTH = 32; constexpr int MAP_HEIGHT = 16; for (int row = 0; row < MAP_HEIGHT; ++row) { out << " - ["; for (int col = 0; col < MAP_WIDTH; ++col) { int index = row * MAP_WIDTH + col; if (index < static_cast(room_data.tile_map.size())) { out << room_data.tile_map[index]; } else { out << -1; } if (col < MAP_WIDTH - 1) { out << ", "; } } out << "]\n"; } // --- Enemigos --- if (!room_data.enemies.empty()) { out << "\n"; out << "# Enemigos en esta habitación\n"; out << "enemies:\n"; for (const auto& enemy : room_data.enemies) { out << " - animation: " << enemy.animation_path << "\n"; int pos_x = static_cast(std::round(enemy.x / Tile::SIZE)); int pos_y = static_cast(std::round(enemy.y / Tile::SIZE)); out << " position: {x: " << pos_x << ", y: " << pos_y << "}\n"; out << " velocity: {x: " << enemy.vx << ", y: " << enemy.vy << "}\n"; int b1_x = enemy.x1 / Tile::SIZE; int b1_y = enemy.y1 / Tile::SIZE; int b2_x = enemy.x2 / Tile::SIZE; int b2_y = enemy.y2 / Tile::SIZE; out << " boundaries:\n"; out << " position1: {x: " << b1_x << ", y: " << b1_y << "}\n"; out << " position2: {x: " << b2_x << ", y: " << b2_y << "}\n"; if (!enemy.color.empty() && enemy.color != "white") { out << " color: " << enemy.color << "\n"; } if (enemy.flip) { out << " flip: true\n"; } if (enemy.mirror) { out << " mirror: true\n"; } if (enemy.frame != -1) { out << " frame: " << enemy.frame << "\n"; } out << "\n"; } } // --- Items --- if (!room_data.items.empty()) { out << "# Objetos en esta habitación\n"; out << "items:\n"; for (const auto& item : room_data.items) { out << " - tileSetFile: " << item.tile_set_file << "\n"; out << " tile: " << item.tile << "\n"; int item_x = static_cast(std::round(item.x / Tile::SIZE)); int item_y = static_cast(std::round(item.y / Tile::SIZE)); out << " position: {x: " << item_x << ", y: " << item_y << "}\n"; if (item.counter != 0) { out << " counter: " << item.counter << "\n"; } out << "\n"; } } return out.str(); } // Guarda el YAML a disco auto RoomSaver::saveYAML(const std::string& file_path, const fkyaml::node& original_yaml, const Room::Data& room_data) -> std::string { std::string content = buildYAML(original_yaml, room_data); std::ofstream file(file_path); if (!file.is_open()) { std::cerr << "RoomSaver: Cannot write to " << file_path << "\n"; return "Error: Cannot write to " + file_path; } file << content; file.close(); const std::string FILE_NAME = file_path.substr(file_path.find_last_of("\\/") + 1); std::cout << "RoomSaver: Saved " << FILE_NAME << "\n"; return "Saved " + FILE_NAME; } #endif // _DEBUG