initial commit, lordsawar source, slightly modified
[lordsawar] / src / game-client.cpp
diff --git a/src/game-client.cpp b/src/game-client.cpp
new file mode 100644 (file)
index 0000000..c140aaa
--- /dev/null
@@ -0,0 +1,408 @@
+// Copyright (C) 2008 Ole Laursen
+//
+//  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 3 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 
+//  02110-1301, USA.
+
+#include <iostream>
+#include <fstream>
+
+#include "game-client.h"
+
+#include "network-connection.h"
+#include "File.h"
+#include "action.h"
+#include "network-action.h"
+#include "network-history.h"
+#include "playerlist.h"
+#include "network_player.h"
+#include "xmlhelper.h"
+  
+#include "real_player.h" 
+#include "network_player.h" 
+
+
+GameClient * GameClient::s_instance = 0;
+
+
+GameClient* GameClient::getInstance()
+{
+    if (s_instance == 0)
+        s_instance = new GameClient();
+
+    return s_instance;
+}
+
+void GameClient::deleteInstance()
+{
+    if (s_instance)
+        delete s_instance;
+
+    s_instance = 0;
+}
+
+GameClient::GameClient()
+{
+  d_connected = false;
+  player_id = -1;
+}
+
+GameClient::~GameClient()
+{
+  if (network_connection.get() != NULL)
+    network_connection->send(MESSAGE_TYPE_PARTICIPANT_DISCONNECT, d_nickname);
+}
+
+void GameClient::start(std::string host, guint32 port, std::string nick)
+{
+  d_host = host;
+  d_port = port;
+  player_id = -1;
+  setNickname(nick);
+  network_connection.reset(new NetworkConnection());
+  network_connection->connected.connect(
+    sigc::mem_fun(this, &GameClient::onConnected));
+  network_connection->connection_lost.connect(
+    sigc::mem_fun(this, &GameClient::onConnectionLost));
+  network_connection->got_message.connect(
+    sigc::mem_fun(this, &GameClient::onGotMessage));
+  network_connection->connectToHost(host, port);
+}
+
+void GameClient::onConnected() 
+{
+  std::cerr << "connected" << std::endl;
+  d_connected = true;
+
+  network_connection->send(MESSAGE_TYPE_PING, "");
+
+  client_connected.emit();
+}
+
+void GameClient::onConnectionLost()
+{
+  std::cerr << "connection lost" << std::endl;
+  if (d_connected)
+    client_disconnected.emit();
+  else
+    client_could_not_connect.emit();
+}
+
+void GameClient::sat_down(Player *player, std::string nickname)
+{
+  if (!player)
+    return;
+  if (player->getType() == Player::NETWORKED)
+    dynamic_cast<NetworkPlayer*>(player)->setConnected(true);
+  player_sits.emit(player, nickname);
+}
+
+void GameClient::stood_up(Player *player, std::string nickname)
+{
+  if (!player)
+    return;
+  if (player->getType() == Player::HUMAN)
+    {
+      //this covers the "boot", or forcibly-stand case.
+      NetworkPlayer *new_p = new NetworkPlayer(*player);
+      Playerlist::getInstance()->swap(player, new_p);
+      delete player;
+      new_p->setConnected(false);
+    }
+  else if (player->getType() == Player::NETWORKED)
+    dynamic_cast<NetworkPlayer*>(player)->setConnected(false);
+  player_stands.emit(player, nickname);
+}
+
+void GameClient::onGotMessage(MessageType type, std::string payload)
+{
+  std::cerr << "got message of type " << type << std::endl;
+  switch (type) {
+  case MESSAGE_TYPE_PING:
+    network_connection->send(MESSAGE_TYPE_PONG, "PONGOGOGO");
+    break;
+
+  case MESSAGE_TYPE_PONG:
+    network_connection->send(MESSAGE_TYPE_PARTICIPANT_CONNECT, d_nickname);
+    break;
+
+  case MESSAGE_TYPE_SENDING_ACTIONS:
+    gotActions(payload);
+    break;
+
+  case MESSAGE_TYPE_SENDING_MAP:
+    gotScenario(payload);
+    break;
+
+  case MESSAGE_TYPE_PARTICIPANT_CONNECTED:
+    remote_participant_joins.emit(payload);
+    break;
+  case MESSAGE_TYPE_PARTICIPANT_DISCONNECTED:
+    remote_participant_departs.emit(payload);
+    break;
+
+  case MESSAGE_TYPE_REQUEST_SEAT_MANIFEST:
+  case MESSAGE_TYPE_P1_SIT:
+  case MESSAGE_TYPE_P2_SIT:
+  case MESSAGE_TYPE_P3_SIT:
+  case MESSAGE_TYPE_P4_SIT:
+  case MESSAGE_TYPE_P5_SIT:
+  case MESSAGE_TYPE_P6_SIT:
+  case MESSAGE_TYPE_P7_SIT:
+  case MESSAGE_TYPE_P8_SIT:
+  case MESSAGE_TYPE_P1_STAND:
+  case MESSAGE_TYPE_P2_STAND:
+  case MESSAGE_TYPE_P3_STAND:
+  case MESSAGE_TYPE_P4_STAND:
+  case MESSAGE_TYPE_P5_STAND:
+  case MESSAGE_TYPE_P6_STAND:
+  case MESSAGE_TYPE_P7_STAND:
+  case MESSAGE_TYPE_P8_STAND:
+  case MESSAGE_TYPE_PARTICIPANT_CONNECT:
+  case MESSAGE_TYPE_PARTICIPANT_DISCONNECT:
+  case MESSAGE_TYPE_CHAT:
+  case MESSAGE_TYPE_ROUND_OVER:
+    //FIXME: faulty server.
+    break;
+
+  case MESSAGE_TYPE_CHATTED:
+    gotChatMessage("", payload);
+    break;
+    //this is the client realizing that some other player joined the server
+  case MESSAGE_TYPE_P1_SAT_DOWN:
+    sat_down(Playerlist::getInstance()->getPlayer(0), payload);
+    break;
+  case MESSAGE_TYPE_P2_SAT_DOWN:
+    sat_down(Playerlist::getInstance()->getPlayer(1), payload);
+    break;
+  case MESSAGE_TYPE_P3_SAT_DOWN:
+    sat_down(Playerlist::getInstance()->getPlayer(2), payload);
+    break;
+  case MESSAGE_TYPE_P4_SAT_DOWN:
+    sat_down(Playerlist::getInstance()->getPlayer(3), payload);
+    break;
+  case MESSAGE_TYPE_P5_SAT_DOWN:
+    sat_down(Playerlist::getInstance()->getPlayer(4), payload);
+    break;
+  case MESSAGE_TYPE_P6_SAT_DOWN:
+    sat_down(Playerlist::getInstance()->getPlayer(5), payload);
+    break;
+  case MESSAGE_TYPE_P7_SAT_DOWN:
+    sat_down(Playerlist::getInstance()->getPlayer(6), payload);
+    break;
+  case MESSAGE_TYPE_P8_SAT_DOWN:
+    sat_down(Playerlist::getInstance()->getPlayer(7), payload);
+    break;
+  case MESSAGE_TYPE_P1_STOOD_UP:
+    stood_up(Playerlist::getInstance()->getPlayer(0), payload);
+    break;
+  case MESSAGE_TYPE_P2_STOOD_UP:
+    stood_up(Playerlist::getInstance()->getPlayer(1), payload);
+    break;
+  case MESSAGE_TYPE_P3_STOOD_UP:
+    stood_up(Playerlist::getInstance()->getPlayer(2), payload);
+    break;
+  case MESSAGE_TYPE_P4_STOOD_UP:
+    stood_up(Playerlist::getInstance()->getPlayer(3), payload);
+    break;
+  case MESSAGE_TYPE_P5_STOOD_UP:
+    stood_up(Playerlist::getInstance()->getPlayer(4), payload);
+    break;
+  case MESSAGE_TYPE_P6_STOOD_UP:
+    stood_up(Playerlist::getInstance()->getPlayer(5), payload);
+    break;
+  case MESSAGE_TYPE_P7_STOOD_UP:
+    stood_up(Playerlist::getInstance()->getPlayer(6), payload);
+    break;
+  case MESSAGE_TYPE_P8_STOOD_UP:
+    stood_up(Playerlist::getInstance()->getPlayer(7), payload);
+    break;
+
+  case MESSAGE_TYPE_SENDING_HISTORY:
+    gotHistories(payload);
+    break;
+  
+  case MESSAGE_TYPE_SERVER_DISCONNECT:
+    client_disconnected.emit();
+    break;
+
+  case MESSAGE_TYPE_TURN_ORDER:
+    gotTurnOrder (payload);
+    break;
+
+  case MESSAGE_TYPE_KILL_PLAYER:
+    gotKillPlayer(Playerlist::getInstance()->getPlayer(atoi(payload.c_str())));
+    break;
+
+  case MESSAGE_TYPE_ROUND_START:
+    round_begins.emit();
+    break;
+  }
+}
+
+void GameClient::gotKillPlayer(Player *player)
+{
+  player->kill();
+}  
+
+void GameClient::onHistoryDone(NetworkHistory *history)
+{
+  std::string desc = history->toString();
+  std::cerr << "Game Client got " << desc <<"\n";
+
+  if (history->getHistory()->getType() == History::PLAYER_VANQUISHED)
+    local_player_died(history->getOwner());
+
+  histories.push_back(history);
+  sendHistories();
+  clearNetworkHistorylist(histories);
+}
+
+void GameClient::onActionDone(NetworkAction *action)
+{
+  std::string desc = action->toString();
+  std::cerr << "Game Client got " << desc <<"\n";
+
+  if (action->getAction()->getType() == Action::END_TURN)
+    local_player_moved(action->getOwner());
+  if (action->getAction()->getType() == Action::INIT_TURN)
+    local_player_starts_move(action->getOwner());
+
+  actions.push_back(action);
+  sendActions();
+  clearNetworkActionlist(actions);
+
+}
+void GameClient::sendActions()
+{
+  std::ostringstream os;
+  XML_Helper helper(&os);
+
+  helper.begin("1");
+  helper.openTag("actions");
+
+  for (std::list<NetworkAction *>::iterator i = actions.begin(),
+       end = actions.end(); i != end; ++i)
+    {
+      (*i)->save(&helper);
+    }
+
+  helper.closeTag();
+
+  std::cerr << "sending actions" << std::endl;
+  network_connection->send(MESSAGE_TYPE_SENDING_ACTIONS, os.str());
+}
+
+void GameClient::sendHistories()
+{
+  std::ostringstream os;
+  XML_Helper helper(&os);
+
+  helper.begin("1");
+  helper.openTag("histories");
+
+  for (std::list<NetworkHistory *>::iterator i = histories.begin(),
+       end = histories.end(); i != end; ++i)
+    (**i).save(&helper);
+
+  helper.closeTag();
+
+  network_connection->send(MESSAGE_TYPE_SENDING_HISTORY, os.str());
+}
+
+void GameClient::sit_down (Player *player)
+{
+  if (!player)
+    return;
+  MessageType type;
+  switch (player->getId())
+    {
+    case 0: type = MESSAGE_TYPE_P1_SIT; break;
+    case 1: type = MESSAGE_TYPE_P2_SIT; break;
+    case 2: type = MESSAGE_TYPE_P3_SIT; break;
+    case 3: type = MESSAGE_TYPE_P4_SIT; break;
+    case 4: type = MESSAGE_TYPE_P5_SIT; break;
+    case 5: type = MESSAGE_TYPE_P6_SIT; break;
+    case 6: type = MESSAGE_TYPE_P7_SIT; break;
+    case 7: type = MESSAGE_TYPE_P8_SIT; break;
+    default:
+           return;
+    }
+  RealPlayer *new_p = new RealPlayer (*player);
+  Playerlist::getInstance()->swap(player, new_p);
+  stopListeningForLocalEvents(player);
+  listenForLocalEvents(new_p);
+  delete player;
+  network_connection->send(type, d_nickname);
+}
+
+void GameClient::stand_up (Player *player)
+{
+  if (!player)
+    return;
+  MessageType type;
+  switch (player->getId())
+    {
+    case 0: type = MESSAGE_TYPE_P1_STAND; break;
+    case 1: type = MESSAGE_TYPE_P2_STAND; break;
+    case 2: type = MESSAGE_TYPE_P3_STAND; break;
+    case 3: type = MESSAGE_TYPE_P4_STAND; break;
+    case 4: type = MESSAGE_TYPE_P5_STAND; break;
+    case 5: type = MESSAGE_TYPE_P6_STAND; break;
+    case 6: type = MESSAGE_TYPE_P7_STAND; break;
+    case 7: type = MESSAGE_TYPE_P8_STAND; break;
+    default:
+           return;
+    }
+  //now turning a human player into a network player
+  NetworkPlayer *new_p = new NetworkPlayer(*player);
+  Playerlist::getInstance()->swap(player, new_p);
+  stopListeningForLocalEvents(new_p);
+  delete player;
+  new_p->setConnected(false);
+  network_connection->send(type, d_nickname);
+}
+
+void GameClient::chat(std::string message)
+{
+  network_connection->send(MESSAGE_TYPE_CHAT, d_nickname + ":" + message);
+}
+  
+void GameClient::request_seat_manifest()
+{
+  network_connection->send(MESSAGE_TYPE_REQUEST_SEAT_MANIFEST, "");
+}
+    
+void GameClient::gotTurnOrder (std::string payload)
+{
+  std::list<guint32> player_ids;
+  std::stringstream players;
+  players.str(payload);
+
+  int ival;
+  while (players.eof() == false)
+    {
+      ival = -1;
+      players >> ival;
+      if (ival != -1)
+       player_ids.push_back(ival);
+    }
+  Playerlist::getInstance()->reorder(player_ids);
+  playerlist_reorder_received.emit();
+}
+
+void GameClient::sendRoundOver()
+{
+  network_connection->send(MESSAGE_TYPE_ROUND_OVER, "");
+}