Major refactoring - internal server state machine implemented

This commit is contained in:
Vladislav Khorev committed 2026-10-29 00:09:16 +06:00
1 parent 71c654e5b6
commit 66e93d46f4
48 files changed
+3948 -3696

No files matched your search

+227
View File
@@ -0,0 +1,227 @@
#pragma once
#include "../GameState.h"
#include "../external/nlohmann/json.hpp"
#include <cstdint>
#include <memory>
#include <string>
#include <variant>
#include <vector>
namespace FRG {
// Value-only view of authoritative state. It deliberately contains no runtime
// pointers, callbacks, renderer objects, or mutable references, so the same
// contract can later be transported over a network.
struct ChatMessageSnapshot {
std::string text;
bool incoming = false;
};
struct CharacterSnapshot {
std::string id;
CharacterState state;
};
struct InteractiveObjectSnapshot {
std::string id;
InteractiveObjectState state;
};
struct LocationSnapshot {
std::string id;
LocationState state;
std::unordered_map<std::string, CharacterSnapshot> npcs;
std::unordered_map<std::string, InteractiveObjectSnapshot> interactiveObjects;
std::unordered_map<std::string, TriggerZoneGameState> triggerZones;
std::unordered_map<std::string, bool> teleportZones;
nlohmann::json dialogue;
nlohmann::json scriptGlobals;
};
struct GameSnapshot {
std::uint64_t revision = 0;
std::string campaignId;
std::string currentLocationId;
bool isDarklands = false;
bool isNight = false;
bool isDawn = false;
float playerHp = 0.f;
float playerMaxHp = 0.f;
int money = 0;
TutorialStep tutorialStep = TutorialStep::Completed;
bool tutorialPhoneChatScreenOpened = false;
bool tutorialJournalScreenOpened = false;
bool tutorialNeedOpenTaxiScreen = false;
bool tutorialTaxiHintDone = false;
bool taxiIsCalled = false;
bool chatUnread[3] = {};
std::string chatPreview[3];
std::vector<ChatMessageSnapshot> chatHistory[3];
std::vector<std::string> inventoryItemIds;
nlohmann::json questJournal;
std::unordered_map<std::string, int> globalInts;
std::unordered_map<std::string, float> globalFloats;
std::unordered_map<std::string, CharacterSnapshot> players;
std::unordered_map<std::string, LocationSnapshot> locations;
std::vector<Quest::QuestState> quests;
bool isTutorialActive() const { return tutorialStep != TutorialStep::Completed; }
};
struct SetWorldModeCommand { bool darklands; bool night; bool dawn; };
struct SetCurrentLocationCommand { std::string locationId; };
struct SetPlayerHealthCommand { float hp; float maxHp; };
struct SetMoneyCommand { int amount; };
struct SpendMoneyCommand { int amount; };
struct CompleteTutorialStepCommand { TutorialStep step; };
struct SetTutorialStepCommand { TutorialStep step; };
struct SetTutorialFlagsCommand {
bool phoneChatOpened;
bool journalOpened;
bool needTaxiHint;
bool taxiHintDone;
};
struct SetChatCommand {
int index;
bool unread;
std::string preview;
};
struct AppendChatMessageCommand {
int index;
std::string text;
bool incoming;
};
struct SetTaxiCalledCommand { bool called; };
struct StartTaxiCommand { std::string locationId; };
struct AddInventoryItemCommand { std::string itemId; };
struct RemoveInventoryItemCommand { std::string itemId; };
struct SetGlobalIntCommand { std::string key; int value; };
struct SetGlobalFloatCommand { std::string key; float value; };
struct SetCharacterTransformCommand {
std::string locationId;
std::string characterId;
Eigen::Vector3f position;
float facingAngle;
};
struct SetCharacterTargetCommand {
std::string locationId;
std::string characterId;
std::string targetId;
};
struct ClearCharacterAttackTargetCommand {
std::string locationId;
std::string characterId;
};
struct SetCharacterDestinationCommand {
std::string locationId;
std::string characterId;
Eigen::Vector3f target;
std::string callbackName;
};
struct StopCharacterCommand {
std::string locationId;
std::string characterId;
};
struct FaceCharacterCommand {
std::string locationId;
std::string characterId;
std::string targetId;
};
struct ReplanCharacterCommand {
std::string locationId;
std::string characterId;
};
struct ResetCharacterAfterDeathCommand {
std::string locationId;
std::string characterId;
};
struct TryCharacterAttackComboCommand {
std::string locationId;
std::string characterId;
};
struct SetCharacterHealthCommand {
std::string locationId;
std::string characterId;
float hp;
};
struct SetCharacterAnimationMetadataCommand {
std::string locationId;
std::string characterId;
AnimationState animationState;
int startFrame;
int frameCount;
};
struct DamageCharacterCommand {
std::string locationId;
std::string characterId;
float amount;
std::string attackerId;
};
struct CommitCharacterStateCommand {
std::string locationId;
std::string characterId;
CharacterState state;
};
struct SetInteractiveObjectActiveCommand {
std::string locationId;
std::string objectId;
bool active;
};
struct SetTriggerZoneEnabledCommand {
std::string locationId;
std::string zoneId;
bool enabled;
};
struct ReloadQuestDefinitionsCommand { std::string path; std::string zipFile; };
using GameCommand = std::variant<
SetWorldModeCommand,
SetCurrentLocationCommand,
SetPlayerHealthCommand,
SetMoneyCommand,
SpendMoneyCommand,
CompleteTutorialStepCommand,
SetTutorialStepCommand,
SetTutorialFlagsCommand,
SetChatCommand,
AppendChatMessageCommand,
SetTaxiCalledCommand,
StartTaxiCommand,
AddInventoryItemCommand,
RemoveInventoryItemCommand,
SetGlobalIntCommand,
SetGlobalFloatCommand,
SetCharacterTransformCommand,
SetCharacterTargetCommand,
ClearCharacterAttackTargetCommand,
SetCharacterDestinationCommand,
StopCharacterCommand,
FaceCharacterCommand,
ReplanCharacterCommand,
ResetCharacterAfterDeathCommand,
TryCharacterAttackComboCommand,
SetCharacterHealthCommand,
SetCharacterAnimationMetadataCommand,
DamageCharacterCommand,
CommitCharacterStateCommand,
SetInteractiveObjectActiveCommand,
SetTriggerZoneEnabledCommand,
ReloadQuestDefinitionsCommand>;
class IGameServer {
public:
virtual ~IGameServer() = default;
// Each returned object is immutable and remains valid after later commands.
virtual std::shared_ptr<const GameSnapshot> snapshot() const = 0;
virtual void submit(const GameCommand& command) = 0;
virtual void update(std::int64_t deltaMs) = 0;
// Persistence stays server-side. The JSON shape is GameState's established
// save schema and is intentionally not the wire snapshot shape.
virtual void save(nlohmann::json& out) const = 0;
virtual void load(const nlohmann::json& in) = 0;
};
} // namespace FRG