aboutsummaryrefslogtreecommitdiff
path: root/src/server/game/Movement/Waypoints
diff options
context:
space:
mode:
authorModoX <moardox@gmail.com>2024-01-05 17:56:19 +0100
committerGitHub <noreply@github.com>2024-01-05 17:56:19 +0100
commit12186ef8573f60abeff4747da58767ee71092600 (patch)
tree7d9a1da93e86fa3ccd84c02658bface3ef536721 /src/server/game/Movement/Waypoints
parent390f0be9fb22766638006f43e4d0887108ba49e8 (diff)
Core/Waypoints: Refactor to split data into path and node related info in db (#29506)
Diffstat (limited to 'src/server/game/Movement/Waypoints')
-rw-r--r--src/server/game/Movement/Waypoints/WaypointDefines.h69
-rw-r--r--src/server/game/Movement/Waypoints/WaypointManager.cpp326
-rw-r--r--src/server/game/Movement/Waypoints/WaypointManager.h36
3 files changed, 327 insertions, 104 deletions
diff --git a/src/server/game/Movement/Waypoints/WaypointDefines.h b/src/server/game/Movement/Waypoints/WaypointDefines.h
index 119219dd3d4..d801531b316 100644
--- a/src/server/game/Movement/Waypoints/WaypointDefines.h
+++ b/src/server/game/Movement/Waypoints/WaypointDefines.h
@@ -19,51 +19,68 @@
#define TRINITY_WAYPOINTDEFINES_H
#include "Define.h"
+#include "EnumFlag.h"
#include "Optional.h"
#include <vector>
-enum WaypointMoveType
+#define WAYPOINT_PATH_FLAG_FOLLOW_PATH_BACKWARDS_MINIMUM_NODES 2
+
+enum class WaypointMoveType : uint8
{
- WAYPOINT_MOVE_TYPE_WALK,
- WAYPOINT_MOVE_TYPE_RUN,
- WAYPOINT_MOVE_TYPE_LAND,
- WAYPOINT_MOVE_TYPE_TAKEOFF,
+ Walk = 0,
+ Run = 1,
+ Land = 2,
+ TakeOff = 3,
- WAYPOINT_MOVE_TYPE_MAX
+ Max
};
+enum class WaypointPathFlags : uint8
+{
+ None = 0x00,
+ FollowPathBackwardsFromEndToStart = 0x01,
+};
+
+DEFINE_ENUM_FLAG(WaypointPathFlags);
+
struct WaypointNode
{
- WaypointNode() : id(0), x(0.f), y(0.f), z(0.f), delay(0), moveType(WAYPOINT_MOVE_TYPE_RUN) { }
- WaypointNode(uint32 _id, float _x, float _y, float _z, Optional<float> _orientation = { }, uint32 _delay = 0)
+ WaypointNode() : Id(0), X(0.f), Y(0.f), Z(0.f), Delay(0), MoveType(WaypointMoveType::Walk) { }
+ WaypointNode(uint32 id, float x, float y, float z, Optional<float> orientation = { }, uint32 delay = 0)
{
- id = _id;
- x = _x;
- y = _y;
- z = _z;
- orientation = _orientation;
- delay = _delay;
- moveType = WAYPOINT_MOVE_TYPE_WALK;
+ Id = id;
+ X = x;
+ Y = y;
+ Z = z;
+ Orientation = orientation;
+ Delay = delay;
+ MoveType = WaypointMoveType::Walk;
}
- uint32 id;
- float x, y, z;
- Optional<float> orientation;
- uint32 delay;
- uint32 moveType;
+ uint32 Id;
+ float X;
+ float Y;
+ float Z;
+ Optional<float> Orientation;
+ uint32 Delay;
+ WaypointMoveType MoveType;
};
struct WaypointPath
{
- WaypointPath() : id(0) { }
- WaypointPath(uint32 _id, std::vector<WaypointNode>&& _nodes)
+ WaypointPath() : Id(0), MoveType(WaypointMoveType::Walk), Flags(WaypointPathFlags::None) { }
+ WaypointPath(uint32 id, std::vector<WaypointNode>&& nodes, WaypointMoveType moveType = WaypointMoveType::Walk, WaypointPathFlags flags = WaypointPathFlags::None)
{
- id = _id;
- nodes = _nodes;
+ Id = id;
+ Nodes = nodes;
+ Flags = flags;
+ MoveType = moveType;
}
- std::vector<WaypointNode> nodes;
- uint32 id;
+ std::vector<WaypointNode> Nodes;
+ uint32 Id;
+ WaypointMoveType MoveType;
+ EnumFlag<WaypointPathFlags> Flags = WaypointPathFlags::None;
};
#endif
diff --git a/src/server/game/Movement/Waypoints/WaypointManager.cpp b/src/server/game/Movement/Waypoints/WaypointManager.cpp
index ab018e66233..cb282e6ec30 100644
--- a/src/server/game/Movement/Waypoints/WaypointManager.cpp
+++ b/src/server/game/Movement/Waypoints/WaypointManager.cpp
@@ -19,17 +19,31 @@
#include "DatabaseEnv.h"
#include "GridDefines.h"
#include "Log.h"
+#include "MapUtils.h"
+#include "ObjectAccessor.h"
+#include "Optional.h"
+#include "TemporarySummon.h"
+#include "Unit.h"
-void WaypointMgr::Load()
+void WaypointMgr::LoadPaths()
+{
+ _LoadPaths();
+ _LoadPathNodes();
+ DoPostLoadingChecks();
+}
+
+void WaypointMgr::_LoadPaths()
{
uint32 oldMSTime = getMSTime();
- // 0 1 2 3 4 5 6 7
- QueryResult result = WorldDatabase.Query("SELECT id, point, position_x, position_y, position_z, orientation, move_type, delay FROM waypoint_data ORDER BY id, point");
+ _pathStore.clear();
+
+ // 0 1 2
+ QueryResult result = WorldDatabase.Query("SELECT PathId, MoveType, Flags FROM waypoint_path");
if (!result)
{
- TC_LOG_INFO("server.loading", ">> Loaded 0 waypoints. DB table `waypoint_data` is empty!");
+ TC_LOG_INFO("server.loading", ">> Loaded 0 waypoint paths. DB table `waypoint_path` is empty!");
return;
}
@@ -37,42 +51,92 @@ void WaypointMgr::Load()
do
{
- Field* fields = result->Fetch();
- uint32 pathId = fields[0].GetUInt32();
- float x = fields[2].GetFloat();
- float y = fields[3].GetFloat();
- float z = fields[4].GetFloat();
- Optional<float> o;
- if (!fields[5].IsNull())
- o = fields[5].GetFloat();
-
- Trinity::NormalizeMapCoord(x);
- Trinity::NormalizeMapCoord(y);
-
- WaypointNode waypoint;
- waypoint.id = fields[1].GetUInt32();
- waypoint.x = x;
- waypoint.y = y;
- waypoint.z = z;
- waypoint.orientation = o;
- waypoint.moveType = fields[6].GetUInt32();
-
- if (waypoint.moveType >= WAYPOINT_MOVE_TYPE_MAX)
- {
- TC_LOG_ERROR("sql.sql", "Waypoint {} in waypoint_data has invalid move_type, ignoring", waypoint.id);
- continue;
- }
+ LoadPathFromDB(result->Fetch());
+ ++count;
+ } while (result->NextRow());
+
+ TC_LOG_INFO("server.loading", ">> Loaded {} waypoint paths in {} ms", count, GetMSTimeDiffToNow(oldMSTime));
+}
+
+void WaypointMgr::_LoadPathNodes()
+{
+ uint32 oldMSTime = getMSTime();
+ // 0 1 2 3 4 5 6
+ QueryResult result = WorldDatabase.Query("SELECT PathId, NodeId, PositionX, PositionY, PositionZ, Orientation, Delay FROM waypoint_path_node ORDER BY PathId, NodeId");
+
+ if (!result)
+ {
+ TC_LOG_INFO("server.loading", ">> Loaded 0 waypoint path nodes. DB table `waypoint_path_node` is empty!");
+ return;
+ }
- waypoint.delay = fields[7].GetUInt32();
+ uint32 count = 0;
- WaypointPath& path = _waypointStore[pathId];
- path.id = pathId;
- path.nodes.push_back(std::move(waypoint));
+ do
+ {
+ LoadPathNodesFromDB(result->Fetch());
++count;
}
while (result->NextRow());
- TC_LOG_INFO("server.loading", ">> Loaded {} waypoints in {} ms", count, GetMSTimeDiffToNow(oldMSTime));
+ TC_LOG_INFO("server.loading", ">> Loaded {} waypoint path nodes in {} ms", count, GetMSTimeDiffToNow(oldMSTime));
+ DoPostLoadingChecks();
+}
+
+void WaypointMgr::LoadPathFromDB(Field* fields)
+{
+ uint32 pathId = fields[0].GetUInt32();
+
+ WaypointPath& path = _pathStore[pathId];
+ path.Id = pathId;
+ path.MoveType = (WaypointMoveType)fields[1].GetUInt8();
+
+ if (path.MoveType >= WaypointMoveType::Max)
+ {
+ TC_LOG_ERROR("sql.sql", "PathId {} in `waypoint_path` has invalid MoveType {}, ignoring", pathId, AsUnderlyingType(path.MoveType));
+ return;
+ }
+ path.Flags = (WaypointPathFlags)fields[2].GetUInt8();
+ path.Nodes.clear();
+}
+
+void WaypointMgr::LoadPathNodesFromDB(Field* fields)
+{
+ uint32 pathId = fields[0].GetUInt32();
+
+ if (_pathStore.find(pathId) == _pathStore.end())
+ {
+ TC_LOG_ERROR("sql.sql", "PathId {} in `waypoint_path_node` does not exist in `waypoint_path`, ignoring", pathId);
+ return;
+ }
+
+ float x = fields[2].GetFloat();
+ float y = fields[3].GetFloat();
+ float z = fields[4].GetFloat();
+ Optional<float> o;
+ if (!fields[5].IsNull())
+ o = fields[5].GetFloat();
+
+ Trinity::NormalizeMapCoord(x);
+ Trinity::NormalizeMapCoord(y);
+
+ WaypointNode waypoint(fields[1].GetUInt32(), x, y, z, o, fields[6].GetUInt32());
+
+ WaypointPath& path = _pathStore[pathId];
+ path.Nodes.push_back(std::move(waypoint));
+}
+
+void WaypointMgr::DoPostLoadingChecks()
+{
+ for (auto const& path : _pathStore)
+ {
+ WaypointPath pathInfo = path.second;
+ if (pathInfo.Nodes.empty())
+ TC_LOG_ERROR("sql.sql", "PathId {} in `waypoint_path` has no assigned nodes in `waypoint_path_node`", pathInfo.Id);
+
+ if (pathInfo.Flags.HasFlag(WaypointPathFlags::FollowPathBackwardsFromEndToStart) && pathInfo.Nodes.size() < WAYPOINT_PATH_FLAG_FOLLOW_PATH_BACKWARDS_MINIMUM_NODES)
+ TC_LOG_ERROR("sql.sql", "PathId {} in `waypoint_path` has FollowPathBackwardsFromEndToStart set, but only {} nodes, requires {}", pathInfo.Id, pathInfo.Nodes.size(), WAYPOINT_PATH_FLAG_FOLLOW_PATH_BACKWARDS_MINIMUM_NODES);
+ }
}
WaypointMgr* WaypointMgr::instance()
@@ -81,61 +145,177 @@ WaypointMgr* WaypointMgr::instance()
return &instance;
}
-void WaypointMgr::ReloadPath(uint32 id)
+void WaypointMgr::ReloadPath(uint32 pathId)
{
- WorldDatabasePreparedStatement* stmt = WorldDatabase.GetPreparedStatement(WORLD_SEL_WAYPOINT_DATA_BY_ID);
+ // waypoint_path
+ {
+ WorldDatabasePreparedStatement* stmt = WorldDatabase.GetPreparedStatement(WORLD_SEL_WAYPOINT_PATH_BY_PATHID);
+ stmt->setUInt32(0, pathId);
- stmt->setUInt32(0, id);
+ PreparedQueryResult result = WorldDatabase.Query(stmt);
- PreparedQueryResult result = WorldDatabase.Query(stmt);
+ if (!result)
+ {
+ TC_LOG_ERROR("sql.sql", "PathId {} in `waypoint_path` not found, ignoring", pathId);
+ return;
+ }
- if (!result)
- return;
+ do
+ {
+ LoadPathFromDB(result->Fetch());
+ } while (result->NextRow());
+ }
- std::vector<WaypointNode> values;
- do
+ // waypoint_path_data
{
- Field* fields = result->Fetch();
- float x = fields[1].GetFloat();
- float y = fields[2].GetFloat();
- float z = fields[3].GetFloat();
- Optional<float> o;
- if (!fields[4].IsNull())
- o = fields[4].GetFloat();
-
- Trinity::NormalizeMapCoord(x);
- Trinity::NormalizeMapCoord(y);
-
- WaypointNode waypoint;
- waypoint.id = fields[0].GetUInt32();
- waypoint.x = x;
- waypoint.y = y;
- waypoint.z = z;
- waypoint.orientation = o;
- waypoint.moveType = fields[5].GetUInt32();
-
- if (waypoint.moveType >= WAYPOINT_MOVE_TYPE_MAX)
+ WorldDatabasePreparedStatement* stmt = WorldDatabase.GetPreparedStatement(WORLD_SEL_WAYPOINT_PATH_NODE_BY_PATHID);
+ stmt->setUInt32(0, pathId);
+
+ PreparedQueryResult result = WorldDatabase.Query(stmt);
+
+ if (!result)
{
- TC_LOG_ERROR("sql.sql", "Waypoint {} in waypoint_data has invalid move_type, ignoring", waypoint.id);
+ TC_LOG_ERROR("sql.sql", "PathId {} in `waypoint_path_node` not found, ignoring", pathId);
+ return;
+ }
+
+ do
+ {
+ LoadPathNodesFromDB(result->Fetch());
+ } while (result->NextRow());
+ }
+}
+
+void WaypointMgr::VisualizePath(Unit* owner, WaypointPath const* path, Optional<uint32> displayId)
+{
+ for (WaypointNode const& node : path->Nodes)
+ {
+ std::pair<uint32, uint32> pathNodePair(path->Id, node.Id);
+
+ auto itr = _nodeToVisualWaypointGUIDsMap.find(pathNodePair);
+ if (itr != _nodeToVisualWaypointGUIDsMap.end())
+ continue;
+
+ TempSummon* summon = owner->SummonCreature(VISUAL_WAYPOINT, node.X, node.Y, node.Z, node.Orientation ? *node.Orientation : 0.0f);
+ if (!summon)
continue;
+
+ if (displayId)
+ {
+ summon->SetDisplayId(*displayId, true);
+ summon->SetObjectScale(0.5f);
}
- waypoint.delay = fields[6].GetUInt32();
+ _nodeToVisualWaypointGUIDsMap[pathNodePair] = summon->GetGUID();
+ _visualWaypointGUIDToNodeMap[summon->GetGUID()] = std::pair<WaypointPath const*, WaypointNode const*>(path, &node);
+ }
+}
+
+void WaypointMgr::DevisualizePath(Unit* owner, WaypointPath const* path)
+{
+ for (WaypointNode const& node : path->Nodes)
+ {
+ std::pair<uint32, uint32> pathNodePair(path->Id, node.Id);
+ auto itr = _nodeToVisualWaypointGUIDsMap.find(pathNodePair);
+ if (itr == _nodeToVisualWaypointGUIDsMap.end())
+ continue;
+
+ Creature* creature = ObjectAccessor::GetCreature(*owner, itr->second);
+ if (!creature)
+ continue;
+
+ _visualWaypointGUIDToNodeMap.erase(itr->second);
+ _nodeToVisualWaypointGUIDsMap.erase(pathNodePair);
- values.push_back(std::move(waypoint));
+ creature->DespawnOrUnsummon();
}
- while (result->NextRow());
+}
+
+void WaypointMgr::MoveNode(WaypointPath const* path, WaypointNode const* node, Position const& pos)
+{
+ WorldDatabasePreparedStatement* stmt = WorldDatabase.GetPreparedStatement(WORLD_UPD_WAYPOINT_PATH_NODE_POSITION);
+ stmt->setFloat(0, pos.GetPositionX());
+ stmt->setFloat(1, pos.GetPositionY());
+ stmt->setFloat(2, pos.GetPositionZ());
+ stmt->setFloat(3, pos.GetOrientation());
+ stmt->setUInt32(4, path->Id);
+ stmt->setUInt32(5, node->Id);
+ WorldDatabase.Execute(stmt);
+}
+
+void WaypointMgr::DeleteNode(WaypointPath const* path, WaypointNode const* node)
+{
+ WorldDatabasePreparedStatement* stmt = WorldDatabase.GetPreparedStatement(WORLD_DEL_WAYPOINT_PATH_NODE);
+ stmt->setUInt32(0, path->Id);
+ stmt->setUInt32(1, node->Id);
+ WorldDatabase.Execute(stmt);
+
+ stmt = WorldDatabase.GetPreparedStatement(WORLD_UPD_WAYPOINT_PATH_NODE);
+ stmt->setUInt32(0, path->Id);
+ stmt->setUInt32(1, node->Id);
+ WorldDatabase.Execute(stmt);
+}
+
+void WaypointMgr::DeleteNode(uint32 pathId, uint32 nodeId)
+{
+ WaypointPath const* path = GetPath(pathId);
+ if (!path)
+ return;
+
+ WaypointNode const* node = GetNode(path, nodeId);
+ if (!node)
+ return;
- WaypointPath& path = _waypointStore[id];
- path.id = id;
- path.nodes = std::move(values);
+ DeleteNode(path, node);
}
-WaypointPath const* WaypointMgr::GetPath(uint32 id) const
+WaypointPath const* WaypointMgr::GetPath(uint32 pathId) const
{
- auto itr = _waypointStore.find(id);
- if (itr != _waypointStore.end())
- return &itr->second;
+ return Trinity::Containers::MapGetValuePtr(_pathStore, pathId);
+}
+WaypointNode const* WaypointMgr::GetNode(WaypointPath const* path, uint32 nodeId) const
+{
+ for (WaypointNode const& node : path->Nodes)
+ {
+ if (node.Id == nodeId)
+ return &node;
+ }
return nullptr;
}
+
+WaypointNode const* WaypointMgr::GetNode(uint32 pathId, uint32 nodeId) const
+{
+ WaypointPath const* path = GetPath(pathId);
+ if (!path)
+ return nullptr;
+
+ return GetNode(path->Id, nodeId);
+}
+
+WaypointPath const* WaypointMgr::GetPathByVisualGUID(ObjectGuid guid) const
+{
+ auto itr = _visualWaypointGUIDToNodeMap.find(guid);
+ if (itr == _visualWaypointGUIDToNodeMap.end())
+ return nullptr;
+
+ return itr->second.first;
+}
+
+WaypointNode const* WaypointMgr::GetNodeByVisualGUID(ObjectGuid guid) const
+{
+ auto itr = _visualWaypointGUIDToNodeMap.find(guid);
+ if (itr == _visualWaypointGUIDToNodeMap.end())
+ return nullptr;
+
+ return itr->second.second;
+}
+
+ObjectGuid const& WaypointMgr::GetVisualGUIDByNode(uint32 pathId, uint32 nodeId) const
+{
+ auto itr = _nodeToVisualWaypointGUIDsMap.find(std::make_pair(pathId, nodeId));
+ if (itr == _nodeToVisualWaypointGUIDsMap.end())
+ return ObjectGuid::Empty;
+
+ return itr->second;
+}
diff --git a/src/server/game/Movement/Waypoints/WaypointManager.h b/src/server/game/Movement/Waypoints/WaypointManager.h
index 906c6981e28..721f79d76a6 100644
--- a/src/server/game/Movement/Waypoints/WaypointManager.h
+++ b/src/server/game/Movement/Waypoints/WaypointManager.h
@@ -19,27 +19,53 @@
#define TRINITY_WAYPOINTMANAGER_H
#include "Define.h"
+#include "Field.h"
+#include "Hash.h"
+#include "ObjectGuid.h"
+#include "Position.h"
#include "WaypointDefines.h"
#include <unordered_map>
+class Unit;
+
class TC_GAME_API WaypointMgr
{
public:
static WaypointMgr* instance();
// Attempts to reload a single path from database
- void ReloadPath(uint32 id);
+ void ReloadPath(uint32 pathId);
// Loads all paths from database, should only run on startup
- void Load();
+ void LoadPaths();
+ void LoadPathFromDB(Field* fields);
+ void LoadPathNodesFromDB(Field* fields);
+ void DoPostLoadingChecks();
+
+ void VisualizePath(Unit* owner, WaypointPath const* path, Optional<uint32> displayId);
+ void DevisualizePath(Unit* owner, WaypointPath const* path);
+
+ void MoveNode(WaypointPath const* path, WaypointNode const* node, Position const& pos);
+ void DeleteNode(WaypointPath const* path, WaypointNode const* node);
+ void DeleteNode(uint32 pathId, uint32 nodeId);
- // Returns the path from a given id
- WaypointPath const* GetPath(uint32 id) const;
+ WaypointPath const* GetPath(uint32 pathId) const;
+ WaypointNode const* GetNode(WaypointPath const* path, uint32 nodeId) const;
+ WaypointNode const* GetNode(uint32 pathId, uint32 nodeId) const;
+ WaypointPath const* GetPathByVisualGUID(ObjectGuid guid) const;
+ WaypointNode const* GetNodeByVisualGUID(ObjectGuid guid) const;
+ ObjectGuid const& GetVisualGUIDByNode(uint32 pathId, uint32 nodeId) const;
private:
WaypointMgr() { }
- std::unordered_map<uint32, WaypointPath> _waypointStore;
+ void _LoadPaths();
+ void _LoadPathNodes();
+
+ std::unordered_map<uint32 /*pathId*/, WaypointPath> _pathStore;
+
+ std::unordered_map<std::pair<uint32 /*pathId*/, uint32 /*nodeId*/>, ObjectGuid> _nodeToVisualWaypointGUIDsMap;
+ std::unordered_map<ObjectGuid, std::pair<WaypointPath const*, WaypointNode const*>> _visualWaypointGUIDToNodeMap;
};
#define sWaypointMgr WaypointMgr::instance()