summaryrefslogtreecommitdiff
path: root/src/gamehandler.cpp
diff options
context:
space:
mode:
authorGuillaume Melquiond <guillaume.melquiond@gmail.com>2006-05-23 05:35:13 +0000
committerGuillaume Melquiond <guillaume.melquiond@gmail.com>2006-05-23 05:35:13 +0000
commit351f050dd77c7dfae7ab901b9dab08336e59b4fc (patch)
tree709142480b61e116eca5ac17685e29b6fe658e5a /src/gamehandler.cpp
parent71ef3ccdc4d628e93d445251121f36a35c6f6a4e (diff)
downloadmanaserv-351f050dd77c7dfae7ab901b9dab08336e59b4fc.tar.gz
manaserv-351f050dd77c7dfae7ab901b9dab08336e59b4fc.tar.bz2
manaserv-351f050dd77c7dfae7ab901b9dab08336e59b4fc.tar.xz
manaserv-351f050dd77c7dfae7ab901b9dab08336e59b4fc.zip
Split server into three logical servers: an account server, a chat
server, and a game server.
Diffstat (limited to 'src/gamehandler.cpp')
-rw-r--r--src/gamehandler.cpp202
1 files changed, 198 insertions, 4 deletions
diff --git a/src/gamehandler.cpp b/src/gamehandler.cpp
index ff4a0dde..dc14fd2a 100644
--- a/src/gamehandler.cpp
+++ b/src/gamehandler.cpp
@@ -23,23 +23,184 @@
#include "gamehandler.h"
+#include <cassert>
#include <iostream>
+#include <map>
#include "messagein.h"
#include "messageout.h"
#include "netcomputer.h"
#include "packet.h"
+#include "state.h"
-void GameHandler::receiveMessage(NetComputer &comp, MessageIn &message)
+using tmwserv::BeingPtr;
+
+class GameClient: public NetComputer
{
- ClientComputer &computer = static_cast< ClientComputer & >(comp);
- if (computer.getCharacter().get() == NULL)
- return;
+ public:
+ /**
+ * Constructor.
+ */
+ GameClient(GameHandler *, ENetPeer *);
+
+ /**
+ * Destructor.
+ */
+ ~GameClient();
+
+ /**
+ * Set the selected character associated with connection.
+ */
+ void setCharacter(BeingPtr ch);
+
+ /**
+ * Deselect the character associated with connection.
+ */
+ void unsetCharacter();
+
+ /**
+ * Get character associated with the connection.
+ */
+ BeingPtr getCharacter() { return mCharacterPtr; }
+
+ private:
+ /** Character associated with the conneciton. */
+ BeingPtr mCharacterPtr;
+};
+
+GameClient::GameClient(GameHandler *handler, ENetPeer *peer):
+ NetComputer(handler, peer),
+ mCharacterPtr(NULL)
+{
+}
+
+GameClient::~GameClient()
+{
+ unsetCharacter();
+}
+
+
+void GameClient::setCharacter(tmwserv::BeingPtr ch)
+{
+ assert(mCharacterPtr.get() == NULL);
+ tmwserv::State &state = tmwserv::State::instance();
+ mCharacterPtr = ch;
+ state.addBeing(mCharacterPtr, mCharacterPtr->getMapId());
+}
+
+void GameClient::unsetCharacter()
+{
+ if (mCharacterPtr.get() == NULL) return;
+ // remove being from world
+ tmwserv::State &state = tmwserv::State::instance();
+ state.removeBeing(mCharacterPtr);
+ mCharacterPtr = tmwserv::BeingPtr(NULL);
+}
+
+struct GamePendingLogin
+{
+ tmwserv::BeingPtr character;
+ int timeout;
+};
+
+typedef std::map< std::string, GamePendingLogin > GamePendingLogins;
+static GamePendingLogins pendingLogins;
+
+typedef std::map< std::string, GameClient * > GamePendingClients;
+static GamePendingClients pendingClients;
+
+void registerGameClient(std::string const &token, tmwserv::BeingPtr ch)
+{
+ GamePendingClients::iterator i = pendingClients.find(token);
+ if (i != pendingClients.end())
+ {
+ GameClient *computer = i->second;
+ computer->setCharacter(ch);
+ pendingClients.erase(i);
+ MessageOut result;
+ result.writeShort(SMSG_GAMESRV_CONNECT_RESPONSE);
+ result.writeByte(GSRV_CONNECT_OK);
+ computer->send(result.getPacket());
+ }
+ else
+ {
+ GamePendingLogin p;
+ p.character = ch;
+ p.timeout = 300; // world ticks
+ pendingLogins.insert(std::make_pair(token, p));
+ }
+}
+
+void GameHandler::removeOutdatedPending()
+{
+ GamePendingLogins::iterator i = pendingLogins.begin(), next;
+ while (i != pendingLogins.end())
+ {
+ next = i; ++next;
+ if (--i->second.timeout <= 0) pendingLogins.erase(i);
+ i = next;
+ }
+}
+NetComputer *GameHandler::computerConnected(ENetPeer *peer)
+{
+ return new GameClient(this, peer);
+}
+
+void GameHandler::computerDisconnected(NetComputer *computer)
+{
+ for (GamePendingClients::iterator i = pendingClients.begin(), i_end = pendingClients.end();
+ i != i_end; ++i)
+ {
+ if (i->second == computer)
+ {
+ pendingClients.erase(i);
+ break;
+ }
+ }
+ delete computer;
+}
+
+void GameHandler::process()
+{
+ ConnectionHandler::process();
+ removeOutdatedPending();
+}
+
+void GameHandler::processMessage(NetComputer *comp, MessageIn &message)
+{
+ GameClient &computer = *static_cast< GameClient * >(comp);
MessageOut result;
+ if (computer.getCharacter().get() == NULL) {
+ if (message.getId() != CMSG_GAMESRV_CONNECT) return;
+ std::string magic_token = message.readString(32);
+ GamePendingLogins::iterator i = pendingLogins.find(magic_token);
+ if (i == pendingLogins.end())
+ {
+ for (GamePendingClients::iterator i = pendingClients.begin(), i_end = pendingClients.end();
+ i != i_end; ++i) {
+ if (i->second == &computer) return;
+ }
+ pendingClients.insert(std::make_pair(magic_token, &computer));
+ return;
+ }
+ computer.setCharacter(i->second.character);
+ pendingLogins.erase(i);
+ result.writeShort(SMSG_GAMESRV_CONNECT_RESPONSE);
+ result.writeByte(GSRV_CONNECT_OK);
+ computer.send(result.getPacket());
+ return;
+ }
+
switch (message.getId())
{
+ case CMSG_SAY:
+ {
+ std::string say = message.readString();
+ sayAround(computer, say);
+ } break;
+
case CMSG_PICKUP:
{
// add item to inventory (this is too simplistic atm)
@@ -121,3 +282,36 @@ void GameHandler::receiveMessage(NetComputer &comp, MessageIn &message)
if (result.getPacket()->length > 0)
computer.send(result.getPacket());
}
+
+void GameHandler::sayAround(GameClient &computer, std::string const &text)
+{
+ BeingPtr beingPtr = computer.getCharacter();
+ MessageOut msg;
+ msg.writeShort(SMSG_SAY);
+ msg.writeString(beingPtr->getName());
+ msg.writeString(text);
+ unsigned speakerMapId = beingPtr->getMapId();
+ std::pair<unsigned, unsigned> speakerXY = beingPtr->getXY();
+ for (NetComputers::iterator i = clients.begin(), i_end = clients.end();
+ i != i_end; ++i)
+ {
+ // See if the other being is near enough, then send the message
+ tmwserv::Being const *listener = static_cast< GameClient * >(*i)->getCharacter().get();
+ if (!listener || listener->getMapId() != speakerMapId) continue;
+ std::pair<unsigned, unsigned> listenerXY = listener->getXY();
+ if (abs(listenerXY.first - speakerXY.first ) > (int)AROUND_AREA_IN_TILES) continue;
+ if (abs(listenerXY.second - speakerXY.second) > (int)AROUND_AREA_IN_TILES) continue;
+ (*i)->send(msg.getPacket());
+ }
+}
+
+void GameHandler::sendTo(BeingPtr beingPtr, MessageOut &msg)
+{
+ for (NetComputers::iterator i = clients.begin(), i_end = clients.end();
+ i != i_end; ++i) {
+ if (static_cast< GameClient * >(*i)->getCharacter().get() == beingPtr.get()) {
+ (*i)->send(msg.getPacket());
+ break;
+ }
+ }
+}