refactor(HandlingService): Use JSON to store profiles (#711)

* fix(HandlingService): Correctly apply profile from storage
* fix(HandlingService): Name inconsistency in UI
* feat(HandlingService): Convert old handling profiles
This commit is contained in:
Yimura 2022-12-17 15:11:36 +01:00 committed by GitHub
parent 9829e0e3ab
commit fac091ba6f
5 changed files with 74 additions and 16 deletions

View File

@ -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();

View File

@ -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;

View File

@ -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;

View File

@ -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<handling_profile>();
auto profile_file = std::ifstream(file_path, std::ios::binary);
profile_file.read(reinterpret_cast<char*>(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<handling_profile>());
++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<char*>(&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<handling_profile>());
++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<handling_profile>(vehicle);
auto profile = handling_profile(vehicle);
auto save_file = std::ofstream(save.get_path(), std::ios::binary);
save_file.write(reinterpret_cast<const char*>(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<handling_profile>();
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<handling_profile>(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);
}
}
}

View File

@ -3,7 +3,7 @@
namespace big
{
using handling_profiles = std::map<std::string, std::unique_ptr<handling_profile>>;
using handling_profiles = std::map<std::string, handling_profile>;
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<std::uint32_t, std::unique_ptr<handling_profile>> m_vehicle_backups;
std::unordered_map<std::uint32_t, handling_profile> m_vehicle_backups;
};