summaryrefslogtreecommitdiff
path: root/src/game-server/state.cpp
diff options
context:
space:
mode:
authorGuillaume Melquiond <guillaume.melquiond@gmail.com>2007-09-23 12:55:09 +0000
committerGuillaume Melquiond <guillaume.melquiond@gmail.com>2007-09-23 12:55:09 +0000
commit5618f4890df5eb9ea91eb73a7a7dd7df745863a6 (patch)
tree07873952b5f3f7efae06b3045692e2d90bd45a58 /src/game-server/state.cpp
parent203ed8e40105c17d300b12ee461327cb4416acf2 (diff)
downloadmanaserv-5618f4890df5eb9ea91eb73a7a7dd7df745863a6.tar.gz
manaserv-5618f4890df5eb9ea91eb73a7a7dd7df745863a6.tar.bz2
manaserv-5618f4890df5eb9ea91eb73a7a7dd7df745863a6.tar.xz
manaserv-5618f4890df5eb9ea91eb73a7a7dd7df745863a6.zip
Robustified code with respect to insertion failures.
Diffstat (limited to 'src/game-server/state.cpp')
-rw-r--r--src/game-server/state.cpp75
1 files changed, 55 insertions, 20 deletions
diff --git a/src/game-server/state.cpp b/src/game-server/state.cpp
index b9185e92..2f68d6ba 100644
--- a/src/game-server/state.cpp
+++ b/src/game-server/state.cpp
@@ -427,7 +427,7 @@ void GameState::update()
break;
case EVENT_INSERT:
- insert(o);
+ insertSafe(o);
break;
case EVENT_WARP:
@@ -439,33 +439,63 @@ void GameState::update()
delayedEvents.clear();
}
-void GameState::insert(Thing *ptr)
+bool GameState::insert(Thing *ptr)
{
assert(!dbgLockObjects);
MapComposite *map = ptr->getMap();
- if (!map || !map->insert(ptr))
+ assert(map && map->isActive());
+
+ /* Non-visible objects have neither position nor public ID, so their
+ insertion cannot fail. Take care of them first. */
+ if (!ptr->isVisible())
{
- // TODO: Deal with failure to place Thing on the map.
- return;
+ map->insert(ptr);
+ ptr->inserted();
+ return true;
}
- ptr->inserted();
+ // Check that coordinates are actually valid.
+ Object *obj = static_cast< Object * >(ptr);
+ Map *mp = map->getMap();
+ Point pos = obj->getPosition();
+ if (pos.x / 32 >= (unsigned)mp->getWidth() ||
+ pos.y / 32 >= (unsigned)mp->getHeight())
+ {
+ LOG_ERROR("Tried to insert an object at position " << pos.x << ','
+ << pos.y << " outside map " << map->getID() << '.');
+ // Set an arbitrary small position.
+ pos = Point(100, 100);
+ obj->setPosition(pos);
+ }
- if (ptr->isVisible())
+ if (!map->insert(obj))
{
- Object *obj = static_cast< Object * >(ptr);
- obj->raiseUpdateFlags(UPDATEFLAG_NEW_ON_MAP);
- if (obj->getType() != OBJECT_CHARACTER) return;
-
- /* Since the character doesn't know yet where on the world he is after
- connecting to the map server, we send him an initial change map message. */
- MessageOut mapChangeMessage(GPMSG_PLAYER_MAP_CHANGE);
- mapChangeMessage.writeString(map->getName());
- Point pos = obj->getPosition();
- mapChangeMessage.writeShort(pos.x);
- mapChangeMessage.writeShort(pos.y);
- gameHandler->sendTo(static_cast< Character * >(obj), mapChangeMessage);
+ // The map is overloaded. No room to add a new object.
+ LOG_ERROR("Too many objects on map " << map->getID() << '.');
+ return false;
}
+
+ obj->inserted();
+
+ obj->raiseUpdateFlags(UPDATEFLAG_NEW_ON_MAP);
+ if (obj->getType() != OBJECT_CHARACTER) return true;
+
+ /* Since the player does not know yet where in the world its character is,
+ we send a map-change message, even if it is the first time it
+ connects to this server. */
+ MessageOut mapChangeMessage(GPMSG_PLAYER_MAP_CHANGE);
+ mapChangeMessage.writeString(map->getName());
+ mapChangeMessage.writeShort(pos.x);
+ mapChangeMessage.writeShort(pos.y);
+ gameHandler->sendTo(static_cast< Character * >(obj), mapChangeMessage);
+ return true;
+}
+
+bool GameState::insertSafe(Thing *ptr)
+{
+ if (insert(ptr)) return true;
+ delete ptr;
+ return false;
}
void GameState::remove(Thing *ptr)
@@ -529,7 +559,12 @@ void GameState::warp(Character *ptr, MapComposite *map, int x, int y)
if (map->isActive())
{
- insert(ptr);
+ if (!insert(ptr))
+ {
+ ptr->disconnected();
+ gameHandler->kill(ptr);
+ delete ptr;
+ }
}
else
{