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