refactor(MobileService): Auto load personal vehicles, modernized code & improved caching (#195)

This commit is contained in:
Yimura 2022-05-10 19:02:30 +02:00 committed by GitHub
parent 740a4d48cf
commit 7ac3632553
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 71 additions and 49 deletions

View File

@ -2,37 +2,35 @@
#include "fiber_pool.hpp" #include "fiber_pool.hpp"
#include "natives.hpp" #include "natives.hpp"
#include "script.hpp" #include "script.hpp"
#include "thread_pool.hpp"
#include "util/mobile.hpp" #include "util/mobile.hpp"
namespace big namespace big
{ {
PersonalVehicle::PersonalVehicle(int idx, script_global vehicle_idx) personal_vehicle::personal_vehicle(int idx, script_global vehicle_idx)
: m_id(idx)
{ {
m_id = idx;
m_hash = *vehicle_idx.at(66).as<Hash*>(); m_hash = *vehicle_idx.at(66).as<Hash*>();
m_state_bitfield = vehicle_idx.at(103).as<int*>(); m_state_bitfield = vehicle_idx.at(103).as<int*>();
m_name = HUD::GET_LABEL_TEXT_(VEHICLE::GET_DISPLAY_NAME_FROM_VEHICLE_MODEL(m_hash)); m_name = HUD::GET_LABEL_TEXT_(VEHICLE::GET_DISPLAY_NAME_FROM_VEHICLE_MODEL(m_hash));
} }
std::string PersonalVehicle::get_display_name() std::string personal_vehicle::get_display_name() const
{ {
return m_name + "##" + std::to_string(m_id); return m_name + "##" + std::to_string(m_id);
} }
Hash PersonalVehicle::get_hash() Hash personal_vehicle::get_hash() const
{ {
return m_hash; return m_hash;
} }
int PersonalVehicle::get_id() int personal_vehicle::get_id() const
{ {
return m_id; return m_id;
} }
void PersonalVehicle::summon() void personal_vehicle::summon() const
{ {
mobile::mechanic::summon_vehicle_by_index(m_id); mobile::mechanic::summon_vehicle_by_index(m_id);
} }
@ -47,38 +45,58 @@ namespace big
g_mobile_service = nullptr; g_mobile_service = nullptr;
} }
void mobile_service::refresh_personal_vehicles()
{
const auto now = std::chrono::high_resolution_clock::now();
if (now - m_last_update < 10s) return;
g_fiber_pool->queue_job([this]
{
register_vehicles();
});
}
void mobile_service::register_vehicles() void mobile_service::register_vehicles()
{ {
for (int i = 0; i < *mobile::vehicle_global.as<int*>(); i++) const auto array_size = *mobile::vehicle_global.as<int*>();
for (int i = 0; i < array_size; i++)
{ {
script::get_current()->yield(); if (i % 100 == 0)
script::get_current()->yield();
auto veh_idx_global = mobile::vehicle_global.at(i, 142); auto veh_idx_global = mobile::vehicle_global.at(i, 142);
Hash hash = *veh_idx_global.at(66).as<Hash*>(); const auto hash = *veh_idx_global.at(66).as<Hash*>();
auto& it = m_pv_lookup.find(i); const auto& it = m_pv_lookup.find(i);
const auto exists = it != m_pv_lookup.end();
// double check if model is a vehicle
if (STREAMING::IS_MODEL_A_VEHICLE(hash)) if (STREAMING::IS_MODEL_A_VEHICLE(hash))
{ {
auto veh = std::make_unique<PersonalVehicle>(i, veh_idx_global); auto veh = std::make_unique<personal_vehicle>(i, veh_idx_global);
if (it != m_pv_lookup.end()) if (exists)
{ {
m_personal_vehicles.erase(it->second); // vehicle name is no longer the same, update the vehicle at that index
if (veh->get_display_name() != it->second)
{
m_personal_vehicles.erase(it->second);
it->second = veh->get_display_name(); it->second = veh->get_display_name();
m_personal_vehicles.emplace(veh->get_display_name(), std::move(veh)); m_personal_vehicles.emplace(veh->get_display_name(), std::move(veh));
}
continue; continue;
} }
m_pv_lookup.emplace(i, veh->get_display_name()); m_pv_lookup.emplace(i, veh->get_display_name()); // update lookup table
m_personal_vehicles.emplace(veh->get_display_name(), std::move(veh)); m_personal_vehicles.emplace(veh->get_display_name(), std::move(veh)); // add new vehicle
continue; continue;
} }
if (it != m_pv_lookup.end()) // vehicle existed at some point but no longer does
if (exists)
{ {
m_personal_vehicles.erase(it->second); m_personal_vehicles.erase(it->second);
m_pv_lookup.erase(i); m_pv_lookup.erase(i);

View File

@ -4,7 +4,7 @@ namespace big
{ {
class script_global; class script_global;
class PersonalVehicle class personal_vehicle final
{ {
std::string m_name; std::string m_name;
int m_id; int m_id;
@ -12,28 +12,37 @@ namespace big
int* m_state_bitfield; int* m_state_bitfield;
public: public:
PersonalVehicle(int idx, script_global vehicle_idx); personal_vehicle(int idx, script_global vehicle_idx);
std::string get_display_name(); [[nodiscard]] std::string get_display_name() const;
Hash get_hash(); [[nodiscard]] Hash get_hash() const;
int get_id(); [[nodiscard]] int get_id() const;
void summon(); void summon() const;
}; };
class mobile_service class mobile_service final
{ {
std::map<std::string, std::unique_ptr<personal_vehicle>> m_personal_vehicles;
std::map<int, std::string> m_pv_lookup;
std::chrono::time_point<std::chrono::steady_clock> m_last_update;
public: public:
mobile_service(); mobile_service();
~mobile_service(); ~mobile_service();
mobile_service(const mobile_service&) = delete;
mobile_service(mobile_service&&) noexcept = delete;
mobile_service& operator=(const mobile_service&) = delete;
mobile_service& operator=(mobile_service&&) noexcept = delete;
std::map<std::string, std::unique_ptr<personal_vehicle>>& personal_vehicles()
{ return m_personal_vehicles; }
void refresh_personal_vehicles();
void register_vehicles(); void register_vehicles();
std::map<std::string, std::unique_ptr<PersonalVehicle>> m_personal_vehicles;
std::map<int, std::string> m_pv_lookup;
}; };
class mobile_service;
inline mobile_service* g_mobile_service{}; inline mobile_service* g_mobile_service{};
} }

View File

@ -35,29 +35,28 @@ namespace big
std::transform(lower_search.begin(), lower_search.end(), lower_search.begin(), tolower); std::transform(lower_search.begin(), lower_search.end(), lower_search.begin(), tolower);
} }
g_mobile_service->refresh_personal_vehicles();
if (ImGui::ListBoxHeader("##personal_veh_list", { 400.f, 500.f })) if (ImGui::ListBoxHeader("##personal_veh_list", { 400.f, 500.f }))
{ {
for (auto& it : g_mobile_service->m_personal_vehicles) const auto personal_veh_idx = mobile::util::get_current_personal_vehicle();
for (const auto& it : g_mobile_service->personal_vehicles())
{ {
std::string label = it.first; const auto& label = it.first;
auto& personal_veh = it.second; const auto& personal_veh = it.second;
std::string lower = label.c_str(); auto lower = label;
std::transform(lower.begin(), lower.end(), lower.begin(), ::tolower); std::transform(lower.begin(), lower.end(), lower.begin(), ::tolower);
if (lower.find(lower_search) != std::string::npos) if (lower.find(lower_search) != std::string::npos)
{ {
if (ImGui::Selectable( if (ImGui::Selectable(label.c_str(), personal_veh->get_id() == personal_veh_idx))
label.c_str(),
personal_veh->get_id() == mobile::util::get_current_personal_vehicle()
))
{ {
strcpy(search, ""); strcpy(search, "");
lower_search = search; lower_search = search;
g_fiber_pool->queue_job([&personal_veh] { g_fiber_pool->queue_job([&personal_veh] {
personal_veh->summon(); personal_veh->summon();
}); });
} }
} }
} }
@ -68,14 +67,10 @@ namespace big
ImGui::EndGroup(); ImGui::EndGroup();
ImGui::BeginGroup(); ImGui::BeginGroup();
if (ImGui::Button("Load/Reload Personal Vehicles"))
{
g_fiber_pool->queue_job([] {
g_mobile_service->register_vehicles();
});
}
ImGui::Checkbox("Spawn in Vehicle", &g->vehicle.pv_teleport_into); ImGui::Checkbox("Spawn in Vehicle", &g->vehicle.pv_teleport_into);
ImGui::EndGroup();
} }
} }