summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGuillaume Melquiond <guillaume.melquiond@gmail.com>2006-08-27 15:00:59 +0000
committerGuillaume Melquiond <guillaume.melquiond@gmail.com>2006-08-27 15:00:59 +0000
commit23da8710e86683f4f9e09045b7790f0f3a983101 (patch)
treedfd1d7bdd74d720267caab78b63e2a4704663b8b
parent9b2efb931324906556b1a8f77a2a409cfdc9a861 (diff)
downloadmanaserv-23da8710e86683f4f9e09045b7790f0f3a983101.tar.gz
manaserv-23da8710e86683f4f9e09045b7790f0f3a983101.tar.bz2
manaserv-23da8710e86683f4f9e09045b7790f0f3a983101.tar.xz
manaserv-23da8710e86683f4f9e09045b7790f0f3a983101.zip
Changed state handler so that entering and leaving beings are only reported when they are in range.
-rw-r--r--ChangeLog2
-rw-r--r--src/state.cpp115
2 files changed, 64 insertions, 53 deletions
diff --git a/ChangeLog b/ChangeLog
index ae69e5f7..d86f1228 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -3,6 +3,8 @@
* src/object.cpp: Fixed assertion failure on being movements.
* src/accounthandler.cpp: Matched server-side speed with client-side
speed. Removed position hack.
+ * src/state.cpp: Changed state handler so that entering and leaving
+ beings are only reported when they are in range.
2006-08-26 Rogier Polak <rogier_polak@users.sourceforge.net>
diff --git a/src/state.cpp b/src/state.cpp
index a32d082e..0d4fb28d 100644
--- a/src/state.cpp
+++ b/src/state.cpp
@@ -21,6 +21,8 @@
* $Id$
*/
+#include <cassert>
+
#include "state.h"
#include "gamehandler.h"
@@ -73,7 +75,7 @@ State::update()
{
std::pair<unsigned, unsigned> ps = (*p)->getXY();
std::pair<unsigned, unsigned> pn = (*p)->getNextPosition();
- bool po = !(*p)->isNew();
+ bool po = !(*p)->isNew(); // Is p old?
MessageOut msg(GPMSG_BEINGS_MOVE);
for (Movings::iterator o = movings.begin(),
@@ -84,14 +86,54 @@ State::update()
bool oo = po && !(*o)->isNew(); // Are p and o both old?
/* Look whether p and o "were" around the last time and whether
- they "will" be around the next time. p has to be informed when
- this proximity changes or if o will move in range. */
+ they "will" be around the next time. */
bool were = areAround(ps.first, ps.second, os.first, os.second) && oo;
bool will = areAround(pn.first, pn.second, on.first, on.second);
- bool has_moved = os.first != on.first || os.second != on.second;
- if (!(will && has_moved) && (were == will))
+
+ if (!were)
+ {
+ // o was outside p's range.
+ if (!will)
+ {
+ // Nothing to report: o will not be inside p's range.
+ continue;
+ }
+
+ int type = (*o)->getType();
+ MessageOut msg2(GPMSG_BEING_ENTER);
+ msg2.writeByte(type);
+ msg2.writeLong((*o)->getID());
+ switch (type) {
+ case OBJECT_PLAYER:
+ {
+ PlayerPtr q(*o);
+ msg2.writeString(q->getName());
+ msg2.writeByte(q->getHairStyle());
+ msg2.writeByte(q->getHairColor());
+ msg2.writeByte(q->getGender());
+ } break;
+ default:
+ assert(false); // TODO
+ }
+ gameHandler->sendTo(*p, msg2);
+ }
+ else if (!will)
+ {
+ // o is no longer visible from p.
+ MessageOut msg2(GPMSG_BEING_LEAVE);
+ msg2.writeByte((*o)->getType());
+ msg2.writeLong((*o)->getID());
+ gameHandler->sendTo(*p, msg2);
continue;
+ }
+ else if (os.first == on.first && os.second == on.second)
+ {
+ // o does not move, nothing to report.
+ continue;
+ }
+ /* At this point, either o has entered p's range, either o is
+ moving inside p's range. Report o's movements. */
std::pair<unsigned, unsigned> od = (*o)->getDestination();
msg.writeLong((*o)->getID());
msg.writeShort(on.first);
@@ -100,6 +142,7 @@ State::update()
msg.writeShort(od.second);
}
+ // Don't send a packet if nothing happed in p's range.
if (msg.getLength() > 2)
gameHandler->sendTo(*p, msg);
}
@@ -122,29 +165,7 @@ State::addObject(ObjectPtr objectPtr)
maps[mapId].objects.push_back(objectPtr);
objectPtr->setNew(true);
if (objectPtr->getType() != OBJECT_PLAYER) return;
- Players &players = maps[mapId].players;
- PlayerPtr playerPtr(objectPtr);
-
- /* Currently when a player is added, all existing players are notified
- * about this. This will need to be modified so that players only know
- * about players close to them.
- */
- MessageOut msg(GPMSG_BEING_ENTER);
- msg.writeByte(OBJECT_PLAYER);
- msg.writeLong(playerPtr->getID());
- msg.writeString(playerPtr->getName());
- msg.writeByte(playerPtr->getHairStyle());
- msg.writeByte(playerPtr->getHairColor());
- msg.writeByte(playerPtr->getGender());
-
- for (Players::iterator p = players.begin(),
- p_end = players.end(); p != p_end; ++p)
- {
- gameHandler->sendTo(*p, msg);
- }
-
- // Add the new player to the list
- players.push_back(playerPtr);
+ maps[mapId].players.push_back(PlayerPtr(objectPtr));
}
void
@@ -162,25 +183,31 @@ State::removeObject(ObjectPtr objectPtr)
}
}
if (objectPtr->getType() != OBJECT_PLAYER) return;
- PlayerPtr playerPtr(objectPtr);
- Players &players = maps[mapId].players;
- /* Also see note add addObject. All other players are notified about this
- * player leaving, but not all of them need to know.
- */
+ PlayerPtr playerPtr(objectPtr);
+ std::pair< unsigned, unsigned > pos = playerPtr->getXY();
MessageOut msg(GPMSG_BEING_LEAVE);
msg.writeByte(OBJECT_PLAYER);
msg.writeLong(playerPtr->getID());
+ Players &players = maps[mapId].players;
Players::iterator p_end = players.end(), j = p_end;
for (Players::iterator p = players.begin(); p != p_end; ++p)
{
if (p->get() == playerPtr.get())
+ {
j = p;
- else
+ }
+ else if (areAround(pos.first, pos.second, (*p)->getX(), (*p)->getY()))
+ {
gameHandler->sendTo(*p, msg);
+ }
+ }
+
+ if (j != p_end)
+ {
+ players.erase(j);
}
- if (j != players.end()) players.erase(j);
}
void
@@ -189,7 +216,6 @@ State::informPlayer(PlayerPtr playerPtr)
unsigned mapId = playerPtr->getMapId();
std::map<unsigned, MapComposite>::iterator m = maps.find(mapId);
if (m == maps.end()) return;
- Players &players = m->second.players;
/* Since the player doesn't know yet where on the world he is after
* connecting to the map server, we send him an initial change map message.
@@ -201,23 +227,6 @@ State::informPlayer(PlayerPtr playerPtr)
mapChangeMessage.writeShort(playerPtr->getY());
mapChangeMessage.writeByte(0);
gameHandler->sendTo(playerPtr, mapChangeMessage);
-
- /* Here the player is informed about all the other players on the map.
- * However, the player should only be told about other players within
- * visual range. See also notes at addObject and removeObject.
- */
- for (Players::iterator p = players.begin(),
- p_end = players.end(); p != p_end; ++p)
- {
- MessageOut msg(GPMSG_BEING_ENTER);
- msg.writeByte(OBJECT_PLAYER);
- msg.writeLong((*p)->getID());
- msg.writeString((*p)->getName());
- msg.writeByte((*p)->getHairStyle());
- msg.writeByte((*p)->getHairColor());
- msg.writeByte((*p)->getGender());
- gameHandler->sendTo(playerPtr, msg);
- }
}
bool