aboutsummaryrefslogtreecommitdiff
path: root/src/server/collision/Maps/MapTree.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/server/collision/Maps/MapTree.cpp')
-rw-r--r--src/server/collision/Maps/MapTree.cpp121
1 files changed, 75 insertions, 46 deletions
diff --git a/src/server/collision/Maps/MapTree.cpp b/src/server/collision/Maps/MapTree.cpp
index 8c77ee109f3..b47e34b2b72 100644
--- a/src/server/collision/Maps/MapTree.cpp
+++ b/src/server/collision/Maps/MapTree.cpp
@@ -1,29 +1,37 @@
/*
+ * Copyright (C) 2008-2010 TrinityCore <http://www.trinitycore.org/>
* Copyright (C) 2005-2010 MaNGOS <http://getmangos.com/>
*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
*
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
*
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "MapTree.h"
#include "ModelInstance.h"
#include "VMapManager2.h"
#include "VMapDefinitions.h"
+#include "Log.h"
#include <string>
#include <sstream>
#include <iomanip>
+#include <limits>
+
+#ifndef NO_CORE_FUNCS
+ #include "Errors.h"
+#else
+ #define ASSERT(x)
+#endif
using G3D::Vector3;
@@ -33,13 +41,18 @@ namespace VMAP
class MapRayCallback
{
public:
- MapRayCallback(ModelInstance *val): prims(val) {}
- ModelInstance *prims;
+ MapRayCallback(ModelInstance *val): prims(val), hit(false) {}
bool operator()(const G3D::Ray& ray, uint32 entry, float& distance, bool pStopAtFirstHit=true)
{
- return prims[entry].intersectRay(ray, distance, pStopAtFirstHit);
- //std::cout << "trying to intersect '" << entity->name << "'\n";
+ bool result = prims[entry].intersectRay(ray, distance, pStopAtFirstHit);
+ if (result)
+ hit = true;
+ return result;
}
+ bool didHit() { return hit; }
+ protected:
+ ModelInstance *prims;
+ bool hit;
};
class AreaInfoCallback
@@ -49,7 +62,7 @@ namespace VMAP
void operator()(const Vector3& point, uint32 entry)
{
#ifdef VMAP_DEBUG
- std::cout << "trying to intersect '" << prims[entry].name << "'\n";
+ sLog.outDebug("AreaInfoCallback: trying to intersect '%s'", prims[entry].name.c_str());
#endif
prims[entry].intersectPoint(point, aInfo);
}
@@ -65,7 +78,7 @@ namespace VMAP
void operator()(const Vector3& point, uint32 entry)
{
#ifdef VMAP_DEBUG
- std::cout << "trying to intersect '" << prims[entry].name << "'\n";
+ sLog.outDebug("LocationInfoCallback: trying to intersect '%s'", prims[entry].name.c_str());
#endif
if (prims[entry].GetLocationInfo(point, locInfo))
result = true;
@@ -113,7 +126,7 @@ namespace VMAP
}
StaticMapTree::StaticMapTree(uint32 mapID, const std::string &basePath):
- iMapID(mapID), /* iTree(0), */ iTreeValues(0), iBasePath(basePath)
+ iMapID(mapID), iTreeValues(0), iBasePath(basePath)
{
if (iBasePath.length() > 0 && (iBasePath[iBasePath.length()-1] != '/' || iBasePath[iBasePath.length()-1] != '\\'))
{
@@ -130,33 +143,35 @@ namespace VMAP
//=========================================================
/**
- return dist to hit or inf() if no hit
+ If intersection is found within pMaxDist, sets pMaxDist to intersection distance and returns true.
+ Else, pMaxDist is not modified and returns false;
*/
- float StaticMapTree::getIntersectionTime(const G3D::Ray& pRay, float pMaxDist, bool pStopAtFirstHit) const
+ bool StaticMapTree::getIntersectionTime(const G3D::Ray& pRay, float &pMaxDist, bool pStopAtFirstHit) const
{
float distance = pMaxDist;
MapRayCallback intersectionCallBack(iTreeValues);
iTree.intersectRay(pRay, intersectionCallBack, distance, pStopAtFirstHit);
- return distance;
+ if (intersectionCallBack.didHit())
+ pMaxDist = distance;
+ return intersectionCallBack.didHit();
}
//=========================================================
bool StaticMapTree::isInLineOfSight(const Vector3& pos1, const Vector3& pos2) const
{
- bool result = true;
float maxDist = (pos2 - pos1).magnitude();
+ // valid map coords should *never ever* produce float overflow, but this would produce NaNs too
+ ASSERT(maxDist < std::numeric_limits<float>::max());
// prevent NaN values which can cause BIH intersection to enter infinite loop
if (maxDist < 1e-10f)
return true;
// direction with length of 1
G3D::Ray ray = G3D::Ray::fromOriginAndDirection(pos1, (pos2 - pos1)/maxDist);
- float resultDist = getIntersectionTime(ray, maxDist, true);
- if (resultDist < maxDist)
- {
- result = false;
- }
- return result;
+ if (getIntersectionTime(ray, maxDist, true))
+ return false;
+
+ return true;
}
//=========================================================
/**
@@ -168,6 +183,8 @@ namespace VMAP
{
bool result=false;
float maxDist = (pPos2 - pPos1).magnitude();
+ // valid map coords should *never ever* produce float overflow, but this would produce NaNs too
+ ASSERT(maxDist < std::numeric_limits<float>::max());
// prevent NaN values which can cause BIH intersection to enter infinite loop
if (maxDist < 1e-10f)
{
@@ -176,8 +193,8 @@ namespace VMAP
}
Vector3 dir = (pPos2 - pPos1)/maxDist; // direction with length of 1
G3D::Ray ray(pPos1, dir);
- float dist = getIntersectionTime(ray, maxDist, false);
- if (dist < maxDist)
+ float dist = maxDist;
+ if (getIntersectionTime(ray, dist, false))
{
pResultHitPos = pPos1 + dir * dist;
if (pModifyDist < 0)
@@ -213,10 +230,9 @@ namespace VMAP
Vector3 dir = Vector3(0,0,-1);
G3D::Ray ray(pPos, dir); // direction with length of 1
float maxDist = VMapDefinitions::getMaxCanFallDistance();
- float dist = getIntersectionTime(ray, maxDist, false);
- if (dist < maxDist)
+ if (getIntersectionTime(ray, maxDist, false))
{
- height = pPos.z - dist;
+ height = pPos.z - maxDist;
}
return(height);
}
@@ -248,7 +264,11 @@ namespace VMAP
if (!tf)
success = false;
else
+ {
+ if (!readChunk(tf, chunk, VMAP_MAGIC, 8))
+ success = false;
fclose(tf);
+ }
}
fclose(rf);
return success;
@@ -258,7 +278,7 @@ namespace VMAP
bool StaticMapTree::InitMap(const std::string &fname, VMapManager2 *vm)
{
- std::cout << "Initializing StaticMapTree '" << fname << "'\n";
+ sLog.outDebug("StaticMapTree::InitMap() : initializing StaticMapTree '%s'", fname.c_str());
bool success = true;
std::string fullname = iBasePath + fname;
FILE *rf = fopen(fullname.c_str(), "rb");
@@ -286,12 +306,12 @@ namespace VMAP
// only non-tiled maps have them, and if so exactly one (so far at least...)
ModelSpawn spawn;
#ifdef VMAP_DEBUG
- std::cout << "Map isTiled:" << bool(iIsTiled) << std::endl;
+ sLog.outDebug("StaticMapTree::InitMap() : map isTiled: %u", static_cast<uint32>(iIsTiled));
#endif
if (!iIsTiled && ModelSpawn::readFromFile(rf, spawn))
{
WorldModel *model = vm->acquireModelInstance(iBasePath, spawn.name);
- std::cout << "StaticMapTree::InitMap(): loading " << spawn.name << std::endl;
+ sLog.outDebug("StaticMapTree::InitMap() : loading %s", spawn.name.c_str());
if (model)
{
// assume that global model always is the first and only tree value (could be improved...)
@@ -301,7 +321,7 @@ namespace VMAP
else
{
success = false;
- std::cout << "error: could not acquire WorldModel pointer!\n";
+ sLog.outError("StaticMapTree::InitMap() : could not acquire WorldModel pointer for '%s'", spawn.name.c_str());
}
}
@@ -337,7 +357,7 @@ namespace VMAP
}
if (!iTreeValues)
{
- std::cout << "Tree has not been initialized!\n";
+ sLog.outError("StaticMapTree::LoadMapTile() : tree has not been initialized [%u,%u]", tileX, tileY);
return false;
}
bool result = true;
@@ -346,8 +366,12 @@ namespace VMAP
FILE* tf = fopen(tilefile.c_str(), "rb");
if (tf)
{
+ char chunk[8];
+
+ if (!readChunk(tf, chunk, VMAP_MAGIC, 8))
+ result = false;
uint32 numSpawns;
- if (fread(&numSpawns, sizeof(uint32), 1, tf) != 1)
+ if (result && fread(&numSpawns, sizeof(uint32), 1, tf) != 1)
result = false;
for (uint32 i=0; i<numSpawns && result; ++i)
{
@@ -358,7 +382,8 @@ namespace VMAP
{
// acquire model instance
WorldModel *model = vm->acquireModelInstance(iBasePath, spawn.name);
- if (!model) std::cout << "error: could not acquire WorldModel pointer!\n";
+ if (!model)
+ sLog.outError("StaticMapTree::LoadMapTile() : could not acquire WorldModel pointer [%u,%u]", tileX, tileY);
// update tree
uint32 referencedVal;
@@ -369,7 +394,7 @@ namespace VMAP
#ifdef VMAP_DEBUG
if (referencedVal > iNTreeValues)
{
- std::cout << "invalid tree element! (" << referencedVal << "/" << iNTreeValues << ")\n";
+ sLog.outDebug("StaticMapTree::LoadMapTile() : invalid tree element (%u/%u)", referencedVal, iNTreeValues);
continue;
}
#endif
@@ -380,8 +405,10 @@ namespace VMAP
{
++iLoadedSpawns[referencedVal];
#ifdef VMAP_DEBUG
- if (iTreeValues[referencedVal].ID != spawn.ID) std::cout << "error: trying to load wrong spawn in node!\n";
- else if (iTreeValues[referencedVal].name != spawn.name) std::cout << "error: name collision on GUID="<< spawn.ID << "\n";
+ if (iTreeValues[referencedVal].ID != spawn.ID)
+ sLog.outDebug("StaticMapTree::LoadMapTile() : trying to load wrong spawn in node");
+ else if (iTreeValues[referencedVal].name != spawn.name)
+ sLog.outDebug("StaticMapTree::LoadMapTile() : name collision on GUID=%u", spawn.ID);
#endif
}
}
@@ -402,7 +429,7 @@ namespace VMAP
loadedTileMap::iterator tile = iLoadedTiles.find(tileID);
if (tile == iLoadedTiles.end())
{
- std::cout << "WARNING: trying to unload non-loaded tile. Map:" << iMapID << " X:" << tileX << " Y:" << tileY << std::endl;
+ sLog.outError("StaticMapTree::UnloadMapTile() : trying to unload non-loaded tile - Map:%u X:%u Y:%u", iMapID, tileX, tileY);
return;
}
if (tile->second) // file associated with tile
@@ -412,6 +439,9 @@ namespace VMAP
if (tf)
{
bool result=true;
+ char chunk[8];
+ if (!readChunk(tf, chunk, VMAP_MAGIC, 8))
+ result = false;
uint32 numSpawns;
if (fread(&numSpawns, sizeof(uint32), 1, tf) != 1)
result = false;
@@ -431,11 +461,10 @@ namespace VMAP
fread(&referencedNode, sizeof(uint32), 1, tf);
if (!iLoadedSpawns.count(referencedNode))
{
- std::cout << "error! trying to unload non-referenced model '" << spawn.name << "' (ID:" << spawn.ID << ")\n";
+ sLog.outError("StaticMapTree::UnloadMapTile() : trying to unload non-referenced model '%s' (ID:%u)", spawn.name.c_str(), spawn.ID);
}
else if (--iLoadedSpawns[referencedNode] == 0)
{
- //std::cout << "MapTree: removing '" << spawn.name << "' from tree\n";
iTreeValues[referencedNode].setUnloaded();
iLoadedSpawns.erase(referencedNode);
}