TrinityCore
Loading...
Searching...
No Matches
VMapManager2.cpp
Go to the documentation of this file.
1/*
2 * This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the
6 * Free Software Foundation; either version 2 of the License, or (at your
7 * option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18#include <iostream>
19#include <iomanip>
20#include <string>
21#include <sstream>
22#include "VMapManager2.h"
23#include "MapTree.h"
24#include "ModelInstance.h"
25#include "WorldModel.h"
26#include <G3D/Vector3.h>
27#include "Log.h"
28#include "VMapDefinitions.h"
29#include "Errors.h"
30
31using G3D::Vector3;
32
33namespace VMAP
34{
41
43 {
44 for (std::pair<uint32 const, StaticMapTree*>& iInstanceMapTree : iInstanceMapTrees)
45 {
46 delete iInstanceMapTree.second;
47 }
48 for (std::pair<std::string const, ManagedModel>& iLoadedModelFile : iLoadedModelFiles)
49 {
50 delete iLoadedModelFile.second.getModel();
51 }
52 }
53
54 void VMapManager2::InitializeThreadUnsafe(const std::vector<uint32>& mapIds)
55 {
56 // the caller must pass the list of all mapIds that will be used in the VMapManager2 lifetime
57 for (uint32 const& mapId : mapIds)
58 iInstanceMapTrees.insert(InstanceTreeMap::value_type(mapId, nullptr));
59
61 }
62
63 Vector3 VMapManager2::convertPositionToInternalRep(float x, float y, float z) const
64 {
65 Vector3 pos;
66 const float mid = 0.5f * 64.0f * 533.33333333f;
67 pos.x = mid - x;
68 pos.y = mid - y;
69 pos.z = z;
70
71 return pos;
72 }
73
74 // move to MapTree too?
75 std::string VMapManager2::getMapFileName(unsigned int mapId)
76 {
77 std::stringstream fname;
78 fname.width(3);
79 fname << std::setfill('0') << mapId << std::string(MAP_FILENAME_EXTENSION2);
80
81 return fname.str();
82 }
83
84 int VMapManager2::loadMap(char const* basePath, unsigned int mapId, int x, int y)
85 {
86 int result = VMAP_LOAD_RESULT_IGNORED;
88 {
89 if (_loadMap(mapId, basePath, x, y))
90 result = VMAP_LOAD_RESULT_OK;
91 else
93 }
94
95 return result;
96 }
97
98 InstanceTreeMap::const_iterator VMapManager2::GetMapTree(uint32 mapId) const
99 {
100 // return the iterator if found or end() if not found/NULL
101 InstanceTreeMap::const_iterator itr = iInstanceMapTrees.find(mapId);
102 if (itr != iInstanceMapTrees.cend() && !itr->second)
103 itr = iInstanceMapTrees.cend();
104
105 return itr;
106 }
107
108 // load one tile (internal use only)
109 bool VMapManager2::_loadMap(uint32 mapId, const std::string& basePath, uint32 tileX, uint32 tileY)
110 {
111 InstanceTreeMap::iterator instanceTree = iInstanceMapTrees.find(mapId);
112 if (instanceTree == iInstanceMapTrees.end())
113 {
115 instanceTree = iInstanceMapTrees.insert(InstanceTreeMap::value_type(mapId, nullptr)).first;
116 else
117 ABORT_MSG("Invalid mapId %u tile [%u, %u] passed to VMapManager2 after startup in thread unsafe environment",
118 mapId, tileX, tileY);
119 }
120
121 if (!instanceTree->second)
122 {
123 std::string mapFileName = getMapFileName(mapId);
124 StaticMapTree* newTree = new StaticMapTree(mapId, basePath);
125 if (!newTree->InitMap(mapFileName, this))
126 {
127 delete newTree;
128 return false;
129 }
130 instanceTree->second = newTree;
131 }
132
133 return instanceTree->second->LoadMapTile(tileX, tileY, this);
134 }
135
136 void VMapManager2::unloadMap(unsigned int mapId)
137 {
138 InstanceTreeMap::iterator instanceTree = iInstanceMapTrees.find(mapId);
139 if (instanceTree != iInstanceMapTrees.end() && instanceTree->second)
140 {
141 instanceTree->second->UnloadMap(this);
142 if (instanceTree->second->numLoadedTiles() == 0)
143 {
144 delete instanceTree->second;
145 instanceTree->second = nullptr;
146 }
147 }
148 }
149
150 void VMapManager2::unloadMap(unsigned int mapId, int x, int y)
151 {
152 InstanceTreeMap::iterator instanceTree = iInstanceMapTrees.find(mapId);
153 if (instanceTree != iInstanceMapTrees.end() && instanceTree->second)
154 {
155 instanceTree->second->UnloadMapTile(x, y, this);
156 if (instanceTree->second->numLoadedTiles() == 0)
157 {
158 delete instanceTree->second;
159 instanceTree->second = nullptr;
160 }
161 }
162 }
163
164 bool VMapManager2::isInLineOfSight(unsigned int mapId, float x1, float y1, float z1, float x2, float y2, float z2, ModelIgnoreFlags ignoreFlags)
165 {
167 return true;
168
169 InstanceTreeMap::const_iterator instanceTree = GetMapTree(mapId);
170 if (instanceTree != iInstanceMapTrees.end())
171 {
172 Vector3 pos1 = convertPositionToInternalRep(x1, y1, z1);
173 Vector3 pos2 = convertPositionToInternalRep(x2, y2, z2);
174 if (pos1 != pos2)
175 {
176 return instanceTree->second->isInLineOfSight(pos1, pos2, ignoreFlags);
177 }
178 }
179
180 return true;
181 }
182
187 bool VMapManager2::getObjectHitPos(unsigned int mapId, float x1, float y1, float z1, float x2, float y2, float z2, float& rx, float &ry, float& rz, float modifyDist)
188 {
190 {
191 InstanceTreeMap::const_iterator instanceTree = GetMapTree(mapId);
192 if (instanceTree != iInstanceMapTrees.end())
193 {
194 Vector3 pos1 = convertPositionToInternalRep(x1, y1, z1);
195 Vector3 pos2 = convertPositionToInternalRep(x2, y2, z2);
196 Vector3 resultPos;
197 bool result = instanceTree->second->getObjectHitPos(pos1, pos2, resultPos, modifyDist);
198 resultPos = convertPositionToInternalRep(resultPos.x, resultPos.y, resultPos.z);
199 rx = resultPos.x;
200 ry = resultPos.y;
201 rz = resultPos.z;
202 return result;
203 }
204 }
205
206 rx = x2;
207 ry = y2;
208 rz = z2;
209
210 return false;
211 }
212
217 float VMapManager2::getHeight(unsigned int mapId, float x, float y, float z, float maxSearchDist)
218 {
220 {
221 InstanceTreeMap::const_iterator instanceTree = GetMapTree(mapId);
222 if (instanceTree != iInstanceMapTrees.end())
223 {
224 Vector3 pos = convertPositionToInternalRep(x, y, z);
225 float height = instanceTree->second->getHeight(pos, maxSearchDist);
226 if (!(height < G3D::finf()))
227 return height = VMAP_INVALID_HEIGHT_VALUE; // No height
228
229 return height;
230 }
231 }
232
234 }
235
236 bool VMapManager2::getAreaAndLiquidData(unsigned int mapId, float x, float y, float z, Optional<uint8> reqLiquidType, AreaAndLiquidData& data) const
237 {
238 InstanceTreeMap::const_iterator instanceTree = GetMapTree(mapId);
239 if (instanceTree != iInstanceMapTrees.end())
240 {
241 LocationInfo info;
242 Vector3 pos = convertPositionToInternalRep(x, y, z);
243 if (instanceTree->second->GetLocationInfo(pos, info))
244 {
245 ASSERT(info.hitModel);
246 ASSERT(info.hitInstance);
247 data.floorZ = info.ground_Z;
249 {
250 uint32 liquidType = info.hitModel->GetLiquidType(); // entry from LiquidType.dbc
251 float liquidLevel;
252 if (!reqLiquidType || (GetLiquidFlagsPtr(liquidType) & *reqLiquidType))
253 if (info.hitInstance->GetLiquidLevel(pos, info, liquidLevel))
254 data.liquidInfo.emplace(liquidType, liquidLevel);
255 }
256
258 data.areaInfo.emplace(info.hitModel->GetWmoID(), info.hitInstance->adtId, info.rootId, info.hitModel->GetMogpFlags(), info.hitInstance->ID);
259
260 return true;
261 }
262 }
263
264 return false;
265 }
266
267 WorldModel* VMapManager2::acquireModelInstance(const std::string& basepath, const std::string& filename, uint32 flags/* Only used when creating the model */)
268 {
270 std::lock_guard<std::mutex> lock(LoadedModelFilesLock);
271
272 ModelFileMap::iterator model = iLoadedModelFiles.find(filename);
273 if (model == iLoadedModelFiles.end())
274 {
275 WorldModel* worldmodel = new WorldModel();
276 if (!worldmodel->readFile(basepath + filename + ".vmo"))
277 {
278 TC_LOG_ERROR("misc", "VMapManager2: could not load '{}{}.vmo'", basepath, filename);
279 delete worldmodel;
280 return nullptr;
281 }
282 TC_LOG_DEBUG("maps", "VMapManager2: loading file '{}{}'", basepath, filename);
283
284 worldmodel->Flags = flags;
285
286 model = iLoadedModelFiles.insert(std::pair<std::string, ManagedModel>(filename, ManagedModel())).first;
287 model->second.setModel(worldmodel);
288 }
289 model->second.incRefCount();
290 return model->second.getModel();
291 }
292
293 void VMapManager2::releaseModelInstance(const std::string &filename)
294 {
296 std::lock_guard<std::mutex> lock(LoadedModelFilesLock);
297
298 ModelFileMap::iterator model = iLoadedModelFiles.find(filename);
299 if (model == iLoadedModelFiles.end())
300 {
301 TC_LOG_ERROR("misc", "VMapManager2: trying to unload non-loaded file '{}'", filename);
302 return;
303 }
304 if (model->second.decRefCount() == 0)
305 {
306 TC_LOG_DEBUG("maps", "VMapManager2: unloading file '{}'", filename);
307 delete model->second.getModel();
308 iLoadedModelFiles.erase(model);
309 }
310 }
311
312 LoadResult VMapManager2::existsMap(char const* basePath, unsigned int mapId, int x, int y)
313 {
314 return StaticMapTree::CanLoadMap(std::string(basePath), mapId, x, y);
315 }
316
318 {
319 instanceMapTree = iInstanceMapTrees;
320 }
321
322} // namespace VMAP
uint32_t uint32
Definition Define.h:133
uint16 flags
#define ABORT_MSG
Definition Errors.h:75
#define ASSERT
Definition Errors.h:68
#define VMAP_INVALID_HEIGHT_VALUE
#define TC_LOG_DEBUG(filterType__,...)
Definition Log.h:156
#define TC_LOG_ERROR(filterType__,...)
Definition Log.h:165
std::optional< T > Optional
Optional helper class to wrap optional values within.
Definition Optional.h:25
#define MAP_FILENAME_EXTENSION2
uint32 GetLiquidType() const
uint32 GetMogpFlags() const
Definition WorldModel.h:95
uint32 GetWmoID() const
Definition WorldModel.h:96
bool isHeightCalcEnabled() const
bool isMapLoadingEnabled() const
bool isLineOfSightCalcEnabled() const
bool GetLiquidLevel(G3D::Vector3 const &p, LocationInfo &info, float &liqHeight) const
static LoadResult CanLoadMap(const std::string &basePath, uint32 mapID, uint32 tileX, uint32 tileY)
Definition MapTree.cpp:207
bool LoadMapTile(uint32 tileX, uint32 tileY, VMapManager2 *vm)
Definition MapTree.cpp:311
bool InitMap(const std::string &fname, VMapManager2 *vm)
Definition MapTree.cpp:246
void InitializeThreadUnsafe(const std::vector< uint32 > &mapIds)
bool getAreaAndLiquidData(uint32 mapId, float x, float y, float z, Optional< uint8 > reqLiquidType, AreaAndLiquidData &data) const override
G3D::Vector3 convertPositionToInternalRep(float x, float y, float z) const
void releaseModelInstance(const std::string &filename)
InstanceTreeMap::const_iterator GetMapTree(uint32 mapId) const
std::mutex LoadedModelFilesLock
ModelFileMap iLoadedModelFiles
void getInstanceMapTree(InstanceTreeMap &instanceMapTree)
IsVMAPDisabledForFn IsVMAPDisabledForPtr
static bool IsVMAPDisabledForDummy(uint32, uint8)
virtual LoadResult existsMap(char const *basePath, unsigned int mapId, int x, int y) override
void unloadMap(unsigned int mapId, int x, int y) override
WorldModel * acquireModelInstance(const std::string &basepath, const std::string &filename, uint32 flags=0)
bool isInLineOfSight(unsigned int mapId, float x1, float y1, float z1, float x2, float y2, float z2, ModelIgnoreFlags ignoreFlags) override
bool getObjectHitPos(unsigned int mapId, float x1, float y1, float z1, float x2, float y2, float z2, float &rx, float &ry, float &rz, float modifyDist) override
InstanceTreeMap iInstanceMapTrees
GetLiquidFlagsFn GetLiquidFlagsPtr
static std::string getMapFileName(unsigned int mapId)
bool _loadMap(uint32 mapId, const std::string &basePath, uint32 tileX, uint32 tileY)
int loadMap(char const *pBasePath, unsigned int mapId, int x, int y) override
static uint32 GetLiquidFlagsDummy(uint32)
float getHeight(unsigned int mapId, float x, float y, float z, float maxSearchDist) override
bool readFile(const std::string &filename)
std::unordered_map< uint32, StaticMapTree * > InstanceTreeMap
@ VMAP_LOAD_RESULT_ERROR
@ VMAP_LOAD_RESULT_OK
@ VMAP_LOAD_RESULT_IGNORED
@ VMAP_DISABLE_LIQUIDSTATUS
@ VMAP_DISABLE_LOS
@ VMAP_DISABLE_HEIGHT
@ VMAP_DISABLE_AREAFLAG
Optional< AreaInfo > areaInfo
Optional< LiquidInfo > liquidInfo
GroupModel const * hitModel
Definition MapTree.h:44
ModelInstance const * hitInstance
Definition MapTree.h:43