305 lines
8.2 KiB
C++
305 lines
8.2 KiB
C++
#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;
|
|
LocationNetworkState 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;
|
|
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 ResetTaxiCommand { std::string locationId; };
|
|
struct SetLocationTargetsCommand {
|
|
std::string locationId;
|
|
std::string interactiveObjectId;
|
|
std::string npcId;
|
|
std::string teleportZoneId;
|
|
};
|
|
struct SwitchLocationNavigationCommand {
|
|
std::string locationId;
|
|
int index;
|
|
};
|
|
struct SetNavigationAreaAvailableCommand {
|
|
std::string locationId;
|
|
std::string areaName;
|
|
bool available;
|
|
};
|
|
struct AddNavigationObstacleCommand {
|
|
std::string locationId;
|
|
std::string name;
|
|
std::vector<Eigen::Vector2f> polygon;
|
|
};
|
|
struct AddInventoryItemCommand { std::string itemId; };
|
|
struct RemoveInventoryItemCommand { std::string itemId; };
|
|
struct UnlockQuestCommand { std::string questId; };
|
|
struct CompleteQuestCommand { std::string questId; };
|
|
struct FailQuestCommand { std::string questId; };
|
|
struct SetQuestObjectiveCompletedCommand {
|
|
std::string questId;
|
|
std::string objectiveId;
|
|
bool completed;
|
|
};
|
|
struct SetQuestObjectiveVisibleCommand {
|
|
std::string questId;
|
|
std::string objectiveId;
|
|
bool visible;
|
|
};
|
|
struct SetQuestActiveObjectiveCommand {
|
|
std::string questId;
|
|
int objectiveIndex;
|
|
};
|
|
struct SetGlobalIntCommand { std::string key; int value; };
|
|
struct SetGlobalFloatCommand { std::string key; float value; };
|
|
struct SetCharacterPositionCommand {
|
|
std::string locationId;
|
|
std::string characterId;
|
|
Eigen::Vector3f position;
|
|
bool updateHomePosition = false;
|
|
};
|
|
struct SetCharacterFacingAngleCommand {
|
|
std::string locationId;
|
|
std::string characterId;
|
|
float angle;
|
|
bool setCurrentAngle = false;
|
|
};
|
|
struct SetCharacterHomePositionCommand {
|
|
std::string locationId;
|
|
std::string characterId;
|
|
Eigen::Vector3f position;
|
|
};
|
|
struct SetCharacterTargetCommand {
|
|
std::string locationId;
|
|
std::string characterId;
|
|
std::string targetId;
|
|
};
|
|
struct SetCharacterFaceTargetCommand {
|
|
std::string locationId;
|
|
std::string characterId;
|
|
std::string targetId;
|
|
};
|
|
struct SetCharacterEnabledCommand {
|
|
std::string locationId;
|
|
std::string characterId;
|
|
bool enabled;
|
|
};
|
|
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 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,
|
|
ResetTaxiCommand,
|
|
SetLocationTargetsCommand,
|
|
SwitchLocationNavigationCommand,
|
|
SetNavigationAreaAvailableCommand,
|
|
AddNavigationObstacleCommand,
|
|
AddInventoryItemCommand,
|
|
RemoveInventoryItemCommand,
|
|
UnlockQuestCommand,
|
|
CompleteQuestCommand,
|
|
FailQuestCommand,
|
|
SetQuestObjectiveCompletedCommand,
|
|
SetQuestObjectiveVisibleCommand,
|
|
SetQuestActiveObjectiveCommand,
|
|
SetGlobalIntCommand,
|
|
SetGlobalFloatCommand,
|
|
SetCharacterPositionCommand,
|
|
SetCharacterFacingAngleCommand,
|
|
SetCharacterHomePositionCommand,
|
|
SetCharacterTargetCommand,
|
|
SetCharacterFaceTargetCommand,
|
|
SetCharacterEnabledCommand,
|
|
ClearCharacterAttackTargetCommand,
|
|
SetCharacterDestinationCommand,
|
|
StopCharacterCommand,
|
|
FaceCharacterCommand,
|
|
ReplanCharacterCommand,
|
|
ResetCharacterAfterDeathCommand,
|
|
TryCharacterAttackComboCommand,
|
|
SetCharacterHealthCommand,
|
|
SetCharacterAnimationMetadataCommand,
|
|
DamageCharacterCommand,
|
|
SetInteractiveObjectActiveCommand,
|
|
SetTriggerZoneEnabledCommand,
|
|
ReloadQuestDefinitionsCommand>;
|
|
|
|
struct InventoryItemAddedEvent { std::string itemId; };
|
|
struct InventoryItemRemovedEvent { std::string itemId; };
|
|
|
|
using GameServerEvent = std::variant<
|
|
InventoryItemAddedEvent,
|
|
InventoryItemRemovedEvent,
|
|
Quest::QuestEvent>;
|
|
|
|
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;
|
|
// Client-relative identity assigned by this server connection.
|
|
virtual const std::string& localPlayerId() const = 0;
|
|
virtual void submit(const GameCommand& command) = 0;
|
|
virtual std::vector<GameServerEvent> drainEvents() = 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
|