feat(Core/GameObjects): Instance gameobject save data implementation (#11113)

* fix(Core): Save gameobject state on instances

Currently, azerothcore doesn't save gameobject states on instances.
Whenever there's a re-start or crash, the instance's gameobjects and
their states aren't saved, producing un-wanted behaviours and blocking instances at times.

Implemented CRUD for new table `instance_saved_data` that holds the states of gameobjects.

- When worldserver launches and gameobjects are loaded, this will check
  if this object's state exists on the DB and sets the previous state.
- On instance deletion (reset) these states are also removed based on
  the instance ID.
- Whenever a gameobject state changes inside a dungeon or raid, we save
  on the database the set state.

* Select query to synchronous and used FindMap()

* loading gameobject states on create

* reseting instance saved data

* missing reset methods and on create state

* database structure

* Update src/server/game/Entities/GameObject/GameObject.cpp

Co-authored-by: Kitzunu <24550914+Kitzunu@users.noreply.github.com>

* Update src/server/game/Entities/GameObject/GameObject.cpp

Co-authored-by: Kitzunu <24550914+Kitzunu@users.noreply.github.com>

* Update src/server/game/Entities/GameObject/GameObject.cpp

Co-authored-by: Kitzunu <24550914+Kitzunu@users.noreply.github.com>

* Update src/server/game/Entities/GameObject/GameObject.cpp

Co-authored-by: Kitzunu <24550914+Kitzunu@users.noreply.github.com>

* Update src/server/game/Entities/Player/PlayerMisc.cpp

Co-authored-by: Kitzunu <24550914+Kitzunu@users.noreply.github.com>

* Update src/server/game/Groups/Group.cpp

Co-authored-by: Kitzunu <24550914+Kitzunu@users.noreply.github.com>

* codestyle

* table changes

* table style

* codestyle

* table changes for columns

* data sanitization

* todo:

- Finish loading db data into the containers
- Using containers to find data
- How to get data from ObjectMGR inside Gameobject?

* loading on start up and db changes

* Removing unused data structure

* Uninitialised integer

* Whitespace

* clean-up and hooks to save states on memory

* Codestyle MySQL deprecated backticks

* i dont understand codefactor

* build

* Update data/sql/updates/pending_db_world/rev_1643395587559675400.sql

Co-authored-by: Kitzunu <24550914+Kitzunu@users.noreply.github.com>

* Update src/server/game/Globals/ObjectMgr.h

Co-authored-by: Kargatum <dowlandtop@yandex.com>

* review changes

* unecessary removal

* pushback instead of emplace

* wrong database update

* Update ObjectMgr.cpp

* missing check

* removing entry from the PR

* missing removals

* last delete

* build

* aha! Found the culprit for the sudden assert errors

* type safety, save only important gameobjects

* static cast to unsigned short

* Update data/sql/updates/pending_db_characters/rev_1643629468629316100.sql

Co-authored-by: Kitzunu <24550914+Kitzunu@users.noreply.github.com>

* type changes

* queries fix

* fix build

* enabling which gameobjects to save on the database

* deadmines iron clad door

* Adjustment to gameobject onj create state and instances:

- Gnomeregan doors and Grubbis boss state
- Deadmines missing doors
- Stratholme gameobjects state saved

* forgot emi blastfuse change to despawn

* Leaving group logic

* codestyle

* fixing merge issues

* prevent bad behaviour

* brain meltdown

* Update data/sql/updates/pending_db_characters/rev_1643629468629316100.sql

* Update data/sql/updates/pending_db_world/rev_1649359139539727000.sql

Co-authored-by: Claudiodfc <54484196+claudiodfc@users.noreply.github.com>
Co-authored-by: Kitzunu <24550914+Kitzunu@users.noreply.github.com>
Co-authored-by: Kargatum <dowlandtop@yandex.com>
Co-authored-by: Skjalf <47818697+Nyeriah@users.noreply.github.com>
This commit is contained in:
Hanabi
2022-05-24 14:33:45 +01:00
committed by GitHub
parent 305a2689e9
commit a6a2ca8ef7
22 changed files with 502 additions and 6 deletions

View File

@@ -32,7 +32,13 @@ enum DataTypes
enum GameObjects
{
GO_FACTORY_DOOR = 13965,
GO_IRON_CLAD_DOOR = 16397
GO_HEAVY_DOOR_1 = 17153,
GO_HEAVY_DOOR_2 = 17154,
GO_IRON_CLAD_DOOR = 16397,
GO_DOOR_LEVER_1 = 101831,
GO_DOOR_LEVER_2 = 101833,
GO_DOOR_LEVER_3 = 101834,
GO_CANNON = 16398,
};
template <class AI, class T>

View File

@@ -1,4 +1,4 @@
/*
/*
* This file is part of the AzerothCore Project. See AUTHORS file for Copyright information
*
* This program is free software; you can redistribute it and/or modify it
@@ -39,13 +39,25 @@ public:
{
switch (gameobject->GetEntry())
{
case GO_HEAVY_DOOR_1:
case GO_HEAVY_DOOR_2:
case GO_DOOR_LEVER_1:
case GO_DOOR_LEVER_2:
case GO_DOOR_LEVER_3:
case GO_CANNON:
gameobject->UpdateSaveToDb(true);
break;
case GO_FACTORY_DOOR:
gameobject->UpdateSaveToDb(true);
if (_encounters[TYPE_RHAHK_ZOR] == DONE)
gameobject->SetGoState(GO_STATE_ACTIVE);
break;
case GO_IRON_CLAD_DOOR:
if (_encounters[TYPE_CANNON] == DONE)
HandleGameObject(ObjectGuid::Empty, true, gameobject);
gameobject->UpdateSaveToDb(true);
if (gameobject->GetStateSavedOnInstance() == GO_STATE_ACTIVE)
{
gameobject->DespawnOrUnsummon();
}
break;
}
}

View File

@@ -28,4 +28,23 @@ inline AI* GetGnomereganAI(T* obj)
return GetInstanceAI<AI>(obj, GnomereganScriptName);
}
enum DataTypes
{
TYPE_GRUBBIS = 0,
MAX_ENCOUNTERS = 1
};
enum GameObjects
{
GO_CAVE_IN_1 = 146085,
GO_CAVE_IN_2 = 146086,
GO_WORKSHOP_DOOR = 90858,
GO_FINAL_CHAMBER_DOOR = 142207,
};
enum NPCs
{
NPC_EMI_SHORTFUSE = 7998
};
#endif

View File

@@ -37,6 +37,74 @@ public:
instance_gnomeregan_InstanceMapScript(Map* map) : InstanceScript(map)
{
}
void OnCreatureCreate(Creature* creature) override
{
switch (creature->GetEntry())
{
case NPC_EMI_SHORTFUSE:
if (_encounters[TYPE_GRUBBIS] == DONE)
{
creature->DespawnOrUnsummon();
}
break;
}
}
void OnGameObjectCreate(GameObject* gameobject) override
{
switch (gameobject->GetEntry())
{
case GO_CAVE_IN_1:
case GO_CAVE_IN_2:
case GO_WORKSHOP_DOOR:
case GO_FINAL_CHAMBER_DOOR:
gameobject->UpdateSaveToDb(true);
break;
}
}
void SetData(uint32 type, uint32 data) override
{
switch (type)
{
case TYPE_GRUBBIS:
_encounters[type] = data;
break;
}
if (data == DONE)
SaveToDB();
}
std::string GetSaveData() override
{
std::ostringstream saveStream;
saveStream << "D E " << _encounters[0];
return saveStream.str();
}
void Load(const char* in) override
{
if (!in)
return;
char dataHead1, dataHead2;
std::istringstream loadStream(in);
loadStream >> dataHead1 >> dataHead2;
if (dataHead1 == 'D' && dataHead2 == 'E')
{
for (uint8 i = 0; i < MAX_ENCOUNTERS; ++i)
{
loadStream >> _encounters[i];
if (_encounters[i] == IN_PROGRESS)
_encounters[i] = NOT_STARTED;
}
}
}
private:
uint32 _encounters[MAX_ENCOUNTERS];
};
};

View File

@@ -62,6 +62,9 @@ public:
case GO_GATE_KIRTONOS:
GateKirtonosGUID = go->GetGUID();
break;
case GO_DOOR_OPENED_WITH_KEY:
go->UpdateSaveToDb(true);
break;
case GO_GATE_GANDLING_DOWN_NORTH:
GandlingGatesGUID[0] = go->GetGUID();
break;

View File

@@ -52,6 +52,8 @@ enum GameobjectIds
GO_BRAZIER_KIRTONOS = 175564,
GO_GATE_KIRTONOS = 175570,
GO_DOOR_OPENED_WITH_KEY = 175167,
GO_GATE_GANDLING_ENTRANCE = 177374,
GO_GATE_GANDLING_DOWN_NORTH = 177371,

View File

@@ -171,55 +171,74 @@ public:
{
switch (go->GetEntry())
{
case GO_CRUSADER_SQUARE_DOOR:
case GO_HOARD_DOOR:
case GO_HALL_OF_HIGH_COMMAND:
case GO_GAUNTLET_DOOR_1:
case GO_GAUNTLET_DOOR_2:
go->UpdateSaveToDb(true);
break;
case GO_ZIGGURAT_DOORS1:
go->UpdateSaveToDb(true);
_zigguratDoorsGUID1 = go->GetGUID();
if (GetData(TYPE_ZIGGURAT1) >= 1)
go->SetGoState(GO_STATE_ACTIVE);
break;
case GO_ZIGGURAT_DOORS2:
go->UpdateSaveToDb(true);
_zigguratDoorsGUID2 = go->GetGUID();
if (GetData(TYPE_ZIGGURAT2) >= 1)
go->SetGoState(GO_STATE_ACTIVE);
break;
case GO_ZIGGURAT_DOORS3:
go->UpdateSaveToDb(true);
_zigguratDoorsGUID3 = go->GetGUID();
if (GetData(TYPE_ZIGGURAT3) >= 1)
go->SetGoState(GO_STATE_ACTIVE);
break;
case GO_GAUNTLET_GATE:
go->UpdateSaveToDb(true);
_gauntletGateGUID = go->GetGUID();
if (_zigguratState1 == 2 && _zigguratState2 == 2 && _zigguratState3 == 2)
go->SetGoState(GO_STATE_ACTIVE);
break;
case GO_SLAUGTHER_GATE:
go->UpdateSaveToDb(true);
_slaughterGateGUID = go->GetGUID();
if (_zigguratState1 == 2 && _zigguratState2 == 2 && _zigguratState3 == 2)
go->SetGoState(GO_STATE_ACTIVE);
break;
case GO_ZIGGURAT_DOORS4:
go->UpdateSaveToDb(true);
_zigguratDoorsGUID4 = go->GetGUID();
if (_slaughterProgress == 4)
go->SetGoState(GO_STATE_ACTIVE);
break;
case GO_ZIGGURAT_DOORS5:
go->UpdateSaveToDb(true);
_zigguratDoorsGUID5 = go->GetGUID();
if (_slaughterProgress == 4)
go->SetGoState(GO_STATE_ACTIVE);
break;
case GO_SLAUGHTER_GATE_SIDE:
go->UpdateSaveToDb(true);
if (_slaughterProgress >= 2)
go->SetGoState(GO_STATE_ACTIVE);
break;
case GO_PORT_TRAP_GATE_1:
go->UpdateSaveToDb(true);
_trapGatesGUIDs[0] = go->GetGUID();
break;
case GO_PORT_TRAP_GATE_2:
go->UpdateSaveToDb(true);
_trapGatesGUIDs[1] = go->GetGUID();
break;
case GO_PORT_TRAP_GATE_3:
go->UpdateSaveToDb(true);
_trapGatesGUIDs[2] = go->GetGUID();
break;
case GO_PORT_TRAP_GATE_4:
go->UpdateSaveToDb(true);
_trapGatesGUIDs[3] = go->GetGUID();
break;
}

View File

@@ -57,6 +57,11 @@ enum CreatureIds
enum GameobjectIds
{
GO_CRUSADER_SQUARE_DOOR = 175967,
GO_HOARD_DOOR = 175968,
GO_HALL_OF_HIGH_COMMAND = 176194,
GO_GAUNTLET_DOOR_1 = 175357,
GO_GAUNTLET_DOOR_2 = 175356,
GO_ZIGGURAT_DOORS1 = 175380, // baroness
GO_ZIGGURAT_DOORS2 = 175379, // nerub'enkan
GO_ZIGGURAT_DOORS3 = 175381, // maleki