Working on the server

This commit is contained in:
Vladislav Khorev committed 2026-11-05 20:12:30 +06:00
1 parent 075750442f
commit 28c6e83eda
30 files changed
+646 -362

No files matched your search

+1 -7
View File
@@ -30,7 +30,7 @@ struct InteractiveObjectSnapshot {
struct LocationSnapshot {
std::string id;
LocationState state;
LocationNetworkState state;
std::unordered_map<std::string, CharacterSnapshot> npcs;
std::unordered_map<std::string, InteractiveObjectSnapshot> interactiveObjects;
std::unordered_map<std::string, TriggerZoneGameState> triggerZones;
@@ -95,11 +95,6 @@ struct AppendChatMessageCommand {
struct SetTaxiCalledCommand { bool called; };
struct StartTaxiCommand { std::string locationId; };
struct ResetTaxiCommand { std::string locationId; };
struct SetLocationCameraCommand {
std::string locationId;
float azimuth;
float inclination;
};
struct SetLocationTargetsCommand {
std::string locationId;
std::string interactiveObjectId;
@@ -232,7 +227,6 @@ using GameCommand = std::variant<
SetTaxiCalledCommand,
StartTaxiCommand,
ResetTaxiCommand,
SetLocationCameraCommand,
SetLocationTargetsCommand,
SwitchLocationNavigationCommand,
SetNavigationAreaAvailableCommand,
+3 -9
View File
@@ -305,12 +305,6 @@ void InternalGameServer::submit(const GameCommand& command)
auto location = state_.locations.find(value.locationId);
if (location != state_.locations.end())
location->second.resetTaxi();
} else if constexpr (std::is_same_v<T, SetLocationCameraCommand>) {
auto location = state_.locations.find(value.locationId);
if (location != state_.locations.end() && location->second.location) {
location->second.location->cameraAzimuth = value.azimuth;
location->second.location->cameraInclination = value.inclination;
}
} else if constexpr (std::is_same_v<T, SetLocationTargetsCommand>) {
auto location = state_.locations.find(value.locationId);
if (location != state_.locations.end() && location->second.location) {
@@ -326,7 +320,7 @@ void InternalGameServer::submit(const GameCommand& command)
value.index >= 0 &&
value.index < static_cast<int>(
location->second.location->navigationMaps.size())) {
LocationState& locationState = *location->second.location;
LocationNetworkState& locationState = *location->second.location;
locationState.activeNavigationIndex = value.index;
for (const auto& [id, player] : state_.players)
if (player) player->forceReplan(locationState, id);
@@ -336,7 +330,7 @@ void InternalGameServer::submit(const GameCommand& command)
} else if constexpr (std::is_same_v<T, SetNavigationAreaAvailableCommand>) {
auto location = state_.locations.find(value.locationId);
if (location != state_.locations.end() && location->second.location) {
LocationState& locationState = *location->second.location;
LocationNetworkState& locationState = *location->second.location;
const int index = locationState.activeNavigationIndex;
if (index >= 0 &&
index < static_cast<int>(locationState.navigationMaps.size())) {
@@ -347,7 +341,7 @@ void InternalGameServer::submit(const GameCommand& command)
} else if constexpr (std::is_same_v<T, AddNavigationObstacleCommand>) {
auto location = state_.locations.find(value.locationId);
if (location != state_.locations.end() && location->second.location) {
LocationState& locationState = *location->second.location;
LocationNetworkState& locationState = *location->second.location;
const int index = locationState.activeNavigationIndex;
if (index >= 0 &&
index < static_cast<int>(locationState.navigationMaps.size())) {
+14 -2
View File
@@ -15,18 +15,21 @@ void LocalGameServerHost::initializeCampaign(
const std::string& campaignId, const std::string& questsPath,
const std::string& zipFile)
{
localState_.clear();
server_.initializeCampaign(campaignId, questsPath, zipFile);
}
void LocalGameServerHost::clearCampaign()
{
runtimeLocations_.clear();
localState_.clear();
server_.clearCampaign();
}
void LocalGameServerHost::resetCampaign(
const std::string& questsPath, const std::string& zipFile)
{
localState_.clear();
server_.resetCampaign(questsPath, zipFile);
}
@@ -44,6 +47,7 @@ void LocalGameServerHost::setupRuntimeLocation(
throw std::runtime_error("Location state was not prepared");
params.definition = stored->second.definition;
params.gameState = &stored->second;
params.localState = localState_.getOrCreate(id);
location->setup(params, audioPlayer);
server_.publishMutation();
}
@@ -122,12 +126,20 @@ void LocalGameServerHost::update(std::int64_t deltaMs)
void LocalGameServerHost::save(nlohmann::json& out)
{
synchronizeRuntimeAuxiliaryState();
server_.save(out);
nlohmann::json networkState;
server_.save(networkState);
saveSinglePlayerPersistence(networkState, localState_, out);
}
void LocalGameServerHost::load(const nlohmann::json& in)
{
server_.load(in);
nlohmann::json networkState;
ClientLocationState loadedLocalState;
loadSinglePlayerPersistence(in, networkState, loadedLocalState);
server_.load(networkState);
nlohmann::json localStateJson;
loadedLocalState.save(localStateJson);
localState_.load(localStateJson);
applyStateToRuntime();
}
+2
View File
@@ -1,6 +1,7 @@
#pragma once
#include "IGameServerHost.h"
#include "../LocationState.h"
#include <unordered_map>
namespace FRG {
@@ -39,6 +40,7 @@ private:
void applyStateToRuntime();
InternalGameServer& server_;
ClientLocationState localState_;
std::unordered_map<std::string, std::shared_ptr<Location>> runtimeLocations_;
};
+1
View File
@@ -1,6 +1,7 @@
#include "NetworkProtocol.h"
#include <exception>
namespace FRG {
std::string makeStateMessage(const nlohmann::json& state)
+12 -2
View File
@@ -15,6 +15,7 @@ void RemoteGameServerHost::initializeCampaign(
const std::string& campaignId, const std::string&,
const std::string& zipFile)
{
localState_.clear();
const CampaignConfig* campaign =
CampaignRegistry::instance().find(campaignId);
if (!campaign)
@@ -25,6 +26,7 @@ void RemoteGameServerHost::initializeCampaign(
void RemoteGameServerHost::clearCampaign()
{
runtimeLocations_.clear();
localState_.clear();
client_.replica_.clearCampaign();
}
@@ -48,6 +50,7 @@ void RemoteGameServerHost::setupRuntimeLocation(
throw std::runtime_error("Remote location state was not prepared");
params.definition = stored->second.definition;
params.gameState = &stored->second;
params.localState = localState_.getOrCreate(id);
location->setup(params, audioPlayer);
}
@@ -101,9 +104,16 @@ void RemoteGameServerHost::save(nlohmann::json&)
// Persistence remains server-side.
}
void RemoteGameServerHost::load(const nlohmann::json&)
void RemoteGameServerHost::load(const nlohmann::json& in)
{
// Persistence remains server-side.
// The authoritative half is loaded by the standalone server. Each client
// restores only its local presentation state from the shared start state.
nlohmann::json ignoredNetworkState;
ClientLocationState loadedLocalState;
loadSinglePlayerPersistence(in, ignoredNetworkState, loadedLocalState);
nlohmann::json localStateJson;
loadedLocalState.save(localStateJson);
localState_.load(localStateJson);
}
} // namespace FRG
+2
View File
@@ -1,6 +1,7 @@
#pragma once
#include "IGameServerHost.h"
#include "../LocationState.h"
#include <unordered_map>
namespace FRG {
@@ -33,6 +34,7 @@ public:
private:
WebsocketGameClient& client_;
ClientLocationState localState_;
std::unordered_map<std::string, std::shared_ptr<Location>> runtimeLocations_;
};
+8
View File
@@ -47,6 +47,7 @@ public:
}
bool connected() const { return connected_.load(); }
bool connectionFailed() const { return connectionFailed_.load(); }
private:
void resolve()
@@ -101,6 +102,7 @@ private:
void fail(const char* operation, beast::error_code error)
{
connected_.store(false);
connectionFailed_.store(true);
std::cerr << "[network] WebSocket " << operation << " failed: "
<< error.message() << '\n';
}
@@ -114,6 +116,7 @@ private:
std::string port_;
std::string path_;
std::atomic_bool connected_{false};
std::atomic_bool connectionFailed_{false};
std::mutex messagesMutex_;
std::vector<std::string> messages_;
};
@@ -186,4 +189,9 @@ bool WebsocketGameClient::connected() const
return impl_->connected();
}
bool WebsocketGameClient::connectionFailed() const
{
return impl_->connectionFailed();
}
} // namespace FRG
+1
View File
@@ -29,6 +29,7 @@ public:
void load(const nlohmann::json& in) override;
bool connected() const;
bool connectionFailed() const;
private:
friend class RemoteGameServerHost;