From cc5823bbcdfa0d99d3b8de846efbbb256f596ec4 Mon Sep 17 00:00:00 2001 From: Nat Quayle Nelson Date: Thu, 1 Aug 2024 10:42:28 -0500 Subject: [PATCH] de-duplicate quitting logic --- src/game/boe.appleevents.mm | 28 ++++------- src/game/boe.main.cpp | 98 ++++++++++++++++--------------------- src/game/boe.main.hpp | 1 + 3 files changed, 54 insertions(+), 73 deletions(-) diff --git a/src/game/boe.appleevents.mm b/src/game/boe.appleevents.mm index a8480c44..092c7103 100644 --- a/src/game/boe.appleevents.mm +++ b/src/game/boe.appleevents.mm @@ -19,6 +19,7 @@ extern void finish_load_party(); extern void end_startup(); extern void post_load(); +extern void queue_fake_event(const sf::Event&); extern bool ae_loading, All_Done, party_in_memory, finished_init; extern eGameMode overall_mode; @@ -72,25 +73,16 @@ void set_up_apple_events() { return TRUE; } -// TODO: Something about the cChoiceDlog causes this to crash... AFTER returning. -(NSApplicationTerminateReply)applicationShouldTerminate: (NSApplication*)sender { (void) sender; // Suppress "unused parameter" warning - if(overall_mode == MODE_STARTUP && !party_in_memory) { - All_Done = true; - return NSTerminateNow; - } - - if(overall_mode == MODE_TOWN || overall_mode == MODE_OUTDOORS || (overall_mode == MODE_STARTUP && party_in_memory)) { - std::string choice = cChoiceDlog("quit-confirm-save", {"save", "quit", "cancel"}).show(); - if(choice == "cancel") return NSTerminateCancel; - if(choice == "save") - save_party(univ.file, univ); - } else { - std::string choice = cChoiceDlog("quit-confirm-nosave", {"quit", "cancel"}).show(); - if(choice == "cancel") return NSTerminateCancel; - } - - All_Done = true; - return NSTerminateNow; + + // To avoid code duplication and fix a weird crash, cancel Apple's + // termination event, but queue a fake sfml close event for + // boe.main.cpp to handle on the next frame + sf::Event event; + event.type = sf::Event::Closed; + queue_fake_event(event); + + return NSTerminateCancel; } @end diff --git a/src/game/boe.main.cpp b/src/game/boe.main.cpp index da50426f..c89258c1 100644 --- a/src/game/boe.main.cpp +++ b/src/game/boe.main.cpp @@ -11,6 +11,7 @@ #include #include #include +#include #include "boe.graphics.hpp" #include "boe.newgraph.hpp" #include "boe.fileio.hpp" @@ -63,6 +64,8 @@ cUniverse univ; bool flushingInput = false, ae_loading = false; long start_time; +std::deque fake_event_queue; + short on_spell_menu[2][62]; short on_monst_menu[256]; @@ -134,6 +137,8 @@ void handle_drop_item(short item_hit, bool& need_redraw); void handle_drop_item(location destination, bool& need_redraw); void handle_give_item(short item_hit, bool& did_something, bool& need_redraw); +void handle_quit_event(); + #ifdef __APPLE__ eMenuChoice menuChoice=eMenuChoice::MENU_CHOICE_NONE; short menuChoiceId=-1; @@ -419,6 +424,11 @@ void handle_events() { menuChoiceId=-1; } #endif + while(!fake_event_queue.empty()){ + const sf::Event& next_event = fake_event_queue.front(); + fake_event_queue.pop_front(); + handle_one_event(next_event); + } while(mainPtr.pollEvent(currentEvent)) handle_one_event(currentEvent); // It would be nice to have minimap inside the main game window (we have lots of screen space in fullscreen mode). @@ -448,6 +458,33 @@ void handle_events() { } } +void handle_quit_event() { + if(overall_mode == MODE_STARTUP) { + if(party_in_memory) { + std::string choice = cChoiceDlog("quit-confirm-save", {"save","quit","cancel"}).show(); + if(choice == "cancel") return; + if(choice == "save") { + fs::path file = nav_put_or_temp_party(); + if(!file.empty()) return; + save_party(file, univ); + } + } + All_Done = true; + } + if(overall_mode == MODE_TOWN || overall_mode == MODE_OUTDOORS){ + std::string choice = cChoiceDlog("quit-confirm-save", {"save", "quit", "cancel"}).show(); + if(choice == "cancel") + return; + if(choice == "save") + save_party(univ.file, univ); + } else { + std::string choice = cChoiceDlog("quit-confirm-nosave", {"quit", "cancel"}).show(); + if(choice == "cancel") + return; + } + All_Done = true; +} + void handle_one_event(const sf::Event& event) { // What does this do and should it be here? @@ -496,37 +533,17 @@ void handle_one_event(const sf::Event& event) { break; case sf::Event::Closed: - if(overall_mode == MODE_STARTUP) { - if(party_in_memory) { - std::string choice = cChoiceDlog("quit-confirm-save", {"save","quit","cancel"}).show(); - if(choice == "cancel") break; - if(choice == "save") { - fs::path file = nav_put_or_temp_party(); - if(!file.empty()) break; - save_party(file, univ); - } - } - All_Done = true; - break; - } - if(overall_mode == MODE_TOWN || overall_mode == MODE_OUTDOORS){ - std::string choice = cChoiceDlog("quit-confirm-save", {"save", "quit", "cancel"}).show(); - if(choice == "cancel") - break; - if(choice == "save") - save_party(univ.file, univ); - } else { - std::string choice = cChoiceDlog("quit-confirm-nosave", {"quit", "cancel"}).show(); - if(choice == "cancel") - break; - } - All_Done = true; + handle_quit_event(); break; default: break; // There's several events we don't need to handle at all } } +void queue_fake_event(const sf::Event& event) { + fake_event_queue.push_back(event); +} + void handle_one_minimap_event(const sf::Event& event) { if(event.type == sf::Event::Closed) { mini_map.setVisible(false); @@ -648,36 +665,7 @@ void handle_menu_choice(eMenu item_hit) { pick_preferences(); break; case eMenu::QUIT: - if(overall_mode == MODE_STARTUP) { - if(party_in_memory) { - std::string choice = cChoiceDlog("quit-confirm-save", {"save","quit","cancel"}).show(); - if(choice == "cancel") break; - if(choice == "save") { - fs::path file = nav_put_or_temp_party(); - if(!file.empty()) break; - save_party(file, univ); - } - } - All_Done = true; - break; - } - if(overall_mode == MODE_TOWN || overall_mode == MODE_OUTDOORS) { - std::string choice = cChoiceDlog("quit-confirm-save",{"quit","save","cancel"}).show(); - if(choice == "cancel") - break; - if(choice == "save") { - if(univ.file.empty()) { - univ.file = nav_put_or_temp_party(); - if(univ.file.empty()) break; - } - save_party(univ.file, univ); - } - } else { - std::string choice = cChoiceDlog("quit-confirm-nosave",{"quit","cancel"}).show(); - if(choice == "cancel") - return; - } - All_Done = true; + handle_quit_event(); break; case eMenu::OPTIONS_PC_GRAPHIC: choice = char_select_pc(1,"New graphic for who?"); diff --git a/src/game/boe.main.hpp b/src/game/boe.main.hpp index 1914ed76..beb89701 100644 --- a/src/game/boe.main.hpp +++ b/src/game/boe.main.hpp @@ -23,5 +23,6 @@ void update_terrain_animation(); void update_startup_animation(); void handle_events(); void handle_one_event(const sf::Event&); +void queue_fake_event(const sf::Event&); void handle_one_minimap_event(const sf::Event &);