/* * gtkatlantic - the gtk+ monopd client, enjoy network monopoly games * * * Copyright (C) 2002-2004 Rochet Sylvain * * gtkatlantic is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #define GTK_ENABLE_BROKEN = 1 #include #include #include #include #include #include #include "engine.h" #include "xmlparse.h" #include "game.h" #include "client.h" #include "interface.h" #include "global.h" #include "load.h" #include "callback.h" #include "display.h" #include "trade.h" /* ok server ok client ok msg ok display dep updateplayerlist ok updategamelist ok playerupdate ok deleteplayer ok estateupdate ok cardupdate ok estategroupupdate ok tradeupdate ok auctionupdate ok gameupdate dep commandlist ok configupdate */ /* ok .gn ok .gl ok .gj no-need .gd ok .gp ok .gs ok .gx ok .Tn ok .Tc ok .Te ok .Tm ok .Ta ok .Tr ok .r ok .E ok .t ok .D no-need .p ok .eb ok .ea ok .hb ok .hs ok .em ok .ab ok .jc ok .jp ok .jr ok .T$ ok .T% no-need .f ok .n no-need .d ok .R no-need .pi */ void xmlparse_getgamelist_plugger(guint32 connectid, guchar *buffer) { xmlDocPtr doc; xmlNodePtr cur; doc = xmlParseMemory(buffer, strlen(buffer) ); if(doc == NULL) { printf("XML ERROR ON: %s %d\n", connection[connectid]->host, connection[connectid]->port); return; } cur = xmlDocGetRootElement(doc); if (cur == NULL) { xmlFreeDoc(doc); return; } if( xmlStrcmp(cur->name, SERVER_XMLROOTELEMENT) ) { xmlFreeDoc(doc); return; } for( cur = cur->xmlChildrenNode ; cur != NULL ; cur = cur -> next) { if(! xmlStrcmp(cur->name, "server") ) xmlparse_server(connectid, doc, cur); if(! xmlStrcmp(cur->name, "updategamelist") ) xmlparse_updategamelist(connectid, doc, cur); } xmlFreeDoc(doc); } void xmlparse_game_plugger(guint32 connectid, guchar *buffer) { xmlDocPtr doc; xmlNodePtr cur; doc = xmlParseMemory(buffer, strlen(buffer) ); if(doc == NULL) return; cur = xmlDocGetRootElement(doc); if (cur == NULL) { xmlFreeDoc(doc); return; } if( xmlStrcmp(cur->name, SERVER_XMLROOTELEMENT) ) { xmlFreeDoc(doc); return; } for(cur = cur->xmlChildrenNode ; cur != NULL ; cur = cur -> next) { if(! xmlStrcmp(cur->name, "gameupdate") ) xmlparse_gameupdate(connectid, doc, cur); if(! xmlStrcmp(cur->name, "server") ) xmlparse_server(connectid, doc, cur); if(! xmlStrcmp(cur->name, "client") ) xmlparse_client(connectid, doc, cur); if(! xmlStrcmp(cur->name, "msg") ) xmlparse_message(connectid, doc, cur); if(! xmlStrcmp(cur->name, "estateupdate") ) xmlparse_estateupdate(connectid, doc, cur); if(! xmlStrcmp(cur->name, "playerupdate") ) xmlparse_playerupdate(connectid, doc, cur); if(! xmlStrcmp(cur->name, "auctionupdate") ) xmlparse_auctionupdate(connectid, doc, cur); if(! xmlStrcmp(cur->name, "display") ) xmlparse_display(connectid, doc, cur); if(! xmlStrcmp(cur->name, "configupdate") ) xmlparse_configupdate(connectid, doc, cur); if(! xmlStrcmp(cur->name, "tradeupdate") ) xmlparse_tradeupdate(connectid, doc, cur); if(! xmlStrcmp(cur->name, "cardupdate") ) xmlparse_cardupdate(connectid, doc, cur); if(! xmlStrcmp(cur->name, "estategroupupdate") ) xmlparse_estategroupupdate(connectid, doc, cur); if(! xmlStrcmp(cur->name, "deleteplayer") ) xmlparse_deleteplayer(connectid, doc, cur); } xmlFreeDoc(doc); } void xmlparse_server(guint32 connectid, xmlDocPtr doc, xmlNodePtr cur) { guchar *tmp; tmp = xmlGetProp(cur, "version"); if(tmp) connection[connectid]->server_version = tmp; } void xmlparse_client(guint32 connectid, xmlDocPtr doc, xmlNodePtr cur) { guchar *tmp; tmp = xmlGetProp(cur, "playerid"); if( tmp ) { game->my_playerid = atoi( tmp ); g_free(tmp); } tmp = xmlGetProp(cur, "cookie"); if( tmp ) { game_write_cookie( tmp ); g_free(tmp); } } void xmlparse_gameupdate(guint32 connectid, xmlDocPtr doc, xmlNodePtr cur) { guchar *tmp; struct timeval tv; guint32 i; tmp = xmlGetProp(cur, "gameid"); if(tmp) { game->gameid = atoi(tmp); g_free(tmp); } tmp = xmlGetProp(cur, "status"); if(! tmp) return; if(! xmlStrcmp(tmp, "config") ) { if(game->status != GAME_STATUS_CONFIG) { game->status = GAME_STATUS_CONFIG; interface_create_gameconfigpage(); } } if(! xmlStrcmp(tmp, "init") ) { if(game->status != GAME_STATUS_INIT) { game->status = GAME_STATUS_INIT; interface_create_gameinitpage(); if(! game_load_pngs() ) exit(-1); } } if(! xmlStrcmp(tmp, "run") ) { if(game->status != GAME_STATUS_RUN) { gettimeofday(&tv, NULL); game->start_time = tv.tv_sec; game->status = GAME_STATUS_RUN; interface_create_gameboardpage(); } } if(! xmlStrcmp(tmp, "end") ) { if(game->status != GAME_STATUS_END) { game->status = GAME_STATUS_END; /* remove all commands */ if(game->CommandsBox) gtk_widget_destroy(game->CommandsBox); game->CommandsBox = 0; display_clear_buttons(); /* destroy all open trades */ for(i = 0 ; i < MAX_TRADES ; i++) { trade_destroy_slot(i); } } } g_free(tmp); } void xmlparse_message(guint32 connectid, xmlDocPtr doc, xmlNodePtr cur) { gchar *type, *text, *author, *value; type = xmlGetProp(cur, "type"); if(! g_strncasecmp(type, "chat", 4) ) { author = xmlGetProp(cur, "author"); value = xmlGetProp(cur, "value"); if(value && author) { if(! strncmp("[ACTION]", value, 8) ) text = g_strdup_printf("* %s%s", author, value + 8); else if(! strncmp("/me", value, 3) ) text = g_strdup_printf("* %s%s", author, value + 3); else text = g_strdup_printf("<%s> %s", author, value); text_insert_chat(text, strlen(text)); g_free(text); } if(value[0] == '!') parse_specific_chat_message(value); if(author) g_free(author); if(value) g_free(value); } else { g_strup( type ); value = xmlGetProp(cur, "value"); text = g_strdup_printf("%s: %s", type, value); text_insert_message(text, strlen(text)); g_free(text); g_free(value); } g_free(type); } void xmlparse_estateupdate(guint32 connectid, xmlDocPtr doc, xmlNodePtr cur) { guint32 color[3], i; gchar *key, *tmp; guint32 id, frame, pic, star; gint32 t, u; gboolean owner_mortgage_changed = FALSE; tmp = xmlGetProp(cur, "estateid"); if(!tmp) return; id = atoi( tmp ); g_free(tmp); if(id < 0) return; tmp = xmlGetProp(cur, "name"); if(tmp) game->estate[id].name = tmp; tmp = xmlGetProp(cur, "color"); if(tmp) { sscanf(tmp, "#%2X%2X%2X", &color[0], &color[1], &color[2]); game->estate[id].color[0] = color[0]; game->estate[id].color[1] = color[1]; game->estate[id].color[2] = color[2]; g_free(tmp); } tmp = xmlGetProp(cur, "bgcolor"); if(tmp) { sscanf(tmp, "#%2X%2X%2X", &color[0], &color[1], &color[2]); game->estate[id].bgcolor[0] = color[0]; game->estate[id].bgcolor[1] = color[1]; game->estate[id].bgcolor[2] = color[2]; g_free(tmp); } tmp = xmlGetProp(cur, "owner"); if(tmp) { t = game->estate[id].owner = atoi(tmp); g_free(tmp); owner_mortgage_changed = TRUE; } tmp = xmlGetProp(cur, "mortgaged"); if(tmp) { u = game->estate[id].mortgaged = atoi(tmp); g_free(tmp); owner_mortgage_changed = TRUE; } if(owner_mortgage_changed) { t = game->estate[id].owner; u = game->estate[id].mortgaged; /* reset unowned cards of this estate to all players */ for(i = 0 ; i < MAX_PLAYERS ; i++) { if(! global->player[i].playerid) continue; if(global->player[i].game != game->gameid) continue; frame = global->player[i].playerlist_cards_frame; pic = global->player[i].playerlist_cards_pic[ get_playerlistcard_id_with_estate(id) ]; pic_set_alpha(frame, pic, data->playerlist_cards_alphaunowned); } if(t > 0 && !u) { /* star */ frame = game->board_frame; star = global->player[ get_player_slot_with_playerid(t) ].buffer_star; pic = game->estate[id].star_alpha; pic_set_width(frame, pic, data->pngfile_star_width[star]); pic_set_height(frame, pic, data->pngfile_star_height[star]); pic_buff(frame, pic, data->pngfile_star_alpha[star]); pic = game->estate[id].star_pic; pic_set_width(frame, pic, data->pngfile_star_width[star]); pic_set_height(frame, pic, data->pngfile_star_height[star]); pic_buff(frame, pic, data->pngfile_star_image[star]); pic_show(frame, pic); /* playerlist card */ frame = global->player[ get_player_slot_with_playerid(t) ].playerlist_cards_frame; pic = global->player[ get_player_slot_with_playerid(t) ].playerlist_cards_pic[ get_playerlistcard_id_with_estate(id) ]; pic_set_bgcolor(frame, pic, data->playerlist_cards_cardbgcolor); pic_set_alpha(frame, pic, data->playerlist_cards_alphaowned); } else if(t > 0 && u) { /* star */ frame = game->board_frame; star = global->player[ get_player_slot_with_playerid(t) ].buffer_star; pic = game->estate[id].star_alpha; pic_set_width(frame, pic, data->pngfile_star_m_width[star]); pic_set_height(frame, pic, data->pngfile_star_m_height[star]); pic_buff(frame, pic, data->pngfile_star_m_alpha[star]); pic = game->estate[id].star_pic; pic_set_width(frame, pic, data->pngfile_star_m_width[star]); pic_set_height(frame, pic, data->pngfile_star_m_height[star]); pic_buff(frame, pic, data->pngfile_star_m_image[star]); pic_show(frame, pic); /* playerlist card */ frame = global->player[ get_player_slot_with_playerid(t) ].playerlist_cards_frame; pic = global->player[ get_player_slot_with_playerid(t) ].playerlist_cards_pic[ get_playerlistcard_id_with_estate(id) ]; pic_set_bgcolor(frame, pic, data->playerlist_cards_cardbgcolormortgage); pic_set_alpha(frame, pic, data->playerlist_cards_alphamortgage); } else /* if( t <= 0 ) */ { /* star */ frame = game->board_frame; pic_unshow(frame, game->estate[id].star_pic); } /* update estatelist in trade panel */ for(i = 0 ; i < MAX_TRADES ; i++) { if(! game->trade[i].open) continue; if(game->trade[i].current_component != TRADE_CURRENT_COMPONENT_ESTATE) continue; trade_rebuild_subcomponent(i); } } tmp = xmlGetProp(cur, "houses"); if(tmp) { t = game->estate[id].houses = atoi(tmp); g_free(tmp); frame = game->board_frame; if(t <= 0) { /* houses */ pic = game->estate[id].house_pic; pic_unshow(frame, pic); } else if(t > 0 && data->estate[id].type_house == TYPE_HOUSE_HORIZONTAL) { /* houses */ pic = game->estate[id].house_alpha; pic_set_width(frame, pic, data->pngfile_horiz_house_width[t]); pic_set_height(frame, pic, data->pngfile_horiz_house_height[t]); pic_set_buff(frame, pic, data->pngfile_horiz_house_alpha[t]); pic = game->estate[id].house_pic; pic_set_width(frame, pic, data->pngfile_horiz_house_width[t]); pic_set_height(frame, pic, data->pngfile_horiz_house_height[t]); pic_set_buff(frame, pic, data->pngfile_horiz_house_image[t]); pic_show(frame, pic); } else if(t > 0 && data->estate[id].type_house == TYPE_HOUSE_VERTICAL) { /* houses */ pic = game->estate[id].house_alpha; pic_set_width(frame, pic, data->pngfile_vert_house_width[t]); pic_set_height(frame, pic, data->pngfile_vert_house_height[t]); pic_set_buff(frame, pic, data->pngfile_vert_house_alpha[t]); pic = game->estate[id].house_pic; pic_set_width(frame, pic, data->pngfile_vert_house_width[t]); pic_set_height(frame, pic, data->pngfile_vert_house_height[t]); pic_set_buff(frame, pic, data->pngfile_vert_house_image[t]); pic_show(frame, pic); } } tmp = xmlGetProp(cur, "houseprice"); if(tmp) { game->estate[id].houseprice = atoi(tmp); g_free(tmp); } tmp = xmlGetProp(cur, "sellhouseprice"); if(tmp) { game->estate[id].sellhouseprice = atoi(tmp); g_free(tmp); } tmp = xmlGetProp(cur, "mortgageprice"); if(tmp) { game->estate[id].mortgageprice = atoi(tmp); g_free(tmp); } tmp = xmlGetProp(cur, "unmortgageprice"); if(tmp) { game->estate[id].unmortgageprice = atoi(tmp); g_free(tmp); } tmp = xmlGetProp(cur, "group"); if(tmp) { game->estate[id].group = atoi(tmp); g_free(tmp); } tmp = xmlGetProp(cur, "can_be_owned"); if(tmp) { game->estate[id].can_be_owned = atoi(tmp); g_free(tmp); } tmp = xmlGetProp(cur, "can_toggle_mortgage"); if(tmp) { game->estate[id].can_toggle_mortgage = atoi(tmp); g_free(tmp); } tmp = xmlGetProp(cur, "can_buy_houses"); if(tmp) { game->estate[id].can_buy_houses = atoi(tmp); g_free(tmp); } tmp = xmlGetProp(cur, "can_sell_houses"); if(tmp) { game->estate[id].can_sell_houses = atoi(tmp); g_free(tmp); } tmp = xmlGetProp(cur, "money"); if(tmp) { game->estate[id].money = atoi(tmp); g_free(tmp); } tmp = xmlGetProp(cur, "price"); if(tmp) { game->estate[id].price = atoi(tmp); g_free(tmp); } for(i = 0 ; i <= 5 ; i++) { key = g_strdup_printf("rent%d", i); tmp = xmlGetProp(cur, key); if(tmp) { game->estate[id].rent[i] = atoi(tmp); g_free(tmp); } g_free(key); } } void xmlparse_playerupdate(guint32 connectid, xmlDocPtr doc, xmlNodePtr cur) { gint32 playerid, i; gint8 id; guchar *tmp; GtkWidget *Combo, *StartButton, *Button; GList *list; tmp = xmlGetProp(cur, "playerid"); if(!tmp) return; playerid = atoi(tmp); g_free(tmp); if(!playerid) return; id = get_player_slot_with_playerid(playerid); /* create new player */ if(id < 0) { if(game->status <= GAME_STATUS_CONFIG) { if(! game_get_valid_player_slot(&id) ) return; memset(&global->player[id], 0, sizeof(_player) ); global->player[id].playerid = playerid; game->nb_players++; } else return; } if(id >= 0 && game->status > GAME_STATUS_CONFIG && global->player[id].game != game->gameid) return; tmp = xmlGetProp(cur, "game"); if(tmp) { global->player[id].game = atoi(tmp); g_free(tmp); } tmp = xmlGetProp(cur, "host"); if(tmp) { if(global->player[id].host) g_free(global->player[id].host); global->player[id].host = tmp; } tmp = xmlGetProp(cur, "master"); if(tmp) { global->player[id].master = atoi(tmp); g_free(tmp); if(global->player[id].master && game->my_playerid == playerid) game->i_am_the_master = TRUE; if(!global->player[id].master && game->my_playerid == playerid) game->i_am_the_master = FALSE; /* set sensitive mode of start button */ if(game->status == GAME_STATUS_CONFIG) { StartButton = gtk_object_get_data(GTK_OBJECT(global->MainVerticalBox), "start_button"); gtk_widget_set_sensitive(StartButton, game->i_am_the_master); } } tmp = xmlGetProp(cur, "image"); if(tmp) { if(global->player[id].image) g_free(global->player[id].image); global->player[id].image = tmp; } tmp = xmlGetProp(cur, "name"); if(tmp) { if(global->player[id].name) g_free(global->player[id].name); global->player[id].name = g_strndup(tmp, MAX_LENGTH_NICK); g_free(tmp); if(! strcmp(global->player[id].name, "_metaserver_")) { game_delete_player(id); return; } /* playerlist name */ if(global->player[id].playerlist_LabelNamePlayer) gtk_label_set_text(GTK_LABEL(global->player[id].playerlist_LabelNamePlayer), global->player[id].name); /* popdown string trade combo */ Combo = gtk_object_get_data(GTK_OBJECT(global->MainVerticalBox), "trade_combo_listplayer"); if(Combo) { list = NULL; for(i = 0 ; i < MAX_PLAYERS ; i++) { if(! global->player[i].playerid) continue; if(global->player[i].game != game->gameid) continue; if(global->player[i].playerid == game->my_playerid) continue; list = g_list_append(list, global->player[i].name); } gtk_combo_set_popdown_strings(GTK_COMBO(Combo), list); g_list_free(list); } /* playerlist in trade panel */ for(i = 0 ; i < MAX_TRADES ; i++) { if(! game->trade[i].open) continue; trade_rebuild_playerlist(i); } /* update sub component players in trade panel */ for(i = 0 ; i < MAX_TRADES ; i++) { if(! game->trade[i].open) continue; trade_rebuild_subcomponent(i); } } tmp = xmlGetProp(cur, "money"); if(tmp) { global->player[id].money = atoi(tmp); if(global->player[id].playerlist_LabelMoneyPlayer) gtk_label_set_text(GTK_LABEL(global->player[id].playerlist_LabelMoneyPlayer), tmp); g_free(tmp); } tmp = xmlGetProp(cur, "location"); if(tmp) { global->player[id].location_to = atoi(tmp); g_free(tmp); } tmp = xmlGetProp(cur, "jailed"); if(tmp) { global->player[id].jailed = atoi(tmp); g_free(tmp); game_update_tokens(); } tmp = xmlGetProp(cur, "directmove"); if(tmp) { global->player[id].directmove = atoi(tmp); g_free(tmp); game_start_move_token(global->player[id].playerid); } tmp = xmlGetProp(cur, "bankrupt"); if(tmp) { global->player[id].bankrupt = atoi(tmp); g_free(tmp); /* remove token */ if(global->player[id].bankrupt) pic_unshow(game->board_frame, global->player[id].token_pic); } tmp = xmlGetProp(cur, "hasturn"); if(tmp) { global->player[id].hasturn = atoi(tmp); g_free(tmp); /* set has turn attributes */ if(global->player[id].hasturn) { if(global->player[id].playerlist_LabelNamePlayer) { gtk_widget_set_style( gtk_object_get_data(GTK_OBJECT(global->player[id].playerlist_AlignementNamePlayer), "namelabel") , global->style_player_turn); gtk_widget_set_style( gtk_object_get_data(GTK_OBJECT(global->player[id].playerlist_AlignementMoneyPlayer), "moneylabel") , global->style_player_turn); } pic_unset_alpha(game->board_frame, global->player[id].token_pic); } else { if(global->player[id].playerlist_LabelNamePlayer) { gtk_widget_set_style( gtk_object_get_data(GTK_OBJECT(global->player[id].playerlist_AlignementNamePlayer), "namelabel") , global->style_player_normal); gtk_widget_set_style( gtk_object_get_data(GTK_OBJECT(global->player[id].playerlist_AlignementMoneyPlayer), "moneylabel") , global->style_player_normal); } if(config->game_token_transparency) pic_set_alpha(game->board_frame, global->player[id].token_pic, 0x7f); } } tmp = xmlGetProp(cur, "can_roll"); if(tmp) { global->player[id].can_roll = atoi(tmp); g_free(tmp); if(game->status == GAME_STATUS_RUN) { Button = gtk_object_get_data(GTK_OBJECT(game->CommandsBox), "roll_button"); if(global->player[id].can_roll) gtk_widget_show_all(Button); else gtk_widget_hide(Button); } } tmp = xmlGetProp(cur, "can_buyestate"); if(tmp) { global->player[id].can_buyestate = atoi(tmp); g_free(tmp); } game_buildplayerlist(); } void xmlparse_auctionupdate(guint32 connectid, xmlDocPtr doc, xmlNodePtr cur) { GtkWidget *text, *entry, *box; GtkTextBuffer *textbuff; GtkTextIter textiter; GtkTextMark *textmark; guint32 actor = 0, auctionid, estateid, highbid = 0, highbidder, len, status; guchar *ptr, *message, *tmp; tmp = xmlGetProp(cur, "auctionid"); if(!tmp) return; auctionid = atoi(tmp); g_free(tmp); /* initialise auction */ tmp = xmlGetProp(cur, "actor"); if(tmp) { actor = atoi(tmp); g_free(tmp); } tmp = xmlGetProp(cur, "estateid"); if(tmp) { estateid = atoi(tmp); g_free(tmp); display_hide(); interface_create_auctionbox(); gtk_object_set_data(GTK_OBJECT(game->BoardCenter), "auction_highbid", 0); text = gtk_object_get_data(GTK_OBJECT(game->BoardCenter), "auction_text"); entry = gtk_object_get_data(GTK_OBJECT(game->BoardCenter), "auction_entry"); ptr = g_strdup_printf("%d", auctionid); gtk_object_set_data_full(GTK_OBJECT(entry), "auctionid", ptr, g_free); message = g_strdup_printf("%s auction estate %s", global->player[ get_player_slot_with_playerid( actor ) ].name, game->estate[ estateid ].name); textbuff = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text)); gtk_text_buffer_get_end_iter(textbuff, &textiter); gtk_text_buffer_insert(textbuff, &textiter, message, strlen(message)); gtk_text_buffer_insert(textbuff, &textiter, "\n", -1); g_free(message); } /* bid */ tmp = xmlGetProp(cur, "highbid"); if(tmp) { highbid = atoi(tmp); gtk_object_set_data(GTK_OBJECT(game->BoardCenter), "auction_highbid", GINT_TO_POINTER(highbid)); g_free(tmp); } tmp = xmlGetProp(cur, "highbidder"); if(tmp) { highbidder = atoi(tmp); g_free(tmp); message = g_strdup_printf("%s bid %d", global->player[ get_player_slot_with_playerid(highbidder) ].name, highbid); text = gtk_object_get_data(GTK_OBJECT(game->BoardCenter), "auction_text"); textbuff = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text)); gtk_text_buffer_get_end_iter(textbuff, &textiter); gtk_text_buffer_insert(textbuff, &textiter, message, strlen(message)); gtk_text_buffer_insert(textbuff, &textiter, "\n", -1); /* Scroll the text */ textmark = gtk_text_buffer_get_mark(textbuff, "endmark"); gtk_text_view_scroll_to_mark(GTK_TEXT_VIEW(text), textmark, 0.0, FALSE, 0.0, 0.0); g_free(message); } /* status */ tmp = xmlGetProp(cur, "status"); if(tmp) { status = atoi(tmp); g_free(tmp); switch( status ) { case 1: text = gtk_object_get_data(GTK_OBJECT(game->BoardCenter), "auction_text"); message = g_strdup("<- going once ->"); textbuff = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text)); gtk_text_buffer_get_end_iter(textbuff, &textiter); gtk_text_buffer_insert(textbuff, &textiter, message, strlen(message)); gtk_text_buffer_insert(textbuff, &textiter, "\n", -1); /* Scroll the text */ textmark = gtk_text_buffer_get_mark(textbuff, "endmark"); gtk_text_view_scroll_to_mark(GTK_TEXT_VIEW(text), textmark, 0.0, FALSE, 0.0, 0.0); g_free(message); break; case 2: text = gtk_object_get_data(GTK_OBJECT(game->BoardCenter), "auction_text"); message = g_strdup("\n<- going twice ->"); textbuff = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text)); gtk_text_buffer_get_end_iter(textbuff, &textiter); gtk_text_buffer_insert(textbuff, &textiter, message, strlen(message)); gtk_text_buffer_insert(textbuff, &textiter, "\n", -1); /* Scroll the text */ textmark = gtk_text_buffer_get_mark(textbuff, "endmark"); gtk_text_view_scroll_to_mark(GTK_TEXT_VIEW(text), textmark, 0.0, FALSE, 0.0, 0.0); g_free(message); break; case 3: box = gtk_object_get_data(GTK_OBJECT(game->BoardCenter), "auctionbox"); if(box) gtk_widget_destroy(box); gtk_object_set_data(GTK_OBJECT(game->BoardCenter), "auctionbox", 0); display_clear_buttons(); /* FIXME: SERVER BUG ! */ display_unhide(); break; } } } void xmlparse_display(guint32 connectid, xmlDocPtr doc, xmlNodePtr cur) { xmlNodePtr cur2; gint32 estateid; guchar *tmp, *caption, *command; gboolean enable; if( game->status != GAME_STATUS_RUN) return; display_init(); tmp = xmlGetProp(cur, "cleartext"); if(tmp) { if( atoi(tmp) ) display_clear_text(); g_free(tmp); } tmp = xmlGetProp(cur, "clearbuttons"); if(tmp) { if( atoi(tmp) ) display_clear_buttons(); g_free(tmp); } tmp = xmlGetProp(cur, "estateid"); if(tmp) { estateid = atoi(tmp); g_free(tmp); if(estateid < 0) display_clear_title(); else display_estate(estateid); } tmp = xmlGetProp(cur, "text"); if(tmp) { if( strlen(tmp) > 0) display_text(tmp); g_free(tmp); } /* buttons */ for(cur2 = cur->xmlChildrenNode ; cur2 != NULL ; cur2 = cur2 -> next) { if(game->status == GAME_STATUS_END) continue; if(! xmlStrcmp(cur2->name, "button") ) { caption = xmlGetProp(cur2, "caption"); command = xmlGetProp(cur2, "command"); tmp = xmlGetProp(cur2, "enabled"); enable = atoi(tmp); g_free(tmp); display_button(caption, command, enable); g_free(caption); g_free(command); } } } void xmlparse_configupdate(guint32 connectid, xmlDocPtr doc, xmlNodePtr cur) { GtkWidget *CButton; xmlNodePtr cur2; guchar *text, *tmp, *title, *command; guint32 signalid; for( cur2 = cur->xmlChildrenNode ; cur2 != NULL ; cur2 = cur2 -> next) { if(! xmlStrcmp(cur2->name, "option") ) { tmp = xmlGetProp(cur2, "type"); if(!tmp) continue; if(xmlStrcmp(tmp, "bool") ) { g_free(tmp); continue; } g_free(tmp); command = xmlGetProp(cur2, "command"); if(!command) continue; /* create it if not created */ if(! gtk_object_get_data(GTK_OBJECT(game->GameConfigBox), command) ) { title = xmlGetProp(cur2, "title"); if(!title) continue; CButton = gtk_check_button_new_with_label(title); signalid = gtk_signal_connect(GTK_OBJECT(CButton), "toggled", (GtkSignalFunc)Callback_toggle_boolean_gameoption, NULL); gtk_box_pack_start(GTK_BOX(game->GameConfigBox), CButton, FALSE, FALSE, 0); /* store signal identifier */ text = g_strdup_printf("%d", signalid); gtk_object_set_data_full(GTK_OBJECT(CButton), "signal", text, g_free); /* store command under CButton */ text = g_strdup(command); gtk_object_set_data_full(GTK_OBJECT(CButton), "command", text, g_free); /* save the pointer of button for use in the future */ gtk_object_set_data(GTK_OBJECT(game->GameConfigBox), command, CButton); g_free(title); } /* modify */ CButton = gtk_object_get_data(GTK_OBJECT(game->GameConfigBox), command); tmp = xmlGetProp(cur2, "value"); if(tmp) { /* disconnect signal */ text = gtk_object_get_data(GTK_OBJECT(CButton), "signal"); gtk_signal_disconnect(GTK_OBJECT(CButton), atoi(text) ); if( atoi(tmp) ) gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(CButton), TRUE); else gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(CButton), FALSE); g_free(tmp); /* reconnect signal */ signalid = gtk_signal_connect(GTK_OBJECT(CButton), "toggled", (GtkSignalFunc)Callback_toggle_boolean_gameoption, NULL); text = g_strdup_printf("%d", signalid); gtk_object_set_data_full(GTK_OBJECT(CButton), "signal", text, g_free); } tmp = xmlGetProp(cur2, "edit"); if(tmp) { if( atoi(tmp) ) gtk_widget_set_sensitive(CButton, TRUE); else gtk_widget_set_sensitive(CButton, FALSE); g_free(tmp); } g_free(command); } } gtk_widget_show_all(game->GameConfigBox); } void xmlparse_tradeupdate(guint32 connectid, xmlDocPtr doc, xmlNodePtr cur) { xmlNodePtr cur2; guchar *tmp; guint32 tradeid = 0, playerid = 0, actor = 0, cardid = 0, estateid = 0; guint32 targetplayer = 0, playerfrom = 0, playerto = 0, money = 0; gboolean accept = FALSE; if( game->status != GAME_STATUS_RUN) return; tmp = xmlGetProp(cur, "tradeid"); if(tmp) { tradeid = atoi(tmp); g_free(tmp); } else return; tmp = xmlGetProp(cur, "actor"); if(tmp) { actor = atoi(tmp); g_free(tmp); } tmp = xmlGetProp(cur, "type"); if(tmp) { if(! xmlStrcmp(tmp, "rejected") ) { trade_destroy(tradeid); g_free(tmp); return; } if(! xmlStrcmp(tmp, "completed") ) { trade_destroy(tradeid); g_free(tmp); return; } if(! xmlStrcmp(tmp, "accepted") ) { g_free(tmp); return; } if(! xmlStrcmp(tmp, "new") ) { trade_initnew(tradeid); g_free(tmp); } } /* create trade panel if wasn't created (server bug I suppose) */ trade_initnew(tradeid); for(cur2 = cur->xmlChildrenNode ; cur2 != NULL ; cur2 = cur2 -> next) { /* -- player -- */ if(! xmlStrcmp(cur2->name, "tradeplayer") ) { tmp = xmlGetProp(cur2, "playerid"); if(tmp) { playerid = atoi(tmp); g_free(tmp); } tmp = xmlGetProp(cur2, "accept"); if(tmp) { accept = atoi(tmp); g_free(tmp); } trade_update_player(tradeid, playerid, accept); } /* -- card -- */ if(! xmlStrcmp(cur2->name, "tradecard") ) { tmp = xmlGetProp(cur2, "cardid"); if(tmp) { cardid = atoi(tmp); g_free(tmp); } tmp = xmlGetProp(cur2, "targetplayer"); if(tmp) { targetplayer = atoi(tmp); g_free(tmp); } trade_update_card(tradeid, cardid, targetplayer); } /* -- estate -- */ if(! xmlStrcmp(cur2->name, "tradeestate") ) { tmp = xmlGetProp(cur2, "estateid"); if(tmp) { estateid = atoi(tmp); g_free(tmp); } tmp = xmlGetProp(cur2, "targetplayer"); if(tmp) { targetplayer = atoi(tmp); g_free(tmp); } trade_update_estate(tradeid, estateid, targetplayer); } /* -- money -- */ if(! xmlStrcmp(cur2->name, "trademoney") ) { tmp = xmlGetProp(cur2, "playerfrom"); if(tmp) { playerfrom = atoi(tmp); g_free(tmp); } tmp = xmlGetProp(cur2, "playerto"); if(tmp) { playerto = atoi(tmp); g_free(tmp); } tmp = xmlGetProp(cur2, "money"); if(tmp) { money = atoi(tmp); g_free(tmp); } trade_update_money(tradeid, playerfrom, playerto, money); } } } void xmlparse_cardupdate(guint32 connectid, xmlDocPtr doc, xmlNodePtr cur) { guchar *tmp; gint32 cardid = 0, owner = 0, i; gint8 cardslot = 0; if( game->status != GAME_STATUS_RUN) return; tmp = xmlGetProp(cur, "cardid"); if(tmp) { cardid = atoi(tmp); g_free(tmp); } tmp = xmlGetProp(cur, "owner"); if(tmp) { owner = atoi(tmp); g_free(tmp); } /* create new card slot */ if(owner >= 0) { cardslot = get_card_slot_with_cardid(cardid); if(cardslot < 0) if(! game_get_valid_card_slot(&cardslot) ) return; game->card[cardslot].cardid = cardid; game->card[cardslot].owner = owner; } /* destroy a card slot */ else { cardslot = get_card_slot_with_cardid(cardid); if(cardslot < 0) return; game->card[cardslot].cardid = 0; game->card[cardslot].owner = 0; } /* update component list in trade panel */ for(i = 0 ; i < MAX_TRADES ; i++) { if(! game->trade[i].open) continue; trade_rebuild_component(i); trade_rebuild_subcomponent(i); } } void xmlparse_estategroupupdate(guint32 connectid, xmlDocPtr doc, xmlNodePtr cur) { guchar *tmp; gint32 groupid = -1; tmp = xmlGetProp(cur, "groupid"); if(tmp) { groupid = atoi(tmp); g_free(tmp); } if(groupid < 0) return; if(game->group[groupid].name) g_free(game->group[groupid].name); game->group[groupid].name = xmlGetProp(cur, "name"); } void xmlparse_deleteplayer(guint32 connectid, xmlDocPtr doc, xmlNodePtr cur) { guchar *tmp; gint32 playerid = -1, id; tmp = xmlGetProp(cur, "playerid"); if(tmp) { playerid = atoi(tmp); g_free(tmp); } if(playerid < 0) return; id = get_player_slot_with_playerid(playerid); if(id < 0) return; /* delete a player */ game_delete_player(id); game_buildplayerlist(); } void xmlparse_updategamelist(guint32 connectid, xmlDocPtr doc, xmlNodePtr cur) { gchar *type, *txt[10], *host, *port, *name, **text[2], *tmp; gint32 id, test, i; xmlNodePtr cur2; if(global->phase != PHASE_GETGAMES) { client_disconnect(connectid); return; } type = xmlGetProp(cur, "type"); if(!type) return; if(! xmlStrcmp(type, "full") ) { gtk_clist_freeze(GTK_CLIST(global->GameCList)); gameclist_title_showgames(); host = g_strdup( g_strstrip(connection[connectid]->host) ); port = g_strdup_printf("%d", connection[connectid]->port); /* remove all game from same host & port */ text[0] = g_malloc0(8192); text[1] = g_malloc0(8192); for(i = 0 ; ; i++) { test = gtk_clist_get_text(GTK_CLIST(global->GameCList), i, 0, text[0]); if(!test) break; test = gtk_clist_get_text(GTK_CLIST(global->GameCList), i, 5, text[1]); if(!test) break; if(! strncmp(host, *text[0], strlen(host)) && ! strncmp(port, *text[1], strlen(port))) { gtk_clist_remove(GTK_CLIST(global->GameCList), i); i--; } } g_free(text[0]); g_free(text[1]); for(cur2 = cur->xmlChildrenNode ; cur2 != NULL ; cur2 = cur2 -> next ) { if(! xmlStrcmp(cur2->name, "game") ) { tmp = xmlGetProp(cur2, "canbejoined"); if(tmp && atoi(tmp) == 0 ) { g_free(tmp); continue; } if(tmp) g_free(tmp); /* ONLY TEMPORARLY ! */ tmp = xmlGetProp(cur2, "gametype"); if(xmlStrcmp(tmp, "city") && xmlStrcmp(tmp, "french_city") ) { g_free(tmp); continue; } g_free(tmp); tmp = xmlGetProp(cur2, "id"); id = atoi(tmp); g_free(tmp); name = xmlGetProp(cur2, "name"); txt[0] = g_strdup(host); txt[1] = g_strdup(connection[connectid]->server_version); if(id < 0) txt[2] = g_strdup_printf("Create a new %s game", name); else txt[2] = g_strdup_printf("Join %s game #%d", name, id); txt[3] = xmlGetProp(cur2, "description"); txt[4] = xmlGetProp(cur2, "players"); txt[5] = g_strdup(port); txt[6] = xmlGetProp(cur2, "gametype"); txt[7] = xmlGetProp(cur2, "id"); gtk_clist_append(GTK_CLIST(global->GameCList), txt); for(i = 0 ; i < 8 ; i++) g_free(txt[i]); g_free(name); } } gtk_clist_thaw(GTK_CLIST(global->GameCList)); g_free(host); g_free(port); client_disconnect(connectid); } g_free(type); } void xmlparse_metaserver(guint32 connectid, guchar *buffer) { gchar *txt[10], *text; guchar *tmp; xmlDocPtr doc; xmlNodePtr cur, cur2; guint32 i, do_close = TRUE; doc = xmlParseMemory(buffer, strlen(buffer) ); if(doc == NULL) return; cur = xmlDocGetRootElement(doc); if (cur == NULL) { xmlFreeDoc(doc); return; } if( xmlStrcmp(cur->name, METASERVER_XMLROOTELEMENT) ) { xmlFreeDoc(doc); return; } gtk_clist_freeze(GTK_CLIST(global->GameCList)); if(connection[connectid]->type == CONNECT_TYPE_META_GETLIST) { gameclist_title_showservers(); gtk_clist_clear(GTK_CLIST(global->GameCList)); } else if(connection[connectid]->type == CONNECT_TYPE_META_GETGAME) { gameclist_title_showgames(); gtk_clist_clear(GTK_CLIST(global->GameCList)); } for(cur = cur->xmlChildrenNode ; cur != NULL ; cur = cur -> next) { if(! xmlStrcmp(cur->name, "metaserver") ) { tmp = xmlGetProp(cur, "version"); text = g_strdup_printf("Atlantic metaserver version %s", tmp); g_free(tmp); text_insert_message(text, strlen(text)); g_free(text); do_close = FALSE; } if(! xmlStrcmp(cur->name, "msg") ) { tmp = xmlGetProp(cur, "value"); text = g_strdup_printf("%s", tmp); g_free(tmp); interface_create_messagewin(text); g_free(text); do_close = FALSE; } if(connection[connectid]->type == CONNECT_TYPE_META_GETLIST && !xmlStrcmp(cur->name, "server") ) { txt[0] = xmlGetProp(cur, "host"); txt[1] = xmlGetProp(cur, "port"); txt[2] = xmlGetProp(cur, "version"); txt[3] = xmlGetProp(cur, "users"); txt[4] = g_strdup(""); txt[5] = g_strdup(""); txt[6] = g_strdup(""); txt[7] = g_strdup(""); gtk_clist_append(GTK_CLIST(global->GameCList), txt); for(i = 0 ; i < 8 ; i++) g_free(txt[i]); } if(connection[connectid]->type == CONNECT_TYPE_META_GETGAME && !xmlStrcmp(cur->name, "servergamelist") ) { guchar *host, *port, *version, *name; gint32 id; host = xmlGetProp(cur, "host"); port = xmlGetProp(cur, "port"); version = xmlGetProp(cur, "version"); for(cur2 = cur->xmlChildrenNode ; cur2 != NULL ; cur2 = cur2 -> next ) { if(! xmlStrcmp(cur2->name, "game") ) { tmp = xmlGetProp(cur2, "canbejoined"); if(tmp && atoi(tmp) == 0 ) { g_free(tmp); continue; } if(tmp) g_free(tmp); /* ONLY TEMPORARLY ! */ tmp = xmlGetProp(cur2, "gametype"); if(xmlStrcmp(tmp, "city") && xmlStrcmp(tmp, "french_city") ) { g_free(tmp); continue; } g_free(tmp); tmp = xmlGetProp(cur2, "id"); id = atoi(tmp); g_free(tmp); name = xmlGetProp(cur2, "name"); txt[0] = g_strdup(host); txt[1] = g_strdup(version); if(id < 0) txt[2] = g_strdup_printf("Create a new %s game", name); else txt[2] = g_strdup_printf("Join %s game #%d", name, id); txt[3] = xmlGetProp(cur2, "description"); txt[4] = xmlGetProp(cur2, "players"); txt[5] = g_strdup(port); txt[6] = xmlGetProp(cur2, "gametype"); txt[7] = xmlGetProp(cur2, "id"); gtk_clist_append(GTK_CLIST(global->GameCList), txt); for(i = 0 ; i < 8 ; i++) g_free(txt[i]); g_free(name); } } g_free(host); g_free(port ); g_free(version); } } gtk_clist_thaw(GTK_CLIST(global->GameCList)); xmlFreeDoc(doc); if(do_close) client_disconnect(connectid); }