Write editor state to a new, separate xml file (fix #728)

This commit is contained in:
2025-05-07 20:56:56 -05:00
parent 744a7eb591
commit e95d4dcaf8
7 changed files with 58 additions and 11 deletions

2
.gitignore vendored
View File

@@ -98,6 +98,8 @@ test/junk/*.map
oldstructs.txt oldstructs.txt
src/tools/gitrev.hpp src/tools/gitrev.hpp
rsrc/**/scenario rsrc/**/scenario
rsrc/scenarios/**/editor.xml
rsrc/bases/**/editor.xml
# Dependency-generated files # Dependency-generated files
deps/**/ deps/**/

View File

@@ -49,6 +49,7 @@ static bool load_scenario_v2(fs::path file_to_load, cScenario& scenario, eLoadSc
// Some of these are non-static so that the test cases can access them. // Some of these are non-static so that the test cases can access them.
ticpp::Document xmlDocFromStream(std::istream& stream, std::string name); ticpp::Document xmlDocFromStream(std::istream& stream, std::string name);
void readScenarioFromXml(ticpp::Document&& data, cScenario& scenario); void readScenarioFromXml(ticpp::Document&& data, cScenario& scenario);
void readEditorStateFromXml(ticpp::Document&& data, cScenario& scenario);
void readTerrainFromXml(ticpp::Document&& data, cScenario& scenario); void readTerrainFromXml(ticpp::Document&& data, cScenario& scenario);
void readItemsFromXml(ticpp::Document&& data, cScenario& scenario); void readItemsFromXml(ticpp::Document&& data, cScenario& scenario);
void readMonstersFromXml(ticpp::Document&& data, cScenario& scenario); void readMonstersFromXml(ticpp::Document&& data, cScenario& scenario);
@@ -932,7 +933,7 @@ void readScenarioFromXml(ticpp::Document&& data, cScenario& scenario) {
if(!reqs.empty()) if(!reqs.empty())
throw xMissingElem("game", *reqs.begin(), elem->Row(), elem->Column(), fname); throw xMissingElem("game", *reqs.begin(), elem->Row(), elem->Column(), fname);
} else if(type == "editor") { } else if(type == "editor") {
std::set<std::string> reqs = {"default-ground", "last-out-section", "last-town"}; std::set<std::string> reqs = {"default-ground"};
Iterator<Element> edit; Iterator<Element> edit;
int num_storage = 0, num_pics = 0; int num_storage = 0, num_pics = 0;
for(edit = edit.begin(elem.Get()); edit != edit.end(); edit++) { for(edit = edit.begin(elem.Get()); edit != edit.end(); edit++) {
@@ -940,11 +941,14 @@ void readScenarioFromXml(ticpp::Document&& data, cScenario& scenario) {
reqs.erase(type); reqs.erase(type);
if(type == "default-ground") { if(type == "default-ground") {
edit->GetText(&scenario.default_ground); edit->GetText(&scenario.default_ground);
} else if(type == "last-out-section") { }
// Old scenario files may have last-out-section and last-town in scenario.xml
else if(type == "last-out-section") {
scenario.last_out_edited = readLocFromXml(*edit); scenario.last_out_edited = readLocFromXml(*edit);
} else if(type == "last-town") { } else if(type == "last-town") {
edit->GetText(&scenario.last_town_edited); edit->GetText(&scenario.last_town_edited);
} else if(type == "sound") { }
else if(type == "sound") {
int sndnum = 0; int sndnum = 0;
edit->GetAttribute("id", &sndnum); edit->GetAttribute("id", &sndnum);
if(sndnum < 100) if(sndnum < 100)
@@ -1066,6 +1070,23 @@ void readScenarioFromXml(ticpp::Document&& data, cScenario& scenario) {
throw xMissingElem("scenario", *reqs.begin(), data.FirstChildElement()->Row(), data.FirstChildElement()->Column(), fname); throw xMissingElem("scenario", *reqs.begin(), data.FirstChildElement()->Row(), data.FirstChildElement()->Column(), fname);
} }
void readEditorStateFromXml(ticpp::Document&& data, cScenario& scenario) {
using namespace ticpp;
int maj, min, rev;
std::string fname, type, name, val;
initialXmlRead(data, "editor", maj, min, rev, fname);
Iterator<Attribute> attr;
Iterator<Element> elem;
for(elem = elem.begin(data.FirstChildElement()); elem != elem.end(); elem++) {
elem->GetValue(&type);
if(type == "last-out-section") {
scenario.last_out_edited = readLocFromXml(*elem);
} else if(type == "last-town") {
elem->GetText(&scenario.last_town_edited);
}
}
}
void readTerrainFromXml(ticpp::Document&& data, cScenario& scenario) { void readTerrainFromXml(ticpp::Document&& data, cScenario& scenario) {
using namespace ticpp; using namespace ticpp;
int maj, min, rev; int maj, min, rev;
@@ -2187,6 +2208,10 @@ bool load_scenario_v2(fs::path file_to_load, cScenario& scenario, eLoadScenario
return false; return false;
} }
} }
auto hasFile = [&](std::string relpath) -> bool {
if(is_packed) return pack.hasFile("scenario/" + relpath);
return fs::exists(file_to_load/relpath);
};
auto getFile = [&](std::string relpath) -> std::istream& { auto getFile = [&](std::string relpath) -> std::istream& {
if(is_packed) return pack.getFile("scenario/" + relpath); if(is_packed) return pack.getFile("scenario/" + relpath);
if(fin.is_open()) fin.close(); if(fin.is_open()) fin.close();
@@ -2217,6 +2242,12 @@ bool load_scenario_v2(fs::path file_to_load, cScenario& scenario, eLoadScenario
if(load_type == eLoadScenario::ONLY_HEADER) return true; if(load_type == eLoadScenario::ONLY_HEADER) return true;
if(load_type != eLoadScenario::SAVE_PREVIEW){ if(load_type != eLoadScenario::SAVE_PREVIEW){
// Editor state, even though the game won't need it
if(hasFile("editor.xml")){
std::istream& editor = getFile("editor.xml");
readEditorStateFromXml(xmlDocFromStream(editor, "editor.xml"), scenario);
}
// Next, terrain types... // Next, terrain types...
std::istream& terrain = getFile("terrain.xml"); std::istream& terrain = getFile("terrain.xml");
readTerrainFromXml(xmlDocFromStream(terrain, "terrain.xml"), scenario); readTerrainFromXml(xmlDocFromStream(terrain, "terrain.xml"), scenario);

View File

@@ -241,8 +241,7 @@ static bool handle_lb_action(location the_point) {
case LB_LOAD_SCEN: case LB_LOAD_SCEN:
file_to_load = nav_get_scenario(); file_to_load = nav_get_scenario();
if(!file_to_load.empty() && load_scenario(file_to_load, scenario)) { if(!file_to_load.empty() && load_scenario(file_to_load, scenario)) {
set_current_town(scenario.last_town_edited); restore_editor_state();
set_current_out(scenario.last_out_edited);
} else if(!file_to_load.empty()) } else if(!file_to_load.empty())
// If we tried to load but failed, the scenario record is messed up, so boot to start screen. // If we tried to load but failed, the scenario record is messed up, so boot to start screen.
set_up_start_screen(); set_up_start_screen();
@@ -2881,3 +2880,8 @@ bool monst_on_space(location loc,short m_num) {
return false; return false;
} }
void restore_editor_state() {
set_current_town(scenario.last_town_edited);
set_current_out(scenario.last_out_edited);
}

View File

@@ -2,6 +2,7 @@
#include "scen.global.hpp" #include "scen.global.hpp"
#include "tools/undo.hpp" #include "tools/undo.hpp"
void restore_editor_state();
void init_screen_locs(); void init_screen_locs();
void handle_action(location the_point,sf::Event event); void handle_action(location the_point,sf::Event event);
void flash_rect(rectangle to_flash); void flash_rect(rectangle to_flash);

View File

@@ -51,10 +51,9 @@ void set_up_apple_events() {
std::copy(msg.get(), msg.get() + len, std::inserter(fileName, fileName.begin())); std::copy(msg.get(), msg.get() + len, std::inserter(fileName, fileName.begin()));
if(load_scenario(fileName, scenario)) { if(load_scenario(fileName, scenario)) {
set_current_town(scenario.last_town_edited); restore_editor_state();
change_made = false; change_made = false;
ae_loading = true; ae_loading = true;
set_current_out(scenario.last_out_edited);
} }
return TRUE; return TRUE;
} }

View File

@@ -43,6 +43,7 @@ void load_spec_graphics();
// These aren't static solely so that the test cases can access them. // These aren't static solely so that the test cases can access them.
void writeScenarioToXml(ticpp::Printer&& data, cScenario& scenario); void writeScenarioToXml(ticpp::Printer&& data, cScenario& scenario);
void writeEditorStateToXml(ticpp::Printer&& data, cScenario& scenario);
void writeTerrainToXml(ticpp::Printer&& data, cScenario& scenario); void writeTerrainToXml(ticpp::Printer&& data, cScenario& scenario);
void writeItemsToXml(ticpp::Printer&& data, cScenario& scenario); void writeItemsToXml(ticpp::Printer&& data, cScenario& scenario);
void writeMonstersToXml(ticpp::Printer&& data, cScenario& scenario); void writeMonstersToXml(ticpp::Printer&& data, cScenario& scenario);
@@ -121,6 +122,14 @@ namespace ticpp {
} }
} }
void writeEditorStateToXml(ticpp::Printer&& data, cScenario& scenario) {
data.OpenElement("editor");
data.PushAttribute("boes", scenario.format_ed_version());
data.PushElement("last-out-section", cur_out);
data.PushElement("last-town", cur_town);
data.CloseElement("editor");
}
void writeScenarioToXml(ticpp::Printer&& data, cScenario& scenario) { void writeScenarioToXml(ticpp::Printer&& data, cScenario& scenario) {
data.OpenElement("scenario"); data.OpenElement("scenario");
data.PushAttribute("boes", scenario.format_ed_version()); data.PushAttribute("boes", scenario.format_ed_version());
@@ -357,8 +366,6 @@ void writeScenarioToXml(ticpp::Printer&& data, cScenario& scenario) {
data.CloseElement("game"); data.CloseElement("game");
data.OpenElement("editor"); data.OpenElement("editor");
data.PushElement("default-ground", scenario.default_ground); data.PushElement("default-ground", scenario.default_ground);
data.PushElement("last-out-section", cur_out);
data.PushElement("last-town", cur_town);
if(!scenario.custom_graphics.empty()) { if(!scenario.custom_graphics.empty()) {
data.OpenElement("graphics"); data.OpenElement("graphics");
for(size_t i = 0; i < scenario.custom_graphics.size(); i++) { for(size_t i = 0; i < scenario.custom_graphics.size(); i++) {
@@ -1075,6 +1082,10 @@ void save_scenario(bool rename) {
std::ostream& header = scen_file.newFile("scenario/header.exs"); std::ostream& header = scen_file.newFile("scenario/header.exs");
header.write(reinterpret_cast<char*>(&scenario.format), sizeof(scenario_header_flags)); header.write(reinterpret_cast<char*>(&scenario.format), sizeof(scenario_header_flags));
// Write scenario's editor state to a file that can be added to .gitignore
std::ostream& editor_data = scen_file.newFile("scenario/editor.xml");
writeEditorStateToXml(ticpp::Printer("scenario.xml", editor_data), scenario);
// Next, the bulk scenario data. // Next, the bulk scenario data.
std::ostream& scen_data = scen_file.newFile("scenario/scenario.xml"); std::ostream& scen_data = scen_file.newFile("scenario/scenario.xml");
writeScenarioToXml(ticpp::Printer("scenario.xml", scen_data), scenario); writeScenarioToXml(ticpp::Printer("scenario.xml", scen_data), scenario);

View File

@@ -301,10 +301,9 @@ static void process_args(int argc, char* argv[]) {
} }
if(!file.empty()) { if(!file.empty()) {
if(load_scenario(file, scenario)) { if(load_scenario(file, scenario)) {
set_current_town(scenario.last_town_edited); restore_editor_state();
change_made = false; change_made = false;
ae_loading = true; ae_loading = true;
set_current_out(scenario.last_out_edited);
} else { } else {
std::cout << "Failed to load scenario: " << file << std::endl; std::cout << "Failed to load scenario: " << file << std::endl;
} }