1 /*
2 * gtkatlantic - the gtk+ monopd client, enjoy network monopoly games
3 *
4 *
5 * Copyright © 2002-2015 Sylvain Rochet
6 *
7 * gtkatlantic is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; see the file COPYING. If not, see
19 * <http://www.gnu.org/licenses/>.
20 */
21
22 #include "config.h"
23
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <unistd.h>
27 #include <string.h>
28 #include <stdbool.h>
29
30 #include <gtk/gtk.h>
31 #include <libxml/parser.h>
32
33 #include "engine.h"
34
35 #include "xmlparse.h"
36 #include "game.h"
37 #include "client.h"
38 #include "interface.h"
39 #include "global.h"
40 #include "load.h"
41 #include "callback.h"
42 #include "display.h"
43 #include "trade.h"
44
45 /*
46 ok server
47 ok client
48 ok msg
49 ok display
50 dep updateplayerlist
51 dep updategamelist
52 ok playerupdate
53 ok deleteplayer
54 ok estateupdate
55 ok cardupdate
56 ok estategroupupdate
57 ok tradeupdate
58 ok auctionupdate
59 ok gameupdate
60 ok deletegame
61 dep commandlist
62 ok configupdate
63 */
64
65 /*
66 ok .R
67
68 ok .gn
69 no-need .gl
70 ok .gj
71 ok .gx
72 todo .gk
73 todo .gu
74 ok .gc
75 todo .gS
76
77 ok .Tn
78 ok .Tc
79 ok .Te
80 ok .Tm
81 ok .Ta
82 ok .Tr
83
84 ok .r
85 ok .E
86 ok .t
87
88 ok .D
89 no-need .p
90
91 ok .eb
92 ok .es
93 ok .ea
94 ok .hb
95 ok .hs
96 ok .em
97
98 ok .ab
99
100 ok .jc
101 ok .jp
102 ok .jr
103
104 ok .T$
105 ok .T%
106
107 no-need .pi
108
109 todo .gd
110 ok .gs
111
112 no-need .d
113 ok .n
114 no-need .f
115 */
116
117
xmlparse_getgamelist_plugger(connection * c,gchar * buffer)118 void xmlparse_getgamelist_plugger(connection *c, gchar *buffer) {
119
120 xmlDocPtr doc;
121 xmlNodePtr cur;
122
123 doc = xmlParseMemory(buffer, strlen(buffer));
124 if (doc == NULL) {
125 return;
126 }
127
128 cur = xmlDocGetRootElement(doc);
129 if (cur == NULL) {
130 xmlFreeDoc(doc);
131 return;
132 }
133
134 if( xmlStrcmp(cur->name, SERVER_XMLROOTELEMENT) ) {
135 xmlFreeDoc(doc);
136 return;
137 }
138
139 for( cur = cur->xmlChildrenNode ; cur != NULL ; cur = cur -> next) {
140
141 if(! xmlStrcmp(cur->name, (xmlChar*)"server") ) xmlparse_server(c, doc, cur);
142 if(! xmlStrcmp(cur->name, (xmlChar*)"gameupdate") ) xmlparse_gamelist_gameupdate(c, doc, cur);
143 if(! xmlStrcmp(cur->name, (xmlChar*)"deletegame") ) xmlparse_gamelist_deletegame(c, doc, cur);
144 }
145
146 xmlFreeDoc(doc);
147 }
148
149
150
151
xmlparse_game_plugger(connection * c,gchar * buffer)152 void xmlparse_game_plugger(connection *c, gchar *buffer) {
153
154 xmlDocPtr doc;
155 xmlNodePtr cur;
156
157 doc = xmlParseMemory(buffer, strlen(buffer));
158 if (doc == NULL) {
159 return;
160 }
161
162 cur = xmlDocGetRootElement(doc);
163 if (cur == NULL) {
164 xmlFreeDoc(doc);
165 return;
166 }
167
168 if( xmlStrcmp(cur->name, SERVER_XMLROOTELEMENT) ) {
169 xmlFreeDoc(doc);
170 return;
171 }
172
173 for(cur = cur->xmlChildrenNode ; cur != NULL ; cur = cur -> next) {
174
175 if(! xmlStrcmp(cur->name, (xmlChar*)"gameupdate") ) xmlparse_gameupdate(c, doc, cur);
176 if(! xmlStrcmp(cur->name, (xmlChar*)"deletegame") ) xmlparse_deletegame(c, doc, cur);
177 if(! xmlStrcmp(cur->name, (xmlChar*)"server") ) xmlparse_server(c, doc, cur);
178 if(! xmlStrcmp(cur->name, (xmlChar*)"client") ) xmlparse_client(c, doc, cur);
179 if(! xmlStrcmp(cur->name, (xmlChar*)"msg") ) xmlparse_message(c, doc, cur);
180 if(! xmlStrcmp(cur->name, (xmlChar*)"estateupdate") ) xmlparse_estateupdate(c, doc, cur);
181 if(! xmlStrcmp(cur->name, (xmlChar*)"playerupdate") ) xmlparse_playerupdate(c, doc, cur);
182 if(! xmlStrcmp(cur->name, (xmlChar*)"auctionupdate") ) xmlparse_auctionupdate(c, doc, cur);
183 if(! xmlStrcmp(cur->name, (xmlChar*)"display") ) xmlparse_display(c, doc, cur);
184 if(! xmlStrcmp(cur->name, (xmlChar*)"configupdate") ) xmlparse_configupdate(c, doc, cur);
185 if(! xmlStrcmp(cur->name, (xmlChar*)"tradeupdate") ) xmlparse_tradeupdate(c, doc, cur);
186 if(! xmlStrcmp(cur->name, (xmlChar*)"cardupdate") ) xmlparse_cardupdate(c, doc, cur);
187 if(! xmlStrcmp(cur->name, (xmlChar*)"estategroupupdate") ) xmlparse_estategroupupdate(c, doc, cur);
188 if(! xmlStrcmp(cur->name, (xmlChar*)"deleteplayer") ) xmlparse_deleteplayer(c, doc, cur);
189 }
190
191 xmlFreeDoc(doc);
192 }
193
194
195
196
xmlparse_server(connection * c,xmlDocPtr doc,xmlNodePtr cur)197 void xmlparse_server(connection *c, xmlDocPtr doc, xmlNodePtr cur) {
198 (void)doc;
199
200 c->server_version = (gchar*)xmlGetProp(cur, (xmlChar*)"version");
201 }
202
203
204
205
xmlparse_client(connection * c,xmlDocPtr doc,xmlNodePtr cur)206 void xmlparse_client(connection *c, xmlDocPtr doc, xmlNodePtr cur) {
207
208 xmlChar *tmp;
209 (void)c;
210 (void)doc;
211
212 tmp = xmlGetProp(cur, (xmlChar*)"playerid");
213 if( tmp ) {
214 global->my_playerid = atoi( (gchar*)tmp );
215 g_free(tmp);
216 }
217
218 tmp = xmlGetProp(cur, (xmlChar*)"cookie");
219 if( tmp ) {
220 if(global->cookie) g_free(global->cookie);
221 global->cookie = (gchar*)tmp;
222 }
223 }
224
225
226
227
xmlparse_gameupdate(connection * c,xmlDocPtr doc,xmlNodePtr cur)228 void xmlparse_gameupdate(connection *c, xmlDocPtr doc, xmlNodePtr cur) {
229 xmlChar *tmp;
230 struct timeval tv;
231 gint32 gameid;
232 game *game;
233 guint8 newstatus;
234 (void)c;
235 (void)doc;
236
237 tmp = xmlGetProp(cur, (xmlChar*)"gameid");
238 if (tmp) {
239 gameid = atoi((gchar*)tmp);
240 g_free(tmp);
241 } else {
242 return;
243 }
244
245 /* We do not need game templates */
246 if (gameid < 0) {
247 return;
248 }
249
250 game = game_find(gameid);
251 if (!game) {
252 game = game_new(gameid);
253 if (!game) {
254 return;
255 }
256 }
257
258 tmp = xmlGetProp(cur, (xmlChar*)"status");
259 if(tmp) {
260 if(!xmlStrcmp(tmp, (xmlChar*)"config") ) {
261 newstatus = GAME_STATUS_CONFIG;
262 }
263 else if(!xmlStrcmp(tmp, (xmlChar*)"init") ) {
264 newstatus = GAME_STATUS_INIT;
265 }
266 else if(!xmlStrcmp(tmp, (xmlChar*)"run") ) {
267 newstatus = GAME_STATUS_RUN;
268 }
269 else if(!xmlStrcmp(tmp, (xmlChar*)"end") ) {
270 newstatus = GAME_STATUS_END;
271 }
272 else {
273 g_free(tmp);
274 return;
275 }
276
277 if (game->status != newstatus) {
278 game->status = newstatus;
279
280 if (newstatus == GAME_STATUS_RUN) {
281 gettimeofday(&tv, NULL);
282 game->start_time = tv.tv_sec;
283 }
284
285 if (currentgame == game) {
286 game_switch_status();
287 }
288 }
289 }
290 g_free(tmp);
291
292 tmp = xmlGetProp(cur, (xmlChar*)"master");
293 if (tmp) {
294 game->master = atoi((gchar*)tmp);
295 g_free(tmp);
296
297 if (game->GameConfigBox) {
298 GList *list = gtk_container_get_children(GTK_CONTAINER(game->GameConfigBox));
299 for (list = g_list_first(list); list; list = g_list_next(list)) {
300 gtk_widget_set_sensitive(GTK_WIDGET(list->data), (global->my_playerid == game->master));
301 }
302 g_list_free(list);
303 }
304
305 /* set sensitive mode of start button */
306 if (currentgame == game && game->status == GAME_STATUS_CONFIG) {
307 GtkWidget *StartButton = g_object_get_data(G_OBJECT(global->MainVerticalBox), "start_button");
308 gtk_widget_set_sensitive(StartButton, (global->my_playerid == game->master));
309 }
310 }
311 }
312
313
xmlparse_deletegame(connection * c,xmlDocPtr doc,xmlNodePtr cur)314 void xmlparse_deletegame(connection *c, xmlDocPtr doc, xmlNodePtr cur) {
315 xmlChar *tmp;
316 gint32 gameid;
317 (void)c;
318 (void)doc;
319
320 tmp = xmlGetProp(cur, (xmlChar*)"gameid");
321 if (tmp) {
322 gameid = atoi((gchar*)tmp);
323 g_free(tmp);
324 } else {
325 return;
326 }
327
328 if (!currentgame || currentgame->gameid != gameid) {
329 game_free(gameid);
330 }
331 }
332
333
xmlparse_message(connection * c,xmlDocPtr doc,xmlNodePtr cur)334 void xmlparse_message(connection *c, xmlDocPtr doc, xmlNodePtr cur) {
335
336 gchar *type, *text, *author, *value;
337 (void)c;
338 (void)doc;
339
340 type = (gchar*)xmlGetProp(cur, (xmlChar*)"type");
341
342 if (!g_ascii_strncasecmp(type, "chat", 4)) {
343
344 author = (gchar*)xmlGetProp(cur, (xmlChar*)"author");
345 value = (gchar*)xmlGetProp(cur, (xmlChar*)"value");
346 if(value && author) {
347
348 if(! strncmp("[ACTION]", value, 8) )
349 text = g_strdup_printf("* %s%s", author, value + 8);
350 else if(! strncmp("/me", value, 3) )
351 text = g_strdup_printf("* %s%s", author, value + 3);
352 else
353 text = g_strdup_printf("<%s> %s", author, value);
354
355 text_insert_chat(text, strlen(text));
356 g_free(text);
357 }
358 if(value[0] == '!') parse_specific_chat_message(value);
359 if(author) g_free(author);
360 if(value) g_free(value);
361 }
362 else {
363 value = (gchar*)xmlGetProp(cur, (xmlChar*)"value");
364 if (!g_ascii_strncasecmp(type, "error", 5)) {
365 interface_set_infolabel(value, "b00000", false);
366 } else {
367 interface_set_infolabel(value, "808000", false);
368 }
369 g_free(value);
370 }
371
372 g_free(type);
373 }
374
375
376
377
xmlparse_estateupdate(connection * c,xmlDocPtr doc,xmlNodePtr cur)378 void xmlparse_estateupdate(connection *c, xmlDocPtr doc, xmlNodePtr cur) {
379
380 guint32 color[3], i;
381 xmlChar *tmp;
382 eng_obj *pic;
383 gint32 star, id, t, u;
384 gboolean refresh = FALSE;
385 gboolean owner_mortgage_changed = FALSE;
386 (void)c;
387 (void)doc;
388
389 if (!currentgame) {
390 return;
391 }
392
393 tmp = xmlGetProp(cur, (xmlChar*)"estateid");
394 if(!tmp) return;
395 id = atoi( (gchar*)tmp );
396 g_free(tmp);
397 if(id < 0) return;
398
399 tmp = xmlGetProp(cur, (xmlChar*)"name");
400 if(tmp) currentgame->estate[id].name = (gchar*)tmp;
401
402 tmp = xmlGetProp(cur, (xmlChar*)"color");
403 if(tmp) {
404
405 sscanf((gchar*)tmp, "#%2X%2X%2X", &color[0], &color[1], &color[2]);
406 currentgame->estate[id].color[0] = color[0];
407 currentgame->estate[id].color[1] = color[1];
408 currentgame->estate[id].color[2] = color[2];
409 g_free(tmp);
410 }
411
412 tmp = xmlGetProp(cur, (xmlChar*)"bgcolor");
413 if(tmp) {
414
415 sscanf((gchar*)tmp, "#%2X%2X%2X", &color[0], &color[1], &color[2]);
416 currentgame->estate[id].bgcolor[0] = color[0];
417 currentgame->estate[id].bgcolor[1] = color[1];
418 currentgame->estate[id].bgcolor[2] = color[2];
419 g_free(tmp);
420 }
421
422 tmp = xmlGetProp(cur, (xmlChar*)"owner");
423 if(tmp) {
424
425 t = currentgame->estate[id].owner = atoi((gchar*)tmp);
426 g_free(tmp);
427 owner_mortgage_changed = TRUE;
428 }
429
430 tmp = xmlGetProp(cur, (xmlChar*)"mortgaged");
431 if(tmp) {
432
433 u = currentgame->estate[id].mortgaged = atoi((gchar*)tmp);
434 g_free(tmp);
435 owner_mortgage_changed = TRUE;
436 }
437
438 if(owner_mortgage_changed) {
439 gint32 cardid = get_playerlistcard_id_with_estate(id);
440
441 t = currentgame->estate[id].owner;
442 u = currentgame->estate[id].mortgaged;
443
444 /* reset unowned cards of this estate to all players */
445 if (cardid >= 0) {
446 player *p;
447 for (p = player_h; p; p = p->next) {
448 if (p->spectator) continue;
449 if (p->game != currentgame->gameid) continue;
450
451 pic = p->playerlist_cards_pic[cardid];
452 eng_pic_set_alpha(pic, data->playerlist_cards_alphaunowned);
453 }
454 }
455
456 if(t > 0 && !u) {
457
458 /* star */
459 star = player_from_id(t)->tokenid;
460
461 pic = currentgame->estate[id].star_pic;
462 eng_pic_set_width(pic, data->pngfile_star_width[star]);
463 eng_pic_set_height(pic, data->pngfile_star_height[star]);
464 eng_pic_set_pixbuf(pic, data->pngfile_star_buf[star]);
465 eng_pic_show(pic);
466
467 /* playerlist card */
468 if (cardid >= 0) {
469 pic = player_from_id(t)->playerlist_cards_pic[cardid];
470 }
471
472 eng_pic_set_bgcolor(pic, data->playerlist_cards_cardbgcolor);
473 eng_pic_set_alpha(pic, data->playerlist_cards_alphaowned);
474 }
475 else if(t > 0 && u) {
476
477 /* star */
478 star = player_from_id(t)->tokenid;
479
480 pic = currentgame->estate[id].star_pic;
481 eng_pic_set_width(pic, data->pngfile_star_m_width[star]);
482 eng_pic_set_height(pic, data->pngfile_star_m_height[star]);
483 eng_pic_set_pixbuf(pic, data->pngfile_star_m_buf[star]);
484 eng_pic_show(pic);
485
486 /* playerlist card */
487 if (cardid >= 0) {
488 pic = player_from_id(t)->playerlist_cards_pic[cardid];
489 }
490
491 eng_pic_set_bgcolor(pic, data->playerlist_cards_cardbgcolormortgage);
492 eng_pic_set_alpha(pic, data->playerlist_cards_alphamortgage);
493 }
494 else /* if( t <= 0 ) */ {
495
496 /* star */
497 eng_pic_unshow(currentgame->estate[id].star_pic);
498 }
499
500 /* update estatelist in trade panel */
501 for(i = 0 ; i < MAX_TRADES ; i++) {
502
503 if(! currentgame->trade[i].open) continue;
504 if(currentgame->trade[i].current_component != TRADE_TYPE_ESTATE) continue;
505
506 trade_rebuild_subcomponent(i);
507 }
508
509 refresh = TRUE;
510 }
511
512 tmp = xmlGetProp(cur, (xmlChar*)"houses");
513 if(tmp) {
514
515 t = currentgame->estate[id].houses = atoi((gchar*)tmp);
516 g_free(tmp);
517
518 if(t <= 0) {
519
520 /* houses */
521 pic = currentgame->estate[id].house_pic;
522 eng_pic_unshow(pic);
523 }
524 else if(t > 0 && data->estate[id].type_house == TYPE_HOUSE_HORIZONTAL) {
525
526 /* houses */
527 pic = currentgame->estate[id].house_pic;
528 eng_pic_set_width(pic, data->pngfile_horiz_house_width[t]);
529 eng_pic_set_height(pic, data->pngfile_horiz_house_height[t]);
530 eng_pic_set_pixbuf(pic, data->pngfile_horiz_house_buf[t]);
531 eng_pic_show(pic);
532 }
533 else if(t > 0 && data->estate[id].type_house == TYPE_HOUSE_VERTICAL) {
534
535 /* houses */
536 pic = currentgame->estate[id].house_pic;
537 eng_pic_set_width(pic, data->pngfile_vert_house_width[t]);
538 eng_pic_set_height(pic, data->pngfile_vert_house_height[t]);
539 eng_pic_set_pixbuf(pic, data->pngfile_vert_house_buf[t]);
540 eng_pic_show(pic);
541 }
542
543 refresh = TRUE;
544 }
545
546 tmp = xmlGetProp(cur, (xmlChar*)"houseprice");
547 if(tmp) {
548 currentgame->estate[id].houseprice = atoi((gchar*)tmp);
549 g_free(tmp);
550 }
551
552 tmp = xmlGetProp(cur, (xmlChar*)"sellhouseprice");
553 if(tmp) {
554 currentgame->estate[id].sellhouseprice = atoi((gchar*)tmp);
555 g_free(tmp);
556 }
557
558 tmp = xmlGetProp(cur, (xmlChar*)"mortgageprice");
559 if(tmp) {
560 currentgame->estate[id].mortgageprice = atoi((gchar*)tmp);
561 g_free(tmp);
562 }
563
564 tmp = xmlGetProp(cur, (xmlChar*)"unmortgageprice");
565 if(tmp) {
566 currentgame->estate[id].unmortgageprice = atoi((gchar*)tmp);
567 g_free(tmp);
568 }
569
570 tmp = xmlGetProp(cur, (xmlChar*)"group");
571 if(tmp) {
572 currentgame->estate[id].group = atoi((gchar*)tmp);
573 g_free(tmp);
574 }
575
576 tmp = xmlGetProp(cur, (xmlChar*)"can_be_owned");
577 if(tmp) {
578 currentgame->estate[id].can_be_owned = atoi((gchar*)tmp);
579 g_free(tmp);
580 }
581
582 tmp = xmlGetProp(cur, (xmlChar*)"can_toggle_mortgage");
583 if(tmp) {
584 currentgame->estate[id].can_toggle_mortgage = atoi((gchar*)tmp);
585 g_free(tmp);
586 }
587
588 tmp = xmlGetProp(cur, (xmlChar*)"can_buy_houses");
589 if(tmp) {
590 currentgame->estate[id].can_buy_houses = atoi((gchar*)tmp);
591 g_free(tmp);
592 }
593
594 tmp = xmlGetProp(cur, (xmlChar*)"can_sell_houses");
595 if(tmp) {
596 currentgame->estate[id].can_sell_houses = atoi((gchar*)tmp);
597 g_free(tmp);
598 }
599
600 tmp = xmlGetProp(cur, (xmlChar*)"money");
601 if(tmp) {
602 currentgame->estate[id].money = atoi((gchar*)tmp);
603 g_free(tmp);
604 }
605
606 tmp = xmlGetProp(cur, (xmlChar*)"price");
607 if(tmp) {
608 currentgame->estate[id].price = atoi((gchar*)tmp);
609 g_free(tmp);
610 }
611
612 for(i = 0 ; i <= 5 ; i++) {
613
614 xmlChar *key = (xmlChar*)g_strdup_printf("rent%d", i);
615 tmp = xmlGetProp(cur, key);
616
617 if(tmp) {
618 currentgame->estate[id].rent[i] = atoi((gchar*)tmp);
619 g_free(tmp);
620 }
621 g_free(key);
622 }
623
624 if (refresh) {
625 update_display();
626 }
627 }
628
629
630
631
xmlparse_playerupdate(connection * c,xmlDocPtr doc,xmlNodePtr cur)632 void xmlparse_playerupdate(connection *c, xmlDocPtr doc, xmlNodePtr cur) {
633
634 gint32 id, i;
635 player *p;
636 xmlChar *tmp;
637 gboolean refresh = FALSE;
638 (void)c;
639 (void)doc;
640
641 tmp = xmlGetProp(cur, (xmlChar*)"playerid");
642 if(!tmp) return;
643 id = atoi((gchar*)tmp);
644 g_free(tmp);
645 if(!id) return;
646
647 /* create new player */
648 p = player_from_id(id);
649 if (p == NULL) {
650 p = game_new_player(id);
651 if (!p) {
652 return;
653 }
654 }
655
656 tmp = xmlGetProp(cur, (xmlChar*)"game");
657 if(tmp) {
658 p->game = atoi((gchar*)tmp);
659 g_free(tmp);
660
661 if (id == global->my_playerid) {
662 if (p->game < 0) {
663 if (currentgame) {
664 game_quit();
665 }
666 } else {
667 if (!currentgame) {
668 game *game = game_find(p->game);
669 if (game) {
670 currentgame = game;
671 printf("Current game: %d\n", game->gameid);
672 game_switch_status();
673 }
674 }
675 }
676 } else if (p->game < 0) {
677 interface_gameboard_remove_player(p);
678 refresh = TRUE;
679 }
680 }
681
682 tmp = xmlGetProp(cur, (xmlChar*)"host");
683 if(tmp) {
684 if(p->host) g_free(p->host);
685 p->host = (gchar*)tmp;
686 }
687
688 tmp = xmlGetProp(cur, (xmlChar*)"image");
689 if(tmp) {
690 if(p->image) g_free(p->image);
691 p->image = (gchar*)tmp;
692 }
693
694 tmp = xmlGetProp(cur, (xmlChar*)"name");
695 if(tmp) {
696 if(p->name) g_free(p->name);
697 p->name = (char*)tmp;
698
699 if (currentgame && p->game == currentgame->gameid) {
700 /* playerlist name */
701 /* FIXME: handle hasturn color */
702 if(p->playerlist_LabelNamePlayer)
703 gtk_label_set_text(GTK_LABEL(p->playerlist_LabelNamePlayer), p->name);
704
705 /* playerlist in trade panel */
706 for(i = 0 ; i < MAX_TRADES ; i++) {
707
708 if(! currentgame->trade[i].open) continue;
709
710 trade_rebuild_playerlist(i);
711 }
712
713 /* update sub component players in trade panel */
714 for(i = 0 ; i < MAX_TRADES ; i++) {
715
716 if(! currentgame->trade[i].open) continue;
717
718 trade_rebuild_subcomponent(i);
719 }
720 }
721 }
722
723 tmp = xmlGetProp(cur, (xmlChar*)"money");
724 if(tmp) {
725 p->money = atoi((gchar*)tmp);
726 g_free(tmp);
727
728 if (currentgame && p->game == currentgame->gameid) {
729 if(p->playerlist_LabelMoneyPlayer) {
730 if(p->hasturn) {
731 gchar *tmp = g_markup_printf_escaped("<span foreground=\"#ff0000\">%d</span>", p->money);
732 gtk_label_set_markup(GTK_LABEL(p->playerlist_LabelMoneyPlayer), tmp);
733 g_free(tmp);
734 } else {
735 gchar *tmp = g_markup_printf_escaped("<span foreground=\"#000000\">%d</span>", p->money);
736 gtk_label_set_markup(GTK_LABEL(p->playerlist_LabelMoneyPlayer), tmp);
737 g_free(tmp);
738 }
739 }
740 }
741 }
742
743 tmp = xmlGetProp(cur, (xmlChar*)"location");
744 if(tmp) {
745 p->location_to = atoi((gchar*)tmp);
746 g_free(tmp);
747
748 tmp = xmlGetProp(cur, (xmlChar*)"directmove");
749 if (tmp) {
750 p->directmove = atoi((gchar*)tmp);
751 g_free(tmp);
752 }
753
754 if (currentgame && p->game == currentgame->gameid) {
755 refresh = TRUE;
756 }
757 }
758
759 tmp = xmlGetProp(cur, (xmlChar*)"jailed");
760 if(tmp) {
761 gboolean jailed = atoi((gchar*)tmp);
762 g_free(tmp);
763
764 if (jailed != p->jailed) {
765 p->jailed = jailed;
766 p->directmove = TRUE; /* force directmove when player is going to or leaving jail */
767 }
768
769 if (currentgame && p->game == currentgame->gameid) {
770 refresh = TRUE;
771 }
772 }
773
774 tmp = xmlGetProp(cur, (xmlChar*)"bankrupt");
775 if(tmp) {
776 p->bankrupt = atoi((gchar*)tmp);
777 g_free(tmp);
778
779 if (currentgame && p->game == currentgame->gameid) {
780 /* remove token */
781 if(p->bankrupt) {
782 eng_pic_unshow(p->token_pic);
783 refresh = TRUE;
784 }
785 }
786 }
787
788 tmp = xmlGetProp(cur, (xmlChar*)"hasturn");
789 if(tmp) {
790 p->hasturn = atoi((gchar*)tmp);
791 g_free(tmp);
792
793 if (currentgame && p->game == currentgame->gameid) {
794 /* set has turn attributes */
795 if(p->hasturn) {
796
797 if (p->playerlist_LabelNamePlayer) {
798 gchar *tmp = g_markup_printf_escaped("<span foreground=\"#ff0000\">%s</span>", p->name);
799 gtk_label_set_markup(GTK_LABEL(p->playerlist_LabelNamePlayer), tmp);
800 g_free(tmp);
801
802 tmp = g_markup_printf_escaped("<span foreground=\"#ff0000\">%d</span>", p->money);
803 gtk_label_set_markup(GTK_LABEL(p->playerlist_LabelMoneyPlayer), tmp);
804 g_free(tmp);
805 }
806
807 eng_pic_unset_alpha(p->token_pic);
808 }
809 else {
810
811 if (p->playerlist_LabelNamePlayer) {
812 gchar *tmp = g_markup_printf_escaped("<span foreground=\"#000000\">%s</span>", p->name);
813 gtk_label_set_markup(GTK_LABEL(p->playerlist_LabelNamePlayer), tmp);
814 g_free(tmp);
815
816 tmp = g_markup_printf_escaped("<span foreground=\"#000000\">%d</span>", p->money);
817 gtk_label_set_markup(GTK_LABEL(p->playerlist_LabelMoneyPlayer), tmp);
818 g_free(tmp);
819 }
820
821 if(config->game_token_transparency)
822 eng_pic_set_alpha(p->token_pic, 0x7f);
823 }
824
825 refresh = TRUE;
826 }
827 }
828
829 tmp = xmlGetProp(cur, (xmlChar*)"can_roll");
830 if(tmp) {
831 p->can_roll = atoi((gchar*)tmp);
832 g_free(tmp);
833 }
834
835 tmp = xmlGetProp(cur, (xmlChar*)"can_buyestate");
836 if(tmp) {
837 p->can_buyestate = atoi((gchar*)tmp);
838 g_free(tmp);
839 }
840
841 tmp = xmlGetProp(cur, (xmlChar*)"turnorder");
842 if(tmp) {
843 p->turnorder = atoi((gchar*)tmp);
844 g_free(tmp);
845 }
846
847 tmp = xmlGetProp(cur, (xmlChar*)"spectator");
848 if(tmp) {
849 p->spectator = atoi((gchar*)tmp);
850 g_free(tmp);
851 if (currentgame && p->game == currentgame->gameid && !p->spectator) {
852 /* note: turnorder must be fetched before */
853 game_sort_playerlist_by_turnorder();
854 interface_gameboard_add_player(p);
855 game_update_tokens();
856 }
857 }
858
859 game_buildplayerlist();
860 if (refresh) {
861 game_initiate_token_movement();
862 update_display();
863 }
864 }
865
866
867
868
xmlparse_auctionupdate(connection * c,xmlDocPtr doc,xmlNodePtr cur)869 void xmlparse_auctionupdate(connection *c, xmlDocPtr doc, xmlNodePtr cur) {
870
871 guint32 auctionid, highbid = 0;
872 xmlChar *tmp;
873 (void)c;
874 (void)doc;
875
876 if (!currentgame || currentgame->status != GAME_STATUS_RUN) {
877 return;
878 }
879
880 tmp = xmlGetProp(cur, (xmlChar*)"auctionid");
881 if(!tmp) return;
882 auctionid = atoi((gchar*)tmp);
883 g_free(tmp);
884
885 /* initialise auction */
886 tmp = xmlGetProp(cur, (xmlChar*)"estateid");
887 if (tmp && g_object_get_data(G_OBJECT(currentgame->BoardCenter), "auctionbox") == NULL) {
888 guint32 estateid = atoi((gchar*)tmp);
889 g_free(tmp);
890
891 display_hide();
892 interface_create_auctionbox(auctionid, estateid);
893 g_object_set_data(G_OBJECT(currentgame->BoardCenter), "auction_highbid", 0);
894 }
895
896 if (g_object_get_data(G_OBJECT(currentgame->BoardCenter), "auctionbox") == NULL) {
897 return;
898 }
899
900 /* bid */
901 tmp = xmlGetProp(cur, (xmlChar*)"highbid");
902 if(tmp) {
903 highbid = atoi((gchar*)tmp);
904 g_object_set_data(G_OBJECT(currentgame->BoardCenter), "auction_highbid", GINT_TO_POINTER(highbid));
905 g_free(tmp);
906 }
907
908 tmp = xmlGetProp(cur, (xmlChar*)"highbidder");
909 if(tmp) {
910 guint32 highbidder = atoi((gchar*)tmp);
911 g_free(tmp);
912
913 GtkListStore *store;
914 GtkTreeIter iter;
915 gboolean valid;
916
917 store = g_object_get_data(G_OBJECT(currentgame->BoardCenter), "auction_store");
918 valid = gtk_tree_model_get_iter_first(GTK_TREE_MODEL(store), &iter);
919 while (valid) {
920 guint32 eplayerid;
921
922 gtk_tree_model_get(GTK_TREE_MODEL(store), &iter, AUCTIONPLAYERLIST_COLUMN_PLAYERID, &eplayerid, -1);
923 if (eplayerid == highbidder) {
924 gtk_list_store_set(store, &iter,
925 AUCTIONPLAYERLIST_COLUMN_BID, highbid,
926 AUCTIONPLAYERLIST_WEIGHT, PANGO_WEIGHT_BOLD,
927 -1);
928 } else {
929 gtk_list_store_set(store, &iter,
930 AUCTIONPLAYERLIST_WEIGHT, PANGO_WEIGHT_NORMAL,
931 -1);
932 }
933
934 valid = gtk_tree_model_iter_next(GTK_TREE_MODEL(store), &iter);
935 }
936 }
937
938 /* status */
939 tmp = xmlGetProp(cur, (xmlChar*)"status");
940 if(tmp) {
941 guint32 status = atoi((gchar*)tmp);
942 g_free(tmp);
943
944 GtkWidget *label = g_object_get_data(G_OBJECT(currentgame->BoardCenter), "auction_statuslabel");
945
946 switch (status) {
947 case 0:
948 gtk_label_set_text(GTK_LABEL(label), NULL);
949 break;
950
951 case 1:
952 gtk_label_set_text(GTK_LABEL(label), "Going once…");
953 break;
954
955 case 2:
956 gtk_label_set_text(GTK_LABEL(label), "Going twice…");
957 break;
958
959 case 3:
960 gtk_widget_destroy(g_object_get_data(G_OBJECT(currentgame->BoardCenter), "auctionbox"));
961 g_object_set_data(G_OBJECT(currentgame->BoardCenter), "auctionbox", NULL);
962 display_show();
963 break;
964 }
965 }
966 }
967
968
969
970
xmlparse_display(connection * c,xmlDocPtr doc,xmlNodePtr cur)971 void xmlparse_display(connection *c, xmlDocPtr doc, xmlNodePtr cur) {
972
973 xmlNodePtr cur2;
974 gint32 estateid;
975 xmlChar *tmp;
976 gchar *caption, *command;
977 gboolean enable;
978 (void)c;
979 (void)doc;
980
981 if (!currentgame || currentgame->status < GAME_STATUS_INIT) {
982 return;
983 }
984
985 tmp = xmlGetProp(cur, (xmlChar*)"cleartext");
986 if(tmp) {
987 if( atoi((gchar*)tmp) ) display_clear_text();
988 g_free(tmp);
989 }
990
991 tmp = xmlGetProp(cur, (xmlChar*)"clearbuttons");
992 if(tmp) {
993 if( atoi((gchar*)tmp) ) display_clear_buttons();
994 g_free(tmp);
995 }
996
997 tmp = xmlGetProp(cur, (xmlChar*)"estateid");
998 if(tmp) {
999 estateid = atoi((gchar*)tmp);
1000 g_free(tmp);
1001 display_estate(estateid);
1002 }
1003
1004 tmp = xmlGetProp(cur, (xmlChar*)"text");
1005 if(tmp) {
1006
1007 if( strlen((gchar*)tmp) > 0) display_text((gchar*)tmp);
1008 g_free(tmp);
1009 }
1010
1011 /* buttons */
1012 for(cur2 = cur->xmlChildrenNode ; cur2 != NULL ; cur2 = cur2 -> next) {
1013
1014 if(! xmlStrcmp(cur2->name, (xmlChar*)"button") ) {
1015
1016 caption = (gchar*)xmlGetProp(cur2, (xmlChar*)"caption");
1017 command = (gchar*)xmlGetProp(cur2, (xmlChar*)"command");
1018
1019 tmp = xmlGetProp(cur2, (xmlChar*)"enabled");
1020 enable = atoi((gchar*)tmp);
1021 g_free(tmp);
1022
1023 display_add_button((gchar*)caption, (gchar*)command, enable);
1024 g_free(caption);
1025 g_free(command);
1026 }
1027 }
1028 }
1029
1030
1031
1032
xmlparse_configupdate(connection * c,xmlDocPtr doc,xmlNodePtr cur)1033 void xmlparse_configupdate(connection *c, xmlDocPtr doc, xmlNodePtr cur) {
1034
1035 GtkWidget *CButton;
1036 gchar *description;
1037 guint32 signalid;
1038 xmlChar *tmp;
1039 game *game;
1040 gint32 id;
1041 (void)c;
1042 (void)doc;
1043
1044 tmp = xmlGetProp(cur, (xmlChar*)"gameid");
1045 if (!tmp) {
1046 return;
1047 }
1048
1049 game = game_find(atoi((gchar*)tmp));
1050 g_free(tmp);
1051 if (!game) {
1052 return;
1053 }
1054
1055 tmp = xmlGetProp(cur, (xmlChar*)"configid");
1056 if (!tmp) {
1057 return;
1058 }
1059
1060 id = atoi((gchar*)tmp);
1061 g_free(tmp);
1062 if (id <= 0) {
1063 return;
1064 }
1065
1066 /* We are going to receive <configupdate/> events before we know in which game we are
1067 * therefore we create the config box before the config panel is created
1068 */
1069 if (!game->GameConfigBox) {
1070 game->GameConfigBox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
1071 }
1072
1073 /* create it if not created */
1074 gchar *strid = g_strdup_printf("%d", id);
1075 if ( !(CButton = g_object_get_data(G_OBJECT(game->GameConfigBox), strid)) ) {
1076
1077 /* We only handle boolean type for now */
1078 tmp = xmlGetProp(cur, (xmlChar*)"type");
1079 if (!tmp) {
1080 goto abort;
1081 }
1082 if(xmlStrcmp(tmp, (xmlChar*)"bool") ) {
1083 g_free(tmp);
1084 goto abort;
1085 }
1086 g_free(tmp);
1087
1088 description = (gchar*)xmlGetProp(cur, (xmlChar*)"description");
1089 if (!description) {
1090 goto abort;
1091 }
1092
1093 CButton = gtk_check_button_new_with_label(description);
1094 signalid = g_signal_connect(G_OBJECT(CButton), "toggled", G_CALLBACK(Callback_toggle_boolean_gameoption), NULL);
1095 gtk_widget_set_sensitive(CButton, (global->my_playerid == game->master));
1096 gtk_box_pack_start(GTK_BOX(game->GameConfigBox), CButton, FALSE, FALSE, 0);
1097
1098 /* store signal identifier */
1099 g_object_set_data(G_OBJECT(CButton), "signal", GINT_TO_POINTER(signalid));
1100
1101 /* store id under CButton */
1102 g_object_set_data(G_OBJECT(CButton), "id", GINT_TO_POINTER(id));
1103
1104 /* save the pointer of button to use in the future */
1105 g_object_set_data(G_OBJECT(game->GameConfigBox), strid, CButton);
1106
1107 g_free(description);
1108 }
1109
1110 /* modify */
1111 tmp = xmlGetProp(cur, (xmlChar*)"value");
1112 if (tmp) {
1113
1114 /* disconnect signal */
1115 signalid = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(CButton), "signal"));
1116 g_signal_handler_disconnect(G_OBJECT(CButton), signalid);
1117
1118 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(CButton), (atoi((gchar*)tmp) != 0));
1119 g_free(tmp);
1120
1121 /* reconnect signal */
1122 signalid = g_signal_connect(G_OBJECT(CButton), "toggled", G_CALLBACK(Callback_toggle_boolean_gameoption), NULL);
1123 g_object_set_data(G_OBJECT(CButton), "signal", GINT_TO_POINTER(signalid));
1124 }
1125
1126 /* tmp = xmlGetProp(cur, (xmlChar*)"edit"); USELESS */
1127
1128 abort:
1129 g_free(strid);
1130 gtk_widget_show_all(game->GameConfigBox);
1131 }
1132
1133
1134
1135
xmlparse_tradeupdate(connection * c,xmlDocPtr doc,xmlNodePtr cur)1136 void xmlparse_tradeupdate(connection *c, xmlDocPtr doc, xmlNodePtr cur) {
1137
1138 xmlNodePtr cur2;
1139 xmlChar *tmp;
1140 guint32 tradeid = 0, playerid = 0, cardid = 0, estateid = 0;
1141 guint32 targetplayer = 0, playerfrom = 0, playerto = 0, money = 0;
1142 gboolean accept = FALSE;
1143 (void)c;
1144 (void)doc;
1145
1146 if (!currentgame || currentgame->status != GAME_STATUS_RUN) {
1147 return;
1148 }
1149
1150 tmp = xmlGetProp(cur, (xmlChar*)"tradeid");
1151 if(tmp) {
1152 tradeid = atoi((gchar*)tmp);
1153 g_free(tmp);
1154 }
1155 else return;
1156
1157 // tmp = xmlGetProp(cur, (xmlChar*)"actor");
1158 // if(tmp) {
1159 // actor = atoi((gchar*)tmp);
1160 // g_free(tmp);
1161 // }
1162
1163 tmp = xmlGetProp(cur, (xmlChar*)"type");
1164 if(tmp) {
1165 if (!xmlStrcmp(tmp, (xmlChar*)"rejected") || !xmlStrcmp(tmp, (xmlChar*)"accepted") || !xmlStrcmp(tmp, (xmlChar*)"completed")) {
1166 trade_destroy(tradeid);
1167 g_free(tmp);
1168 return;
1169 }
1170
1171 if (!xmlStrcmp(tmp, (xmlChar*)"new")) {
1172 trade_initnew(tradeid);
1173 }
1174
1175 g_free(tmp);
1176 }
1177
1178 tmp = xmlGetProp(cur, (xmlChar*)"revision");
1179 if (tmp) {
1180 trade_update_revision(tradeid, atoi((gchar*)tmp));
1181 g_free(tmp);
1182 }
1183
1184 for(cur2 = cur->xmlChildrenNode ; cur2 != NULL ; cur2 = cur2 -> next) {
1185
1186 /* -- player -- */
1187 if(! xmlStrcmp(cur2->name, (xmlChar*)"tradeplayer") ) {
1188
1189 tmp = xmlGetProp(cur2, (xmlChar*)"playerid");
1190 if(tmp) {
1191 playerid = atoi((gchar*)tmp);
1192 g_free(tmp);
1193 }
1194
1195 tmp = xmlGetProp(cur2, (xmlChar*)"accept");
1196 if(tmp) {
1197 accept = atoi((gchar*)tmp);
1198 g_free(tmp);
1199 }
1200
1201 trade_update_player(tradeid, playerid, accept);
1202 }
1203
1204 /* -- card -- */
1205 if(! xmlStrcmp(cur2->name, (xmlChar*)"tradecard") ) {
1206
1207 tmp = xmlGetProp(cur2, (xmlChar*)"cardid");
1208 if(tmp) {
1209 cardid = atoi((gchar*)tmp);
1210 g_free(tmp);
1211 }
1212
1213 tmp = xmlGetProp(cur2, (xmlChar*)"targetplayer");
1214 if(tmp) {
1215 targetplayer = atoi((gchar*)tmp);
1216 g_free(tmp);
1217 }
1218
1219 trade_update_card(tradeid, cardid, targetplayer);
1220 }
1221
1222 /* -- estate -- */
1223 if(! xmlStrcmp(cur2->name, (xmlChar*)"tradeestate") ) {
1224
1225 tmp = xmlGetProp(cur2, (xmlChar*)"estateid");
1226 if(tmp) {
1227 estateid = atoi((gchar*)tmp);
1228 g_free(tmp);
1229 }
1230
1231 tmp = xmlGetProp(cur2, (xmlChar*)"targetplayer");
1232 if(tmp) {
1233 targetplayer = atoi((gchar*)tmp);
1234 g_free(tmp);
1235 }
1236
1237 trade_update_estate(tradeid, estateid, targetplayer);
1238 }
1239
1240 /* -- money -- */
1241 if(! xmlStrcmp(cur2->name, (xmlChar*)"trademoney") ) {
1242
1243 tmp = xmlGetProp(cur2, (xmlChar*)"playerfrom");
1244 if(tmp) {
1245 playerfrom = atoi((gchar*)tmp);
1246 g_free(tmp);
1247 }
1248
1249 tmp = xmlGetProp(cur2, (xmlChar*)"playerto");
1250 if(tmp) {
1251 playerto = atoi((gchar*)tmp);
1252 g_free(tmp);
1253 }
1254
1255 tmp = xmlGetProp(cur2, (xmlChar*)"money");
1256 if(tmp) {
1257 money = atoi((gchar*)tmp);
1258 g_free(tmp);
1259 }
1260
1261 trade_update_money(tradeid, playerfrom, playerto, money);
1262 }
1263 }
1264
1265 }
1266
1267
1268
1269
xmlparse_cardupdate(connection * c,xmlDocPtr doc,xmlNodePtr cur)1270 void xmlparse_cardupdate(connection *c, xmlDocPtr doc, xmlNodePtr cur) {
1271
1272 xmlChar *tmp;
1273 gint32 cardid, owner, i, cardslot;
1274 (void)c;
1275 (void)doc;
1276
1277 if (!currentgame || currentgame->status < GAME_STATUS_INIT) {
1278 return;
1279 }
1280
1281 tmp = xmlGetProp(cur, (xmlChar*)"cardid");
1282 if (!tmp) {
1283 return;
1284 }
1285 cardid = atoi((gchar*)tmp);
1286 g_free(tmp);
1287
1288 tmp = xmlGetProp(cur, (xmlChar*)"owner");
1289 if (!tmp) {
1290 return;
1291 }
1292 owner = atoi((gchar*)tmp);
1293 g_free(tmp);
1294
1295 cardslot = get_card_slot_with_cardid(cardid);
1296
1297 /* create new or update card slot */
1298 if (owner >= 0) {
1299 if (cardslot < 0 && !game_get_valid_card_slot(&cardslot)) {
1300 return;
1301 }
1302
1303 currentgame->card[cardslot].cardid = cardid;
1304 currentgame->card[cardslot].owner = owner;
1305
1306 xmlChar *title = xmlGetProp(cur, (xmlChar*)"title");
1307 if (title) {
1308 if (currentgame->card[cardslot].title) {
1309 g_free(currentgame->card[cardslot].title);
1310 }
1311 currentgame->card[cardslot].title = (gchar*)title;
1312 }
1313 }
1314
1315 /* destroy a card slot */
1316 else {
1317 if (cardslot < 0) {
1318 return;
1319 }
1320
1321 currentgame->card[cardslot].cardid = 0;
1322 currentgame->card[cardslot].owner = 0;
1323 if (currentgame->card[cardslot].title) {
1324 g_free(currentgame->card[cardslot].title);
1325 currentgame->card[cardslot].title = NULL;
1326 }
1327
1328 }
1329
1330 /* update component list in trade panel */
1331 for(i = 0 ; i < MAX_TRADES ; i++) {
1332
1333 if(! currentgame->trade[i].open) continue;
1334
1335 trade_rebuild_component(i);
1336 trade_rebuild_subcomponent(i);
1337 }
1338 }
1339
1340
1341
1342
xmlparse_estategroupupdate(connection * c,xmlDocPtr doc,xmlNodePtr cur)1343 void xmlparse_estategroupupdate(connection *c, xmlDocPtr doc, xmlNodePtr cur) {
1344
1345 xmlChar *tmp;
1346 gint32 groupid = -1;
1347 (void)c;
1348 (void)doc;
1349
1350 if (!currentgame) {
1351 return;
1352 }
1353
1354 tmp = xmlGetProp(cur, (xmlChar*)"groupid");
1355 if(tmp) {
1356 groupid = atoi((gchar*)tmp);
1357 g_free(tmp);
1358 }
1359
1360 if(groupid < 0) return;
1361
1362 if(currentgame->group[groupid].name) g_free(currentgame->group[groupid].name);
1363
1364 currentgame->group[groupid].name = (gchar*)xmlGetProp(cur, (xmlChar*)"name");
1365 }
1366
1367
1368
1369
xmlparse_deleteplayer(connection * c,xmlDocPtr doc,xmlNodePtr cur)1370 void xmlparse_deleteplayer(connection *c, xmlDocPtr doc, xmlNodePtr cur) {
1371
1372 xmlChar *tmp;
1373 gint32 id;
1374 player *p;
1375 (void)c;
1376 (void)doc;
1377
1378 tmp = xmlGetProp(cur, (xmlChar*)"playerid");
1379 if (!tmp) return;
1380 id = atoi((gchar*)tmp);
1381 g_free(tmp);
1382
1383 if (id < 0) return;
1384
1385 p = player_from_id(id);
1386 if (p == NULL) return;
1387
1388 interface_gameboard_remove_player(p);
1389 update_display();
1390 game_free_player(p);
1391 game_buildplayerlist();
1392 }
1393
1394
1395
1396
xmlparse_gamelist_gameupdate(connection * c,xmlDocPtr doc,xmlNodePtr cur)1397 void xmlparse_gamelist_gameupdate(connection *c, xmlDocPtr doc, xmlNodePtr cur) {
1398 xmlChar *tmp;
1399 gchar *players = NULL;
1400 gint32 id;
1401 GtkTreeIter iter;
1402 gboolean valid;
1403 gboolean update = FALSE;
1404 gchar *status = NULL;
1405 gint32 canbejoined = -1, canbewatched = -1;
1406 (void)doc;
1407
1408 tmp = xmlGetProp(cur, (xmlChar*)"gameid");
1409 id = atoi((gchar*)tmp);
1410 g_free(tmp);
1411
1412 /* lookup if gameid on same server already exist */
1413 if (id > 0) {
1414 valid = gtk_tree_model_get_iter_first(GTK_TREE_MODEL(global->game_store), &iter);
1415 while (valid) {
1416 gint32 source;
1417 gint32 eid;
1418
1419 gtk_tree_model_get(GTK_TREE_MODEL(global->game_store), &iter, GAMELIST_COLUMN_GAMEID, &eid, GAMELIST_COLUMN_SOURCE, &source, -1);
1420 if (eid == id && source == GAMELIST_SOURCE_CUSTOM) {
1421 update = TRUE;
1422 break;
1423 }
1424
1425 valid = gtk_tree_model_iter_next(GTK_TREE_MODEL(global->game_store), &iter);
1426 }
1427 }
1428
1429 /* ONLY TEMPORARY ! */
1430 tmp = xmlGetProp(cur, (xmlChar*)"gametype");
1431 if (tmp && xmlStrcmp(tmp, (xmlChar*)"city") && xmlStrcmp(tmp, (xmlChar*)"french_city") ) {
1432 g_free(tmp);
1433 return;
1434 }
1435
1436 tmp = xmlGetProp(cur, (xmlChar*)"turn");
1437 if(tmp) {
1438 int turn = atoi((gchar*)tmp);
1439 g_free(tmp);
1440
1441 if (turn >= 1) {
1442 status = g_strdup_printf("Playing, turn %d", turn);
1443 }
1444 }
1445
1446 tmp = xmlGetProp(cur, (xmlChar*)"status");
1447 if(tmp) {
1448 if (!xmlStrcmp(tmp, (xmlChar*)"config") ) {
1449 if (status) {
1450 g_free(status);
1451 }
1452 status = g_strdup("Waiting for players");
1453 }
1454 else if (!xmlStrcmp(tmp, (xmlChar*)"end") ) {
1455 if (status) {
1456 g_free(status);
1457 }
1458 status = g_strdup("Finished");
1459 }
1460
1461 g_free(tmp);
1462 }
1463
1464 // game template
1465 if (id < 0) {
1466 canbejoined = true;
1467 canbewatched = false;
1468 }
1469 tmp = xmlGetProp(cur, (xmlChar*)"canbejoined");
1470 if (tmp) {
1471 canbejoined = atoi((gchar*)tmp);
1472 g_free(tmp);
1473 }
1474
1475 tmp = xmlGetProp(cur, (xmlChar*)"canbewatched");
1476 if (tmp) {
1477 canbewatched = atoi((gchar*)tmp);
1478 g_free(tmp);
1479 }
1480
1481 players = (gchar*)xmlGetProp(cur, (xmlChar*)"players");
1482
1483 if (update) {
1484 if (status) {
1485 gtk_list_store_set(global->game_store, &iter,
1486 GAMELIST_COLUMN_STATUS, status,
1487 -1);
1488 }
1489
1490 if (players) {
1491 gtk_list_store_set(global->game_store, &iter,
1492 GAMELIST_COLUMN_PLAYERS, players,
1493 -1);
1494 }
1495
1496 if (canbejoined >= 0) {
1497 gtk_list_store_set(global->game_store, &iter,
1498 GAMELIST_COLUMN_CANBEJOINED, canbejoined,
1499 -1);
1500 }
1501
1502 if (canbewatched >= 0) {
1503 gtk_list_store_set(global->game_store, &iter,
1504 GAMELIST_COLUMN_CANBEWATCHED, canbewatched,
1505 -1);
1506 }
1507
1508 if (canbejoined >= 0 || canbewatched >= 0) {
1509 gint32 joined, watched;
1510
1511 gtk_tree_model_get(GTK_TREE_MODEL(global->game_store), &iter, GAMELIST_COLUMN_CANBEJOINED, &joined, GAMELIST_COLUMN_CANBEWATCHED, &watched, -1);
1512 gtk_list_store_set(global->game_store, &iter,
1513 GAMELIST_COLUMN_BGCOLOR, (joined || watched) ? global->bg_green : global->bg_red,
1514 -1);
1515 }
1516 }
1517 else {
1518 gchar *game = NULL;
1519 gchar *gametype = (gchar*)xmlGetProp(cur, (xmlChar*)"gametype");
1520
1521 tmp = xmlGetProp(cur, (xmlChar*)"name");
1522 if (tmp) {
1523 if (id < 0) {
1524 game = g_strdup_printf("Create new %s game", (gchar*)tmp);
1525 } else {
1526 game = g_strdup_printf("%s game %d", (gchar*)tmp, id);
1527 }
1528 g_free(tmp);
1529 }
1530
1531 gtk_list_store_append(global->game_store, &iter);
1532 gtk_list_store_set(global->game_store, &iter,
1533 GAMELIST_COLUMN_HOST, c->host,
1534 GAMELIST_COLUMN_VERSION, c->server_version,
1535 GAMELIST_COLUMN_GAME, game,
1536 GAMELIST_COLUMN_STATUS, status,
1537 GAMELIST_COLUMN_PLAYERS, players,
1538 GAMELIST_COLUMN_PORT, c->port,
1539 GAMELIST_COLUMN_GAMETYPE, gametype,
1540 GAMELIST_COLUMN_GAMEID, id,
1541 GAMELIST_COLUMN_CANBEJOINED, canbejoined,
1542 GAMELIST_COLUMN_CANBEWATCHED, canbewatched,
1543 GAMELIST_COLUMN_BGCOLOR, (canbejoined || canbewatched) ? global->bg_green : global->bg_red,
1544 GAMELIST_COLUMN_SOURCE, GAMELIST_SOURCE_CUSTOM,
1545 -1);
1546
1547 g_free(gametype);
1548 g_free(game);
1549 }
1550
1551 if(players) g_free(players);
1552 if(status) g_free(status);
1553 }
1554
1555
xmlparse_gamelist_deletegame(connection * c,xmlDocPtr doc,xmlNodePtr cur)1556 void xmlparse_gamelist_deletegame(connection *c, xmlDocPtr doc, xmlNodePtr cur) {
1557 xmlChar *tmp;
1558 gint32 id;
1559 GtkTreeIter iter;
1560 gboolean valid;
1561 (void)doc;
1562 (void)c;
1563
1564 tmp = xmlGetProp(cur, (xmlChar*)"gameid");
1565 id = atoi((gchar*)tmp);
1566 g_free(tmp);
1567
1568 valid = gtk_tree_model_get_iter_first(GTK_TREE_MODEL(global->game_store), &iter);
1569 while (valid) {
1570 gint32 source;
1571 gint32 eid;
1572 GtkTreeIter curiter = iter;
1573
1574 valid = gtk_tree_model_iter_next(GTK_TREE_MODEL(global->game_store), &iter); /* get next iter so we can remove the current entry safely */
1575
1576 gtk_tree_model_get(GTK_TREE_MODEL(global->game_store), &curiter, GAMELIST_COLUMN_GAMEID, &eid, GAMELIST_COLUMN_SOURCE, &source, -1);
1577 if (eid == id && source == GAMELIST_SOURCE_CUSTOM) {
1578 gtk_list_store_remove(global->game_store, &curiter);
1579 }
1580 }
1581 }
1582
1583
xmlparse_metaserver(connection * c,gchar * buffer)1584 void xmlparse_metaserver(connection *c, gchar *buffer) {
1585
1586 xmlChar *tmp;
1587 xmlDocPtr doc;
1588 xmlNodePtr cur, cur2;
1589 (void)c;
1590
1591 doc = xmlParseMemory(buffer, strlen(buffer) );
1592 if(doc == NULL) return;
1593
1594 cur = xmlDocGetRootElement(doc);
1595 if (cur == NULL) {
1596 xmlFreeDoc(doc);
1597 return;
1598 }
1599
1600 if( xmlStrcmp(cur->name, METASERVER_XMLROOTELEMENT) ) {
1601 xmlFreeDoc(doc);
1602 return;
1603 }
1604
1605 for(cur = cur->xmlChildrenNode ; cur != NULL ; cur = cur -> next) {
1606
1607 if(! xmlStrcmp(cur->name, (xmlChar*)"metaserver") ) {
1608 gchar *text;
1609
1610 tmp = xmlGetProp(cur, (xmlChar*)"version");
1611 text = g_strdup_printf("Atlantic metaserver version %s", tmp);
1612 g_free(tmp);
1613 interface_set_infolabel(text, "008000", false);
1614 g_free(text);
1615 }
1616
1617 if(! xmlStrcmp(cur->name, (xmlChar*)"msg") ) {
1618 gchar *text;
1619
1620 tmp = xmlGetProp(cur, (xmlChar*)"value");
1621 text = g_strdup_printf("%s", tmp);
1622 g_free(tmp);
1623 interface_create_messagewin(text);
1624 g_free(text);
1625 }
1626
1627 if(!xmlStrcmp(cur->name, (xmlChar*)"server") ) {
1628 gint32 serverid, users = -1;
1629 GtkTreeIter serveriter;
1630 bool valid, update = false;
1631
1632 tmp = xmlGetProp(cur, (xmlChar*)"id");
1633 if (!tmp) {
1634 continue;
1635 }
1636 serverid = atoi((gchar*)tmp);
1637 g_free(tmp);
1638
1639 /* lookup if server already exist */
1640 valid = gtk_tree_model_get_iter_first(GTK_TREE_MODEL(global->server_store), &serveriter);
1641 while (valid) {
1642 gint32 eid;
1643
1644 gtk_tree_model_get(GTK_TREE_MODEL(global->server_store), &serveriter, SERVERLIST_COLUMN_SERVERID, &eid, -1);
1645 if (eid == serverid) {
1646 update = true;
1647 break;
1648 }
1649
1650 valid = gtk_tree_model_iter_next(GTK_TREE_MODEL(global->server_store), &serveriter);
1651 }
1652
1653 tmp = xmlGetProp(cur, (xmlChar*)"users");
1654 if (tmp) {
1655 users = atoi((gchar*)tmp);
1656 g_free(tmp);
1657
1658 if (update == true) {
1659 gtk_list_store_set(global->server_store, &serveriter,
1660 SERVERLIST_COLUMN_USERS, users,
1661 -1);
1662 }
1663 }
1664
1665 if (update == false) {
1666 gchar *host, *version;
1667 gint32 port = -1;
1668
1669 host = (gchar*)xmlGetProp(cur, (xmlChar*)"host");
1670
1671 tmp = xmlGetProp(cur, (xmlChar*)"port");
1672 if (tmp) {
1673 port = atoi((gchar*)tmp);
1674 g_free(tmp);
1675 }
1676 version = (gchar*)xmlGetProp(cur, (xmlChar*)"version");
1677
1678 if (! (host && version && port >= 0 && users >= 0)) {
1679 continue;
1680 }
1681
1682 gtk_list_store_append(global->server_store, &serveriter);
1683 gtk_list_store_set(global->server_store, &serveriter,
1684 SERVERLIST_COLUMN_HOST, host,
1685 SERVERLIST_COLUMN_PORT, port,
1686 SERVERLIST_COLUMN_VERSION, version,
1687 SERVERLIST_COLUMN_USERS, users,
1688 SERVERLIST_COLUMN_SERVERID, serverid,
1689 -1);
1690
1691 g_free(host);
1692 g_free(version);
1693 }
1694
1695 for(cur2 = cur->xmlChildrenNode ; cur2 != NULL ; cur2 = cur2 -> next ) {
1696
1697 if (!xmlStrcmp(cur2->name, (xmlChar*)"game") ) {
1698 gchar *players;
1699 gint32 gameid;
1700 GtkTreeIter iter;
1701 bool valid, update = false;
1702 gchar *status = NULL;
1703 gint32 canbejoined = -1, canbewatched = -1;
1704
1705 /* ONLY TEMPORARY ! */
1706 tmp = xmlGetProp(cur2, (xmlChar*)"gametype");
1707 if (tmp && xmlStrcmp(tmp, (xmlChar*)"city") && xmlStrcmp(tmp, (xmlChar*)"french_city") ) {
1708 g_free(tmp);
1709 continue;
1710 }
1711
1712 tmp = xmlGetProp(cur2, (xmlChar*)"id");
1713 if (!tmp) {
1714 continue;
1715 }
1716 gameid = atoi((gchar*)tmp);
1717 g_free(tmp);
1718
1719 /* lookup if gameid on same server already exist */
1720 if (gameid > 0) {
1721 valid = gtk_tree_model_get_iter_first(GTK_TREE_MODEL(global->game_store), &iter);
1722 while (valid) {
1723 gint32 source;
1724 gint32 egameid, eserverid;
1725
1726 gtk_tree_model_get(GTK_TREE_MODEL(global->game_store), &iter, GAMELIST_COLUMN_GAMEID, &egameid, GAMELIST_COLUMN_SERVERID, &eserverid, GAMELIST_COLUMN_SOURCE, &source, -1);
1727 if (source == GAMELIST_SOURCE_METASERVER && egameid == gameid && eserverid == serverid) {
1728 update = true;
1729 break;
1730 }
1731
1732 valid = gtk_tree_model_iter_next(GTK_TREE_MODEL(global->game_store), &iter);
1733 }
1734 }
1735
1736 tmp = xmlGetProp(cur2, (xmlChar*)"turn");
1737 if(tmp) {
1738 int turn = atoi((gchar*)tmp);
1739 g_free(tmp);
1740
1741 if (turn >= 1) {
1742 status = g_strdup_printf("Playing, turn %d", turn);
1743 }
1744 }
1745
1746 tmp = xmlGetProp(cur2, (xmlChar*)"status");
1747 if(tmp) {
1748 if (!xmlStrcmp(tmp, (xmlChar*)"config") ) {
1749 if (status) {
1750 g_free(status);
1751 }
1752 status = g_strdup("Waiting for players");
1753 }
1754 else if (!xmlStrcmp(tmp, (xmlChar*)"end") ) {
1755 if (status) {
1756 g_free(status);
1757 }
1758 status = g_strdup("Finished");
1759 }
1760
1761 g_free(tmp);
1762 }
1763
1764 // game template
1765 if (gameid < 0) {
1766 canbejoined = true;
1767 canbewatched = false;
1768 }
1769 tmp = xmlGetProp(cur2, (xmlChar*)"canbejoined");
1770 if (tmp) {
1771 canbejoined = atoi((gchar*)tmp);
1772 g_free(tmp);
1773 }
1774
1775 tmp = xmlGetProp(cur2, (xmlChar*)"canbewatched");
1776 if (tmp) {
1777 canbewatched = atoi((gchar*)tmp);
1778 g_free(tmp);
1779 }
1780
1781 players = (gchar*)xmlGetProp(cur2, (xmlChar*)"players");
1782
1783 if (update) {
1784 if (status) {
1785 gtk_list_store_set(global->game_store, &iter,
1786 GAMELIST_COLUMN_STATUS, status,
1787 -1);
1788 }
1789
1790 if (players) {
1791 gtk_list_store_set(global->game_store, &iter,
1792 GAMELIST_COLUMN_PLAYERS, players,
1793 -1);
1794 }
1795
1796 if (canbejoined >= 0) {
1797 gtk_list_store_set(global->game_store, &iter,
1798 GAMELIST_COLUMN_CANBEJOINED, canbejoined,
1799 -1);
1800 }
1801
1802 if (canbewatched >= 0) {
1803 gtk_list_store_set(global->game_store, &iter,
1804 GAMELIST_COLUMN_CANBEWATCHED, canbewatched,
1805 -1);
1806 }
1807
1808 if (canbejoined >= 0 || canbewatched >= 0) {
1809 gint32 joined, watched;
1810
1811 gtk_tree_model_get(GTK_TREE_MODEL(global->game_store), &iter, GAMELIST_COLUMN_CANBEJOINED, &joined, GAMELIST_COLUMN_CANBEWATCHED, &watched, -1);
1812 gtk_list_store_set(global->game_store, &iter,
1813 GAMELIST_COLUMN_BGCOLOR, (joined || watched) ? global->bg_green : global->bg_red,
1814 -1);
1815 }
1816 }
1817 else {
1818 gchar *host, *version, *game, *gametype;
1819 gint32 port;
1820
1821 tmp = xmlGetProp(cur2, (xmlChar*)"name");
1822 if (!tmp) {
1823 continue;
1824 }
1825 if(gameid < 0) {
1826 game = g_strdup_printf("Create new %s game", (gchar*)tmp);
1827 } else {
1828 game = g_strdup_printf("%s game %d", (gchar*)tmp, gameid);
1829 }
1830 g_free(tmp);
1831
1832 gametype = (gchar*)xmlGetProp(cur2, (xmlChar*)"gametype");
1833
1834 gtk_tree_model_get(GTK_TREE_MODEL(global->server_store), &serveriter,
1835 SERVERLIST_COLUMN_HOST, &host,
1836 SERVERLIST_COLUMN_PORT, &port,
1837 SERVERLIST_COLUMN_VERSION, &version,
1838 -1);
1839
1840 gtk_list_store_append(global->game_store, &iter);
1841 gtk_list_store_set(global->game_store, &iter,
1842 GAMELIST_COLUMN_HOST, host,
1843 GAMELIST_COLUMN_VERSION, version,
1844 GAMELIST_COLUMN_GAME, game,
1845 GAMELIST_COLUMN_STATUS, status,
1846 GAMELIST_COLUMN_PLAYERS, players,
1847 GAMELIST_COLUMN_PORT, port,
1848 GAMELIST_COLUMN_GAMETYPE, gametype,
1849 GAMELIST_COLUMN_GAMEID, gameid,
1850 GAMELIST_COLUMN_SERVERID, serverid,
1851 GAMELIST_COLUMN_CANBEJOINED, canbejoined,
1852 GAMELIST_COLUMN_CANBEWATCHED, canbewatched,
1853 GAMELIST_COLUMN_BGCOLOR, (canbejoined || canbewatched) ? global->bg_green : global->bg_red,
1854 GAMELIST_COLUMN_SOURCE, GAMELIST_SOURCE_METASERVER,
1855 -1);
1856
1857 g_free(host);
1858 g_free(version);
1859 g_free(game);
1860 g_free(gametype);
1861 }
1862
1863 if (players) g_free(players);
1864 if (status) g_free(status);
1865 }
1866 else if (!xmlStrcmp(cur2->name, (xmlChar*)"deletegame") ) {
1867 gint32 gameid;
1868 GtkTreeIter iter;
1869 bool valid;
1870
1871 tmp = xmlGetProp(cur2, (xmlChar*)"id");
1872 if (!tmp) {
1873 continue;
1874 }
1875 gameid = atoi((gchar*)tmp);
1876 g_free(tmp);
1877
1878 valid = gtk_tree_model_get_iter_first(GTK_TREE_MODEL(global->game_store), &iter);
1879 while (valid) {
1880 gint32 source;
1881 gint32 egameid, eserverid;
1882
1883 gtk_tree_model_get(GTK_TREE_MODEL(global->game_store), &iter, GAMELIST_COLUMN_GAMEID, &egameid, GAMELIST_COLUMN_SERVERID, &eserverid, GAMELIST_COLUMN_SOURCE, &source, -1);
1884 if (source == GAMELIST_SOURCE_METASERVER && egameid == gameid && eserverid == serverid) {
1885 gtk_list_store_remove(global->game_store, &iter);
1886 break;
1887 }
1888
1889 valid = gtk_tree_model_iter_next(GTK_TREE_MODEL(global->game_store), &iter);
1890 }
1891 }
1892 }
1893 }
1894 else if(!xmlStrcmp(cur->name, (xmlChar*)"deleteserver") ) {
1895 gint32 id;
1896 GtkTreeIter iter;
1897 bool valid;
1898
1899 tmp = xmlGetProp(cur, (xmlChar*)"id");
1900 if (!tmp) {
1901 continue;
1902 }
1903 id = atoi((gchar*)tmp);
1904 g_free(tmp);
1905
1906 valid = gtk_tree_model_get_iter_first(GTK_TREE_MODEL(global->server_store), &iter);
1907 while (valid) {
1908 gint32 eid;
1909
1910 gtk_tree_model_get(GTK_TREE_MODEL(global->server_store), &iter, SERVERLIST_COLUMN_SERVERID, &eid, -1);
1911 if (eid == id) {
1912 gtk_list_store_remove(global->server_store, &iter);
1913 break;
1914 }
1915
1916 valid = gtk_tree_model_iter_next(GTK_TREE_MODEL(global->server_store), &iter);
1917 }
1918
1919 valid = gtk_tree_model_get_iter_first(GTK_TREE_MODEL(global->game_store), &iter);
1920 while (valid) {
1921 gint32 source;
1922 gint32 eid;
1923 GtkTreeIter curiter = iter;
1924
1925 valid = gtk_tree_model_iter_next(GTK_TREE_MODEL(global->game_store), &iter); /* get next iter so we can safely remove the current entry */
1926
1927 gtk_tree_model_get(GTK_TREE_MODEL(global->game_store), &curiter, GAMELIST_COLUMN_SERVERID, &eid, GAMELIST_COLUMN_SOURCE, &source, -1);
1928 if (source == GAMELIST_SOURCE_METASERVER && eid == id) {
1929 gtk_list_store_remove(global->game_store, &curiter);
1930 }
1931 }
1932 }
1933
1934 }
1935
1936 xmlFreeDoc(doc);
1937 }
1938