TrinityCore
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 "VMapManager2.h"
19#include "Errors.h"
20#include "Log.h"
21#include "MapTree.h"
22#include "ModelInstance.h"
23#include "VMapDefinitions.h"
24#include "WorldModel.h"
25#include <G3D/Vector3.h>
26#include <iomanip>
27#include <sstream>
28#include <string>
29
30using G3D::Vector3;
31
32namespace VMAP
33{
35 {
36 public:
38 WorldModel* getModel() { return &iModel; }
39 void incRefCount() { ++iRefCount; }
40 int decRefCount() { return --iRefCount; }
41 protected:
44 };
45
46 bool readChunk(FILE* rf, char* dest, const char* compare, uint32 len)
47 {
48 if (fread(dest, sizeof(char), len, rf) != len) return false;
49 return memcmp(dest, compare, len) == 0;
50 }
51
53 {
57 }
58
60 {
61 for (std::pair<uint32 const, StaticMapTree*>& iInstanceMapTree : iInstanceMapTrees)
62 delete iInstanceMapTree.second;
63
64 for (std::pair<std::string const, ManagedModel*>& iLoadedModelFile : iLoadedModelFiles)
65 delete iLoadedModelFile.second;
66 }
67
68 InstanceTreeMap::const_iterator VMapManager2::GetMapTree(uint32 mapId) const
69 {
70 // return the iterator if found or end() if not found/NULL
71 auto itr = iInstanceMapTrees.find(mapId);
72 if (itr != iInstanceMapTrees.cend() && !itr->second)
73 itr = iInstanceMapTrees.cend();
74
75 return itr;
76 }
77
78 void VMapManager2::InitializeThreadUnsafe(std::unordered_map<uint32, std::vector<uint32>> const& mapData)
79 {
80 // the caller must pass the list of all mapIds that will be used in the VMapManager2 lifetime
81 for (std::pair<uint32 const, std::vector<uint32>> const& mapId : mapData)
82 {
83 iInstanceMapTrees.insert(InstanceTreeMap::value_type(mapId.first, nullptr));
84 for (uint32 childMapId : mapId.second)
85 iParentMapData[childMapId] = mapId.first;
86 }
87
89 }
90
91 Vector3 VMapManager2::convertPositionToInternalRep(float x, float y, float z) const
92 {
93 Vector3 pos;
94 const float mid = 0.5f * 64.0f * 533.33333333f;
95 pos.x = mid - x;
96 pos.y = mid - y;
97 pos.z = z;
98
99 return pos;
100 }
101
102 // move to MapTree too?
103 std::string VMapManager2::getMapFileName(unsigned int mapId)
104 {
105 std::stringstream fname;
106 fname.width(4);
107 fname << std::setfill('0') << mapId << std::string(MAP_FILENAME_EXTENSION2);
108
109 return fname.str();
110 }
111
112 LoadResult VMapManager2::loadMap(char const* basePath, unsigned int mapId, int x, int y)
113 {
114 if (!isMapLoadingEnabled())
116
117 auto instanceTree = iInstanceMapTrees.find(mapId);
118 if (instanceTree == iInstanceMapTrees.end())
119 {
121 instanceTree = iInstanceMapTrees.insert(InstanceTreeMap::value_type(mapId, nullptr)).first;
122 else
123 ABORT_MSG("Invalid mapId %u tile [%u, %u] passed to VMapManager2 after startup in thread unsafe environment",
124 mapId, x, y);
125 }
126
127 if (!instanceTree->second)
128 {
129 std::string mapFileName = getMapFileName(mapId);
130 StaticMapTree* newTree = new StaticMapTree(mapId, basePath);
131 LoadResult treeInitResult = newTree->InitMap(mapFileName);
132 if (treeInitResult != LoadResult::Success)
133 {
134 delete newTree;
135 return treeInitResult;
136 }
137 instanceTree->second = newTree;
138 }
139
140 return instanceTree->second->LoadMapTile(x, y, this);
141 }
142
143 void VMapManager2::unloadMap(unsigned int mapId, int x, int y)
144 {
145 auto instanceTree = iInstanceMapTrees.find(mapId);
146 if (instanceTree != iInstanceMapTrees.end() && instanceTree->second)
147 {
148 instanceTree->second->UnloadMapTile(x, y, this);
149 if (instanceTree->second->numLoadedTiles() == 0)
150 {
151 delete instanceTree->second;
152 instanceTree->second = nullptr;
153 }
154 }
155 }
156
157 void VMapManager2::unloadMap(unsigned int mapId)
158 {
159 auto instanceTree = iInstanceMapTrees.find(mapId);
160 if (instanceTree != iInstanceMapTrees.end() && instanceTree->second)
161 {
162 instanceTree->second->UnloadMap(this);
163 if (instanceTree->second->numLoadedTiles() == 0)
164 {
165 delete instanceTree->second;
166 instanceTree->second = nullptr;
167 }
168 }
169 }
170
171 bool VMapManager2::isInLineOfSight(unsigned int mapId, float x1, float y1, float z1, float x2, float y2, float z2, ModelIgnoreFlags ignoreFlags)
172 {
174 return true;
175
176 auto instanceTree = GetMapTree(mapId);
177 if (instanceTree != iInstanceMapTrees.end())
178 {
179 Vector3 pos1 = convertPositionToInternalRep(x1, y1, z1);
180 Vector3 pos2 = convertPositionToInternalRep(x2, y2, z2);
181 if (pos1 != pos2)
182 return instanceTree->second->isInLineOfSight(pos1, pos2, ignoreFlags);
183 }
184
185 return true;
186 }
187
192 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)
193 {
195 {
196 auto instanceTree = GetMapTree(mapId);
197 if (instanceTree != iInstanceMapTrees.end())
198 {
199 Vector3 pos1 = convertPositionToInternalRep(x1, y1, z1);
200 Vector3 pos2 = convertPositionToInternalRep(x2, y2, z2);
201 Vector3 resultPos;
202 bool result = instanceTree->second->getObjectHitPos(pos1, pos2, resultPos, modifyDist);
203 resultPos = convertPositionToInternalRep(resultPos.x, resultPos.y, resultPos.z);
204 rx = resultPos.x;
205 ry = resultPos.y;
206 rz = resultPos.z;
207 return result;
208 }
209 }
210
211 rx = x2;
212 ry = y2;
213 rz = z2;
214
215 return false;
216 }
217
222 float VMapManager2::getHeight(unsigned int mapId, float x, float y, float z, float maxSearchDist)
223 {
225 {
226 auto instanceTree = GetMapTree(mapId);
227 if (instanceTree != iInstanceMapTrees.end())
228 {
229 Vector3 pos = convertPositionToInternalRep(x, y, z);
230 float height = instanceTree->second->getHeight(pos, maxSearchDist);
231 if (!(height < G3D::finf()))
232 return height = VMAP_INVALID_HEIGHT_VALUE; // No height
233
234 return height;
235 }
236 }
237
239 }
240
241 bool VMapManager2::getAreaAndLiquidData(unsigned int mapId, float x, float y, float z, Optional<uint8> reqLiquidType, AreaAndLiquidData& data) const
242 {
243 InstanceTreeMap::const_iterator instanceTree = GetMapTree(mapId);
244 if (instanceTree != iInstanceMapTrees.end())
245 {
246 LocationInfo info;
247 Vector3 pos = convertPositionToInternalRep(x, y, z);
248 if (instanceTree->second->GetLocationInfo(pos, info))
249 {
250 data.floorZ = info.ground_Z;
252 {
253 uint32 liquidType = info.hitModel->GetLiquidType(); // entry from LiquidType.dbc
254 float liquidLevel;
255 if (!reqLiquidType || (GetLiquidFlagsPtr(liquidType) & *reqLiquidType))
256 if (info.hitInstance->GetLiquidLevel(pos, info, liquidLevel))
257 data.liquidInfo.emplace(liquidType, liquidLevel);
258 }
259
261 data.areaInfo.emplace(info.hitModel->GetWmoID(), info.hitInstance->adtId, info.rootId, info.hitModel->GetMogpFlags(), info.hitInstance->ID);
262
263 return true;
264 }
265 }
266
267 return false;
268 }
269
270 WorldModel* VMapManager2::acquireModelInstance(std::string const& basepath, std::string const& filename)
271 {
273 std::lock_guard<std::mutex> lock(LoadedModelFilesLock);
274
275 auto model = iLoadedModelFiles.find(filename);
276 if (model == iLoadedModelFiles.end())
277 {
278 ManagedModel* worldmodel = new ManagedModel();
279 if (!worldmodel->getModel()->readFile(basepath + filename + ".vmo"))
280 {
281 TC_LOG_ERROR("misc", "VMapManager2: could not load '{}{}.vmo'", basepath, filename);
282 delete worldmodel;
283 return nullptr;
284 }
285 TC_LOG_DEBUG("maps", "VMapManager2: loading file '{}{}'", basepath, filename);
286
287 worldmodel->getModel()->SetName(filename);
288
289 model = iLoadedModelFiles.insert(std::pair<std::string, ManagedModel*>(filename, worldmodel)).first;
290 }
291 model->second->incRefCount();
292 return model->second->getModel();
293 }
294
295 void VMapManager2::releaseModelInstance(std::string const& filename)
296 {
298 std::lock_guard<std::mutex> lock(LoadedModelFilesLock);
299
300 auto model = iLoadedModelFiles.find(filename);
301 if (model == iLoadedModelFiles.end())
302 {
303 TC_LOG_ERROR("misc", "VMapManager2: trying to unload non-loaded file '{}'", filename);
304 return;
305 }
306 if (model->second->decRefCount() == 0)
307 {
308 TC_LOG_DEBUG("maps", "VMapManager2: unloading file '{}'", filename);
309 delete model->second;
310 iLoadedModelFiles.erase(model);
311 }
312 }
313
314 LoadResult VMapManager2::existsMap(char const* basePath, unsigned int mapId, int x, int y)
315 {
316 return StaticMapTree::CanLoadMap(std::string(basePath), mapId, x, y, this);
317 }
318
320 {
321 instanceMapTree = iInstanceMapTrees;
322 }
323
325 {
326 auto itr = iParentMapData.find(mapId);
327 if (itr != iParentMapData.end())
328 return int32(itr->second);
329
330 return -1;
331 }
332
333} // namespace VMAP
int32_t int32
Definition: Define.h:138
uint32_t uint32
Definition: Define.h:142
#define ABORT_MSG
Definition: Errors.h:75
#define VMAP_INVALID_HEIGHT_VALUE
Definition: IVMapManager.h:44
#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
Definition: VMapManager2.h:29
uint32 GetLiquidType() const
Definition: WorldModel.cpp:439
uint32 GetMogpFlags() const
Definition: WorldModel.h:99
uint32 GetWmoID() const
Definition: WorldModel.h:100
bool isHeightCalcEnabled() const
Definition: IVMapManager.h:114
bool isMapLoadingEnabled() const
Definition: IVMapManager.h:115
bool isLineOfSightCalcEnabled() const
Definition: IVMapManager.h:113
WorldModel * getModel()
bool GetLiquidLevel(G3D::Vector3 const &p, LocationInfo &info, float &liqHeight) const
LoadResult InitMap(std::string const &fname)
Definition: MapTree.cpp:275
LoadResult LoadMapTile(uint32 tileX, uint32 tileY, VMapManager2 *vm)
Definition: MapTree.cpp:335
static LoadResult CanLoadMap(const std::string &basePath, uint32 mapID, uint32 tileX, uint32 tileY, VMapManager2 *vm)
Definition: MapTree.cpp:231
int32 getParentMapId(uint32 mapId) const
bool getAreaAndLiquidData(uint32 mapId, float x, float y, float z, Optional< uint8 > reqLiquidType, AreaAndLiquidData &data) const override
LoadResult loadMap(char const *pBasePath, unsigned int mapId, int x, int y) override
G3D::Vector3 convertPositionToInternalRep(float x, float y, float z) const
InstanceTreeMap::const_iterator GetMapTree(uint32 mapId) const
std::mutex LoadedModelFilesLock
Definition: VMapManager2.h:74
ModelFileMap iLoadedModelFiles
Definition: VMapManager2.h:69
void getInstanceMapTree(InstanceTreeMap &instanceMapTree)
void releaseModelInstance(std::string const &filename)
std::unordered_map< uint32, uint32 > iParentMapData
Definition: VMapManager2.h:71
IsVMAPDisabledForFn IsVMAPDisabledForPtr
Definition: VMapManager2.h:126
static bool IsVMAPDisabledForDummy(uint32, uint8)
Definition: VMapManager2.h:77
bool thread_safe_environment
Definition: VMapManager2.h:72
virtual LoadResult existsMap(char const *basePath, unsigned int mapId, int x, int y) override
void unloadMap(unsigned int mapId, int x, int y) override
bool isInLineOfSight(unsigned int mapId, float x1, float y1, float z1, float x2, float y2, float z2, ModelIgnoreFlags ignoreFlags) override
void InitializeThreadUnsafe(std::unordered_map< uint32, std::vector< uint32 > > const &mapData)
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
Definition: VMapManager2.h:70
GetLiquidFlagsFn GetLiquidFlagsPtr
Definition: VMapManager2.h:123
static std::string getMapFileName(unsigned int mapId)
WorldModel * acquireModelInstance(std::string const &basepath, std::string const &filename)
static uint32 GetLiquidFlagsDummy(uint32)
Definition: VMapManager2.h:76
float getHeight(unsigned int mapId, float x, float y, float z, float maxSearchDist) override
bool readFile(const std::string &filename)
Definition: WorldModel.cpp:580
void SetName(std::string newName)
Definition: WorldModel.h:131
bool readChunk(FILE *rf, char *dest, const char *compare, uint32 len)
std::unordered_map< uint32, StaticMapTree * > InstanceTreeMap
Definition: VMapManager2.h:54
LoadResult
Definition: IVMapManager.h:35
@ VMAP_DISABLE_LIQUIDSTATUS
Definition: VMapManager2.h:62
@ VMAP_DISABLE_LOS
Definition: VMapManager2.h:61
@ VMAP_DISABLE_HEIGHT
Definition: VMapManager2.h:60
@ VMAP_DISABLE_AREAFLAG
Definition: VMapManager2.h:59
Optional< AreaInfo > areaInfo
Definition: IVMapManager.h:68
Optional< LiquidInfo > liquidInfo
Definition: IVMapManager.h:69
GroupModel const * hitModel
Definition: MapTree.h:44
ModelInstance const * hitInstance
Definition: MapTree.h:43