diff --git a/projects/Core/CMakeLists.txt b/projects/Core/CMakeLists.txt index f18f64ceb4f..84cb64e0c22 100644 --- a/projects/Core/CMakeLists.txt +++ b/projects/Core/CMakeLists.txt @@ -34,8 +34,9 @@ set( "api/messages/text_style.cpp" "api/moon_animator_events.cpp" "api/scenes/create_objects.cpp" - "api/scenes/scene_load.cpp" "api/scenes/polygon.cpp" + "api/scenes/scene_load.cpp" + "api/system/save_files.cpp" "api/audio.cpp" "api/screen_position.cpp" "api/uber_states/uber_state.cpp" @@ -106,6 +107,7 @@ set( "api/scenes/scene_load.h" "api/scenes/polygon.h" "api/system/message_provider.h" + "api/system/save_files.h" "api/audio.h" "api/screen_position.h" "api/uber_states/uber_state.h" diff --git a/projects/Core/api/system/save_files.cpp b/projects/Core/api/system/save_files.cpp new file mode 100644 index 00000000000..ec652f23b50 --- /dev/null +++ b/projects/Core/api/system/save_files.cpp @@ -0,0 +1,26 @@ +#include +#include +#include +#include +#include +#include + +using namespace app::classes; + +namespace core::api::save_files { + app::Byte__Array* get_byte_array(int slot_index, int backup_index) { + if (Grdk::Wrapper::get_InitializedOk()) { // Handle GRDK (Xbox Account) saves + return Grdk::Wrapper::Load_1(slot_index, backup_index); + } + + auto save_info = SaveGameController::GetSaveFileInfo(game::save_controller(), slot_index, backup_index); + auto path = save_info->fields.m_FullBackupSaveFilePath; + auto path_str = il2cpp::convert_csstring(path); + return System::IO::File::ReadAllBytes(path); + } + + std::vector get_bytes(int slot_index, int backup_index) { + return utils::ByteStream(get_byte_array(slot_index, backup_index)).peek_to_end(); + } +} + diff --git a/projects/Core/api/system/save_files.h b/projects/Core/api/system/save_files.h new file mode 100644 index 00000000000..29d633bb691 --- /dev/null +++ b/projects/Core/api/system/save_files.h @@ -0,0 +1,21 @@ +#pragma once + +#include + +namespace core::api::save_files { + /** + * Get the on-disk save data for a save file. + * @param slot_index Save slot index + * @param backup_index Backup slot index. Set this to -1 to request the current game save file. + * @return Pointer to an il2cpp array of System.Byte. + */ + CORE_DLLEXPORT app::Byte__Array* get_byte_array(int slot_index, int backup_index = -1); + + /** + * Get the on-disk save data for a save file. + * @param slot_index Save slot index + * @param backup_index Backup slot index. Set this to -1 to request the current game save file. + * @return Byte vector containing the on-disk save data + */ + CORE_DLLEXPORT std::vector get_bytes(int slot_index, int backup_index = -1); +} diff --git a/projects/Core/save_meta/save_meta.cpp b/projects/Core/save_meta/save_meta.cpp index 2d76a999360..96d16bfcabc 100644 --- a/projects/Core/save_meta/save_meta.cpp +++ b/projects/Core/save_meta/save_meta.cpp @@ -1,12 +1,13 @@ #include +#include #include #include #include +#include #include #include #include #include -#include #include #include #include @@ -268,18 +269,11 @@ namespace core::save_meta { // ...and then load SaveMeta with the ThroughDeathsAndQTMsAndBackups persistence // level from the backup save file if we're on a new/different save slot if (current_save_guid != previous_save_guid) { - app::Byte__Array* bytes; - - if (Grdk::Wrapper::get_InitializedOk()) { // Handle GRDK (Xbox Account) saves - bytes = Grdk::Wrapper::Load_1(save_slot_index, backup_slot); - } else { - auto save_info = SaveGameController::GetSaveFileInfo(this_ptr, save_slot_index, backup_slot); - auto path = save_info->fields.m_FullBackupSaveFilePath; - auto path_str = il2cpp::convert_csstring(path); - bytes = System::IO::File::ReadAllBytes(path); - } - - read_save_meta_from_byte_array(bytes, true, SaveMetaSlotPersistence::ThroughDeathsAndQTMsAndBackups); + read_save_meta_from_byte_array( + api::save_files::get_byte_array(save_slot_index, backup_slot), + true, + SaveMetaSlotPersistence::ThroughDeathsAndQTMsAndBackups + ); } return return_value; diff --git a/projects/Randomizer/league/league.cpp b/projects/Randomizer/league/league.cpp index 6ec0e0bed7b..779c387dbd0 100644 --- a/projects/Randomizer/league/league.cpp +++ b/projects/Randomizer/league/league.cpp @@ -31,7 +31,10 @@ #include #define CPPHTTPLIB_OPENSSL_SUPPORT +#include #include +#include +#include #include #undef MessageBox @@ -173,7 +176,7 @@ namespace randomizer::league { status_message_mutex.unlock(); } - void start_submission_thread(const std::string& save_file_path) { + void start_submission_thread(const int save_slot_index) { using namespace std::chrono_literals; if (!get_multiverse_id().has_value()) { @@ -195,11 +198,10 @@ namespace randomizer::league { const auto multiverse_id = get_multiverse_id().value(); const auto jwt = randomizer::online::get_jwt(); - submit_thread = std::make_shared([host, insecure, multiverse_id, jwt, save_file_path]() { + submit_thread = std::make_shared([host, insecure, multiverse_id, jwt, save_slot_index]() { upload_attempt.store(0); - std::ifstream input(save_file_path, std::ios::binary); - std::vector save_file_data(std::istreambuf_iterator(input), {}); + auto save_file_data = core::api::save_files::get_bytes(save_slot_index); while (submission_status.load() == SubmissionStatus::Uploading) { const auto attempt = upload_attempt.fetch_add(1) + 1; @@ -215,7 +217,7 @@ namespace randomizer::league { auto result = client.Post(std::format("/api/league/{}/submission", multiverse_id), { {"User-Agent", std::format("OriAndTheWillOfTheWispsRandomizer/{}", randomizer_version().to_string())}, {"Authorization", std::format("Bearer {}", jwt)} - }, save_file_data.data(), save_file_data.size(), "application/octet-stream"); + }, reinterpret_cast(save_file_data.data()), save_file_data.size(), "application/octet-stream"); if (result.error() != httplib::Error::Success) { set_status_message_thread_safe("Request failed"); @@ -319,8 +321,7 @@ namespace randomizer::league { core::api::audio::play_sound(SoundEventID::LeagueSubmitted); const auto save_controller = core::api::game::save_controller(); - const auto current_save_file_path = il2cpp::convert_csstring(SaveGameController::get_CurrentSaveFileInfo(save_controller)->fields.m_FullSaveFilePath); - start_submission_thread(current_save_file_path); + start_submission_thread(SaveGameController::get_CurrentSlotIndex(save_controller)); }); } else { const auto resolved_epilogue_timeline = il2cpp::invoke(shriek_entity->fields.EpilogueTimeline, "Resolve", 0); diff --git a/projects/Randomizer/ui/main_menu_seed_info.cpp b/projects/Randomizer/ui/main_menu_seed_info.cpp index 33c1909cd3f..6b5d77244ef 100644 --- a/projects/Randomizer/ui/main_menu_seed_info.cpp +++ b/projects/Randomizer/ui/main_menu_seed_info.cpp @@ -9,28 +9,29 @@ #include #include #include +#include +#include #include #include +#include +#include #include +#include #include #include #include #include #include #include -#include -#include -#include #include #include #include #include #include +#include #include #include #include -#include -#include using namespace utils; using namespace app::classes; @@ -432,20 +433,9 @@ namespace randomizer::main_menu_seed_info { if (SaveSlotsManager::SaveFileExists(index)) { on_seed_loaded_handle = nullptr; - const auto save_controller = core::api::game::save_controller(); - - app::Byte__Array* data; - - if (Grdk::Wrapper::get_InitializedOk()) { // Handle GRDK (Xbox live) saves - data = Grdk::Wrapper::Load_1(index, -1); - } else { - const auto save_info = SaveGameController::GetSaveFileInfo(save_controller, index, -1); - data = System::IO::File::ReadAllBytes(save_info->fields.m_FullSaveFilePath); - } - auto seed_meta_data = std::make_shared(); const auto read_slots = core::save_meta::read_save_meta_slots_from_byte_array( - data, + core::api::save_files::get_byte_array(index, -1), { {SaveMetaSlot::SeedMetaData, seed_meta_data} }