1 //  Copyright (C) 2008, 2009, 2011, 2014, 2015, 2017, 2020 Ben Asselstine
2 //
3 //  This program is free software; you can redistribute it and/or modify
4 //  it under the terms of the GNU General Public License as published by
5 //  the Free Software Foundation; either version 3 of the License, or
6 //  (at your option) any later version.
7 //
8 //  This program is distributed in the hope that it will be useful,
9 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
10 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11 //  GNU Library General Public License for more details.
12 //
13 //  You should have received a copy of the GNU General Public License
14 //  along with this program; if not, write to the Free Software
15 //  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
16 //  02110-1301, USA.
17 
18 #include <config.h>
19 
20 #include <gtkmm.h>
21 #include <map>
22 #include <sigc++/functors/mem_fun.h>
23 
24 #include "game-lobby-dialog.h"
25 
26 #include "ucompose.hpp"
27 #include "defs.h"
28 #include "File.h"
29 #include "citylist.h"
30 #include "playerlist.h"
31 #include "game-options-dialog.h"
32 #include "ImageCache.h"
33 #include "network_player.h"
34 #include "game-client.h"
35 #include "game-server.h"
36 #include "shieldsetlist.h"
37 #include "NextTurnNetworked.h"
38 #include "recently-played-game-list.h"
39 #include "game-parameters.h"
40 #include "font-size.h"
41 
42 #define method(x) sigc::mem_fun(*this, &GameLobbyDialog::x)
43 namespace
44 {
player_type_to_string(guint32 type)45     Glib::ustring player_type_to_string(guint32 type)
46     {
47       Glib::ustring s =
48         GameParameters::player_param_to_string(GameParameters::player_type_to_player_param(type));
49       if (s == NETWORKED_PLAYER_TYPE)
50         return "";
51       else
52         return s;
53     }
54 }
55 
update_city_map()56 void GameLobbyDialog::update_city_map()
57 {
58   if (d_game_scenario->s_hidden_map == false)
59     {
60       if (citymap)
61 	delete citymap;
62       citymap = new CityMap();
63       citymap->map_changed.connect (method(on_map_changed));
64       if (d_game_scenario->getRound() > 1)
65 	{
66 	  citymap->resize();
67 	  citymap->draw();
68 	}
69     }
70   else
71     {
72       Vector<int> dim = OverviewMap::calculate_smallmap_size();
73       Glib::RefPtr<Gdk::Pixbuf> hidden_map =
74         Gdk::Pixbuf::create(Gdk::COLORSPACE_RGB, true, 8, dim.x, dim.y);
75       hidden_map->fill(0x00000000);
76       map_image->property_pixbuf() = hidden_map;
77     }
78 }
79 
initDialog(GameScenario * gamescenario,NextTurnNetworked * next_turn,GameStation * game_station)80 void GameLobbyDialog::initDialog(GameScenario *gamescenario,
81 				 NextTurnNetworked *next_turn,
82 				 GameStation *game_station)
83 {
84   bool broken = false;
85   Shieldsetlist::getInstance()->instantiateImages(broken);
86   d_game_scenario = gamescenario;
87   d_game_station = game_station;
88   d_next_turn = next_turn;
89   d_play_message_received = false;
90   citymap = NULL;
91 
92     xml->get_widget("player_treeview", player_treeview);
93     player_treeview->get_selection()->signal_changed().connect
94           (method(on_player_selected));
95     xml->get_widget("people_treeview", people_treeview);
96     people_treeview->property_headers_visible() = true;
97     xml->get_widget("play_button", play_button);
98     play_button->signal_clicked().connect (method(on_play_clicked));
99     xml->get_widget("cancel_button", cancel_button);
100     cancel_button->signal_clicked().connect (method(on_cancel_clicked));
101     xml->get_widget("map_image", map_image);
102     xml->get_widget("turn_label", turn_label);
103     xml->get_widget("scenario_name_label", scenario_name_label);
104     xml->get_widget("cities_label", cities_label);
105     xml->get_widget("chat_scrolledwindow", chat_scrolledwindow);
106     chat_scrolledwindow->property_hscrollbar_policy() = Gtk::POLICY_NEVER;
107     xml->get_widget("chat_textview", chat_textview);
108     xml->get_widget("chat_entry", chat_entry);
109 
110     chat_entry->signal_key_release_event().connect_notify (method(on_chat_key_pressed));
111 
112     update_city_map();
113 
114     Gtk::EventBox *map_eventbox;
115     xml->get_widget("map_eventbox", map_eventbox);
116     xml->get_widget("show_options_button", show_options_button);
117     show_options_button->signal_clicked().connect (method(on_show_options_clicked));
118 
119     connections.push_back(game_station->remote_player_moved.connect
120       (sigc::hide(method(on_remote_player_ends_turn))));
121     connections.push_back(game_station->remote_player_starts_move.connect
122       (sigc::hide(method(on_remote_player_starts_turn))));
123     connections.push_back(game_station->local_player_moved.connect
124       (sigc::hide(method(on_local_player_ends_turn))));
125     connections.push_back(game_station->local_player_starts_move.connect
126       (sigc::hide(method(on_local_player_starts_turn))));
127     connections.push_back(game_station->remote_participant_joins.connect
128       (method(on_remote_participant_joins)));
129     connections.push_back(game_station->remote_participant_departs.connect
130       (method(on_remote_participant_departs)));
131     connections.push_back(game_station->player_sits.connect (method(on_player_sits)));
132     connections.push_back(game_station->player_stands.connect (sigc::hide(method(on_player_stands))));
133     connections.push_back(game_station->player_changes_name.connect (method(on_player_changes_name)));
134     connections.push_back(game_station->player_changes_type.connect (method(on_player_changes_type)));
135     connections.push_back(game_station->remote_player_named.connect (method(on_remote_player_changes_name)));
136     connections.push_back(game_station->chat_message_received.connect (sigc::hide<0>(method(on_chatted))));
137     connections.push_back(game_station->playerlist_reorder_received.connect (method(on_reorder_playerlist)));
138     connections.push_back(game_station->round_begins.connect (method(on_reorder_playerlist)));
139     connections.push_back(game_station->remote_player_died.connect (method(on_player_died)));
140     connections.push_back(game_station->local_player_died.connect (method(on_player_died)));
141     connections.push_back(game_station->nickname_changed.connect (method(on_nickname_changed)));
142     connections.push_back(game_station->game_may_begin.connect (method(on_play_message_received)));
143     connections.push_back(game_station->player_gets_turned_off.connect (method(on_player_turned_off)));
144 
145     update_player_details();
146     update_buttons();
147 
148     people_list = Gtk::ListStore::create(people_columns);
149     // setup the player settings
150     people_treeview->set_model(people_list);
151 }
152 
update_buttons()153 void GameLobbyDialog::update_buttons()
154 {
155   if (d_play_button_clicked == true)
156     return;
157   //if any types aren't networked, we can play.
158   //if all types are networked then we can't.
159   if (d_has_ops)
160     {
161       Gtk::TreeModel::Children kids = player_list->children();
162       for (Gtk::TreeModel::Children::iterator i = kids.begin();
163            i != kids.end(); i++)
164         {
165           Gtk::TreeModel::Row row = *i;
166           if (row[player_columns.type] != "")
167             {
168               play_button->set_sensitive(true);
169               return;
170             }
171         }
172       play_button->set_sensitive(false);
173     }
174   else
175     {
176       bool found = false;
177       //do we have a horse in the race?
178       Gtk::TreeModel::Children kids = player_list->children();
179       for (Gtk::TreeModel::Children::iterator i = kids.begin();
180            i != kids.end(); i++)
181         {
182           Gtk::TreeModel::Row row = *i;
183           if (row[player_columns.person] == d_game_station->getNickname())
184             {
185               found = true;
186               break;
187             }
188         }
189       if (found)
190         play_button->set_sensitive(d_play_message_received);
191       else
192         play_button->set_sensitive(false);
193     }
194 }
195 
196 void
update_player_details()197 GameLobbyDialog::update_player_details()
198 {
199   if (player_list)
200     {
201       player_list->clear();
202       player_list.reset();
203     }
204   player_list = Gtk::ListStore::create(player_columns);
205   player_list->set_sort_column (player_columns.order, Gtk::SORT_ASCENDING);
206 
207   // setup the player settings
208   player_treeview->set_model(player_list);
209 
210   player_treeview->remove_all_columns();
211 
212 
213   //the sitting toggle
214   sitting_renderer.set_radio (false);
215   sitting_renderer.signal_toggled().connect(method(on_sitting_toggled));
216   sitting_column.set_cell_data_func(sitting_renderer, method(cell_data_sitting));
217   player_treeview->append_column(sitting_column);
218 
219   player_treeview->append_column(_("Player"), player_columns.person);
220 
221   //the shield
222   player_treeview->append_column("", player_columns.shield);
223 
224   // the name column
225   player_name_list = Gtk::ListStore::create(player_name_columns);
226 
227   name_renderer.property_editable() = true;
228 
229   name_renderer.signal_edited().connect(method(on_name_edited));
230   name_column.set_cell_data_func(name_renderer, method(cell_data_name));
231   player_treeview->append_column(name_column);
232 
233 
234   // the type column
235   player_type_list = Gtk::ListStore::create(player_type_columns);
236   Gtk::TreeModel::iterator i;
237   i = player_type_list->append();
238   (*i)[player_type_columns.type] = HUMAN_PLAYER_TYPE;
239   i = player_type_list->append();
240   (*i)[player_type_columns.type] = EASY_PLAYER_TYPE;
241   i = player_type_list->append();
242   (*i)[player_type_columns.type] = HARD_PLAYER_TYPE;
243   i = player_type_list->append();
244   (*i)[player_type_columns.type] = NO_PLAYER_TYPE;
245 
246   type_renderer.property_model() = player_type_list;
247   type_renderer.property_text_column() = 0;
248   type_renderer.property_has_entry() = false;
249   type_renderer.property_editable() = d_has_ops;
250 
251   type_renderer.signal_edited().connect(method(on_type_edited));
252   type_column.set_cell_data_func(type_renderer, method(cell_data_type));
253   player_treeview->append_column(type_column);
254 
255   //if it's this player's turn
256   player_treeview->append_column(_("Turn"), player_columns.turn);
257 
258   Playerlist *pl = Playerlist::getInstance();
259 
260   guint32 count = 0;
261   for (Playerlist::iterator k = pl->begin(), end = pl->end(); k != end; ++k)
262     {
263       Player *player = *k;
264       if (player == pl->getNeutral())
265 	continue;
266       if (player->isDead())
267 	continue;
268       add_player(count, player_type_to_string(player->getType()), player->getName(),
269 		 player);
270       count++;
271     }
272   update_turn_indicator();
273 }
274 
on_sitting_toggled(const Glib::ustring & path)275 void GameLobbyDialog::on_sitting_toggled (const Glib::ustring &path)
276 {
277   Gtk::TreeModel::iterator iter = player_treeview->get_model()->get_iter(path);
278   //if (new_text == SITTING && (*iter)[player_columns.sitting] == true)
279     //return;
280   //if (new_text == NOT_SITTING && (*iter)[player_columns.sitting] == false)
281     //return;
282   Playerlist *pl = Playerlist::getInstance();
283   Player *player;
284   //maybe we can't make other ppl stand up
285   if ((*iter)[player_columns.sitting] &&
286       (*iter)[player_columns.person] != d_game_station->getNickname() &&
287       d_has_ops == false)
288     return;
289 
290   player = pl->getPlayer((*iter)[player_columns.player_id]);
291   d_player_id_of_sit_or_stand_request = player->getId();
292 
293   if (!(*iter)[player_columns.sitting])
294     player_sat_down.emit(player);
295   else
296     player_stood_up.emit(player);
297 }
298 
GameLobbyDialog(Gtk::Window & parent,GameScenario * game_scenario,NextTurnNetworked * next_turn,GameStation * game_station,bool has_ops)299 GameLobbyDialog::GameLobbyDialog(Gtk::Window &parent,
300                                  GameScenario *game_scenario,
301 				 NextTurnNetworked *next_turn,
302 				 GameStation *game_station,
303 				 bool has_ops)
304  : LwDialog(parent, "game-lobby-dialog.ui"),
305     name_column(_("Name"), name_renderer),
306     type_column(_("Type"), type_renderer),
307     sitting_column(_("Sit Down"), sitting_renderer)
308 {
309   d_has_ops = has_ops;
310   d_play_button_clicked = false;
311   d_play_message_received = false;
312   initDialog(game_scenario, next_turn, game_station);
313   update_scenario_details();
314   d_player_id_of_sit_or_stand_request = MAX_PLAYERS + 1;
315   d_player_id_of_name_change_request = MAX_PLAYERS + 1;
316   d_player_id_of_type_change_request = MAX_PLAYERS + 1;
317   name_column.set_resizable();
318   name_column.set_expand();
319   name_column.set_min_width(115);
320   name_renderer.property_ellipsize() = Pango::ELLIPSIZE_END;
321   player_treeview->get_column(2)->set_min_width(75);
322   player_treeview->get_column(2)->set_resizable();
323 }
324 
~GameLobbyDialog()325 GameLobbyDialog::~GameLobbyDialog()
326 {
327   disconnect_signals();
328   if (citymap)
329     delete citymap;
330   clean_up_players();
331 }
332 
update_scenario_details()333 void GameLobbyDialog::update_scenario_details()
334 {
335 
336   Glib::ustring s;
337   s = String::ucompose("%1", d_game_scenario->getRound());
338   turn_label->set_text(s);
339   scenario_name_label->set_text(d_game_scenario->getName());
340   s = String::ucompose("%1", Citylist::getInstance()->size());
341   cities_label->set_text(s);
342 
343   update_city_map();
344 }
345 
on_map_changed(Cairo::RefPtr<Cairo::Surface> map)346 void GameLobbyDialog::on_map_changed(Cairo::RefPtr<Cairo::Surface> map)
347 {
348   Glib::RefPtr<Gdk::Pixbuf> pixbuf =
349     Gdk::Pixbuf::create(map, 0, 0, citymap->get_width(), citymap->get_height());
350   map_image->property_pixbuf() = pixbuf;
351 }
352 
on_show_options_clicked()353 void GameLobbyDialog::on_show_options_clicked()
354 {
355   GameOptionsDialog gd(*dialog, true);
356   gd.run();
357 }
358 
cell_data_type(Gtk::CellRenderer * renderer,const Gtk::TreeIter & i)359 void GameLobbyDialog::cell_data_type(Gtk::CellRenderer *renderer,
360 				     const Gtk::TreeIter& i)
361 {
362   dynamic_cast<Gtk::CellRendererText*>(renderer)->property_text()
363     = (*i)[player_columns.type];
364 }
365 
on_type_edited(const Glib::ustring & path,const Glib::ustring & new_text)366 void GameLobbyDialog::on_type_edited(const Glib::ustring &path,
367 				     const Glib::ustring &new_text)
368 {
369   Gtk::TreeModel::iterator iter = player_treeview->get_model()->get_iter(path);
370 
371   if ((*iter)[player_columns.sitting] == false)
372     return;
373   if ((*iter)[player_columns.person] != d_game_station->getNickname())
374     return;
375   type_renderer.set_sensitive(false);
376   Playerlist *pl = Playerlist::getInstance();
377   Player *player = pl->getPlayer((*iter)[player_columns.player_id]);
378   d_player_id_of_type_change_request = player->getId();
379 
380   int type = GameParameters::player_param_string_to_player_param(new_text);
381   player_changed_type.emit (player, type);
382 }
383 
cell_data_name(Gtk::CellRenderer * renderer,const Gtk::TreeIter & i)384 void GameLobbyDialog::cell_data_name(Gtk::CellRenderer *renderer,
385 				     const Gtk::TreeIter& i)
386 {
387   Playerlist *pl = Playerlist::getInstance();
388   Player *player;
389   player = pl->getPlayer((*i)[player_columns.player_id]);
390 
391   dynamic_cast<Gtk::CellRendererText*>(renderer)->property_text()
392     = player->getName();
393 }
394 
on_name_edited(const Glib::ustring & path,const Glib::ustring & new_text)395 void GameLobbyDialog::on_name_edited(const Glib::ustring &path,
396 				     const Glib::ustring &new_text)
397 {
398   Playerlist *pl = Playerlist::getInstance();
399   Player *player;
400   Gtk::TreeModel::iterator iter = player_treeview->get_model()->get_iter(path);
401   if (d_has_ops == false)
402     {
403       if ((*iter)[player_columns.sitting] == false)
404         return;
405       if ((*iter)[player_columns.person] != d_game_station->getNickname())
406         return;
407     }
408   Glib::ustring new_name = String::utrim(new_text);
409   if (new_name.empty() == true)
410     return;
411 
412   name_renderer.set_sensitive(false);
413   player = pl->getPlayer((*iter)[player_columns.player_id]);
414   d_player_id_of_name_change_request = player->getId();
415 
416   //here's where we send the message saying that the name has changed.
417   player_changed_name.emit(player, new_name);
418 }
419 
cell_data_sitting(Gtk::CellRenderer * renderer,const Gtk::TreeIter & i)420 void GameLobbyDialog::cell_data_sitting(Gtk::CellRenderer *renderer,
421 					const Gtk::TreeIter& i)
422 {
423   dynamic_cast<Gtk::CellRendererToggle*>(renderer)->property_active () =
424     (*i)[player_columns.sitting];
425 }
426 
add_player(guint32 order,const Glib::ustring & type,const Glib::ustring & name,Player * player)427 void GameLobbyDialog::add_player(guint32 order, const Glib::ustring &type,
428 				 const Glib::ustring &name, Player *player)
429 {
430   ImageCache *gc = ImageCache::getInstance();
431   Gtk::TreeIter i = player_list->append();
432   (*i)[player_columns.order] = order;
433   (*i)[player_columns.shield] =
434     gc->getShieldPic(1, player, false,
435                      FontSize::getInstance ()->get_height ())->to_pixbuf();
436   (*i)[player_columns.type] = type;
437   (*i)[player_columns.name] = name;
438   (*i)[player_columns.player_id] = player->getId();
439   if (player->getType() == Player::NETWORKED)
440     {
441       //do we have the particpant?
442       if (dynamic_cast<NetworkPlayer*>(player)->isConnected() == true)
443 	{
444 	  (*i)[player_columns.sitting] = true;
445 	}
446       else
447 	{
448 	  //otherwise, the player is not here to play.
449 	  (*i)[player_columns.sitting] = false;
450 	}
451     }
452   else
453     {
454       (*i)[player_columns.sitting] = true;
455     }
456 
457 }
458 
on_player_selected()459 void GameLobbyDialog::on_player_selected()
460 {
461 
462 }
463 
on_remote_participant_joins(Glib::ustring nickname)464 void GameLobbyDialog::on_remote_participant_joins(Glib::ustring nickname)
465 {
466   Gtk::TreeIter j = people_list->append();
467   (*j)[people_columns.nickname] = nickname;
468 }
469 
on_remote_participant_departs(Glib::ustring nickname)470 void GameLobbyDialog::on_remote_participant_departs(Glib::ustring nickname)
471 {
472   //iterate through and remove the nickname
473   Gtk::TreeNodeChildren rows = people_list->children();
474   for(Gtk::TreeIter row = rows.begin(); row != rows.end(); ++row)
475     {
476       Gtk::TreeModel::Row my_row = *row;
477       if (my_row[people_columns.nickname] == nickname)
478 	{
479 	  people_list->erase(row);
480 	  return;
481 	}
482     }
483 }
484 
on_player_changes_name(Player * p,Glib::ustring name)485 void GameLobbyDialog::on_player_changes_name(Player *p, Glib::ustring name)
486 {
487   if (!p)
488     return;
489   if (p->getId() == d_player_id_of_name_change_request)
490     {
491       name_renderer.set_sensitive(true);
492       d_player_id_of_name_change_request = MAX_PLAYERS + 1;
493     }
494   //look for the row that has the right player id, and change the name
495   Gtk::TreeModel::Children kids = player_list->children();
496   for (Gtk::TreeModel::Children::iterator i = kids.begin();
497        i != kids.end(); i++)
498     {
499       Gtk::TreeModel::Row row = *i;
500       if (row[player_columns.player_id] == p->getId())
501         {
502           p->setName(name);
503           row[player_columns.name] = name;
504         }
505     }
506 }
507 
on_player_changes_type(Player * p,int type)508 void GameLobbyDialog::on_player_changes_type(Player *p, int type)
509 {
510   if (!p)
511     return;
512   if (p->getId() == d_player_id_of_type_change_request)
513     {
514       type_renderer.set_sensitive(true);
515       d_player_id_of_type_change_request = MAX_PLAYERS + 1;
516     }
517   Gtk::TreeModel::Children kids = player_list->children();
518   //look for the row that has the right player id.
519   for (Gtk::TreeModel::Children::iterator i = kids.begin();
520        i != kids.end(); i++)
521     {
522       Gtk::TreeModel::Row row = *i;
523       if (row[player_columns.player_id] == p->getId())
524 	{
525           Glib::ustring s = GameParameters::player_param_to_string(type);
526           if (s == NETWORKED_PLAYER_TYPE)
527             row[player_columns.type] = "";
528           else
529             row[player_columns.type] = s;
530 	  update_buttons();
531 	  return;
532 	}
533     }
534 }
535 
on_player_sits(Player * p,Glib::ustring nickname)536 void GameLobbyDialog::on_player_sits(Player *p, Glib::ustring nickname)
537 {
538   if (!p)
539     return;
540   if (p->getId() == d_player_id_of_sit_or_stand_request)
541     {
542       sitting_renderer.set_sensitive(true);
543       d_player_id_of_sit_or_stand_request = MAX_PLAYERS + 1;
544     }
545   Gtk::TreeModel::Children kids = player_list->children();
546   //look for the row that has the right player id.
547   for (Gtk::TreeModel::Children::iterator i = kids.begin();
548        i != kids.end(); i++)
549     {
550       Gtk::TreeModel::Row row = *i;
551       if (row[player_columns.player_id] == p->getId())
552 	{
553 	  row[player_columns.sitting] = true;
554 	  row[player_columns.type] = player_type_to_string(p->getType());
555 	  row[player_columns.person] = nickname;
556 	  update_buttons();
557 	  return;
558 	}
559     }
560 }
561 
on_player_stands(Player * p)562 void GameLobbyDialog::on_player_stands(Player *p)
563 {
564   if (!p)
565     return;
566   Gtk::TreeModel::Children kids = player_list->children();
567   for (Gtk::TreeModel::Children::iterator i = kids.begin();
568        i != kids.end(); i++)
569     {
570       Gtk::TreeModel::Row row = *i;
571       if (row[player_columns.player_id] == p->getId())
572 	{
573 	  row[player_columns.sitting] = false;
574 	  row[player_columns.person] = "";
575 	  row[player_columns.type] = player_type_to_string(p->getType());
576 	  update_buttons();
577 	  return;
578 	}
579     }
580 }
581 
on_local_player_ends_turn()582 void GameLobbyDialog::on_local_player_ends_turn()
583 {
584   if ( dialog->get_visible())
585     {
586       //fixme, why are we getting all these updates at the end?
587       //they seem to pile up, one for every turn
588       update_turn_indicator();
589       update_scenario_details();
590     }
591 }
592 
update_turn_indicator()593 void GameLobbyDialog::update_turn_indicator()
594 {
595   ImageCache *gc = ImageCache::getInstance();
596   Gtk::TreeModel::Children kids = player_list->children();
597   for (Gtk::TreeModel::Children::iterator i = kids.begin();
598        i != kids.end(); i++)
599     {
600       Gtk::TreeModel::Row row = *i;
601       Player *active = Playerlist::getActiveplayer();
602       if (active)
603         {
604           if (row[player_columns.player_id] == active->getId())
605             (*i)[player_columns.turn] =
606               gc->getCursorPic
607               (ImageCache::SWORD,
608                FontSize::getInstance ()->get_height ())->to_pixbuf();
609           else
610             {
611               Glib::RefPtr<Gdk::Pixbuf> empty_pic
612                 = Gdk::Pixbuf::create(Gdk::COLORSPACE_RGB, true, 8, 4, 4);
613               empty_pic->fill(0x00000000);
614               (*i)[player_columns.turn] = empty_pic;
615             }
616         }
617     }
618 }
619 
on_remote_player_starts_turn()620 void GameLobbyDialog::on_remote_player_starts_turn()
621 {
622   update_turn_indicator();
623   update_scenario_details();
624 }
625 
on_local_player_starts_turn()626 void GameLobbyDialog::on_local_player_starts_turn()
627 {
628   update_turn_indicator();
629   update_scenario_details();
630 }
631 
on_remote_player_ends_turn()632 void GameLobbyDialog::on_remote_player_ends_turn()
633 {
634   if (GameServer::getInstance()->isListening() == false)
635     {
636       RecentlyPlayedGameList *rpgl = RecentlyPlayedGameList::getInstance();
637       rpgl->updateEntry(d_game_scenario);
638       rpgl->save();
639     }
640   update_turn_indicator();
641   update_scenario_details();
642 }
643 
on_remote_player_changes_name(Player * p)644 void GameLobbyDialog::on_remote_player_changes_name(Player *p)
645 {
646   Gtk::TreeModel::Children kids = player_list->children();
647   for (Gtk::TreeModel::Children::iterator i = kids.begin();
648        i != kids.end(); i++)
649     {
650       Gtk::TreeModel::Row row = *i;
651       if (row[player_columns.player_id] == p->getId())
652 	{
653 	  row[player_columns.name] = p->getName();
654 	  return;
655 	}
656     }
657 }
658 
get_selected_player(Glib::ustring & nick,bool & sitting)659 Player* GameLobbyDialog::get_selected_player(Glib::ustring &nick, bool &sitting)
660 {
661   Glib::RefPtr<Gtk::TreeSelection> selection = player_treeview->get_selection();
662   Gtk::TreeModel::iterator iterrow = selection->get_selected();
663   if (iterrow)
664     {
665       Gtk::TreeModel::Row row = *iterrow;
666       nick = row[player_columns.name];
667       sitting = row[player_columns.sitting];
668       return
669         Playerlist::getInstance()->getPlayer(row[player_columns.player_id]);
670     }
671   else
672     return NULL;
673 }
674 
on_play_clicked()675 void GameLobbyDialog::on_play_clicked()
676 {
677   if (d_play_button_clicked == false)
678     {
679       //we only get here on the first time play is clicked
680       //otherwise it just shows the form (Driver::start_network_game_requested)
681       hide();
682       if (d_has_ops)
683         {
684           lock_down();
685           game_may_begin.emit();
686         }
687       play_button->set_sensitive(false);
688       play_button->property_visible() = false;
689       start_network_game.emit(d_game_scenario, d_next_turn);
690       d_play_button_clicked = true;
691     }
692 }
693 
on_cancel_clicked()694 void GameLobbyDialog::on_cancel_clicked()
695 {
696   hide();
697 }
698 
on_chat_key_pressed(GdkEventKey * event)699 void GameLobbyDialog::on_chat_key_pressed(GdkEventKey *event)
700 {
701   if (event->keyval == 65293) //enter
702     {
703       if (chat_entry->get_text().length() > 0)
704 	message_sent.emit(chat_entry->get_text());
705       chat_entry->set_text("");
706     }
707   return;
708 }
709 
on_chatted(Glib::ustring message)710 void GameLobbyDialog::on_chatted(Glib::ustring message)
711 {
712   Glib::ustring new_text;
713   new_text = chat_textview->get_buffer()->get_text() + "\n" + message;
714   chat_textview->get_buffer()->set_text(new_text);
715   while (g_main_context_iteration(NULL, FALSE)); //doEvents
716   chat_scrolledwindow->get_vadjustment()->set_value(chat_scrolledwindow->get_vadjustment()->get_upper());
717 }
718 
on_player_died(Player * p)719 void GameLobbyDialog::on_player_died(Player *p)
720 {
721   if (!p)
722     return;
723 
724   Gtk::TreeNodeChildren rows = player_list->children();
725   for(Gtk::TreeIter row = rows.begin(); row != rows.end(); ++row)
726     {
727       Gtk::TreeModel::Row my_row = *row;
728       if (my_row[player_columns.player_id] == p->getId())
729 	{
730 	  player_list->erase(row);
731 	  return;
732 	}
733     }
734 }
735 
on_reorder_playerlist()736 void GameLobbyDialog::on_reorder_playerlist()
737 {
738   sort_player_list_by_turn_order();
739 }
740 
run()741 bool GameLobbyDialog::run()
742 {
743   Playerlist *pl = Playerlist::getInstance();
744 
745   if (d_game_scenario->s_hidden_map == false)
746     {
747       citymap->resize();
748       citymap->draw();
749     }
750 
751   people_treeview->remove_all_columns();
752   people_treeview->append_column(_("People"), people_columns.nickname);
753   if (GameServer::getInstance()->isListening() == false)
754     {
755       GameClient::getInstance()->request_seat_manifest();
756       Gtk::TreeIter j = people_list->append();
757       (*j)[people_columns.nickname] = "[" + GameClient::getInstance()->getNickname() + "]";
758     }
759   else
760     {
761       Gtk::TreeIter j = people_list->append();
762       (*j)[people_columns.nickname] = "[" + GameServer::getInstance()->getNickname() + "]";
763       //automatically seat the ai players
764       for (Playerlist::iterator i = pl->begin(), end = pl->end(); i != end; ++i)
765 	{
766 	  Player *player = *i;
767 	  if (player == pl->getNeutral())
768 	    continue;
769 	  if (player->isDead())
770 	    continue;
771 	  if (player->getType() == Player::HUMAN)
772 	    continue;
773 	  if (player->getType() == Player::NETWORKED)
774 	    continue;
775 
776 	  player_sat_down.emit(player);
777 	}
778     }
779   int response = dialog->run();
780   if (response == Gtk::RESPONSE_ACCEPT)
781     return true;
782   else
783     return false;
784 }
785 
on_nickname_changed(Glib::ustring old_name,Glib::ustring new_name)786 void GameLobbyDialog::on_nickname_changed(Glib::ustring old_name, Glib::ustring new_name)
787 {
788   d_game_station->setNickname(new_name);
789   //iterate through and find the nickname
790   Gtk::TreeNodeChildren rows = people_list->children();
791   for(Gtk::TreeIter row = rows.begin(); row != rows.end(); ++row)
792     {
793       Gtk::TreeModel::Row my_row = *row;
794       if (my_row[people_columns.nickname] == old_name)
795         {
796           my_row[people_columns.nickname] = new_name;
797           return;
798         }
799       Glib::ustring match = String::ucompose ("[%1]", old_name);
800       if (my_row[people_columns.nickname] == match)
801         {
802           my_row[people_columns.nickname] = String::ucompose("[%1]", new_name);
803           return;
804         }
805     }
806 
807 }
808 
lock_down()809 void GameLobbyDialog::lock_down ()
810 {
811   name_renderer.set_sensitive(false);
812   name_renderer.property_editable() = false;
813   type_renderer.set_sensitive(false);
814   type_renderer.property_editable() = false;
815 }
816 
on_play_message_received()817 void GameLobbyDialog::on_play_message_received()
818 {
819   d_play_message_received = true;
820   update_buttons();
821   lock_down();
822 }
823 
on_player_turned_off(Player * player)824 void GameLobbyDialog::on_player_turned_off(Player *player)
825 {
826   Gtk::TreeNodeChildren rows = player_list->children();
827   for(Gtk::TreeIter row = rows.begin(); row != rows.end(); ++row)
828     {
829       Gtk::TreeModel::Row my_row = *row;
830       if (my_row[player_columns.player_id] == player->getId())
831         {
832           player_list->erase(row);
833           return;
834         }
835     }
836 }
837 
sort_player_list_by_turn_order()838 void GameLobbyDialog::sort_player_list_by_turn_order()
839 {
840   Playerlist *pl = Playerlist::getInstance();
841   std::map<guint32, guint32> id_order;
842 
843   guint32 count = 0;
844   for (Playerlist::iterator i = pl->begin(), end = pl->end(); i != end; ++i)
845     {
846       Player *player = *i;
847       if (player == pl->getNeutral())
848 	continue;
849       if (player->isDead())
850 	continue;
851       id_order[player->getId()] = count;
852       count++;
853     }
854 
855   Gtk::TreeNodeChildren rows = player_list->children();
856   for(Gtk::TreeIter row = rows.begin(); row != rows.end(); ++row)
857     {
858       Gtk::TreeModel::Row my_row = *row;
859       my_row[player_columns.order] =
860         id_order[my_row[player_columns.player_id]];
861     }
862 }
863 
clean_up_players()864 void GameLobbyDialog::clean_up_players()
865 {
866   player_list->clear();
867 }
868 
disconnect_signals()869 void GameLobbyDialog::disconnect_signals()
870 {
871   std::list<sigc::connection>::iterator it = connections.begin();
872   for (; it != connections.end(); it++)
873     (*it).disconnect();
874   connections.clear();
875 }
876