#include "LocationState.h" #include namespace FRG { std::shared_ptr ClientLocationState::getOrCreate( const std::string& locationId) { auto& state = locations[locationId]; if (!state) state = std::make_shared(); return state; } void ClientLocationState::clear() { locations.clear(); } void LocationLocalState::save(nlohmann::json& out) const { out = { {"cameraAzimuth", cameraAzimuth}, {"cameraInclination", cameraInclination} }; } void LocationLocalState::load(const nlohmann::json& in) { cameraAzimuth = in.at("cameraAzimuth").get(); cameraInclination = in.at("cameraInclination").get(); } void ClientLocationState::save(nlohmann::json& out) const { out["locations"] = nlohmann::json::object(); for (const auto& [id, state] : locations) { if (!state) continue; nlohmann::json value; state->save(value); out["locations"][id] = std::move(value); } } void ClientLocationState::load(const nlohmann::json& in) { const auto& values = in.at("locations"); if (!values.is_object()) throw std::runtime_error("Client location state locations must be an object"); for (auto& [id, state] : locations) if (state) *state = LocationLocalState{}; for (const auto& [id, value] : values.items()) getOrCreate(id)->load(value); } void saveSinglePlayerPersistence( const nlohmann::json& networkState, const ClientLocationState& localState, nlohmann::json& out) { nlohmann::json savedLocalState; localState.save(savedLocalState); out = { {"persistenceVersion", kSinglePlayerPersistenceVersion}, {"networkState", networkState}, {"localState", std::move(savedLocalState)} }; } void loadSinglePlayerPersistence( const nlohmann::json& in, nlohmann::json& networkState, ClientLocationState& localState) { const int version = in.value("persistenceVersion", -1); if (version != kSinglePlayerPersistenceVersion) throw std::runtime_error( "Unsupported single-player persistence version: " + std::to_string(version)); networkState = in.at("networkState"); localState.load(in.at("localState")); } namespace { nlohmann::json saveCar(const NpcCar& car) { nlohmann::json waypoints = nlohmann::json::array(); for (const auto& waypoint : car.waypoints) waypoints.push_back( {{"x", waypoint.x()}, {"y", waypoint.y()}, {"z", waypoint.z()}}); return { {"position", {car.position.x(), car.position.y(), car.position.z()}}, {"rotation", car.rotation}, {"velocity", car.velocity}, {"steeringAngle", car.steeringAngle}, {"wheelAngle", car.wheelAngle}, {"mode", static_cast(car.mode)}, {"waypoints", std::move(waypoints)}, {"currentWaypoint", car.currentWaypoint} }; } void loadCar(NpcCar& car, const nlohmann::json& value) { const auto& position = value.at("position"); car.position = { position.at(0).get(), position.at(1).get(), position.at(2).get()}; car.rotation = value.at("rotation").get(); car.velocity = value.at("velocity").get(); car.steeringAngle = value.at("steeringAngle").get(); car.wheelAngle = value.at("wheelAngle").get(); car.mode = static_cast(value.at("mode").get()); car.waypoints.clear(); for (const auto& waypoint : value.at("waypoints")) car.waypoints.push_back({ waypoint.at("x").get(), waypoint.at("y").get(), waypoint.at("z").get()}); car.currentWaypoint = value.at("currentWaypoint").get(); } } std::vector LocationNetworkState::planPathExceptMyself(const Eigen::Vector3f& start, const Eigen::Vector3f& end, const std::string& entityId) const { return navigationMaps[activeNavigationIndex].findPathToNearest(start, end, {}); } void LocationNetworkState::initNavigation( const std::vector& paths, const std::string& zipFile) { const int savedActiveNavigationIndex = activeNavigationIndex; //navigationMapPaths = paths; navigationMaps.clear(); navigationMaps.resize(paths.size()); for (size_t i = 0; i < paths.size(); ++i) { navigationMaps[i].build(paths[i], zipFile); } activeNavigationIndex = savedActiveNavigationIndex >= 0 && savedActiveNavigationIndex < static_cast(navigationMaps.size()) ? savedActiveNavigationIndex : 0; } void LocationNetworkState::save(nlohmann::json& out) const { out["activeNavigationIndex"] = activeNavigationIndex; out["targetInteractiveObjectId"] = targetInteractiveObjectId; out["targetInteractNpcId"] = targetInteractNpcId; out["targetTeleportZoneId"] = targetTeleportZoneId; out["taxi"] = { {"car", saveCar(taxiCar)}, {"arrivedCallbackCalled", taxiArrivedCallbackCalled} }; } void LocationNetworkState::load(const nlohmann::json& in) { activeNavigationIndex = in.value("activeNavigationIndex", activeNavigationIndex); targetInteractiveObjectId = in.value("targetInteractiveObjectId", std::string()); targetInteractNpcId = in.value("targetInteractNpcId", std::string()); targetTeleportZoneId = in.value("targetTeleportZoneId", std::string()); const auto& taxi = in.at("taxi"); loadCar(taxiCar, taxi.at("car")); taxiArrivedCallbackCalled = taxi.at("arrivedCallbackCalled").get(); } } // namespace FRG