From 76be303351ae398b7f9e69e4c472cb5b05fce45e Mon Sep 17 00:00:00 2001 From: Shauren Date: Fri, 3 Jan 2020 21:55:45 +0100 Subject: Core/Scripts: Save instance data in JSON format --- src/server/game/Instances/InstanceScript.h | 112 +++++++++++++++++++++++++---- 1 file changed, 97 insertions(+), 15 deletions(-) (limited to 'src/server/game/Instances/InstanceScript.h') diff --git a/src/server/game/Instances/InstanceScript.h b/src/server/game/Instances/InstanceScript.h index 77c8886628d..a296877d123 100644 --- a/src/server/game/Instances/InstanceScript.h +++ b/src/server/game/Instances/InstanceScript.h @@ -22,9 +22,9 @@ #include "Common.h" #include "Duration.h" #include -#include #include #include +#include #define OUT_SAVE_INST_DATA TC_LOG_DEBUG("scripts", "Saving Instance Data for Instance %s (Map %d, Instance Id %d)", instance->GetMapName(), instance->GetId(), instance->GetInstanceId()) #define OUT_SAVE_INST_DATA_COMPLETE TC_LOG_DEBUG("scripts", "Saving Instance Data for Instance %s (Map %d, Instance Id %d) completed.", instance->GetMapName(), instance->GetId(), instance->GetInstanceId()) @@ -37,6 +37,7 @@ class Creature; class GameObject; class InstanceMap; class ModuleReference; +class PersistentInstanceScriptValueBase; class Player; class Unit; struct DungeonEncounterEntry; @@ -154,12 +155,21 @@ struct MinionInfo BossInfo* bossInfo; }; -struct UpdateSaveDataEvent +struct UpdateBossStateSaveDataEvent { + DungeonEncounterEntry const* DungeonEncounter; uint32 BossId; EncounterState NewState; }; +struct UpdateAdditionalSaveDataEvent +{ + explicit UpdateAdditionalSaveDataEvent(char const* key, std::variant value) : Key(key), Value(value) { } + + char const* Key; + std::variant Value; +}; + typedef std::multimap DoorInfoMap; typedef std::pair DoorInfoMapBounds; @@ -180,14 +190,13 @@ class TC_GAME_API InstanceScript : public ZoneScript // if we're starting without any saved instance data virtual void Create(); // if we're loading existing instance save data - virtual void Load(char const* data); + void Load(char const* data); // When save is needed, this function generates the data - virtual std::string GetSaveData(); - - virtual std::string UpdateSaveData(std::string const& oldData, UpdateSaveDataEvent const& event); + std::string GetSaveData(); - void SaveToDB(); + std::string UpdateBossStateSaveData(std::string const& oldData, UpdateBossStateSaveDataEvent const& event); + std::string UpdateAdditionalSaveData(std::string const& oldData, UpdateAdditionalSaveDataEvent const& event); virtual void Update(uint32 /*diff*/) { } void UpdateCombatResurrection(uint32 diff); @@ -307,6 +316,10 @@ class TC_GAME_API InstanceScript : public ZoneScript uint8 GetCombatResurrectionCharges() const { return _combatResurrectionCharges; } uint32 GetCombatResurrectionChargeInterval() const; + void RegisterPersistentScriptValue(PersistentInstanceScriptValueBase* value) { _persistentScriptValues.push_back(value); } + std::string const& GetHeader() const { return headers; } + std::vector& GetPersistentScriptValues() { return _persistentScriptValues; } + protected: void SetHeaders(std::string const& dataHeaders); void SetBossNumber(uint32 number) { bosses.resize(number); } @@ -337,13 +350,8 @@ class TC_GAME_API InstanceScript : public ZoneScript // Pay very much attention at how the returned BossInfo data is modified to avoid issues. BossInfo* GetBossInfo(uint32 id); - // Instance Load and Save - bool ReadSaveDataHeaders(std::istringstream& data); - void ReadSaveDataBossStates(std::istringstream& data); - virtual void ReadSaveDataMore(std::istringstream& /*data*/) { } - void WriteSaveDataHeaders(std::ostringstream& data); - void WriteSaveDataBossStates(std::ostringstream& data); - virtual void WriteSaveDataMore(std::ostringstream& /*data*/) { } + // Override this function to validate all additional data loads + virtual void AfterDataLoad() { } bool _SkipCheckRequiredBosses(Player const* player = nullptr) const; @@ -352,8 +360,11 @@ class TC_GAME_API InstanceScript : public ZoneScript void LoadDungeonEncounterData(uint32 bossId, std::array const& dungeonEncounterIds); void UpdateEncounterState(EncounterCreditType type, uint32 creditEntry, Unit* source); - std::vector headers; + void SaveToDB(); + + std::string headers; std::vector bosses; + std::vector _persistentScriptValues; DoorInfoMap doors; MinionInfoMap minions; ObjectInfoMap _creatureInfo; @@ -376,4 +387,75 @@ class TC_GAME_API InstanceScript : public ZoneScript friend class debug_commandscript; }; +class TC_GAME_API PersistentInstanceScriptValueBase +{ +protected: + PersistentInstanceScriptValueBase(InstanceScript& instance, char const* name, std::variant value); + +public: + virtual ~PersistentInstanceScriptValueBase(); + + char const* GetName() const { return _name; } + + UpdateAdditionalSaveDataEvent CreateEvent() const + { + return UpdateAdditionalSaveDataEvent(_name, _value); + } + + void LoadValue(int64 value) + { + _value.emplace(value); + } + + void LoadValue(double value) + { + _value.emplace(value); + } + +protected: + void NotifyValueChanged(); + + InstanceScript& _instance; + char const* _name; + std::variant _value; +}; + +template +class PersistentInstanceScriptValue : public PersistentInstanceScriptValueBase +{ +public: + PersistentInstanceScriptValue(InstanceScript& instance, char const* name, T value = {}) + : PersistentInstanceScriptValueBase(instance, name, WrapValue(value)) + { + } + + operator T() const + { + return std::visit([](auto v) { return static_cast(v); }, _value); + } + + PersistentInstanceScriptValue& operator=(T value) + { + _value = WrapValue(value); + NotifyValueChanged(); + return *this; + } + + void LoadValue(T value) + { + _value = WrapValue(value); + } + +private: + static std::variant WrapValue(T value) + { + if constexpr (std::is_integral_v || std::is_enum_v) + return int64(value); + else if constexpr (std::is_floating_point_v) + return double(value); + else + return {}; + } +}; + #endif // TRINITY_INSTANCE_DATA_H -- cgit v1.2.3