-
Notifications
You must be signed in to change notification settings - Fork 29
Implement in game menu for loading mods #512
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
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,10 +1,17 @@ | ||
#include "GameSingleton.hpp" | ||
|
||
#include <cstdint> | ||
#include <functional> | ||
#include <string_view> | ||
|
||
#include <godot_cpp/core/error_macros.hpp> | ||
#include <godot_cpp/variant/dictionary.hpp> | ||
#include <godot_cpp/variant/packed_string_array.hpp> | ||
#include <godot_cpp/variant/string_name.hpp> | ||
#include <godot_cpp/variant/typed_array.hpp> | ||
#include <godot_cpp/variant/utility_functions.hpp> | ||
|
||
#include <openvic-simulation/dataloader/Dataloader.hpp> | ||
#include <openvic-simulation/utility/Logger.hpp> | ||
|
||
#include "openvic-extension/singletons/AssetManager.hpp" | ||
|
@@ -34,13 +41,14 @@ StringName const& GameSingleton::_signal_mapmode_changed() { | |
void GameSingleton::_bind_methods() { | ||
OV_BIND_SMETHOD(setup_logger); | ||
|
||
OV_BIND_METHOD(GameSingleton::load_defines_compatibility_mode); | ||
OV_BIND_METHOD(GameSingleton::set_compatibility_mode_roots, { "file_paths", "replace_paths" }, DEFVAL(PackedStringArray{})); | ||
OV_BIND_METHOD(GameSingleton::set_compatibility_mode_base_path, { "base_path" }); | ||
OV_BIND_METHOD(GameSingleton::load_defines_compatibility_mode, { "base_path", "mods " }); | ||
|
||
OV_BIND_SMETHOD(search_for_game_path, { "hint_path" }, DEFVAL(String {})); | ||
OV_BIND_METHOD(GameSingleton::lookup_file_path, { "path" }); | ||
|
||
OV_BIND_METHOD(GameSingleton::get_bookmark_info); | ||
OV_BIND_METHOD(GameSingleton::get_mod_info); | ||
OV_BIND_METHOD(GameSingleton::setup_game, { "bookmark_index" }); | ||
OV_BIND_METHOD(GameSingleton::start_game_session); | ||
|
||
|
@@ -108,6 +116,38 @@ void GameSingleton::setup_logger() { | |
}); | ||
} | ||
|
||
TypedArray<Dictionary> GameSingleton::get_mod_info() const { | ||
static const StringName mod_info_identifier_key = "mod_identifier"; | ||
static const StringName mod_info_dependencies_key = "mod_dependencies"; | ||
static const StringName mod_info_loaded_key = "mod_loaded"; | ||
|
||
TypedArray<Dictionary> results; | ||
|
||
for (Mod const& mod : game_manager.get_mod_manager().get_mods()) { | ||
Dictionary mod_info_dictionary; | ||
|
||
mod_info_dictionary[mod_info_identifier_key] = Utilities::std_to_godot_string(mod.get_identifier()); | ||
|
||
PackedStringArray dependencies; | ||
for (std::string_view dep_id : mod.get_dependencies()) { | ||
dependencies.push_back(Utilities::std_to_godot_string(dep_id)); | ||
} | ||
mod_info_dictionary[mod_info_dependencies_key] = std::move(dependencies); | ||
|
||
#define loaded_mods game_manager.get_mod_manager().get_loaded_mods() | ||
if (std::find(loaded_mods.begin(), loaded_mods.end(), &mod) != loaded_mods.end()) { | ||
mod_info_dictionary[mod_info_loaded_key] = true; | ||
} else { | ||
mod_info_dictionary[mod_info_loaded_key] = false; | ||
} | ||
#undef loaded_mods | ||
|
||
results.push_back(std::move(mod_info_dictionary)); | ||
} | ||
|
||
return results; | ||
} | ||
|
||
TypedArray<Dictionary> GameSingleton::get_bookmark_info() const { | ||
static const StringName bookmark_info_name_key = "bookmark_name"; | ||
static const StringName bookmark_info_date_key = "bookmark_date"; | ||
|
@@ -610,29 +650,36 @@ Error GameSingleton::_load_flag_sheet() { | |
return ret; | ||
} | ||
|
||
Error GameSingleton::set_compatibility_mode_roots( | ||
PackedStringArray const& file_paths, godot::PackedStringArray const& replace_paths | ||
) { | ||
Dataloader::path_vector_t roots; | ||
roots.reserve(file_paths.size()); | ||
for (String const& path : file_paths) { | ||
roots.emplace_back(Utilities::godot_to_std_string(path)); | ||
} | ||
|
||
Dataloader::path_vector_t replace; | ||
replace.reserve(replace_paths.size()); | ||
for (String const& path : replace_paths) { | ||
replace.emplace_back(Utilities::godot_to_std_string(path)); | ||
Error GameSingleton::set_compatibility_mode_base_path(String const& base_path) { | ||
Dataloader::path_vector_t roots { Utilities::godot_to_std_string(base_path) }, replace_paths; | ||
if (!game_manager.set_base_path(roots)) { | ||
UtilityFunctions::push_error("Failed to set base path!"); | ||
return FAILED; | ||
} | ||
|
||
ERR_FAIL_COND_V_MSG(!game_manager.set_roots(roots, replace), FAILED, "Failed to set dataloader roots!"); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why not use the error macro? |
||
return OK; | ||
} | ||
|
||
Error GameSingleton::load_defines_compatibility_mode() { | ||
Error GameSingleton::load_defines_compatibility_mode(String const& base_path, PackedStringArray const& mods) { | ||
Error err = OK; | ||
auto add_message = std::bind_front(&LoadLocalisation::add_message, LoadLocalisation::get_singleton()); | ||
|
||
if (!game_manager.load_mod_descriptors()) { | ||
UtilityFunctions::push_error("Failed to load mod descriptors!"); | ||
err = FAILED; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It's best to return failed here. No point continuing with a broken state. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think it could be better to load the base game if mods are broken or unavailable rather than crashing the whole game. Open to doing it either way, that was my thought process. |
||
} | ||
|
||
Dataloader::path_vector_t roots { Utilities::godot_to_std_string(base_path) }, replace_paths; | ||
std::vector<std::string> converted_mods; | ||
converted_mods.reserve(mods.size()); | ||
for (String const& mod : mods) { | ||
converted_mods.push_back(Utilities::godot_to_std_string(mod)); | ||
} | ||
|
||
if (!game_manager.load_mods(roots, replace_paths, converted_mods)) { | ||
UtilityFunctions::push_error("Failed to load mods!"); | ||
err = FAILED; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same as comment L667, better to return here and use error macro. |
||
} | ||
|
||
auto add_message = std::bind_front(&LoadLocalisation::add_message, LoadLocalisation::get_singleton()); | ||
if (!game_manager.load_definitions(add_message)) { | ||
UtilityFunctions::push_error("Failed to load defines!"); | ||
err = FAILED; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If you update the above 2 cases, please also update this for consistency. |
||
|
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.
Please do not use macros for this.
Uh oh!
There was an error while loading. Please reload this page.
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.
Just store it in a local variable.
When using methods to get a value, do not assume the method returns the exact same value each invocation.
Also the method might be costly.