Core/Taxi: Filter out unreachable nodes from taxi nodes packet

This commit is contained in:
Shauren
2018-11-25 14:28:44 +01:00
parent b82cb8678d
commit 947771e6bd
6 changed files with 74 additions and 28 deletions

View File

@@ -111,13 +111,13 @@ void PlayerTaxi::AppendTaximaskTo(WorldPackets::Taxi::ShowTaxiNodes& data, bool
{
if (all)
{
data.CanLandNodes = &sTaxiNodesMask; // all existed nodes
data.CanUseNodes = &sTaxiNodesMask;
data.CanLandNodes = sTaxiNodesMask; // all existed nodes
data.CanUseNodes = sTaxiNodesMask;
}
else
{
data.CanLandNodes = &m_taximask; // known nodes
data.CanUseNodes = &m_taximask;
data.CanLandNodes = m_taximask; // known nodes
data.CanUseNodes = m_taximask;
}
}

View File

@@ -21,6 +21,7 @@
#include "DB2Stores.h"
#include "Config.h"
#include "Util.h"
#include <boost/graph/depth_first_search.hpp>
#include <boost/graph/dijkstra_shortest_paths.hpp>
#include <boost/property_map/transform_value_property_map.hpp>
@@ -32,7 +33,7 @@ TaxiPathGraph& TaxiPathGraph::Instance()
void TaxiPathGraph::Initialize()
{
if (GetVertexCount() > 0)
if (boost::num_vertices(m_graph) > 0)
return;
std::vector<std::pair<edge, EdgeCost>> edges;
@@ -47,7 +48,7 @@ void TaxiPathGraph::Initialize()
}
// create graph
m_graph = Graph(GetVertexCount());
m_graph = Graph(m_nodesByVertex.size());
WeightMap weightmap = boost::get(boost::edge_weight, m_graph);
for (std::size_t j = 0; j < edges.size(); ++j)
@@ -59,21 +60,16 @@ void TaxiPathGraph::Initialize()
uint32 TaxiPathGraph::GetNodeIDFromVertexID(vertex_descriptor vertexID)
{
if (vertexID < m_vertices.size())
return m_vertices[vertexID]->ID;
if (vertexID < m_nodesByVertex.size())
return m_nodesByVertex[vertexID]->ID;
return std::numeric_limits<uint32>::max();
}
TaxiPathGraph::vertex_descriptor TaxiPathGraph::GetVertexIDFromNodeID(TaxiNodesEntry const* node)
{
return node->CharacterBitNumber;
}
std::size_t TaxiPathGraph::GetVertexCount()
{
//So we can use this function for readability, we define either max defined vertices or already loaded in graph count
return std::max(boost::num_vertices(m_graph), m_vertices.size());
auto itr = m_verticesByNode.find(node->ID);
return itr != m_verticesByNode.end() ? itr->second : std::numeric_limits<vertex_descriptor>::max();
}
void GetTaxiMapPosition(DBCPosition3D const& position, int32 mapId, DBCPosition2D* uiMapPosition, int32* uiMapId)
@@ -181,14 +177,50 @@ std::size_t TaxiPathGraph::GetCompleteNodeRoute(TaxiNodesEntry const* from, Taxi
return shortestPath.size();
}
template<typename T>
struct DiscoverVertexVisitor : public boost::base_visitor<DiscoverVertexVisitor<T>>
{
using event_filter = boost::on_discover_vertex;
DiscoverVertexVisitor(T&& func) : _func(std::forward<T>(func)) { }
template <class Vertex, class Graph>
void operator()(Vertex v, Graph& /*g*/)
{
_func(v);
}
private:
T _func;
};
template<typename T>
inline auto make_discover_vertex_dfs_visitor(T&& t)
{
return boost::make_dfs_visitor(DiscoverVertexVisitor<T>(std::forward<T>(t)));
}
void TaxiPathGraph::GetReachableNodesMask(TaxiNodesEntry const* from, TaxiMask* mask)
{
boost::vector_property_map<boost::default_color_type> color(boost::num_vertices(m_graph));
std::fill(color.storage_begin(), color.storage_end(), boost::white_color);
boost::depth_first_visit(m_graph, GetVertexIDFromNodeID(from), make_discover_vertex_dfs_visitor([this, mask](vertex_descriptor vertex)
{
if (TaxiNodesEntry const* taxiNode = sTaxiNodesStore.LookupEntry(GetNodeIDFromVertexID(vertex)))
(*mask)[(taxiNode->ID - 1) / 8] |= 1 << ((taxiNode->ID - 1) % 8);
}), color);
}
TaxiPathGraph::vertex_descriptor TaxiPathGraph::CreateVertexFromFromNodeInfoIfNeeded(TaxiNodesEntry const* node)
{
//Check if we need a new one or if it may be already created
if (m_vertices.size() <= node->CharacterBitNumber)
m_vertices.resize(node->CharacterBitNumber + 1);
auto itr = m_verticesByNode.find(node->ID);
if (itr == m_verticesByNode.end())
{
itr = m_verticesByNode.emplace(node->ID, m_nodesByVertex.size()).first;
m_nodesByVertex.push_back(node);
}
m_vertices[node->CharacterBitNumber] = node;
return node->CharacterBitNumber;
return itr->second;
}
uint32 TaxiPathGraph::EdgeCost::EvaluateDistance(Player const* player) const

View File

@@ -20,7 +20,10 @@
#include "Position.h"
#include "Define.h"
#include "DBCEnums.h"
#include <boost/graph/adjacency_list.hpp>
#include <unordered_map>
#include <vector>
class Player;
struct TaxiNodesEntry;
@@ -32,6 +35,7 @@ public:
void Initialize();
std::size_t GetCompleteNodeRoute(TaxiNodesEntry const* from, TaxiNodesEntry const* to, Player const* player, std::vector<uint32>& shortestPath);
void GetReachableNodesMask(TaxiNodesEntry const* from, TaxiMask* mask);
private:
struct EdgeCost
@@ -53,10 +57,10 @@ private:
vertex_descriptor GetVertexIDFromNodeID(TaxiNodesEntry const* node);
uint32 GetNodeIDFromVertexID(vertex_descriptor vertexID);
vertex_descriptor CreateVertexFromFromNodeInfoIfNeeded(TaxiNodesEntry const* node);
std::size_t GetVertexCount();
Graph m_graph;
std::vector<TaxiNodesEntry const*> m_vertices;
std::vector<TaxiNodesEntry const*> m_nodesByVertex;
std::unordered_map<uint32, vertex_descriptor> m_verticesByNode;
TaxiPathGraph(TaxiPathGraph const&) = delete;
TaxiPathGraph& operator=(TaxiPathGraph const&) = delete;

View File

@@ -107,6 +107,16 @@ void WorldSession::SendTaxiMenu(Creature* unit)
GetPlayer()->m_taxi.AppendTaximaskTo(data, lastTaxiCheaterState);
TaxiMask reachableNodes;
std::fill(reachableNodes.begin(), reachableNodes.end(), 0);
sTaxiPathGraph.GetReachableNodesMask(sTaxiNodesStore.LookupEntry(curloc), &reachableNodes);
for (std::size_t i = 0; i < TaxiMaskSize; ++i)
{
data.CanLandNodes[i] &= reachableNodes[i];
data.CanUseNodes[i] &= reachableNodes[i];
}
SendPacket(data.Write());
GetPlayer()->SetTaxiCheater(lastTaxiCheaterState);

View File

@@ -36,8 +36,8 @@ WorldPacket const* WorldPackets::Taxi::ShowTaxiNodes::Write()
_worldPacket.WriteBit(WindowInfo.is_initialized());
_worldPacket.FlushBits();
_worldPacket << uint32(CanLandNodes->size());
_worldPacket << uint32(CanUseNodes->size());
_worldPacket << uint32(CanLandNodes.size());
_worldPacket << uint32(CanUseNodes.size());
if (WindowInfo.is_initialized())
{
@@ -45,8 +45,8 @@ WorldPacket const* WorldPackets::Taxi::ShowTaxiNodes::Write()
_worldPacket << uint32(WindowInfo->CurrentNode);
}
_worldPacket.append(CanLandNodes->data(), CanLandNodes->size());
_worldPacket.append(CanUseNodes->data(), CanUseNodes->size());
_worldPacket.append(CanLandNodes.data(), CanLandNodes.size());
_worldPacket.append(CanUseNodes.data(), CanUseNodes.size());
return &_worldPacket;
}

View File

@@ -62,8 +62,8 @@ namespace WorldPackets
WorldPacket const* Write() override;
Optional<ShowTaxiNodesWindowInfo> WindowInfo;
TaxiMask const* CanLandNodes = nullptr; // Nodes known by player
TaxiMask const* CanUseNodes = nullptr; // Nodes available for use - this can temporarily disable a known node
TaxiMask CanLandNodes; // Nodes known by player
TaxiMask CanUseNodes; // Nodes available for use - this can temporarily disable a known node
};
class EnableTaxiNode final : public ClientPacket