initial commit, lordsawar source, slightly modified
[lordsawar] / src / game-server.cpp
1 // Copyright (C) 2008 Ole Laursen
2 // Copyright (C) 2008 Ben Asselstine
3 //
4 //  This program is free software; you can redistribute it and/or modify
5 //  it under the terms of the GNU General Public License as published by
6 //  the Free Software Foundation; either version 3 of the License, or
7 //  (at your option) any later version.
8 //
9 //  This program is distributed in the hope that it will be useful,
10 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
11 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 //  GNU Library General Public License for more details.
13 //
14 //  You should have received a copy of the GNU General Public License
15 //  along with this program; if not, write to the Free Software
16 //  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 
17 //  02110-1301, USA.
18
19 #include <iostream>
20 #include <sstream>
21 #include <list>
22
23 #include "game-server.h"
24
25 #include "network-server.h"
26 #include "game.h"
27 #include "xmlhelper.h"
28 #include "GameScenario.h"
29 #include "playerlist.h"
30 #include "player.h"
31 #include "network-action.h"
32 #include "network-history.h"
33 #include "Configuration.h"
34 #include "network_player.h"
35 #include "real_player.h"
36 #include "GameScenarioOptions.h"
37
38
39 class NetworkAction;
40
41 struct Participant
42 {
43   void *conn;
44   std::list<guint32> players;
45   std::list<NetworkAction *> actions;
46   std::list<NetworkHistory *> histories;
47   std::string nickname;
48   bool round_finished;
49 };
50
51 GameServer * GameServer::s_instance = 0;
52
53
54 GameServer* GameServer::getInstance()
55 {
56     if (s_instance == 0)
57         s_instance = new GameServer();
58
59     return s_instance;
60 }
61
62 void GameServer::deleteInstance()
63 {
64     if (s_instance)
65         delete s_instance;
66
67     s_instance = 0;
68 }
69
70
71 GameServer::GameServer()
72 {
73 }
74
75 GameServer::~GameServer()
76 {
77   //say goodbye to all participants
78   for (std::list<Participant *>::iterator i = participants.begin(),
79          end = participants.end(); i != end; ++i)
80     network_server->send((*i)->conn, MESSAGE_TYPE_SERVER_DISCONNECT, "bye");
81
82   for (std::list<Participant *>::iterator i = participants.begin(),
83          end = participants.end(); i != end; ++i)
84     delete *i;
85   players_seated_locally.clear();
86 }
87
88 bool GameServer::isListening()
89 {
90   if (network_server.get() != NULL)
91     return network_server->isListening();
92   else
93     return false;
94 }
95
96 void GameServer::start(GameScenario *game_scenario, int port, std::string nick)
97 {
98   setGameScenario(game_scenario);
99   setNickname(nick);
100
101   if (network_server.get() != NULL && network_server->isListening())
102     return;
103   network_server.reset(new NetworkServer());
104   network_server->got_message.connect
105     (sigc::mem_fun(this, &GameServer::onGotMessage));
106   network_server->connection_lost.connect
107     (sigc::mem_fun(this, &GameServer::onConnectionLost));
108   network_server->connection_made.connect
109     (sigc::mem_fun(this, &GameServer::onConnectionMade));
110
111   network_server->startListening(port);
112
113   listenForLocalEvents(Playerlist::getInstance()->getNeutral());
114 }
115
116 void GameServer::checkRoundOver()
117 {
118   bool all_finished = true;
119   for (std::list<Participant *>::iterator i = participants.begin(),
120        end = participants.end(); i != end; ++i)
121     {
122       if ((*i)->round_finished == false)
123         {
124           all_finished = false;
125           break;
126         }
127     }
128
129   if (all_finished)
130     {
131       printf ("hooray!  we're all done the round.\n");
132       for (std::list<Participant *>::iterator i = participants.begin(),
133            end = participants.end(); i != end; ++i)
134         (*i)->round_finished = false;
135
136       //now we can send the start round message, and begin the round ourselves.
137       for (std::list<Participant *>::iterator i = participants.begin(),
138            end = participants.end(); i != end; ++i)
139         network_server->send((*i)->conn, MESSAGE_TYPE_ROUND_START, "");
140
141       round_begins.emit();
142     }
143 }
144
145 void GameServer::gotRoundOver(void *conn)
146 {
147   Participant *part = findParticipantByConn(conn);
148   if (part)
149     {
150       //mark the participant as finished for this round
151       part->round_finished = true;
152       //are all participants finished?
153       checkRoundOver();
154     }
155   return;
156 }
157
158 void GameServer::gotChat(void *conn, std::string message)
159 {
160   Participant *part = findParticipantByConn(conn);
161   if (part)
162     {
163       gotChatMessage(part->nickname, message);
164       for (std::list<Participant *>::iterator i = participants.begin(),
165            end = participants.end(); i != end; ++i)
166         {
167           //if ((*i)->conn != part->conn)
168           //network_server->send((*i)->conn, MESSAGE_TYPE_CHATTED, 
169           //part->nickname + ":" + message);
170           //else
171           network_server->send((*i)->conn, MESSAGE_TYPE_CHATTED, 
172                                message);
173
174         }
175     }
176   return;
177 }
178 void GameServer::onGotMessage(void *conn, MessageType type, std::string payload)
179 {
180   std::cerr << "got message of type " << type << std::endl;
181   switch (type) {
182   case MESSAGE_TYPE_PING:
183     std::cerr << "sending pong" << std::endl;
184     network_server->send(conn, MESSAGE_TYPE_PONG, "");
185     break;
186
187   case MESSAGE_TYPE_PONG:
188     break;
189
190   case MESSAGE_TYPE_SENDING_ACTIONS:
191     gotRemoteActions(conn, payload);
192     break;
193
194   case MESSAGE_TYPE_SENDING_MAP:
195     // should never occur
196     break;
197
198   case MESSAGE_TYPE_SENDING_HISTORY:
199     gotRemoteHistory(conn, payload);
200     break;
201
202   case MESSAGE_TYPE_PARTICIPANT_CONNECT:
203     join(conn, payload);
204     break;
205
206   case MESSAGE_TYPE_REQUEST_SEAT_MANIFEST:
207     sendSeats(conn);
208     sendChatRoster(conn);
209     break;
210
211   case MESSAGE_TYPE_P1_SIT:
212     sit(conn, Playerlist::getInstance()->getPlayer(0), payload);
213     break;
214
215   case MESSAGE_TYPE_P2_SIT:
216     sit(conn, Playerlist::getInstance()->getPlayer(1), payload);
217     break;
218
219   case MESSAGE_TYPE_P3_SIT:
220     sit(conn, Playerlist::getInstance()->getPlayer(2), payload);
221     break;
222
223   case MESSAGE_TYPE_P4_SIT:
224     sit(conn, Playerlist::getInstance()->getPlayer(3), payload);
225     break;
226
227   case MESSAGE_TYPE_P5_SIT:
228     sit(conn, Playerlist::getInstance()->getPlayer(4), payload);
229     break;
230
231   case MESSAGE_TYPE_P6_SIT:
232     sit(conn, Playerlist::getInstance()->getPlayer(5), payload);
233     break;
234
235   case MESSAGE_TYPE_P7_SIT:
236     sit(conn, Playerlist::getInstance()->getPlayer(6), payload);
237     break;
238
239   case MESSAGE_TYPE_P8_SIT:
240     sit(conn, Playerlist::getInstance()->getPlayer(7), payload);
241     break;
242
243   case MESSAGE_TYPE_P1_STAND:
244     stand(conn, Playerlist::getInstance()->getPlayer(0), payload);
245     break;
246
247   case MESSAGE_TYPE_P2_STAND:
248     stand(conn, Playerlist::getInstance()->getPlayer(1), payload);
249     break;
250
251   case MESSAGE_TYPE_P3_STAND:
252     stand(conn, Playerlist::getInstance()->getPlayer(2), payload);
253     break;
254
255   case MESSAGE_TYPE_P4_STAND:
256     stand(conn, Playerlist::getInstance()->getPlayer(3), payload);
257     break;
258
259   case MESSAGE_TYPE_P5_STAND:
260     stand(conn, Playerlist::getInstance()->getPlayer(4), payload);
261     break;
262
263   case MESSAGE_TYPE_P6_STAND:
264     stand(conn, Playerlist::getInstance()->getPlayer(5), payload);
265     break;
266
267   case MESSAGE_TYPE_P7_STAND:
268     stand(conn, Playerlist::getInstance()->getPlayer(6), payload);
269     break;
270
271   case MESSAGE_TYPE_P8_STAND:
272     stand(conn, Playerlist::getInstance()->getPlayer(7), payload);
273     break;
274
275   case MESSAGE_TYPE_PARTICIPANT_DISCONNECT:
276     depart(conn);
277     break;
278
279   case MESSAGE_TYPE_PARTICIPANT_CONNECTED:
280     break;
281
282   case MESSAGE_TYPE_CHAT:
283     gotChat(conn, payload);
284     break;
285
286   case MESSAGE_TYPE_ROUND_OVER:
287     //what do we do now?
288     gotRoundOver(conn);
289     break;
290
291   case MESSAGE_TYPE_PARTICIPANT_DISCONNECTED:
292     break;
293
294   case MESSAGE_TYPE_P1_SAT_DOWN:
295   case MESSAGE_TYPE_P2_SAT_DOWN:
296   case MESSAGE_TYPE_P3_SAT_DOWN:
297   case MESSAGE_TYPE_P4_SAT_DOWN:
298   case MESSAGE_TYPE_P5_SAT_DOWN:
299   case MESSAGE_TYPE_P6_SAT_DOWN:
300   case MESSAGE_TYPE_P7_SAT_DOWN:
301   case MESSAGE_TYPE_P8_SAT_DOWN:
302   case MESSAGE_TYPE_P1_STOOD_UP:
303   case MESSAGE_TYPE_P2_STOOD_UP:
304   case MESSAGE_TYPE_P3_STOOD_UP:
305   case MESSAGE_TYPE_P4_STOOD_UP:
306   case MESSAGE_TYPE_P5_STOOD_UP:
307   case MESSAGE_TYPE_P6_STOOD_UP:
308   case MESSAGE_TYPE_P7_STOOD_UP:
309   case MESSAGE_TYPE_P8_STOOD_UP:
310   case MESSAGE_TYPE_SERVER_DISCONNECT:
311   case MESSAGE_TYPE_CHATTED:
312   case MESSAGE_TYPE_TURN_ORDER:
313   case MESSAGE_TYPE_KILL_PLAYER:
314   case MESSAGE_TYPE_ROUND_START:
315     //faulty client
316     break;
317   }
318 }
319
320 void GameServer::onConnectionMade(void *conn)
321 {
322   remote_participant_connected.emit();
323 }
324
325 void GameServer::onConnectionLost(void *conn)
326 {
327   std::cerr << "connection lost" << std::endl;
328
329   Participant *part = findParticipantByConn(conn);
330   if (part)
331     {
332       std::list<guint32> players_to_stand = part->players;
333
334       depart(conn);
335       participants.remove(part);
336       for (std::list<guint32>::iterator it = players_to_stand.begin();
337            it != players_to_stand.end(); it++)
338         notifyStand(Playerlist::getInstance()->getPlayer(*it), d_nickname);
339       remote_participant_disconnected.emit();
340     }
341   delete part;
342 }
343
344 Participant *GameServer::findParticipantByConn(void *conn)
345 {
346   for (std::list<Participant *>::iterator i = participants.begin(),
347        end = participants.end(); i != end; ++i)
348     if ((*i)->conn == conn)
349       return *i;
350
351   return 0;
352 }
353
354 void GameServer::onActionDone(NetworkAction *action)
355 {
356   std::string desc = action->toString();
357   std::cerr << "Game Server got " << desc <<"\n";
358
359   if (action->getAction()->getType() == Action::END_TURN)
360     local_player_moved(action->getOwner());
361   if (action->getAction()->getType() == Action::INIT_TURN)
362     local_player_starts_move(action->getOwner());
363
364   for (std::list<Participant *>::iterator i = participants.begin(),
365        end = participants.end(); i != end; ++i) 
366     {
367       (*i)->actions.push_back(action);
368       sendActions(*i);
369       clearNetworkActionlist((*i)->actions);
370     }
371
372 }
373
374 void GameServer::onHistoryDone(NetworkHistory *history)
375 {
376   std::string desc = history->toString();
377   std::cerr << "Game Server got " << desc <<"\n";
378
379   if (history->getHistory()->getType() == History::PLAYER_VANQUISHED)
380     local_player_died(history->getOwner());
381
382   for (std::list<Participant *>::iterator i = participants.begin(),
383        end = participants.end(); i != end; ++i) 
384     {
385       (*i)->histories.push_back(history);
386       sendHistories(*i);
387       clearNetworkHistorylist((*i)->histories);
388     }
389 }
390
391 void GameServer::notifyJoin(std::string nickname)
392 {
393   remote_participant_joins.emit(nickname);
394   for (std::list<Participant *>::iterator i = participants.begin(),
395        end = participants.end(); i != end; ++i) 
396     {
397       network_server->send((*i)->conn, MESSAGE_TYPE_PARTICIPANT_CONNECTED, 
398                            nickname);
399       //network_server->send((*i)->conn, MESSAGE_TYPE_CHATTED, 
400       //nickname + " connected.");
401     }
402   gotChatMessage("[server]", nickname + " connected.");
403 }
404
405 void GameServer::notifyDepart(void *conn, std::string nickname)
406 {
407   remote_participant_departs.emit(nickname);
408   for (std::list<Participant *>::iterator i = participants.begin(),
409        end = participants.end(); i != end; ++i) 
410     {
411       if ((*i)->conn == conn)
412         continue;
413       network_server->send((*i)->conn, MESSAGE_TYPE_PARTICIPANT_DISCONNECTED, 
414                            nickname);
415       network_server->send((*i)->conn, MESSAGE_TYPE_CHATTED, 
416                            nickname + " disconnected.");
417     }
418   gotChatMessage("", nickname + " disconnected.");
419 }
420
421 void GameServer::notifySit(Player *player, std::string nickname)
422 {
423   if (!player)
424     return;
425   player_sits.emit(player, nickname);
426   MessageType type;
427   switch (player->getId())
428     {
429     case 0: type = MESSAGE_TYPE_P1_SAT_DOWN; break;
430     case 1: type = MESSAGE_TYPE_P2_SAT_DOWN; break;
431     case 2: type = MESSAGE_TYPE_P3_SAT_DOWN; break;
432     case 3: type = MESSAGE_TYPE_P4_SAT_DOWN; break;
433     case 4: type = MESSAGE_TYPE_P5_SAT_DOWN; break;
434     case 5: type = MESSAGE_TYPE_P6_SAT_DOWN; break;
435     case 6: type = MESSAGE_TYPE_P7_SAT_DOWN; break;
436     case 7: type = MESSAGE_TYPE_P8_SAT_DOWN; break;
437     default:
438             return;
439     }
440
441   for (std::list<Participant *>::iterator i = participants.begin(),
442        end = participants.end(); i != end; ++i) 
443     {
444       network_server->send((*i)->conn, type, nickname);
445       network_server->send((*i)->conn, MESSAGE_TYPE_CHATTED, 
446                            nickname + " assumes control of " + 
447                            player->getName() +".");
448     }
449   gotChatMessage("", nickname + " assumes control of " + 
450                  player->getName() +".");
451 }
452
453 void GameServer::join(void *conn, std::string nickname)
454 {
455   bool new_participant = false;
456   std::cout << "JOIN: " << conn << std::endl;
457
458   Participant *part = findParticipantByConn(conn);
459   if (!part) {
460     part = new Participant;
461     part->conn = conn;
462     part->nickname = nickname;
463     participants.push_back(part);
464     new_participant = true;
465   }
466   if (new_participant)
467     {
468       sendMap(part);
469     }
470
471   notifyJoin(nickname);
472 }
473
474 void GameServer::depart(void *conn)
475 {
476   std::cout << "DEPART: " << conn << std::endl;
477
478   Participant *part = findParticipantByConn(conn);
479
480   notifyDepart(conn, part->nickname);
481   //we don't delete the participant, it gets deleted when it disconnects.
482   //see onConnectionLost
483 }
484
485 bool GameServer::player_already_sitting(Player *p)
486 {
487   //check if the player p is already sitting down as a participant.
488   for (std::list<Participant *>::iterator i = participants.begin(),
489        end = participants.end(); i != end; ++i) 
490     {
491       for (std::list<guint32>::iterator j = (*i)->players.begin(); 
492            j != (*i)->players.end(); j++)
493         {
494           if (p->getId() == *j)
495             return true;
496         }
497     }
498   return false;
499 }
500
501 void GameServer::sit(void *conn, Player *player, std::string nickname)
502 {
503   std::cout << "SIT: " << conn << " " << player << std::endl;
504
505   if (!player || !conn)
506     return;
507   Participant *part = findParticipantByConn(conn);
508   if (!part) 
509     return;
510
511   //fixme: is another player already sitting here?
512   if (player_already_sitting(player) == true)
513     return;
514
515   add_to_player_list(part->players, player->getId());
516
517   if (player)
518     dynamic_cast<NetworkPlayer*>(player)->setConnected(true);
519
520   notifySit(player, nickname);
521 }
522
523 void GameServer::notifyStand(Player *player, std::string nickname)
524 {
525   if (!player)
526     return;
527   player_stands.emit(player, nickname);
528   MessageType type;
529   switch (player->getId())
530     {
531     case 0: type = MESSAGE_TYPE_P1_STOOD_UP; break;
532     case 1: type = MESSAGE_TYPE_P2_STOOD_UP; break;
533     case 2: type = MESSAGE_TYPE_P3_STOOD_UP; break;
534     case 3: type = MESSAGE_TYPE_P4_STOOD_UP; break;
535     case 4: type = MESSAGE_TYPE_P5_STOOD_UP; break;
536     case 5: type = MESSAGE_TYPE_P6_STOOD_UP; break;
537     case 6: type = MESSAGE_TYPE_P7_STOOD_UP; break;
538     case 7: type = MESSAGE_TYPE_P8_STOOD_UP; break;
539     default:
540             return;
541     }
542
543   for (std::list<Participant *>::iterator i = participants.begin(),
544        end = participants.end(); i != end; ++i) 
545     {
546       network_server->send((*i)->conn, type, nickname);
547       network_server->send((*i)->conn, MESSAGE_TYPE_CHATTED, 
548                            nickname + " relinquishes control of " + 
549                            player->getName() +".");
550     }
551   gotChatMessage("", nickname + " relinquishes control of " + 
552                  player->getName() +".");
553 }
554
555 bool
556 GameServer::add_to_player_list(std::list<guint32> &list, guint32 id)
557 {
558   bool found = false;
559   for (std::list<guint32>::iterator i = list.begin(); i != list.end(); i++)
560     {
561       if (*i == id)
562         {
563           found = true;
564           break;
565         }
566     }
567   if (found == false)
568     list.push_back(id);
569   return found;
570 }
571
572 bool
573 GameServer::remove_from_player_list(std::list<guint32> &list, guint32 id)
574 {
575   //remove player id from part.
576   for (std::list<guint32>::iterator i = list.begin(); 
577        i != list.end(); i++)
578     {
579       if (*i == id)
580         {
581           list.erase (i);
582           return true;
583         }
584     }
585   return false;
586 }
587
588 void GameServer::stand(void *conn, Player *player, std::string nickname)
589 {
590   std::cout << "STAND: " << conn << " " << player << std::endl;
591   if (!player || !conn)
592     return;
593
594   Participant *part = findParticipantByConn(conn);
595   if (!part) 
596     return;
597
598   //remove player id from part.
599   bool found = remove_from_player_list (part->players, player->getId());
600
601   if (!found)
602     //okay somebody's trying to boot another player.
603     return;
604
605   if (player && player->getType() == Player::NETWORKED)
606     dynamic_cast<NetworkPlayer*>(player)->setConnected(false);
607   notifyStand(player, nickname);
608 }
609
610 void GameServer::gotRemoteActions(void *conn, const std::string &payload)
611 {
612   gotActions(payload);
613   for (std::list<Participant *>::iterator i = participants.begin(),
614        end = participants.end(); i != end; ++i) 
615     if ((*i)->conn != conn)
616       network_server->send((*i)->conn, MESSAGE_TYPE_SENDING_ACTIONS, payload);
617 }
618
619 void GameServer::gotRemoteHistory(void *conn, const std::string &payload)
620 {
621   gotHistories(payload);
622   for (std::list<Participant *>::iterator i = participants.begin(),
623        end = participants.end(); i != end; ++i) 
624     if ((*i)->conn != conn)
625       network_server->send((*i)->conn, MESSAGE_TYPE_SENDING_HISTORY, payload);
626 }
627
628 void GameServer::sendMap(Participant *part)
629 {
630   Playerlist *pl = Playerlist::getInstance();
631
632   // first hack the players so the player type we serialize is right
633   std::vector<Player*> players;
634   for (Playerlist::iterator i = pl->begin(); i != pl->end(); ++i) 
635     {
636       bool connected = false;
637       players.push_back(*i);
638       if ((*i)->isComputer() == true)
639         connected = true;
640       NetworkPlayer *new_p = new NetworkPlayer(**i);
641       new_p->setConnected(connected);
642       pl->swap(*i, new_p);
643     }
644
645
646   // send the map, and save it to a file somewhere temporarily
647   std::string tmpfile = "lw.XXXX";
648   int fd = Glib::file_open_tmp(tmpfile, "lw.XXXX");
649   close(fd);
650   File::erase(tmpfile);
651   tmpfile += ".sav";
652
653   d_game_scenario->saveGame(tmpfile, "sav");
654
655   std::cerr << "sending map" << std::endl;
656   network_server->send(part->conn, MESSAGE_TYPE_SENDING_MAP, tmpfile);
657   File::erase (tmpfile);
658
659   // unhack the players
660   std::vector<Player*>::iterator j = players.begin();
661   for (Playerlist::iterator i = pl->begin(); i != pl->end(); ++i, ++j) 
662     {
663       pl->swap(*i, *j);
664       //delete *i;
665     }
666 }
667
668 void GameServer::sendActions(Participant *part)
669 {
670   std::ostringstream os;
671   XML_Helper helper(&os);
672
673   helper.begin("1");
674   helper.openTag("actions");
675
676   for (std::list<NetworkAction *>::iterator i = part->actions.begin(),
677        end = part->actions.end(); i != end; ++i)
678     (**i).save(&helper);
679
680   helper.closeTag();
681
682   std::cerr << "sending actions" << std::endl;
683   network_server->send(part->conn, MESSAGE_TYPE_SENDING_ACTIONS, os.str());
684 }
685
686 void GameServer::sendHistories(Participant *part)
687 {
688   std::ostringstream os;
689   XML_Helper helper(&os);
690
691   helper.begin("1");
692   helper.openTag("histories");
693
694   for (std::list<NetworkHistory *>::iterator i = part->histories.begin(),
695        end = part->histories.end(); i != end; ++i)
696     (**i).save(&helper);
697
698   helper.closeTag();
699
700   std::cerr << "sending histories" << std::endl;
701   network_server->send(part->conn, MESSAGE_TYPE_SENDING_HISTORY, os.str());
702 }
703
704 bool GameServer::dumpActionsAndHistories(XML_Helper *helper, Player *player)
705 {
706   Participant *part = NULL;
707   for (std::list<Participant *>::iterator i = participants.begin(),
708        end = participants.end(); i != end; ++i)
709     {
710       bool found = false;
711       for (std::list<guint32>::iterator it = (*i)->players.begin();
712            it != (*i)->players.end(); it++)
713         {
714           if (*it == player->getId())
715             {
716               found = true;
717               break;
718             }
719         }
720
721       if (found)
722         {
723           part = *i;
724           break;
725         }
726     }
727   if (part == NULL)
728     return false;
729   for (std::list<NetworkHistory *>::iterator i = part->histories.begin(),
730        end = part->histories.end(); i != end; ++i)
731     (**i).save(helper);
732   for (std::list<NetworkAction *>::iterator i = part->actions.begin(),
733        end = part->actions.end(); i != end; ++i)
734     (**i).save(helper);
735   return true;
736 }
737
738 bool GameServer::dumpActionsAndHistories(XML_Helper *helper)
739 {
740   Player *player = Playerlist::getActiveplayer();
741   return dumpActionsAndHistories(helper, player);
742 }
743
744 void GameServer::sit_down (Player *player)
745 {
746   if (!player)
747     return;
748   if (player->getType() == Player::NETWORKED)
749     {
750       //alright, we want to sit down as this player
751       //convert the network player to a human player
752       dynamic_cast<NetworkPlayer*>(player)->setConnected(true);
753       RealPlayer *new_p = new RealPlayer (*player);
754       Playerlist::getInstance()->swap(player, new_p);
755       stopListeningForLocalEvents(player);
756       listenForLocalEvents(new_p);
757       delete player;
758       add_to_player_list (players_seated_locally, new_p->getId());
759       notifySit(new_p, d_nickname);
760     }
761   else if (player->getType() == Player::HUMAN)
762     {
763       // do nothing
764     }
765   else // an ai player
766     {
767       stopListeningForLocalEvents(player);
768       listenForLocalEvents(player);
769       add_to_player_list (players_seated_locally, player->getId());
770       notifySit(player, d_nickname);
771     }
772 }
773
774 void GameServer::stand_up (Player *player)
775 {
776   if (!player)
777     return;
778   if (player->getType() == Player::HUMAN)
779     {
780       //alright, we want to stand up as this player
781       //convert the player from a human player back to a network player
782
783       NetworkPlayer *new_p = new NetworkPlayer(*player);
784       Playerlist::getInstance()->swap(player, new_p);
785       stopListeningForLocalEvents(player);
786       delete player;
787       new_p->setConnected(false);
788       notifyStand(new_p, d_nickname);
789       remove_from_player_list (players_seated_locally, new_p->getId());
790     }
791   else if (player->getType() == Player::NETWORKED)
792     {
793       // do nothing
794     }
795   else // an ai player
796     {
797       stopListeningForLocalEvents(player);
798       remove_from_player_list (players_seated_locally, player->getId());
799       notifyStand(player, d_nickname);
800     }
801 }
802
803 void GameServer::chat (std::string message)
804 {
805   notifyChat(d_nickname + ":" + message);
806 }
807
808 void GameServer::notifyChat(std::string message)
809 {
810   gotChatMessage(d_nickname, message);
811   for (std::list<Participant *>::iterator i = participants.begin(),
812        end = participants.end(); i != end; ++i) 
813     network_server->send((*i)->conn, MESSAGE_TYPE_CHATTED, message);
814 }
815
816 void GameServer::sendSeats(void *conn)
817 {
818   Participant *part = findParticipantByConn(conn);
819   if (!part)
820     return;
821   //send seatedness info for remote participants
822
823   for (std::list<Participant *>::iterator i = participants.begin(),
824        end = participants.end(); i != end; ++i) 
825     {
826       if ((*i)->conn == part->conn)
827         continue;
828
829       for (std::list<guint32>::iterator j = (*i)->players.begin(); 
830            j != (*i)->players.end(); j++)
831         {
832           Player *player = Playerlist::getInstance()->getPlayer(*j);
833           MessageType type;
834           switch (player->getId())
835             {
836             case 0: type = MESSAGE_TYPE_P1_SAT_DOWN; break;
837             case 1: type = MESSAGE_TYPE_P2_SAT_DOWN; break;
838             case 2: type = MESSAGE_TYPE_P3_SAT_DOWN; break;
839             case 3: type = MESSAGE_TYPE_P4_SAT_DOWN; break;
840             case 4: type = MESSAGE_TYPE_P5_SAT_DOWN; break;
841             case 5: type = MESSAGE_TYPE_P6_SAT_DOWN; break;
842             case 6: type = MESSAGE_TYPE_P7_SAT_DOWN; break;
843             case 7: type = MESSAGE_TYPE_P8_SAT_DOWN; break;
844             default:
845                     return;
846             }
847           network_server->send(part->conn, type, (*i)->nickname);
848         }
849     }
850   //send out seatedness info for local server
851   for (std::list<guint32>::iterator j = players_seated_locally.begin(); 
852        j != players_seated_locally.end(); j++)
853     {
854       Player *player = Playerlist::getInstance()->getPlayer(*j);
855       MessageType type;
856       switch (player->getId())
857         {
858         case 0: type = MESSAGE_TYPE_P1_SAT_DOWN; break;
859         case 1: type = MESSAGE_TYPE_P2_SAT_DOWN; break;
860         case 2: type = MESSAGE_TYPE_P3_SAT_DOWN; break;
861         case 3: type = MESSAGE_TYPE_P4_SAT_DOWN; break;
862         case 4: type = MESSAGE_TYPE_P5_SAT_DOWN; break;
863         case 5: type = MESSAGE_TYPE_P6_SAT_DOWN; break;
864         case 6: type = MESSAGE_TYPE_P7_SAT_DOWN; break;
865         case 7: type = MESSAGE_TYPE_P8_SAT_DOWN; break;
866         default:
867                 return;
868         }
869       network_server->send(part->conn, type, d_nickname);
870     }
871 }
872
873 void GameServer::sendChatRoster(void *conn)
874 {
875   Participant *part = findParticipantByConn(conn);
876   if (!part)
877     return;
878   for (std::list<Participant *>::iterator i = participants.begin(),
879        end = participants.end(); i != end; ++i) 
880     {
881       if ((*i)->conn == part->conn)
882         continue;
883       network_server->send(part->conn, MESSAGE_TYPE_PARTICIPANT_CONNECTED, 
884                            (*i)->nickname);
885     }
886   network_server->send(part->conn, MESSAGE_TYPE_PARTICIPANT_CONNECTED, 
887                        d_nickname);
888 }
889
890 void GameServer::sendKillPlayer(Player *p)
891 {
892   std::stringstream player;
893   player << p->getId();
894   for (std::list<Participant *>::iterator i = participants.begin(),
895        end = participants.end(); i != end; ++i) 
896     network_server->send((*i)->conn, MESSAGE_TYPE_KILL_PLAYER, player.str());
897
898   remote_player_died.emit(p);
899 }
900
901 void GameServer::sendTurnOrder()
902 {
903   std::stringstream players;
904   Playerlist *pl = Playerlist::getInstance();
905   for (Playerlist::iterator it = pl->begin(); it != pl->end(); it++)
906     players << (*it)->getId() << " ";
907   for (std::list<Participant *>::iterator i = participants.begin(),
908        end = participants.end(); i != end; ++i) 
909     network_server->send((*i)->conn, MESSAGE_TYPE_TURN_ORDER, players.str());
910   playerlist_reorder_received.emit();
911 }
912
913 // End of file