mirror of
https://github.com/mod-playerbots/azerothcore-wotlk.git
synced 2026-01-13 17:19:07 +00:00
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:
@@ -329,7 +329,31 @@ bool GameObject::Create(ObjectGuid::LowType guidlow, uint32 name_id, Map* map, u
|
||||
|
||||
// GAMEOBJECT_BYTES_1, index at 0, 1, 2 and 3
|
||||
SetGoType(GameobjectTypes(goinfo->type));
|
||||
SetGoState(go_state);
|
||||
|
||||
if (IsInstanceGameobject())
|
||||
{
|
||||
switch (GetStateSavedOnInstance())
|
||||
{
|
||||
case 0:
|
||||
SetGoState(GO_STATE_READY);
|
||||
SwitchDoorOrButton(true);
|
||||
break;
|
||||
case 1:
|
||||
SetGoState(GO_STATE_READY);
|
||||
break;
|
||||
case 2:
|
||||
SetGoState(GO_STATE_ACTIVE_ALTERNATIVE);
|
||||
break;
|
||||
default:
|
||||
SetGoState(go_state);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
SetGoState(go_state);
|
||||
}
|
||||
|
||||
SetGoArtKit(artKit);
|
||||
|
||||
SetDisplayId(goinfo->displayId);
|
||||
@@ -2431,6 +2455,146 @@ void GameObject::SetGoState(GOState state)
|
||||
else if (state == GO_STATE_READY)
|
||||
EnableCollision(!startOpen);*/
|
||||
}
|
||||
/* Whenever a gameobject inside an instance changes
|
||||
* save it's state on the database to be loaded properly
|
||||
* on server restart or crash.
|
||||
*/
|
||||
if (IsInstanceGameobject() && IsAbleToSaveOnDb())
|
||||
{
|
||||
// Save the gameobject state on the Database
|
||||
if (!FindStateSavedOnInstance())
|
||||
{
|
||||
SaveInstanceData(GameobjectStateToInt(&state));
|
||||
}
|
||||
else
|
||||
{
|
||||
UpdateInstanceData(GameobjectStateToInt(&state));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool GameObject::IsInstanceGameobject()
|
||||
{
|
||||
// Avoid checking for unecessary gameobjects whose
|
||||
// states don't matter for the dungeon progression
|
||||
if (!ValidateGameobjectType())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (auto* map = FindMap())
|
||||
{
|
||||
if (map->IsDungeon() || map->IsRaid())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool GameObject::ValidateGameobjectType()
|
||||
{
|
||||
switch (m_goInfo->type)
|
||||
{
|
||||
case GAMEOBJECT_TYPE_DOOR:
|
||||
case GAMEOBJECT_TYPE_BUTTON:
|
||||
case GAMEOBJECT_TYPE_TRAP:
|
||||
case GAMEOBJECT_TYPE_DESTRUCTIBLE_BUILDING:
|
||||
case GAMEOBJECT_TYPE_TRAPDOOR:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
uint8 GameObject::GameobjectStateToInt(GOState* state)
|
||||
{
|
||||
uint8 m_state = 3;
|
||||
|
||||
if (state)
|
||||
{
|
||||
switch (*state)
|
||||
{
|
||||
case GO_STATE_ACTIVE:
|
||||
m_state = 0;
|
||||
return m_state;
|
||||
case GO_STATE_READY:
|
||||
m_state = 1;
|
||||
return m_state;
|
||||
case GO_STATE_ACTIVE_ALTERNATIVE:
|
||||
m_state = 2;
|
||||
return m_state;
|
||||
}
|
||||
}
|
||||
|
||||
// Returning any value that is not one of the specified ones
|
||||
// Which will default into the invalid part of the switch
|
||||
return m_state;
|
||||
}
|
||||
|
||||
bool GameObject::IsAbleToSaveOnDb()
|
||||
{
|
||||
return m_saveStateOnDb;
|
||||
}
|
||||
|
||||
void GameObject::UpdateSaveToDb(bool enable)
|
||||
{
|
||||
m_saveStateOnDb = enable;
|
||||
|
||||
if (enable)
|
||||
{
|
||||
SavingStateOnDB();
|
||||
}
|
||||
}
|
||||
|
||||
void GameObject::SavingStateOnDB()
|
||||
{
|
||||
if (IsInstanceGameobject())
|
||||
{
|
||||
GOState param = GetGoState();
|
||||
if (!FindStateSavedOnInstance())
|
||||
{
|
||||
SaveInstanceData(GameobjectStateToInt(¶m));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GameObject::SaveInstanceData(uint8 state)
|
||||
{
|
||||
uint32 id = GetInstanceId();
|
||||
uint32 guid = GetSpawnId();
|
||||
|
||||
CharacterDatabasePreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_INSERT_INSTANCE_SAVED_DATA);
|
||||
stmt->SetData(0, id);
|
||||
stmt->SetData(1, guid);
|
||||
stmt->SetData(2, state);
|
||||
CharacterDatabase.Execute(stmt);
|
||||
|
||||
sObjectMgr->NewInstanceSavedGameobjectState(id, guid, state);
|
||||
}
|
||||
|
||||
void GameObject::UpdateInstanceData(uint8 state)
|
||||
{
|
||||
uint32 id = GetInstanceId();
|
||||
uint32 guid = GetSpawnId();
|
||||
|
||||
CharacterDatabasePreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPDATE_INSTANCE_SAVED_DATA);
|
||||
stmt->SetData(0, state);
|
||||
stmt->SetData(1, guid);
|
||||
stmt->SetData(2, id);
|
||||
CharacterDatabase.Execute(stmt);
|
||||
|
||||
sObjectMgr->SetInstanceSavedGameobjectState(id, guid, state);
|
||||
}
|
||||
|
||||
uint8 GameObject::GetStateSavedOnInstance()
|
||||
{
|
||||
return sObjectMgr->GetInstanceSavedGameobjectState(GetInstanceId(), GetSpawnId());
|
||||
}
|
||||
|
||||
bool GameObject::FindStateSavedOnInstance()
|
||||
{
|
||||
return sObjectMgr->FindInstanceSavedGameobjectState(GetInstanceId(), GetSpawnId());
|
||||
}
|
||||
|
||||
void GameObject::SetDisplayId(uint32 displayid)
|
||||
|
||||
Reference in New Issue
Block a user