-
Notifications
You must be signed in to change notification settings - Fork 283
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
refactor: Clean up world saving/loading codepath (Phase 1 of v2 save format) #5774
Conversation
All the other binaries are listed except for the ones that cmake actually generates for tiles builds. Signed-off-by: David Li <jiawei.davidli@gmail.com>
Clean up and refactor worldfactory and world. * The old 'WORLD' struct is now renamed `WORLDINFO` to better reflect its actual purpose. * Get rid of the WORLDPTR = WORLD* convention. This isn't the Windows API, and nothing else does this. * Move file saving logic into a new class called `world`, meant to encapsulate the idea of a loaded world. I will begin consolidating more world loading logic into this class. Signed-off-by: David Li <jiawei.davidli@gmail.com>
Replace the 2 write and 6 read methods with 1 write and 2 read. This simplification is needed because future save loaders will need to provide their own implementations of these methods. * The `_optional` variants can be replaced with default arguments. * The `JsonDeserializer` variants are never used. * The `_json` variants do save some boilerplate (`path`) so I'll keep that in for now. Signed-off-by: David Li <jiawei.davidli@gmail.com>
Player file IO is still janky, particularly `mm` files - WIP. However, the game does work and the on-disk format should be unchanged. Signed-off-by: David Li <jiawei.davidli@gmail.com>
Clean up how the game determines where to place player- specific files, in preparation for the V2 save format. NOTE: This removes backwards compatibility for the pre-2020 map memory ('mm') format. This logic only triggered when loading a map that has not seen a save event since 2020 - I think it's safe to remove this now. Signed-off-by: David Li <jiawei.davidli@gmail.com>
Autofix has formatted code style violation in this PR. I edit commits locally (e.g: git, github desktop) and want to keep autofix
I do not want the automated commit
If you don't do this, your following commits will be based on the old commit, and cause MERGE CONFLICT. |
gah astyle is going haywire |
No, |
Actually, if there's no objections I'll the keep asyle commit without squashing - it leaves the individual diffs nice and self-consistent. |
Signed-off-by: David Li <jiawei.davidli@gmail.com>
Signed-off-by: David Li <jiawei.davidli@gmail.com>
The consolidation of write_to_file methods introduced a subtle API change where passing nullptr to the third argument no longer caused write_to_file to eat exceptions. This largely only affected tests and a small number of edge cases. Alter the API so that the right way to eat exceptions is via passing in the empty string as the message. Signed-off-by: David Li <jiawei.davidli@gmail.com>
344b84e
to
1229bfa
Compare
Plus misc bug fixes Signed-off-by: David Li <jiawei.davidli@gmail.com>
1229bfa
to
e6dd533
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the changes looks good to me, there's some nitpicks here and there but not critical.
@chaosvolt @RoyalFox2140 could you playtest them before merging to be extra sure?
src/fstream_utils.h
Outdated
using file_read_cb = const std::function<void( std::istream & )> &; | ||
using file_read_json_cb = const std::function<void( JsonIn & )> &; | ||
using file_write_cb = const std::function<void( std::ostream & )> &; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think fn
(function) would be clearer than cb
(callback).
src/cata_utility.cpp
Outdated
@@ -523,8 +530,12 @@ std::istream &safe_getline( std::istream &ins, std::string &str ) | |||
} | |||
} | |||
|
|||
bool read_from_file( const std::string &path, const std::function<void( std::istream & )> &reader ) | |||
bool read_from_file( const std::string &path, file_read_cb reader, bool optional ) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
might be clearer to use enum class over boolean flag, e.g
enum class read_option {
REQUIRED = 0,
OPTIONAL = 1
};
src/game.cpp
Outdated
bool game::take_screenshot( const std::string &path ) | ||
{ | ||
return save_screenshot( path ); | ||
} | ||
|
||
bool game::take_screenshot() const | ||
bool game::take_screenshot() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
could you explain why was the const
removed? does the function internals now mutate states when taking screenshots?
src/world.h
Outdated
*/ | ||
/**@{*/ | ||
void start_save_tx(); | ||
long long commit_save_tx(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
might be clearer to use int64_t
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good to me. Great stuff.
src/game.cpp
Outdated
@@ -2732,16 +2727,23 @@ spell_events &game::spell_events_subscriber() | |||
return *spell_events_ptr; | |||
} | |||
|
|||
static bool save_uistate_data( const game &g ) | |||
bool game::save_uistate_data() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does it affect the state? Should be const if it doesn't
@@ -11413,12 +11418,12 @@ void game::quicksave() | |||
|
|||
void game::quickload() | |||
{ | |||
const WORLDPTR active_world = world_generator->active_world; | |||
world *active_world = get_active_world(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does it have to be non-const?
src/world.cpp
Outdated
// if( SQLITE_OK != ( ret = sqlite3_exec( db, sql, NULL, NULL, &sqlErrMsg ) ) ) { | ||
// dbg( DL::Error ) << "Failed to init db" << db_path << " (" << sqlErrMsg << ")"; | ||
// throw std::runtime_error( "Failed to open db" ); | ||
// } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Commented out code - should be removed from the PR. It's easy to restore it from git history later.
src/cata_utility.cpp
Outdated
@@ -523,8 +530,12 @@ std::istream &safe_getline( std::istream &ins, std::string &str ) | |||
} | |||
} | |||
|
|||
bool read_from_file( const std::string &path, const std::function<void( std::istream & )> &reader ) | |||
bool read_from_file( const std::string &path, file_read_cb reader, bool optional ) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, that bool
is hard to understand there. Especially after function definition.
If not an enum flag, the following options would also work:
- Split into 2 functions: mandatory and optional variant
- Empty class used just as argument here, for overload
I'd like to see if the various code nitpicks can be addressed before I test it. Are any of them deal-breakers or are they all just minor things that can be ignored if nessecary? |
they are pure C++ nitpicks and won't affect gameplay. |
In that case will see about testing it in a bit, later today if getting ready to head out and deal with errands doesn't leave be with enough time. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- Compile-tested.
- Loaded a save from a previous compile-test, no errors seen.
- Started a new world, saved and loaded, also worked fine.
- Started a new character in this new world with one already in it, saving and loading the second character also works.
8cb8210
to
1f4fa77
Compare
Addressed comments. The consts were a leftover from a previous iteration - I added them back in where appropriate. The player data write methods cannot be const to make way for the Phase 2 patch. Because the saveid is not known when the |
strange, MSVC is chocking on here
|
d9ebad7
to
6cfa61d
Compare
Yea, there's something about enum syntax that MSVC really doesn't like. |
6cfa61d
to
45e1ba9
Compare
weird, other enum classes compile fine. |
45e1ba9
to
0f66a62
Compare
If the saves are going to break they're going to break after days of playing the same save file for hours a day, And I can't play self-compile versions. No matter what settings are used my game lags heavily and we've gone over using Release without Debug symbols doing nothing to fix it, and proper releases not lagging. There's nothing for me to do here. If it's going to break everything it's going to do so in a way that won't get caught from standard testing. MSVC and Ubuntu tests failed, so I'll at least re-run those. |
Signed-off-by: David Li <jiawei.davidli@gmail.com>
0f66a62
to
b4c55df
Compare
I changed the enum back to a bool. There's something weird going on with MSVC and I don't have a local environment to test/debug that right now. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- Compiled and load-tested.
- Loaded a save from previous compiling, loads as expected. Loading the two different characters in the save also work right.
- Tested save/load, no oddities found.
- Also quicksaved, debug quit to menu, then loaded with no issues.
- Spawned in an APC and used autodrive to move a long distance before quicksaving, also worked.
Quicksave just standing in starting shelter:
Quicksave after a nice long drive (about 75 thousand blocks of things to save, whatever the number during save progress is counting):
Checklist
Required
main
so it won't cause conflict when updatingmain
branch later.Purpose of change
This PR is Phase 1 of #5771.
It refactors much of the world and player save read/write logic, with a particular focus on consolidating the business logic of what gets saved where. The purpose is to create a clean environment where we can add on support for different save formats in a subsequent PR.
This PR should not change the on-disk format. Everything should continue to work normally. The actual SQLite+compression implementation will happen on top of this refactored backend in a later PR.
Describe the solution
worldfactory
andworld
.WORLD
struct is now renamedWORLDINFO
to better reflect its actual purpose.WORLDPTR = WORLD*
convention. This isn't the Windows API, and nothing else in the codebase does this.world
, meant to encapsulate the idea of a loaded world. All reads and writes to world and player files now go through this class, which forms the foundation for future changes to the save format.read_from_file*
andwrite_to_file*
found incata_utility.cpp
. This replaces the 2 write and 6 read methods with 1 write and 2 read. This simplification is needed because future save loaders will need to provide their own implementations of these methods._optional
variants can be replaced with default arguments.JsonDeserializer
variants are never used._json
variants do save some boilerplate (path
) so I'll keep that in for now.Describe alternatives you've considered
Testing
Awaiting CI signals.
I tested by loading & saving a couple of existing worlds, without obvious issues thus far.
Additional context