Working on the server
This commit is contained in:
1 parent
075750442f
commit
28c6e83eda
30 files changed
+646
-362
No files matched your search
@@ -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,
|
||||
|
||||
@@ -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())) {
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
@@ -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,6 +1,7 @@
|
||||
#include "NetworkProtocol.h"
|
||||
#include <exception>
|
||||
|
||||
|
||||
namespace FRG {
|
||||
|
||||
std::string makeStateMessage(const nlohmann::json& state)
|
||||
|
||||
@@ -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
|
||||
@@ -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_;
|
||||
};
|
||||
|
||||
|
||||
@@ -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
|
||||
@@ -29,6 +29,7 @@ public:
|
||||
void load(const nlohmann::json& in) override;
|
||||
|
||||
bool connected() const;
|
||||
bool connectionFailed() const;
|
||||
|
||||
private:
|
||||
friend class RemoteGameServerHost;
|
||||
|
||||
Reference in new issue
Block a user