/*
* 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 under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see .
*/
#include "ObjectVisibilityContainer.h"
#include "Object.h"
#include "Player.h"
/*
* Some implementation notes:
* Non-player worldobjects do not have any concept of 'visibility', thus,
* the most important and mainly used map is 'VisibleWorldObjectsMap'
* which is only accessible for player objects. The 'VisiblePlayersMap'
* map is simply for managing the references so we can use direct pointers.
*/
ObjectVisibilityContainer::ObjectVisibilityContainer(WorldObject* selfObject) :
_selfObject(selfObject)
{
}
ObjectVisibilityContainer::~ObjectVisibilityContainer()
{
ASSERT(_visiblePlayersMap.empty());
if (_visibleWorldObjectsMap)
ASSERT((*_visibleWorldObjectsMap).empty());
}
void ObjectVisibilityContainer::InitForPlayer()
{
_visibleWorldObjectsMap = std::make_unique();
}
void ObjectVisibilityContainer::CleanVisibilityReferences()
{
for (auto const& kvPair : _visiblePlayersMap)
kvPair.second->GetObjectVisibilityContainer().DirectRemoveVisibilityReference(_selfObject->GetGUID());
if (_visibleWorldObjectsMap)
{
for (auto const& kvPair : *_visibleWorldObjectsMap)
kvPair.second->GetObjectVisibilityContainer().DirectRemoveVisiblePlayerReference(_selfObject->GetGUID());
(*_visibleWorldObjectsMap).clear();
}
_visiblePlayersMap.clear();
}
void ObjectVisibilityContainer::LinkWorldObjectVisibility(WorldObject* worldObject)
{
// Do not link self
if (worldObject == _selfObject)
return;
// Transports are special and should not be added to our visibility map
if (worldObject->IsGameObject() && worldObject->ToGameObject()->IsTransport())
return;
// Only players can link visibility
if (!_visibleWorldObjectsMap)
return;
(*_visibleWorldObjectsMap).insert(std::make_pair(worldObject->GetGUID(), worldObject));
worldObject->GetObjectVisibilityContainer().DirectInsertVisiblePlayerReference(_selfObject->ToPlayer());
}
void ObjectVisibilityContainer::UnlinkWorldObjectVisibility(WorldObject* worldObject)
{
// Only players can unlink visibility
if (!_visibleWorldObjectsMap)
return;
worldObject->GetObjectVisibilityContainer().DirectRemoveVisiblePlayerReference(_selfObject->GetGUID());
(*_visibleWorldObjectsMap).erase(worldObject->GetGUID());
}
VisibleWorldObjectsMap::iterator ObjectVisibilityContainer::UnlinkVisibilityFromPlayer(WorldObject* worldObject, VisibleWorldObjectsMap::iterator itr)
{
ASSERT(_visibleWorldObjectsMap); // Ensure we aren't for some reason calling this as a non-player object
worldObject->GetObjectVisibilityContainer().DirectRemoveVisiblePlayerReference(_selfObject->GetGUID());
return (*_visibleWorldObjectsMap).erase(itr);
}
VisiblePlayersMap::iterator ObjectVisibilityContainer::UnlinkVisibilityFromWorldObject(Player* player, VisiblePlayersMap::iterator itr)
{
player->GetObjectVisibilityContainer().DirectRemoveVisibilityReference(_selfObject->GetGUID());
return _visiblePlayersMap.erase(itr);
}
void ObjectVisibilityContainer::DirectRemoveVisibilityReference(ObjectGuid guid)
{
ASSERT(_visibleWorldObjectsMap);
(*_visibleWorldObjectsMap).erase(guid);
}
void ObjectVisibilityContainer::DirectInsertVisiblePlayerReference(Player* player)
{
_visiblePlayersMap.insert(std::make_pair(player->GetGUID(), player));
}
void ObjectVisibilityContainer::DirectRemoveVisiblePlayerReference(ObjectGuid guid)
{
_visiblePlayersMap.erase(guid);
}