summaryrefslogtreecommitdiffstats
path: root/crawl-ref/source/files.cc
diff options
context:
space:
mode:
authorMatthew Cline <zelgadis@sourceforge.net>2009-10-29 00:59:40 -0700
committerMatthew Cline <zelgadis@sourceforge.net>2009-10-29 00:59:40 -0700
commitf5cf3b82006ffe51f9462ddc8a6f65dce55a03d6 (patch)
tree02619aa602cf52d8d2700d9225bb0c2b1ba5c0c8 /crawl-ref/source/files.cc
parente083e2c09aad37199affe880180f2eda90d213ac (diff)
downloadcrawl-ref-f5cf3b82006ffe51f9462ddc8a6f65dce55a03d6.tar.gz
crawl-ref-f5cf3b82006ffe51f9462ddc8a6f65dce55a03d6.zip
Pre- and post-savefile callbacks.
The constructor of class SavefileCallback can be used to add a callback which is called before a game is saved and after it's restored. This is useful to move data in and out of you.props, or after a restore if there's data not stored in the savefile which can be easily regenerated. NOTE: I experienced some weirdness with C++ global constructors, and since global constructors probably differ with compiler and system, until this has been tested on all compiler/system combinations, any code which uses the callbacks should fail gracefully if the callbacks aren't called.
Diffstat (limited to 'crawl-ref/source/files.cc')
-rw-r--r--crawl-ref/source/files.cc69
1 files changed, 69 insertions, 0 deletions
diff --git a/crawl-ref/source/files.cc b/crawl-ref/source/files.cc
index 759b5c13e7..c27174835e 100644
--- a/crawl-ref/source/files.cc
+++ b/crawl-ref/source/files.cc
@@ -92,6 +92,8 @@
#endif
#endif
+static std::vector<SavefileCallback::callback>* _callback_list = NULL;
+
static void _save_level( int level_saved, level_area_type lt,
branch_type where_were_you);
@@ -1535,6 +1537,8 @@ void save_game(bool leave_game, const char *farewellmsg)
{
unwind_bool saving_game(crawl_state.saving_game, true);
+ SavefileCallback::pre_save();
+
/* Stashes */
std::string stashFile = get_savedir_filename(you.your_name, "", "st");
FILE *stashf = fopen(stashFile.c_str(), "wb");
@@ -1669,6 +1673,13 @@ void save_game(bool leave_game, const char *farewellmsg)
#ifdef DGL_WHEREIS
whereis_record("saved");
#endif
+
+ if (_callback_list != NULL)
+ {
+ delete _callback_list;
+ _callback_list = NULL;
+ }
+
end(0, false, farewellmsg? "%s" : "See you soon, %s!",
farewellmsg? farewellmsg : you.your_name.c_str());
} // end save_game()
@@ -1863,6 +1874,8 @@ void restore_game(void)
load_messages(inf);
fclose(msgf);
}
+
+ SavefileCallback::post_restore();
}
static void _restore_level(const level_id &original)
@@ -2270,3 +2283,59 @@ file_lock::~file_lock()
lk_close(handle, mode, filename);
#endif
}
+
+/////////////////////////////////////////////////////////////////////////////
+// SavefileCallback
+//
+// Callbacks which are called before a save and after a restore. Can be used
+// to move stuff in and out of you.props, or on a restore to recalculate data
+// which isn't stored in the savefile. Declare a SavefileCallback variable
+// using a C++ global constructor to register the callback.
+//
+// XXX: Due to some weirdness with C++ global constructors (see below) I'm
+// not sure if this will work for all compiler/system combos, so make any
+// code which uses this fail gracefully if the callbacks aren't called.
+
+SavefileCallback::SavefileCallback(callback func)
+{
+ ASSERT(func != NULL);
+
+ // XXX: For some reason (at least with GCC 4.3.2 on Linux) if the
+ // callback list is made with a global contructor then it gets emptied
+ // out by the time that pre_save() or post_restore() is called,
+ // probably having something to do with the fact that global
+ // contructors are also used to add the callbacks. Thus we have to do
+ // it this way.
+ if (_callback_list == NULL)
+ _callback_list = new std::vector<SavefileCallback::callback>();
+
+ _callback_list->push_back(func);
+}
+
+void SavefileCallback::pre_save()
+{
+ ASSERT(crawl_state.saving_game);
+
+ if (_callback_list == NULL)
+ return;
+
+ for (unsigned int i = 0; i < _callback_list->size(); i++)
+ {
+ callback func = (*_callback_list)[i];
+ (*func)(true);
+ }
+}
+
+void SavefileCallback::post_restore()
+{
+ ASSERT(!crawl_state.saving_game);
+
+ if (_callback_list == NULL)
+ return;
+
+ for (unsigned int i = 0; i < _callback_list->size(); i++)
+ {
+ callback func = (*_callback_list)[i];
+ (*func)(false);
+ }
+}