diff --git a/src/gui/handling/handling_saved_profiles.cpp b/src/gui/handling/handling_saved_profiles.cpp index 6dc29906..51a6d804 100644 --- a/src/gui/handling/handling_saved_profiles.cpp +++ b/src/gui/handling/handling_saved_profiles.cpp @@ -20,11 +20,11 @@ namespace big if (ImGui::ListBoxHeader("##handling_profiles")) { - for (const auto& [name, profile] : g_handling_service->profiles()) + for (auto& [name, profile] : g_handling_service->profiles()) { - if (components::selectable(name, profile.get() == g_handling_service->active_profile())) + if (components::selectable(name, &profile == g_handling_service->active_profile())) { - g_handling_service->apply_profile(profile.get()); + g_handling_service->apply_profile(&profile); } } ImGui::EndListBox(); diff --git a/src/services/vehicle/handling_profile.cpp b/src/services/vehicle/handling_profile.cpp index 399d28c1..dabdb7ea 100644 --- a/src/services/vehicle/handling_profile.cpp +++ b/src/services/vehicle/handling_profile.cpp @@ -13,7 +13,10 @@ namespace big const auto hash = vehicle->m_handling_data->m_model_hash; vehicle->m_gravity = m_gravity; - *vehicle->m_handling_data = m_handling_data; + + // cursed but works perfectly without overriding members that we shouldn't override + nlohmann::json j = m_handling_data; // exports our binary object so we can apply it field by field instead of copying the whole object + from_json(j, *vehicle->m_handling_data); // macro is defined in global scope of which CHandlingData is part of if (restore_hash) vehicle->m_handling_data->m_model_hash = hash; diff --git a/src/services/vehicle/handling_profile.hpp b/src/services/vehicle/handling_profile.hpp index 196b72ef..2e5ed74a 100644 --- a/src/services/vehicle/handling_profile.hpp +++ b/src/services/vehicle/handling_profile.hpp @@ -1,6 +1,25 @@ #pragma once #include "vehicle/CVehicle.hpp" +// Register to_json/from_json for these GTA classes +namespace rage +{ + NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(rage::fvector3, x, y, z) +} +NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(CHandlingData, + m_mass, m_initial_drag_coeff, m_downforce_multiplier, m_centre_of_mass, m_inertia_mult, + m_buoyancy, m_drive_bias_rear, m_drive_bias_front, m_acceleration, m_initial_drive_gears, + m_drive_inertia, m_upshift, m_downshift, m_initial_drive_force, m_drive_max_flat_velocity, + m_initial_drive_max_flat_vel, m_brake_force, m_brake_bias_front, m_brake_bias_rear, + m_handbrake_force, m_steering_lock, m_steering_lock_ratio, m_traction_curve_max, + m_traction_curve_lateral, m_traction_curve_min, m_traction_curve_ratio, m_curve_lateral, + m_curve_lateral_ratio, m_traction_spring_delta_max, m_traction_spring_delta_max_ratio, + m_low_speed_traction_loss_mult, m_camber_stiffness, m_traction_bias_front, m_traction_bias_rear, + m_traction_loss_mult, m_suspension_force, m_suspension_comp_damp, m_suspension_rebound_damp, + m_suspension_upper_limit, m_suspension_lower_limit, m_suspension_raise, m_suspension_bias_front, + m_suspension_bias_rear, m_anti_rollbar_force, m_anti_rollbar_bias_front, m_anti_rollbar_bias_rear, + m_roll_centre_height_front, m_roll_centre_height_rear, m_collision_damage_mult) + namespace big { class handling_profile final @@ -11,6 +30,9 @@ namespace big void apply_to(CVehicle* vehicle, bool restore_hash = true) const; + public: + NLOHMANN_DEFINE_TYPE_INTRUSIVE(handling_profile, m_gravity, m_handling_data) + private: float m_gravity; CHandlingData m_handling_data; diff --git a/src/services/vehicle/handling_service.cpp b/src/services/vehicle/handling_service.cpp index 332cbef1..3ceb7875 100644 --- a/src/services/vehicle/handling_service.cpp +++ b/src/services/vehicle/handling_service.cpp @@ -19,19 +19,47 @@ namespace big std::size_t handling_service::load_files() { std::size_t files_loaded{}; + m_handling_profiles.clear(); for (const auto& item : std::filesystem::directory_iterator(m_profiles_folder.get_path())) { if (!item.is_regular_file()) continue; - if (auto file_path = item.path(); file_path.extension() == ".bin") + + auto file_path = item.path(); + if (file_path.extension() == ".json") { - auto profile = std::make_unique(); auto profile_file = std::ifstream(file_path, std::ios::binary); - profile_file.read(reinterpret_cast(profile.get()), sizeof(handling_profile)); + nlohmann::json j; + profile_file >> j; profile_file.close(); - m_handling_profiles.emplace(file_path.stem().string(), std::move(profile)); + m_handling_profiles.emplace(file_path.stem().string(), j.get()); + + ++files_loaded; + } + // deprecate this + else if (file_path.extension() == ".bin") + { + LOG(WARNING) << "Attempting to convert old handling files, this feature will be removed in the future."; + + auto profile_file = std::ifstream(file_path, std::ios::binary); + auto profile = handling_profile(); + profile_file.read(reinterpret_cast(&profile), 328); // hardcoded old size to prevent overreading + profile_file.close(); + + const auto new_save = file_path.stem().string(); + + // this will make sure we only copy the fields we want to copy + nlohmann::json j = profile; + const auto save_file_path = m_profiles_folder.get_file("./" + new_save + ".json"); + auto save_file = std::ofstream(save_file_path.get_path(), std::ios::binary); + save_file << j.dump(4); + + // remove old file + std::filesystem::remove(file_path); + + m_handling_profiles.emplace(new_save, j.get()); ++files_loaded; } @@ -65,16 +93,21 @@ namespace big if (!vehicle) return false; - name += ".bin"; + name += ".json"; const auto save = m_profiles_folder.get_file(name); - auto profile = std::make_unique(vehicle); + auto profile = handling_profile(vehicle); auto save_file = std::ofstream(save.get_path(), std::ios::binary); - save_file.write(reinterpret_cast(profile.get()), sizeof(handling_profile)); + nlohmann::json j = profile; + save_file << j.dump(4); save_file.close(); - m_handling_profiles.emplace(name, std::move(profile)); + // reset our profile to prevent copying members we don't want to exist + profile = handling_profile(); + profile = j.get(); + + m_handling_profiles.emplace(save.get_path().stem().string(), std::move(profile)); return true; } @@ -89,7 +122,7 @@ namespace big if (const auto& it = m_vehicle_backups.find(hash); it != m_vehicle_backups.end()) return false; - m_vehicle_backups.emplace(hash, std::make_unique(vehicle)); + m_vehicle_backups.emplace(hash, handling_profile(vehicle)); return true; } @@ -102,7 +135,7 @@ namespace big if (const auto& it = m_vehicle_backups.find(vehicle->m_handling_data->m_model_hash); it != m_vehicle_backups.end()) { - it->second->apply_to(vehicle); + it->second.apply_to(vehicle); } } } \ No newline at end of file diff --git a/src/services/vehicle/handling_service.hpp b/src/services/vehicle/handling_service.hpp index 7862c9a7..d629a476 100644 --- a/src/services/vehicle/handling_service.hpp +++ b/src/services/vehicle/handling_service.hpp @@ -3,7 +3,7 @@ namespace big { - using handling_profiles = std::map>; + using handling_profiles = std::map; class handling_service final { public: @@ -32,7 +32,7 @@ namespace big handling_profiles m_handling_profiles; // contains the handling profiles of a vehicles before they're been modified - std::unordered_map> m_vehicle_backups; + std::unordered_map m_vehicle_backups; };