Legends-of-Azeroth-Pandaria-5.4.8

Форк
0
370 строк · 13.5 Кб
1
/*
2
* This file is part of the Pandaria 5.4.8 Project. See THANKS 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

31
using G3D::Vector3;
32

33
namespace VMAP
34
{
35
    VMapManager2::VMapManager2()
36
    {
37
        GetLiquidFlagsPtr = &GetLiquidFlagsDummy;
38
        IsVMAPDisabledForPtr = &IsVMAPDisabledForDummy;
39
        thread_safe_environment = true;        
40
    }
41

42
    VMapManager2::~VMapManager2(void)
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

60
        thread_safe_environment = false;
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(4);
79
        fname << std::setfill('0') << mapId << std::string(MAP_FILENAME_EXTENSION2);
80

81
        return fname.str();
82
    }
83

84
    int VMapManager2::loadMap(const char* basePath, unsigned int mapId, int x, int y)
85
    {
86
        int result = VMAP_LOAD_RESULT_IGNORED;
87
        if (isMapLoadingEnabled())
88
        {
89
            if (_loadMap(mapId, basePath, x, y))
90
                result = VMAP_LOAD_RESULT_OK;
91
            else
92
                result = VMAP_LOAD_RESULT_ERROR;
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
        {
114
            if (thread_safe_environment)
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
    {
166
        if (!isLineOfSightCalcEnabled() || IsVMAPDisabledForPtr(mapId, VMAP_DISABLE_LOS))
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

183
    /**
184
    get the hit position and return true if we hit something
185
    otherwise the result pos will be the dest pos
186
    */
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() && !IsVMAPDisabledForPtr(mapId, 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

213
    /**
214
    get height or INVALID_HEIGHT if no height available
215
    */
216

217
    float VMapManager2::getHeight(unsigned int mapId, float x, float y, float z, float maxSearchDist)
218
    {
219
        if (isHeightCalcEnabled() && !IsVMAPDisabledForPtr(mapId, VMAP_DISABLE_HEIGHT))
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

233
        return VMAP_INVALID_HEIGHT_VALUE;
234
    }
235

236
    bool VMapManager2::getAreaInfo(uint32 mapId, float x, float y, float& z, uint32& flags, int32& adtId, int32& rootId, int32& groupId) const
237
    {
238
        if (!IsVMAPDisabledForPtr(mapId, VMAP_DISABLE_AREAFLAG))
239
        {
240
            InstanceTreeMap::const_iterator instanceTree = GetMapTree(mapId);
241
            if (instanceTree != iInstanceMapTrees.end())
242
            {
243
                Vector3 pos = convertPositionToInternalRep(x, y, z);
244
                bool result = instanceTree->second->getAreaInfo(pos, flags, adtId, rootId, groupId);
245
                // z is not touched by convertPositionToInternalRep(), so just copy
246
                z = pos.z;
247
                return result;
248
            }
249
        }
250

251
        return false;
252
    }
253

254
    bool VMapManager2::GetLiquidLevel(uint32 mapId, float x, float y, float z, uint8 reqLiquidType, float& level, float& floor, uint32& type, uint32& mogpFlags) const
255
    {
256
        if (!IsVMAPDisabledForPtr(mapId, VMAP_DISABLE_LIQUIDSTATUS))
257
        {
258
            InstanceTreeMap::const_iterator instanceTree = GetMapTree(mapId);
259
            if (instanceTree != iInstanceMapTrees.end())
260
            {
261
                LocationInfo info;
262
                Vector3 pos = convertPositionToInternalRep(x, y, z);
263
                if (instanceTree->second->GetLocationInfo(pos, info))
264
                {
265
                    floor = info.ground_Z;
266
                    ASSERT(floor < std::numeric_limits<float>::max());
267
                    ASSERT(info.hitModel);
268
                    type = info.hitModel->GetLiquidType();  // entry from LiquidType.dbc
269
                    mogpFlags = info.hitModel->GetMogpFlags();
270
                    if (reqLiquidType && !(GetLiquidFlagsPtr(type) & reqLiquidType))
271
                        return false;
272
                    ASSERT(info.hitInstance);
273
                    if (info.hitInstance->GetLiquidLevel(pos, info, level))
274
                        return true;
275
                }
276
            }
277
        }
278

279
        return false;
280
    }
281

282
    void VMapManager2::getAreaAndLiquidData(unsigned int mapId, float x, float y, float z, uint8 reqLiquidType, AreaAndLiquidData& data) const
283
    {
284
        if (IsVMAPDisabledForPtr(mapId, VMAP_DISABLE_LIQUIDSTATUS))
285
        {
286
            data.floorZ = z;
287
            int32 adtId, rootId, groupId;
288
            uint32 flags;
289
            if (getAreaInfo(mapId, x, y, data.floorZ, flags, adtId, rootId, groupId))
290
                data.areaInfo.emplace(adtId, rootId, groupId, flags);
291
            return;
292
        }
293
        InstanceTreeMap::const_iterator instanceTree = GetMapTree(mapId);
294
        if (instanceTree != iInstanceMapTrees.end())
295
        {
296
            LocationInfo info;
297
            Vector3 pos = convertPositionToInternalRep(x, y, z);
298
            if (instanceTree->second->GetLocationInfo(pos, info))
299
            {
300
                ASSERT(info.hitModel);
301
                ASSERT(info.hitInstance);
302
                data.floorZ = info.ground_Z;
303
                uint32 liquidType = info.hitModel->GetLiquidType();
304
                float liquidLevel;
305
                if (!reqLiquidType || (GetLiquidFlagsPtr(liquidType) & reqLiquidType))
306
                    if (info.hitInstance->GetLiquidLevel(pos, info, liquidLevel))
307
                        data.liquidInfo.emplace(liquidType, liquidLevel);
308

309
                if (!IsVMAPDisabledForPtr(mapId, VMAP_DISABLE_AREAFLAG))
310
                    data.areaInfo.emplace(info.hitInstance->adtId, info.rootId, info.hitModel->GetWmoID(), info.hitModel->GetMogpFlags());
311
            }
312
        }
313
    }
314

315
    WorldModel* VMapManager2::acquireModelInstance(const std::string& basepath, const std::string& filename, uint32 flags/* Only used when creating the model */)
316
    {
317
        //! Critical section, thread safe access to iLoadedModelFiles
318
        std::lock_guard<std::mutex> lock(LoadedModelFilesLock);
319

320
        ModelFileMap::iterator model = iLoadedModelFiles.find(filename);
321
        if (model == iLoadedModelFiles.end())
322
        {
323
            WorldModel* worldmodel = new WorldModel();
324
            if (!worldmodel->readFile(basepath + filename + ".vmo"))
325
            {
326
                VMAP_ERROR_LOG("misc", "VMapManager2: could not load '%s%s.vmo'", basepath.c_str(), filename.c_str());
327
                delete worldmodel;
328
                return nullptr;
329
            }
330
            VMAP_DEBUG_LOG("maps", "VMapManager2: loading file '%s%s'", basepath.c_str(), filename.c_str());
331

332
            worldmodel->Flags = flags;
333

334
            model = iLoadedModelFiles.insert(std::pair<std::string, ManagedModel>(filename, ManagedModel())).first;
335
            model->second.setModel(worldmodel);
336
        }
337
        model->second.incRefCount();
338
        return model->second.getModel();
339
    }
340

341
    void VMapManager2::releaseModelInstance(const std::string &filename)
342
    {
343
        //! Critical section, thread safe access to iLoadedModelFiles
344
        std::lock_guard<std::mutex> lock(LoadedModelFilesLock);
345

346
        ModelFileMap::iterator model = iLoadedModelFiles.find(filename);
347
        if (model == iLoadedModelFiles.end())
348
        {
349
            VMAP_ERROR_LOG("misc", "VMapManager2: trying to unload non-loaded file '%s'", filename.c_str());
350
            return;
351
        }
352
        if (model->second.decRefCount() == 0)
353
        {
354
            VMAP_DEBUG_LOG("maps", "VMapManager2: unloading file '%s'", filename.c_str());
355
            delete model->second.getModel();
356
            iLoadedModelFiles.erase(model);
357
        }
358
    }
359

360
    LoadResult VMapManager2::existsMap(const char* basePath, unsigned int mapId, int x, int y)
361
    {
362
        return StaticMapTree::CanLoadMap(std::string(basePath), mapId, x, y);
363
    }
364

365
    void VMapManager2::getInstanceMapTree(InstanceTreeMap &instanceMapTree)
366
    {
367
        instanceMapTree = iInstanceMapTrees;
368
    }
369

370
} // namespace VMAP
371

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.