summaryrefslogtreecommitdiff
path: root/src/game-server/mapcomposite.cpp
diff options
context:
space:
mode:
authorGuillaume Melquiond <guillaume.melquiond@gmail.com>2007-07-07 16:50:47 +0000
committerGuillaume Melquiond <guillaume.melquiond@gmail.com>2007-07-07 16:50:47 +0000
commit04e694b067a21dee8e13368c17d1815cc0624ce4 (patch)
treea57ab98d76040838fa369e6823544baeb19d1bbc /src/game-server/mapcomposite.cpp
parent60b4a57bdfe664a6729b3573a6a614621b6c2b2c (diff)
downloadmanaserv-04e694b067a21dee8e13368c17d1815cc0624ce4.tar.gz
manaserv-04e694b067a21dee8e13368c17d1815cc0624ce4.tar.bz2
manaserv-04e694b067a21dee8e13368c17d1815cc0624ce4.tar.xz
manaserv-04e694b067a21dee8e13368c17d1815cc0624ce4.zip
Simplified code by using map pointers only, instead of using both map IDs and map pointers.
Diffstat (limited to 'src/game-server/mapcomposite.cpp')
-rw-r--r--src/game-server/mapcomposite.cpp197
1 files changed, 156 insertions, 41 deletions
diff --git a/src/game-server/mapcomposite.cpp b/src/game-server/mapcomposite.cpp
index 027db924..627582fd 100644
--- a/src/game-server/mapcomposite.cpp
+++ b/src/game-server/mapcomposite.cpp
@@ -45,6 +45,104 @@
in dealing with zone changes. */
static int const zoneDiam = 256;
+/**
+ * Part of a map.
+ */
+struct MapZone
+{
+ unsigned short nbCharacters, nbMovingObjects;
+ /**
+ * Objects present in this zone.
+ * Characters are stored first, then the remaining MovingObjects, then the
+ * remaining Objects.
+ */
+ std::vector< Object * > objects;
+
+ /**
+ * Destinations of the objects that left this zone.
+ * This is necessary in order to have an accurate iterator around moving
+ * objects.
+ */
+ MapRegion destinations;
+
+ MapZone(): nbCharacters(0), nbMovingObjects(0) {}
+ void insert(Object *);
+ void remove(Object *);
+};
+
+/**
+ * Pool of public IDs for MovingObjects on a map. By maintaining public ID
+ * availability using bits, it can locate an available public ID fast while
+ * using minimal memory access.
+ */
+struct ObjectBucket
+{
+ static int const int_bitsize = sizeof(unsigned) * 8;
+ unsigned bitmap[256 / int_bitsize]; /**< Bitmap of free locations. */
+ short free; /**< Number of empty places. */
+ short next_object; /**< Next object to look at. */
+ MovingObject *objects[256];
+
+ ObjectBucket();
+ int allocate();
+ void deallocate(int);
+};
+
+/**
+ * Entities on a map.
+ */
+struct MapContent
+{
+ MapContent(Map *);
+ ~MapContent();
+
+ /**
+ * Allocates a unique ID for a moving object on this map.
+ */
+ bool allocate(MovingObject *);
+
+ /**
+ * Deallocates an ID.
+ */
+ void deallocate(MovingObject *);
+
+ /**
+ * Fills a region of zones within the range of a point.
+ */
+ void fillRegion(MapRegion &, Point const &, int) const;
+
+ /**
+ * Fills a region of zones inside a rectangle.
+ */
+ void fillRegion(MapRegion &, Rectangle const &) const;
+
+ /**
+ * Gets zone at given position.
+ */
+ MapZone &getZone(Point const &pos) const
+ { return zones[(pos.x / zoneDiam) + (pos.y / zoneDiam) * mapWidth]; }
+
+ /**
+ * Things (items, characters, monsters, etc) located on the map.
+ */
+ std::vector< Thing * > things;
+
+ /**
+ * Buckets of MovingObjects located on the map, referenced by ID.
+ */
+ ObjectBucket *buckets[256];
+
+ int last_bucket; /**< Last bucket acted upon. */
+
+ /**
+ * Partition of the Objects, depending on their position on the map.
+ */
+ MapZone *zones;
+
+ unsigned short mapWidth; /**< Width with respect to zones. */
+ unsigned short mapHeight; /**< Height with respect to zones. */
+};
+
void MapZone::insert(Object *obj)
{
int type = obj->getType();
@@ -141,7 +239,7 @@ static void addZone(MapRegion &r, unsigned z)
}
}
-ZoneIterator::ZoneIterator(MapRegion const &r, MapComposite const *m)
+ZoneIterator::ZoneIterator(MapRegion const &r, MapContent const *m)
: region(r), pos(0), map(m)
{
current = &map->zones[r.empty() ? 0 : r[0]];
@@ -325,8 +423,8 @@ void ObjectBucket::deallocate(int i)
++free;
}
-MapComposite::MapComposite(Map *m)
- : map(m), last_bucket(0)
+MapContent::MapContent(Map *map)
+ : last_bucket(0), zones(NULL)
{
buckets[0] = new ObjectBucket;
for (int i = 1; i < 256; ++i)
@@ -338,17 +436,29 @@ MapComposite::MapComposite(Map *m)
zones = new MapZone[mapWidth * mapHeight];
}
-MapComposite::~MapComposite()
+MapContent::~MapContent()
{
for (int i = 0; i < 256; ++i)
{
delete buckets[i];
}
delete[] zones;
- // MapManger will delete the maps when necessary.
}
-bool MapComposite::allocate(MovingObject *obj)
+void MapComposite::setMap(Map *m)
+{
+ assert(!mMap && m);
+ mMap = m;
+ mContent = new MapContent(m);
+}
+
+MapComposite::~MapComposite()
+{
+ delete mMap;
+ delete mContent;
+}
+
+bool MapContent::allocate(MovingObject *obj)
{
// First, try allocating from the last used bucket.
ObjectBucket *b = buckets[last_bucket];
@@ -387,13 +497,13 @@ bool MapComposite::allocate(MovingObject *obj)
return false;
}
-void MapComposite::deallocate(MovingObject *obj)
+void MapContent::deallocate(MovingObject *obj)
{
unsigned short id = obj->getPublicID();
buckets[id / 256]->deallocate(id % 256);
}
-void MapComposite::fillRegion(MapRegion &r, Point const &p, int radius) const
+void MapContent::fillRegion(MapRegion &r, Point const &p, int radius) const
{
int ax = p.x > radius ? (p.x - radius) / zoneDiam : 0,
ay = p.y > radius ? (p.y - radius) / zoneDiam : 0,
@@ -408,7 +518,7 @@ void MapComposite::fillRegion(MapRegion &r, Point const &p, int radius) const
}
}
-void MapComposite::fillRegion(MapRegion &r, Rectangle const &p) const
+void MapContent::fillRegion(MapRegion &r, Rectangle const &p) const
{
int ax = p.x / zoneDiam,
ay = p.y / zoneDiam,
@@ -426,28 +536,28 @@ void MapComposite::fillRegion(MapRegion &r, Rectangle const &p) const
ZoneIterator MapComposite::getAroundPointIterator(Point const &p, int radius) const
{
MapRegion r;
- fillRegion(r, p, radius);
- return ZoneIterator(r, this);
+ mContent->fillRegion(r, p, radius);
+ return ZoneIterator(r, mContent);
}
ZoneIterator MapComposite::getAroundObjectIterator(Object *obj, int radius) const
{
MapRegion r;
- fillRegion(r, obj->getPosition(), radius);
- return ZoneIterator(r, this);
+ mContent->fillRegion(r, obj->getPosition(), radius);
+ return ZoneIterator(r, mContent);
}
ZoneIterator MapComposite::getInsideRectangleIterator(Rectangle const &p) const
{
MapRegion r;
- fillRegion(r, p);
- return ZoneIterator(r, this);
+ mContent->fillRegion(r, p);
+ return ZoneIterator(r, mContent);
}
ZoneIterator MapComposite::getAroundCharacterIterator(MovingObject *obj, int radius) const
{
MapRegion r1;
- fillRegion(r1, obj->getOldPosition(), radius);
+ mContent->fillRegion(r1, obj->getOldPosition(), radius);
MapRegion r2 = r1;
for (MapRegion::iterator i = r1.begin(), i_end = r1.end(); i != i_end; ++i)
{
@@ -455,7 +565,7 @@ ZoneIterator MapComposite::getAroundCharacterIterator(MovingObject *obj, int rad
This is necessary to detect two moving objects changing zones at the
same time and at the border, and going in opposite directions (or
more simply to detect teleportations, if any). */
- MapRegion &r4 = zones[*i].destinations;
+ MapRegion &r4 = mContent->zones[*i].destinations;
if (!r4.empty())
{
MapRegion r3;
@@ -465,26 +575,25 @@ ZoneIterator MapComposite::getAroundCharacterIterator(MovingObject *obj, int rad
r2.swap(r3);
}
}
- fillRegion(r2, obj->getPosition(), radius);
- return ZoneIterator(r2, this);
+ mContent->fillRegion(r2, obj->getPosition(), radius);
+ return ZoneIterator(r2, mContent);
}
bool MapComposite::insert(Thing *ptr)
{
if (ptr->isVisible())
{
- if (ptr->canMove() && !allocate(static_cast< MovingObject * >(ptr)))
+ if (ptr->canMove() && !mContent->allocate(static_cast< MovingObject * >(ptr)))
{
return false;
}
Object *obj = static_cast< Object * >(ptr);
- Point const &pos = obj->getPosition();
- zones[(pos.x / zoneDiam) + (pos.y / zoneDiam) * mapWidth].insert(obj);
+ mContent->getZone(obj->getPosition()).insert(obj);
}
ptr->setMap(this);
- things.push_back(ptr);
+ mContent->things.push_back(ptr);
return true;
}
@@ -493,22 +602,21 @@ void MapComposite::remove(Thing *ptr)
if (ptr->isVisible())
{
Object *obj = static_cast< Object * >(ptr);
- Point const &pos = obj->getPosition();
- zones[(pos.x / zoneDiam) + (pos.y / zoneDiam) * mapWidth].remove(obj);
+ mContent->getZone(obj->getPosition()).remove(obj);
if (ptr->canMove())
{
- deallocate(static_cast< MovingObject * >(ptr));
+ mContent->deallocate(static_cast< MovingObject * >(ptr));
}
}
- for (std::vector< Thing * >::iterator i = things.begin(),
- i_end = things.end(); i != i_end; ++i)
+ for (std::vector< Thing * >::iterator i = mContent->things.begin(),
+ i_end = mContent->things.end(); i != i_end; ++i)
{
if (*i == ptr)
{
*i = *(i_end - 1);
- things.pop_back();
+ mContent->things.pop_back();
return;
}
}
@@ -517,16 +625,16 @@ void MapComposite::remove(Thing *ptr)
void MapComposite::update()
{
- map->resetTempWalk();
+ mMap->resetTempWalk();
- for (int i = 0; i < mapHeight * mapWidth; ++i)
+ for (int i = 0; i < mContent->mapHeight * mContent->mapWidth; ++i)
{
- zones[i].destinations.clear();
+ mContent->zones[i].destinations.clear();
}
// Cannot use a WholeMap iterator as objects will change zones under its feet.
- for (std::vector< Thing * >::iterator i = things.begin(),
- i_end = things.end(); i != i_end; ++i)
+ for (std::vector< Thing * >::iterator i = mContent->things.begin(),
+ i_end = mContent->things.end(); i != i_end; ++i)
{
if (!(*i)->canMove())
{
@@ -537,15 +645,22 @@ void MapComposite::update()
Point const &pos1 = obj->getOldPosition(),
&pos2 = obj->getPosition();
- map->setTempWalk(pos2.x / 32, pos2.y / 32, false);
+ mMap->setTempWalk(pos2.x / 32, pos2.y / 32, false);
- int src = (pos1.x / zoneDiam) + (pos1.y / zoneDiam) * mapWidth,
- dst = (pos2.x / zoneDiam) + (pos2.y / zoneDiam) * mapWidth;
- if (src != dst)
+ MapZone &src = mContent->getZone(pos1),
+ &dst = mContent->getZone(pos2);
+ if (&src != &dst)
{
- addZone(zones[src].destinations, dst);
- zones[src].remove(obj);
- zones[dst].insert(obj);
+ addZone(src.destinations, &dst - mContent->zones);
+ src.remove(obj);
+ dst.insert(obj);
}
}
}
+
+std::vector< Thing * > const &MapComposite::getEverything() const
+{
+ return mContent->things;
+}
+
+