diff options
author | Matthew Cline <zelgadis@sourceforge.net> | 2009-10-29 00:59:40 -0700 |
---|---|---|
committer | Matthew Cline <zelgadis@sourceforge.net> | 2009-10-29 00:59:40 -0700 |
commit | f5cf3b82006ffe51f9462ddc8a6f65dce55a03d6 (patch) | |
tree | 02619aa602cf52d8d2700d9225bb0c2b1ba5c0c8 /crawl-ref/source/files.cc | |
parent | e083e2c09aad37199affe880180f2eda90d213ac (diff) | |
download | crawl-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.cc | 69 |
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); + } +} |