OregonCore  revision fb2a440-git
Your Favourite TBC server
VMapManager2.cpp
Go to the documentation of this file.
1 /*
2  * This file is part of the OregonCore 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 "VMapDefinitions.h"
27 #include <G3D/Vector3.h>
28 #include <ace/Null_Mutex.h>
29 #include <ace/Singleton.h>
30 //#include "DisableMgr.h"
31 #include "DBCStores.h"
32 
33 using G3D::Vector3;
34 
35 namespace VMAP
36 {
37  static uint32 GetLiquidFlagsDummy(uint32)
38  {
39  return 0;
40  }
41 
43 {
44  GetLiquidFlagsPtr = &GetLiquidFlagsDummy;
46 }
47 
49 {
50  for (InstanceTreeMap::iterator i = iInstanceMapTrees.begin(); i != iInstanceMapTrees.end(); ++i)
51  {
52  delete i->second;
53  }
54  for (ModelFileMap::iterator i = iLoadedModelFiles.begin(); i != iLoadedModelFiles.end(); ++i)
55  {
56  delete i->second.getModel();
57  }
58 }
59 
60 void VMapManager2::InitializeThreadUnsafe(const std::vector<uint32>& mapIds)
61 {
62  // the caller must pass the list of all mapIds that will be used in the VMapManager2 lifetime
63  for (const uint32& mapId : mapIds)
64  iInstanceMapTrees.insert(InstanceTreeMap::value_type(mapId, nullptr));
65 
67 }
68 
69 Vector3 VMapManager2::convertPositionToInternalRep(float x, float y, float z) const
70 {
71  Vector3 pos;
72  const float mid = 0.5f * 64.0f * 533.33333333f;
73  pos.x = mid - x;
74  pos.y = mid - y;
75  pos.z = z;
76 
77  return pos;
78 }
79 
80 // move to MapTree too?
81 std::string VMapManager2::getMapFileName(unsigned int mapId)
82 {
83  std::stringstream fname;
84  fname.width(3);
85  fname << std::setfill('0') << mapId << std::string(MAP_FILENAME_EXTENSION2);
86 
87  return fname.str();
88 }
89 
90 VMAPLoadResult VMapManager2::loadMap(const char* basePath, unsigned int mapId, int x, int y)
91 {
93  if (isMapLoadingEnabled())
94  {
95  if (_loadMap(mapId, basePath, x, y))
96  result = VMAP_LOAD_RESULT_OK;
97  else
98  result = VMAP_LOAD_RESULT_ERROR;
99  }
100 
101  return result;
102 }
103 
104 InstanceTreeMap::const_iterator VMapManager2::GetMapTree(uint32 mapId) const
105 {
106  // return the iterator if found or end() if not found/NULL
107  InstanceTreeMap::const_iterator itr = iInstanceMapTrees.find(mapId);
108  if (itr != iInstanceMapTrees.cend() && !itr->second)
109  itr = iInstanceMapTrees.cend();
110 
111  return itr;
112 }
113 
114 // load one tile (internal use only)
115 bool VMapManager2::_loadMap(unsigned int mapId, const std::string& basePath, uint32 tileX, uint32 tileY)
116 {
117  InstanceTreeMap::iterator instanceTree = iInstanceMapTrees.find(mapId);
118  if (instanceTree == iInstanceMapTrees.end())
119  {
121  instanceTree = iInstanceMapTrees.insert(InstanceTreeMap::value_type(mapId, nullptr)).first;
122  else
123  ASSERT(false);
124  }
125 
126  if (!instanceTree->second)
127  {
128  std::string mapFileName = getMapFileName(mapId);
129  StaticMapTree* newTree = new StaticMapTree(mapId, basePath);
130  if (!newTree->InitMap(mapFileName, this))
131  return false;
132  instanceTree->second = newTree;
133  }
134 
135  return instanceTree->second->LoadMapTile(tileX, tileY, this);
136 }
137 
138 void VMapManager2::unloadMap(unsigned int mapId)
139 {
140  InstanceTreeMap::iterator instanceTree = iInstanceMapTrees.find(mapId);
141  if (instanceTree != iInstanceMapTrees.end() && instanceTree->second)
142  {
143  instanceTree->second->UnloadMap(this);
144  if (instanceTree->second->numLoadedTiles() == 0)
145  {
146  delete instanceTree->second;
147  instanceTree->second = nullptr;
148  }
149  }
150 }
151 
152 void VMapManager2::unloadMap(unsigned int mapId, int x, int y)
153 {
154  InstanceTreeMap::iterator instanceTree = iInstanceMapTrees.find(mapId);
155  if (instanceTree != iInstanceMapTrees.end() && instanceTree->second)
156  {
157  instanceTree->second->UnloadMapTile(x, y, this);
158  if (instanceTree->second->numLoadedTiles() == 0)
159  {
160  delete instanceTree->second;
161  instanceTree->second = nullptr;
162  }
163  }
164 }
165 
166 bool VMapManager2::isInLineOfSight(unsigned int mapId, float x1, float y1, float z1, float x2, float y2, float z2)
167 {
168  if (!isLineOfSightCalcEnabled() /*|| DisableMgr::IsDisabledFor(DISABLE_TYPE_VMAP, mapId, NULL, VMAP_DISABLE_LOS)*/)
169  return true;
170 
171  InstanceTreeMap::const_iterator instanceTree = GetMapTree(mapId);
172  if (instanceTree != iInstanceMapTrees.end())
173  {
174  Vector3 pos1 = convertPositionToInternalRep(x1, y1, z1);
175  Vector3 pos2 = convertPositionToInternalRep(x2, y2, z2);
176  if (pos1 != pos2)
177  return instanceTree->second->isInLineOfSight(pos1, pos2);
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 {
189  if (isLineOfSightCalcEnabled() /*&& !DisableMgr::IsDisabledFor(DISABLE_TYPE_VMAP, mapId, NULL, VMAP_DISABLE_LOS)*/)
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 
216 float VMapManager2::getHeight(unsigned int mapId, float x, float y, float z, float maxSearchDist)
217 {
218  if (isHeightCalcEnabled()/* && !DisableMgr::IsDisabledFor(DISABLE_TYPE_VMAP, mapId, NULL, VMAP_DISABLE_HEIGHT)*/)
219  {
220  InstanceTreeMap::const_iterator instanceTree = GetMapTree(mapId); if (instanceTree != iInstanceMapTrees.end())
221  {
222  Vector3 pos = convertPositionToInternalRep(x, y, z);
223  float height = instanceTree->second->getHeight(pos, maxSearchDist);
224  if (!(height < G3D::inf()))
225  return height = VMAP_INVALID_HEIGHT_VALUE; // No height
226 
227  return height;
228  }
229  }
230 
232 }
233 
234 bool VMapManager2::getAreaInfo(unsigned int mapId, float x, float y, float& z, uint32& flags, int32& adtId, int32& rootId, int32& groupId) const
235 {
236  if (true)
237  {
238  InstanceTreeMap::const_iterator instanceTree = GetMapTree(mapId);
239  if (instanceTree != iInstanceMapTrees.end())
240  {
241  Vector3 pos = convertPositionToInternalRep(x, y, z);
242  bool result = instanceTree->second->getAreaInfo(pos, flags, adtId, rootId, groupId);
243  // z is not touched by convertPositionToInternalRep(), so just copy
244  z = pos.z;
245  return result;
246  }
247  }
248 
249  return false;
250 }
251 
252 bool VMapManager2::GetLiquidLevel(uint32 mapId, float x, float y, float z, uint8 reqLiquidType, float& level, float& floor, uint32& type) const
253 {
254  if (true)
255  {
256  InstanceTreeMap::const_iterator instanceTree = GetMapTree(mapId);
257  if (instanceTree != iInstanceMapTrees.end())
258  {
259  LocationInfo info;
260  Vector3 pos = convertPositionToInternalRep(x, y, z);
261  if (instanceTree->second->GetLocationInfo(pos, info))
262  {
263  floor = info.ground_Z;
264  ASSERT(floor < std::numeric_limits<float>::max());
265  type = info.hitModel->GetLiquidType(); // entry from LiquidType.dbc
266  if (reqLiquidType && !(GetLiquidFlagsPtr(type) & reqLiquidType))
267  return false;
268  if (info.hitInstance->GetLiquidLevel(pos, info, level))
269  return true;
270  }
271  }
272  }
273 
274  return false;
275 }
276 
277 WorldModel* VMapManager2::acquireModelInstance(const std::string& basepath, const std::string& filename)
278 {
280  //ACE_GUARD(ACE_Thread_Mutex, LoadedModelFilesLock);
281 
282  ModelFileMap::iterator model = iLoadedModelFiles.find(filename);
283  if (model == iLoadedModelFiles.end())
284  {
285  WorldModel* worldmodel = new WorldModel();
286  if (!worldmodel->readFile(basepath + filename + ".vmo"))
287  {
288  ERROR_LOG("VMapManager2: could not load '%s%s.vmo'", basepath.c_str(), filename.c_str());
289  delete worldmodel;
290  return NULL;
291  }
292  DEBUG_LOG("VMapManager2: loading file '%s%s'", basepath.c_str(), filename.c_str());
293  model = iLoadedModelFiles.insert(std::pair<std::string, ManagedModel>(filename, ManagedModel())).first;
294  model->second.setModel(worldmodel);
295  }
296  model->second.incRefCount();
297  return model->second.getModel();
298 }
299 
300 void VMapManager2::releaseModelInstance(const std::string& filename)
301 {
303  //ACE_GUARD(ACE_Thread_Mutex, LoadedModelFilesLock);
304 
305  ModelFileMap::iterator model = iLoadedModelFiles.find(filename);
306  if (model == iLoadedModelFiles.end())
307  {
308  ERROR_LOG("VMapManager2: trying to unload non-loaded file '%s'", filename.c_str());
309  return;
310  }
311  if (model->second.decRefCount() == 0)
312  {
313  DEBUG_LOG("VMapManager2: unloading file '%s'", filename.c_str());
314  delete model->second.getModel();
315  iLoadedModelFiles.erase(model);
316  }
317 }
318 
319 bool VMapManager2::existsMap(const char* basePath, unsigned int mapId, int x, int y)
320 {
321  return StaticMapTree::CanLoadMap(std::string(basePath), mapId, x, y);
322 }
323 
324 } // namespace VMAP
VMAPLoadResult loadMap(const char *pBasePath, unsigned int mapId, int x, int y)
bool readFile(const std::string &filename)
Definition: WorldModel.cpp:531
const ModelInstance * hitInstance
Definition: MapTree.h:33
ACE_INT32 int32
Definition: Define.h:67
InstanceTreeMap::const_iterator GetMapTree(uint32 mapId) const
bool getAreaInfo(unsigned int pMapId, float x, float y, float &z, uint32 &flags, int32 &adtId, int32 &rootId, int32 &groupId) const
void unloadMap(unsigned int mapId, int x, int y)
void releaseModelInstance(const std::string &filename)
static std::string getMapFileName(unsigned int mapId)
bool thread_safe_environment
Definition: VMapManager2.h:75
ModelFileMap iLoadedModelFiles
Definition: VMapManager2.h:73
ACE_UINT8 uint8
Definition: Define.h:73
#define ERROR_LOG(...)
G3D::Vector3 convertPositionToInternalRep(float x, float y, float z) const
uint32(* GetLiquidFlagsPtr)(uint32 liquidType)
Definition: VMapManager2.h:120
bool isLineOfSightCalcEnabled() const
Definition: IVMapManager.h:85
#define MAP_FILENAME_EXTENSION2
Definition: VMapManager2.h:29
bool isInLineOfSight(unsigned int mapId, float x1, float y1, float z1, float x2, float y2, float z2)
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)
const GroupModel * hitModel
Definition: MapTree.h:35
#define VMAP_INVALID_HEIGHT_VALUE
Definition: IVMapManager.h:41
VMAPLoadResult
Definition: IVMapManager.h:33
uint32 GetLiquidType() const
Definition: WorldModel.cpp:386
#define DEBUG_LOG(...)
Definition: Log.h:194
void InitializeThreadUnsafe(const std::vector< uint32 > &mapIds)
bool GetLiquidLevel(const G3D::Vector3 &p, LocationInfo &info, float &liqHeight) const
bool isHeightCalcEnabled() const
Definition: IVMapManager.h:86
bool _loadMap(uint32 mapId, const std::string &basePath, uint32 tileX, uint32 tileY)
bool isMapLoadingEnabled() const
Definition: IVMapManager.h:87
virtual bool existsMap(const char *basePath, unsigned int mapId, int x, int y)
static bool CanLoadMap(const std::string &basePath, uint32 mapID, uint32 tileX, uint32 tileY)
Definition: MapTree.cpp:235
#define ASSERT
Definition: Errors.h:29
bool GetLiquidLevel(uint32 pMapId, float x, float y, float z, uint8 reqLiquidType, float &level, float &floor, uint32 &type) const
float getHeight(unsigned int mapId, float x, float y, float z, float maxSearchDist)
bool LoadMapTile(uint32 tileX, uint32 tileY, VMapManager2 *vm)
Definition: MapTree.cpp:342
ACE_UINT32 uint32
Definition: Define.h:71
WorldModel * acquireModelInstance(const std::string &basepath, const std::string &filename)
bool InitMap(const std::string &fname, VMapManager2 *vm)
Definition: MapTree.cpp:272
InstanceTreeMap iInstanceMapTrees
Definition: VMapManager2.h:74