178 lines
5.2 KiB
C++
178 lines
5.2 KiB
C++
#include "LocationState.h"
|
|
#include <stdexcept>
|
|
|
|
namespace FRG {
|
|
|
|
std::shared_ptr<LocationLocalState> ClientLocationState::getOrCreate(
|
|
const std::string& locationId)
|
|
{
|
|
auto& state = locations[locationId];
|
|
if (!state) state = std::make_shared<LocationLocalState>();
|
|
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<float>();
|
|
cameraInclination = in.at("cameraInclination").get<float>();
|
|
}
|
|
|
|
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<int>(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<float>(),
|
|
position.at(1).get<float>(),
|
|
position.at(2).get<float>()};
|
|
car.rotation = value.at("rotation").get<float>();
|
|
car.velocity = value.at("velocity").get<float>();
|
|
car.steeringAngle = value.at("steeringAngle").get<float>();
|
|
car.wheelAngle = value.at("wheelAngle").get<float>();
|
|
car.mode = static_cast<NpcCar::Mode>(value.at("mode").get<int>());
|
|
car.waypoints.clear();
|
|
for (const auto& waypoint : value.at("waypoints"))
|
|
car.waypoints.push_back({
|
|
waypoint.at("x").get<float>(),
|
|
waypoint.at("y").get<float>(),
|
|
waypoint.at("z").get<float>()});
|
|
car.currentWaypoint = value.at("currentWaypoint").get<std::size_t>();
|
|
}
|
|
}
|
|
|
|
|
|
std::vector<Eigen::Vector3f> 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<std::string>& 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<int>(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<bool>();
|
|
}
|
|
|
|
} // namespace FRG
|