Atrinik Client 2.5
client/main.c
Go to the documentation of this file.
00001 /************************************************************************
00002 *            Atrinik, a Multiplayer Online Role Playing Game            *
00003 *                                                                       *
00004 *    Copyright (C) 2009-2011 Alex Tokar and Atrinik Development Team    *
00005 *                                                                       *
00006 * Fork from Daimonin (Massive Multiplayer Online Role Playing Game)     *
00007 * and Crossfire (Multiplayer game for X-windows).                       *
00008 *                                                                       *
00009 * This program is free software; you can redistribute it and/or modify  *
00010 * it under the terms of the GNU General Public License as published by  *
00011 * the Free Software Foundation; either version 2 of the License, or     *
00012 * (at your option) any later version.                                   *
00013 *                                                                       *
00014 * This program is distributed in the hope that it will be useful,       *
00015 * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
00016 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
00017 * GNU General Public License for more details.                          *
00018 *                                                                       *
00019 * You should have received a copy of the GNU General Public License     *
00020 * along with this program; if not, write to the Free Software           *
00021 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.             *
00022 *                                                                       *
00023 * The author can be reached at admin@atrinik.org                        *
00024 ************************************************************************/
00025 
00030 #include <global.h>
00031 
00033 SDL_Surface *ScreenSurface;
00035 struct sockaddr_in insock;
00037 ClientSocket csocket;
00038 
00039 struct _fire_mode fire_mode_tab[FIRE_MODE_INIT];
00040 int RangeFireMode;
00041 
00043 server_struct *selected_server = NULL;
00044 
00046 static char argServerName[2048];
00048 static int argServerPort;
00049 
00051 uint32 LastTick;
00052 
00053 int f_custom_cursor = 0;
00054 int x_custom_cursor = 0;
00055 int y_custom_cursor = 0;
00056 
00057 /* update map area */
00058 int map_udate_flag, map_redraw_flag;
00059 
00061 help_files_struct *help_files;
00063 _game_status GameStatus;
00065 _anim_table *anim_table = NULL;
00066 Animations *animations = NULL;
00068 size_t animations_num = 0;
00069 
00071 struct screensize *Screensize;
00072 
00074 _face_struct FaceList[MAX_FACE_TILES];
00075 
00077 struct msg_anim_struct msg_anim;
00079 static time_t last_keepalive;
00080 
00082 static _bitmap_name bitmap_name[BITMAP_INIT] =
00083 {
00084     {"intro.png", PIC_TYPE_DEFAULT},
00085 
00086     {"player_doll_bg.png", PIC_TYPE_TRANS},
00087     {"login_inp.png", PIC_TYPE_DEFAULT},
00088     {"invslot.png", PIC_TYPE_TRANS},
00089 
00090     {"hp.png", PIC_TYPE_TRANS},
00091     {"sp.png", PIC_TYPE_TRANS},
00092     {"grace.png", PIC_TYPE_TRANS},
00093     {"food.png", PIC_TYPE_TRANS},
00094     {"hp_back.png", PIC_TYPE_DEFAULT},
00095     {"sp_back.png", PIC_TYPE_DEFAULT},
00096     {"grace_back.png", PIC_TYPE_DEFAULT},
00097     {"food_back.png", PIC_TYPE_DEFAULT},
00098 
00099     {"apply.png", PIC_TYPE_DEFAULT},
00100     {"unpaid.png", PIC_TYPE_DEFAULT},
00101     {"cursed.png", PIC_TYPE_DEFAULT},
00102     {"damned.png", PIC_TYPE_DEFAULT},
00103     {"lock.png", PIC_TYPE_DEFAULT},
00104     {"magic.png", PIC_TYPE_DEFAULT},
00105     {"fire_ready.png", PIC_TYPE_DEFAULT},
00106 
00107     {"range.png", PIC_TYPE_TRANS},
00108     {"range_marker.png", PIC_TYPE_TRANS},
00109     {"range_skill.png", PIC_TYPE_TRANS},
00110     {"range_skill_no.png", PIC_TYPE_TRANS},
00111     {"range_throw.png", PIC_TYPE_TRANS},
00112     {"range_throw_no.png", PIC_TYPE_TRANS},
00113     {"range_tool.png", PIC_TYPE_TRANS},
00114     {"range_tool_no.png", PIC_TYPE_TRANS},
00115     {"range_wizard.png", PIC_TYPE_TRANS},
00116     {"range_wizard_no.png", PIC_TYPE_TRANS},
00117 
00118     {"cmark_start.png", PIC_TYPE_TRANS},
00119     {"cmark_end.png", PIC_TYPE_TRANS},
00120     {"cmark_middle.png", PIC_TYPE_TRANS},
00121 
00122     {"textwin_scroll.png", PIC_TYPE_DEFAULT},
00123     {"inv_scroll.png", PIC_TYPE_DEFAULT},
00124     {"below_scroll.png", PIC_TYPE_DEFAULT},
00125 
00126     {"number.png", PIC_TYPE_DEFAULT},
00127     {"invslot_u.png", PIC_TYPE_TRANS},
00128 
00129     {"death.png", PIC_TYPE_TRANS},
00130     {"sleep.png", PIC_TYPE_TRANS},
00131     {"confused.png", PIC_TYPE_TRANS},
00132     {"paralyzed.png", PIC_TYPE_TRANS},
00133     {"scared.png", PIC_TYPE_TRANS},
00134     {"blind.png", PIC_TYPE_TRANS},
00135 
00136     {"quickslots.png", PIC_TYPE_DEFAULT},
00137     {"quickslotsv.png", PIC_TYPE_DEFAULT},
00138     {"inventory.png", PIC_TYPE_DEFAULT},
00139     {"inventory_bg.png", PIC_TYPE_DEFAULT},
00140 
00141     {"exp_border.png", PIC_TYPE_DEFAULT},
00142     {"exp_line.png", PIC_TYPE_DEFAULT},
00143     {"exp_bubble.png", PIC_TYPE_TRANS},
00144     {"exp_bubble2.png", PIC_TYPE_TRANS},
00145 
00146     {"main_stats.png", PIC_TYPE_DEFAULT},
00147     {"below.png", PIC_TYPE_DEFAULT},
00148 
00149     {"target_attack.png", PIC_TYPE_TRANS},
00150     {"target_talk.png", PIC_TYPE_TRANS},
00151     {"target_normal.png", PIC_TYPE_TRANS},
00152 
00153     {"warn_hp.png", PIC_TYPE_DEFAULT},
00154     {"warn_food.png", PIC_TYPE_DEFAULT},
00155 
00156     {"range_buttons_off.png", PIC_TYPE_DEFAULT},
00157     {"range_buttons_left.png", PIC_TYPE_DEFAULT},
00158     {"range_buttons_right.png", PIC_TYPE_DEFAULT},
00159 
00160     {"target_hp.png", PIC_TYPE_DEFAULT},
00161     {"target_hp_b.png", PIC_TYPE_DEFAULT},
00162 
00163     {"textwin_mask.png", PIC_TYPE_DEFAULT},
00164     {"slider_up.png", PIC_TYPE_TRANS},
00165     {"slider_down.png", PIC_TYPE_TRANS},
00166     {"slider.png", PIC_TYPE_TRANS},
00167 
00168     {"exp_skill_border.png", PIC_TYPE_DEFAULT},
00169     {"exp_skill_line.png", PIC_TYPE_DEFAULT},
00170     {"exp_skill_bubble.png", PIC_TYPE_TRANS},
00171 
00172     {"trapped.png", PIC_TYPE_TRANS},
00173     {"pray.png", PIC_TYPE_TRANS},
00174     {"book.png", PIC_TYPE_ALPHA},
00175     {"region_map.png", PIC_TYPE_TRANS},
00176     {"slider_long.png", PIC_TYPE_DEFAULT},
00177     {"invslot_marked.png", PIC_TYPE_TRANS},
00178     {"mouse_cursor_move.png", PIC_TYPE_TRANS},
00179     {"resist_bg.png", PIC_TYPE_DEFAULT},
00180     {"main_level_bg.png",PIC_TYPE_DEFAULT},
00181     {"skill_exp_bg.png",PIC_TYPE_DEFAULT},
00182     {"regen_bg.png",PIC_TYPE_DEFAULT},
00183     {"skill_lvl_bg.png",PIC_TYPE_DEFAULT},
00184     {"menu_buttons.png",PIC_TYPE_DEFAULT},
00185     {"player_info_bg.png",PIC_TYPE_DEFAULT},
00186     {"target_bg.png", PIC_TYPE_DEFAULT},
00187     {"textinput.png", PIC_TYPE_DEFAULT},
00188 
00189     {"square_highlight.png", PIC_TYPE_DEFAULT},
00190     {"servers_bg.png", PIC_TYPE_DEFAULT},
00191     {"servers_bg_over.png", PIC_TYPE_TRANS},
00192     {"news_bg.png", PIC_TYPE_DEFAULT},
00193     {"eyes.png", PIC_TYPE_DEFAULT},
00194     {"popup.png", PIC_TYPE_ALPHA},
00195     {"arrow_up.png", PIC_TYPE_DEFAULT},
00196     {"arrow_up2.png", PIC_TYPE_DEFAULT},
00197     {"arrow_down.png", PIC_TYPE_DEFAULT},
00198     {"arrow_down2.png", PIC_TYPE_DEFAULT},
00199     {"button_round.png", PIC_TYPE_DEFAULT},
00200     {"button_round_down.png", PIC_TYPE_DEFAULT},
00201     {"button_rect.png", PIC_TYPE_DEFAULT},
00202     {"button_rect_hover.png", PIC_TYPE_DEFAULT},
00203     {"button_rect_down.png", PIC_TYPE_DEFAULT},
00204     {"map_marker.png", PIC_TYPE_DEFAULT},
00205     {"loading_off.png", PIC_TYPE_DEFAULT},
00206     {"loading_on.png", PIC_TYPE_DEFAULT},
00207     {"button.png", PIC_TYPE_DEFAULT},
00208     {"button_down.png", PIC_TYPE_DEFAULT},
00209     {"checkbox.png", PIC_TYPE_TRANS},
00210     {"checkbox_on.png", PIC_TYPE_TRANS},
00211     {"content.png", PIC_TYPE_DEFAULT},
00212     {"icon_music.png", PIC_TYPE_ALPHA},
00213     {"icon_magic.png", PIC_TYPE_ALPHA},
00214     {"icon_skill.png", PIC_TYPE_ALPHA},
00215     {"icon_party.png", PIC_TYPE_ALPHA},
00216     {"icon_map.png", PIC_TYPE_ALPHA},
00217     {"icon_cogs.png", PIC_TYPE_ALPHA},
00218     {"icon_quest.png", PIC_TYPE_ALPHA},
00219     {"fps.png", PIC_TYPE_DEFAULT}
00220 };
00221 
00223 #define BITMAP_MAX (sizeof(bitmap_name) / sizeof(_bitmap_name))
00224 
00225 _Sprite *Bitmaps[BITMAP_MAX];
00226 
00227 static void init_game_data();
00228 static void delete_player_lists();
00229 static int load_bitmap(int index);
00230 
00233 static void delete_player_lists()
00234 {
00235     size_t i;
00236 
00237     for (i = 0; i < FIRE_MODE_INIT; i++)
00238     {
00239         fire_mode_tab[i].amun = FIRE_ITEM_NO;
00240         fire_mode_tab[i].item = FIRE_ITEM_NO;
00241         fire_mode_tab[i].skill = NULL;
00242         fire_mode_tab[i].spell = NULL;
00243         fire_mode_tab[i].name[0] = '\0';
00244     }
00245 }
00246 
00249 static void init_game_data()
00250 {
00251     size_t i;
00252 
00253     memset(&fire_mode_tab, 0, sizeof(fire_mode_tab));
00254 
00255     init_widgets_fromCurrent();
00256 
00257     init_map_data(0, 0, 0, 0);
00258 
00259     for (i = 0; i < BITMAP_MAX; i++)
00260     {
00261         Bitmaps[i] = NULL;
00262     }
00263 
00264     memset(FaceList, 0, sizeof(struct _face_struct) * MAX_FACE_TILES);
00265 
00266     init_keys();
00267     clear_player();
00268     text_input_clear();
00269 
00270     msg_anim.message[0] = '\0';
00271 
00272     start_anim = NULL;
00273 
00274     argServerName[0] = '\0';
00275     argServerPort = 13327;
00276 
00277     GameStatus = GAME_STATUS_INIT;
00278     map_udate_flag = 2;
00279     map_redraw_flag = 1;
00280     text_input_string_flag = 0;
00281     text_input_string_end_flag = 0;
00282     text_input_string_esc_flag = 0;
00283     csocket.fd = -1;
00284     RangeFireMode = 0;
00285     help_files = NULL;
00286 
00287     text_input_history_clear();
00288     delete_player_lists();
00289     metaserver_init();
00290 
00291     if (!setting_get_int(OPT_CAT_CLIENT, OPT_OFFSCREEN_WIDGETS))
00292     {
00293         widgets_ensure_onscreen();
00294     }
00295 
00296     SRANDOM(time(NULL));
00297 }
00298 
00300 #ifndef WIN32
00301 
00302 static void fatal_signal(int make_core)
00303 {
00304     if (make_core)
00305     {
00306         abort();
00307     }
00308 
00309     exit(0);
00310 }
00311 
00312 static void rec_sigsegv(int i)
00313 {
00314     (void) i;
00315 
00316     LOG(llevInfo, "\nSIGSEGV received.\n");
00317     fatal_signal(1);
00318 }
00319 
00320 static void rec_sighup(int i)
00321 {
00322     (void) i;
00323 
00324     LOG(llevInfo, "\nSIGHUP received\n");
00325     exit(0);
00326 }
00327 
00328 static void rec_sigquit(int i)
00329 {
00330     (void) i;
00331 
00332     LOG(llevInfo, "\nSIGQUIT received\n");
00333     fatal_signal(1);
00334 }
00335 
00336 static void rec_sigterm(int i)
00337 {
00338     (void) i;
00339 
00340     LOG(llevInfo, "\nSIGTERM received\n");
00341     fatal_signal(0);
00342 }
00343 #endif
00344 
00349 static void init_signals()
00350 {
00351 #ifndef WIN32
00352     signal(SIGHUP, rec_sighup);
00353     signal(SIGQUIT, rec_sigquit);
00354     signal(SIGSEGV, rec_sigsegv);
00355     signal(SIGTERM, rec_sigterm);
00356 #endif
00357 }
00358 
00362 static int game_status_chain()
00363 {
00364     char buf[1024];
00365 
00366     if (GameStatus == GAME_STATUS_INIT)
00367     {
00368         cpl.mark_count = -1;
00369         LOG(llevInfo, "GAMES_STATUS_INIT_1\n");
00370 
00371         map_udate_flag = 2;
00372         delete_player_lists();
00373         LOG(llevInfo, "GAMES_STATUS_INIT_2\n");
00374         sound_start_bg_music("orchestral.ogg", setting_get_int(OPT_CAT_SOUND, OPT_VOLUME_MUSIC), -1);
00375         clear_map();
00376         LOG(llevInfo, "GAMES_STATUS_INIT_3\n");
00377         LOG(llevInfo, "GAMES_STATUS_INIT_4\n");
00378         GameStatus = GAME_STATUS_META;
00379     }
00380     else if (GameStatus == GAME_STATUS_META)
00381     {
00382         metaserver_clear_data();
00383         map_udate_flag = 2;
00384 
00385         metaserver_add("127.0.0.1", 13327, "Localhost", -1, "local", "Localhost. Start server before you try to connect.");
00386 
00387         if (argServerName[0] != '\0')
00388         {
00389             metaserver_add(argServerName, argServerPort, argServerName, -1, "user server", "Server from command line -server option.");
00390         }
00391 
00392         metaserver_get_servers();
00393         GameStatus = GAME_STATUS_START;
00394     }
00395     else if (GameStatus == GAME_STATUS_START)
00396     {
00397         map_udate_flag = 2;
00398 
00399         if (csocket.fd != -1)
00400         {
00401             socket_close(&csocket);
00402         }
00403 
00404         clear_map();
00405         map_redraw_flag = 1;
00406         clear_player();
00407         reset_keys();
00408         GameStatus = GAME_STATUS_WAITLOOP;
00409     }
00410     else if (GameStatus == GAME_STATUS_STARTCONNECT)
00411     {
00412         map_udate_flag = 2;
00413         draw_info_format(COLOR_GREEN, "Trying server %s (%d)...", selected_server->name, selected_server->port);
00414         last_keepalive = time(NULL);
00415         GameStatus = GAME_STATUS_CONNECT;
00416     }
00417     else if (GameStatus == GAME_STATUS_CONNECT)
00418     {
00419         if (!socket_open(&csocket, selected_server->ip, selected_server->port))
00420         {
00421             draw_info(COLOR_RED, "Connection failed!");
00422             GameStatus = GAME_STATUS_START;
00423             return 1;
00424         }
00425 
00426         socket_thread_start();
00427         GameStatus = GAME_STATUS_VERSION;
00428         draw_info(COLOR_GREEN, "Connected. Exchange version.");
00429         cpl.name[0] = '\0';
00430         cpl.password[0] = '\0';
00431         region_map_clear();
00432     }
00433     else if (GameStatus == GAME_STATUS_VERSION)
00434     {
00435         SendVersion();
00436         GameStatus = GAME_STATUS_SETUP;
00437     }
00438     else if (GameStatus == GAME_STATUS_SETUP)
00439     {
00440         snprintf(buf, sizeof(buf), "setup sound 1 mapsize %"FMT64"x%"FMT64, setting_get_int(OPT_CAT_MAP, OPT_MAP_WIDTH), setting_get_int(OPT_CAT_MAP, OPT_MAP_HEIGHT));
00441         server_files_setup_add(buf, sizeof(buf));
00442         cs_write_string(buf, strlen(buf));
00443 
00444         GameStatus = GAME_STATUS_WAITSETUP;
00445     }
00446     else if (GameStatus == GAME_STATUS_REQUEST_FILES)
00447     {
00448         if (!server_files_updating())
00449         {
00450             server_files_load(1);
00451             GameStatus = GAME_STATUS_ADDME;
00452         }
00453     }
00454     else if (GameStatus == GAME_STATUS_ADDME)
00455     {
00456         cpl.mark_count = -1;
00457         SendAddMe();
00458         GameStatus = GAME_STATUS_LOGIN;
00459         /* Now wait for login request of the server */
00460     }
00461     else if (GameStatus == GAME_STATUS_LOGIN)
00462     {
00463         if (text_input_string_esc_flag)
00464         {
00465             draw_info(COLOR_RED, "Break login.");
00466             GameStatus = GAME_STATUS_START;
00467         }
00468 
00469         text_input_clear();
00470     }
00471     else if (GameStatus == GAME_STATUS_NAME)
00472     {
00473         /* We have a finished console input */
00474         if (text_input_string_esc_flag)
00475         {
00476             GameStatus = GAME_STATUS_LOGIN;
00477         }
00478         else if (text_input_string_flag == 0 && text_input_string_end_flag)
00479         {
00480             strcpy(cpl.name, text_input_string);
00481             LOG(llevInfo, "Login: send name %s\n", text_input_string);
00482             send_reply(text_input_string);
00483             GameStatus = GAME_STATUS_LOGIN;
00484         }
00485     }
00486     else if (GameStatus == GAME_STATUS_PSWD)
00487     {
00488         /* We have a finished console input */
00489         if (text_input_string_esc_flag)
00490         {
00491             GameStatus = GAME_STATUS_LOGIN;
00492         }
00493         else if (text_input_string_flag == 0 && text_input_string_end_flag)
00494         {
00495             strncpy(cpl.password, text_input_string, 39);
00496             cpl.password[39] = '\0';
00497 
00498             LOG(llevInfo, "Login: send password <*****>\n");
00499             send_reply(cpl.password);
00500             GameStatus = GAME_STATUS_LOGIN;
00501         }
00502     }
00503     else if (GameStatus == GAME_STATUS_VERIFYPSWD)
00504     {
00505         /* We have a finished console input */
00506         if (text_input_string_esc_flag)
00507         {
00508             GameStatus = GAME_STATUS_LOGIN;
00509         }
00510         else if (text_input_string_flag == 0 && text_input_string_end_flag)
00511         {
00512             LOG(llevInfo, "Login: send verify password <*****>\n");
00513             send_reply(text_input_string);
00514             GameStatus = GAME_STATUS_LOGIN;
00515         }
00516     }
00517     else if (GameStatus == GAME_STATUS_WAITFORPLAY)
00518     {
00519         clear_map();
00520         map_udate_flag = 2;
00521     }
00522 
00523     return 1;
00524 }
00525 
00528 static void load_bitmaps()
00529 {
00530     int i;
00531 
00532     /* add later better error handling here */
00533     for (i = 0; i <= BITMAP_INTRO; i++)
00534     {
00535         load_bitmap(i);
00536     }
00537 }
00538 
00543 static int load_bitmap(int idx)
00544 {
00545     char buf[2048];
00546     uint32 flags = 0;
00547 
00548     snprintf(buf, sizeof(buf), DIRECTORY_BITMAPS"/%s", bitmap_name[idx].name);
00549 
00550     if (bitmap_name[idx].type == PIC_TYPE_PALETTE)
00551     {
00552         flags |= SURFACE_FLAG_PALETTE;
00553     }
00554 
00555     if (bitmap_name[idx].type == PIC_TYPE_TRANS)
00556     {
00557         flags |= SURFACE_FLAG_COLKEY_16M;
00558     }
00559 
00560     if (idx >= BITMAP_INTRO && idx != BITMAP_TEXTWIN_MASK)
00561     {
00562         flags |= bitmap_name[idx].type == PIC_TYPE_ALPHA ? SURFACE_FLAG_DISPLAYFORMATALPHA : SURFACE_FLAG_DISPLAYFORMAT;
00563     }
00564 
00565     Bitmaps[idx] = sprite_load_file(buf, flags);
00566 
00567     if (!Bitmaps[idx] || !Bitmaps[idx]->bitmap)
00568     {
00569         LOG(llevBug, "load_bitmap(): Can't load bitmap %s\n", buf);
00570         return 0;
00571     }
00572 
00573     return 1;
00574 }
00575 
00578 void free_bitmaps()
00579 {
00580     size_t i;
00581 
00582     for (i = 0; i < BITMAP_MAX; i++)
00583     {
00584         sprite_free_sprite(Bitmaps[i]);
00585     }
00586 }
00587 
00590 static void play_action_sounds()
00591 {
00592     if (cpl.warn_statdown)
00593     {
00594         sound_play_effect("warning_statdown.ogg", 100);
00595         cpl.warn_statdown = 0;
00596     }
00597 
00598     if (cpl.warn_statup)
00599     {
00600         sound_play_effect("warning_statup.ogg", 100);
00601         cpl.warn_statup = 0;
00602     }
00603 
00604     if (cpl.warn_hp)
00605     {
00606         if (cpl.warn_hp == 2)
00607         {
00608             sound_play_effect("warning_hp2.ogg", 100);
00609         }
00610         else
00611         {
00612             sound_play_effect("warning_hp.ogg", 100);
00613         }
00614 
00615         cpl.warn_hp = 0;
00616     }
00617 }
00618 
00621 void list_vid_modes()
00622 {
00623     const SDL_VideoInfo* vinfo = NULL;
00624     SDL_Rect **modes;
00625     int i;
00626 
00627     LOG(llevInfo, "List Video Modes\n");
00628 
00629     /* Get available fullscreen/hardware modes */
00630     modes = SDL_ListModes(NULL, SDL_HWACCEL);
00631 
00632     /* Check if there are any modes available */
00633     if (modes == (SDL_Rect **) 0)
00634     {
00635         LOG(llevError, "No modes available!\n");
00636     }
00637 
00638     /* Check if resolution is restricted */
00639     if (modes == (SDL_Rect **) -1)
00640     {
00641         LOG(llevInfo, "All resolutions available.\n");
00642     }
00643     else
00644     {
00645         /* Print valid modes */
00646         LOG(llevInfo, "Available Modes\n");
00647 
00648         for (i = 0; modes[i]; ++i)
00649         {
00650             LOG(llevInfo, "  %d x %d\n", modes[i]->w, modes[i]->h);
00651         }
00652     }
00653 
00654     vinfo = SDL_GetVideoInfo();
00655     LOG(llevInfo, "VideoInfo: hardware surfaces? %s\n", vinfo->hw_available ? "yes" : "no");
00656     LOG(llevInfo, "VideoInfo: windows manager? %s\n", vinfo->wm_available ? "yes" : "no");
00657     LOG(llevInfo, "VideoInfo: hw to hw blit? %s\n", vinfo->blit_hw ? "yes" : "no");
00658     LOG(llevInfo, "VideoInfo: hw to hw ckey blit? %s\n", vinfo->blit_hw_CC ? "yes" : "no");
00659     LOG(llevInfo, "VideoInfo: hw to hw alpha blit? %s\n", vinfo->blit_hw_A ? "yes" : "no");
00660     LOG(llevInfo, "VideoInfo: sw to hw blit? %s\n", vinfo->blit_sw ? "yes" : "no");
00661     LOG(llevInfo, "VideoInfo: sw to hw ckey blit? %s\n", vinfo->blit_sw_CC ? "yes" : "no");
00662     LOG(llevInfo, "VideoInfo: sw to hw alpha blit? %s\n", vinfo->blit_sw_A ? "yes":  "no");
00663     LOG(llevInfo, "VideoInfo: color fill? %s\n", vinfo->blit_fill ? "yes" : "no");
00664     LOG(llevInfo, "VideoInfo: video memory: %dKB\n", vinfo->video_mem);
00665 }
00666 
00669 static void display_layer1()
00670 {
00671     SDL_FillRect(ScreenSurface, NULL, 0);
00672 
00673     if (GameStatus == GAME_STATUS_PLAY)
00674     {
00675         widget_map_render(cur_widget[MAP_ID]);
00676     }
00677 }
00678 
00681 static void display_layer2()
00682 {
00683     cpl.container = NULL;
00684 
00685     if (GameStatus == GAME_STATUS_PLAY)
00686     {
00687         cpl.win_inv_tag = get_inventory_data(cpl.ob, &cpl.win_inv_ctag, &cpl.win_inv_slot, &cpl.win_inv_start, &cpl.win_inv_count, INVITEMXLEN, INVITEMYLEN);
00688 
00689         cpl.real_weight = cpl.window_weight;
00690 
00691         cpl.win_below_tag = get_inventory_data(cpl.below, &cpl.win_below_ctag, &cpl.win_below_slot, &cpl.win_below_start, &cpl.win_below_count, INVITEMBELOWXLEN, INVITEMBELOWYLEN);
00692     }
00693 }
00694 
00697 static void display_layer3()
00698 {
00699     /* Process the widgets */
00700     if (GameStatus == GAME_STATUS_PLAY)
00701     {
00702         process_widgets();
00703     }
00704 }
00705 
00708 static void display_layer4()
00709 {
00710     if (GameStatus == GAME_STATUS_PLAY)
00711     {
00712         /* We have to make sure that these two get hidden right */
00713         /* sanity checks in case they don't exist */
00714         if (cur_widget[IN_CONSOLE_ID])
00715         {
00716             cur_widget[IN_CONSOLE_ID]->show = 0;
00717         }
00718         else
00719         {
00720             create_widget_object(IN_CONSOLE_ID);
00721         }
00722 
00723         if (cur_widget[IN_NUMBER_ID])
00724         {
00725             cur_widget[IN_NUMBER_ID]->show = 0;
00726         }
00727         else
00728         {
00729             create_widget_object(IN_NUMBER_ID);
00730         }
00731 
00732         if (cpl.input_mode == INPUT_MODE_CONSOLE)
00733         {
00734             do_console();
00735         }
00736         else if (cpl.input_mode == INPUT_MODE_NUMBER)
00737         {
00738             do_number();
00739         }
00740     }
00741 }
00742 
00745 static void DisplayCustomCursor()
00746 {
00747     if (f_custom_cursor == MSCURSOR_MOVE)
00748     {
00749         sprite_blt(Bitmaps[BITMAP_MSCURSOR_MOVE], x_custom_cursor - (Bitmaps[BITMAP_MSCURSOR_MOVE]->bitmap->w / 2), y_custom_cursor - (Bitmaps[BITMAP_MSCURSOR_MOVE]->bitmap->h / 2), NULL, NULL);
00750     }
00751 }
00752 
00758 int main(int argc, char *argv[])
00759 {
00760     int x, y, drag, done = 0;
00761     uint32 anim_tick, frame_start_time;
00762     size_t i;
00763     char version[MAX_BUF];
00764 
00765     init_signals();
00766 #ifndef WIN32
00767     br_init(NULL);
00768 #endif
00769     upgrader_init();
00770     settings_init();
00771     init_game_data();
00772     curl_init();
00773 
00774     while (argc > 1)
00775     {
00776         argc--;
00777 
00778         if (strcmp(argv[argc - 1], "-port") == 0)
00779         {
00780             argServerPort = atoi(argv[argc]);
00781             argc--;
00782         }
00783         else if (strcmp(argv[argc - 1], "-server") == 0)
00784         {
00785             strcpy(argServerName, argv[argc]);
00786 
00787             if (strchr(argv[argc], ':') != '\0')
00788             {
00789                 argServerPort = atoi(strrchr(argv[argc], ':') + 1);
00790                 *strchr(argServerName, ':') = '\0';
00791             }
00792 
00793             argc--;
00794         }
00795         else if (!strcmp(argv[argc], "-nometa"))
00796         {
00797             metaserver_disable();
00798         }
00799         else if (!strcmp(argv[argc], "-text-debug"))
00800         {
00801             text_enable_debug();
00802         }
00803         else
00804         {
00805             LOG(llevInfo, "Usage: %s [-server <name>] [-port <num>]\n", argv[0]);
00806             exit(1);
00807         }
00808     }
00809 
00810     if (SDL_Init(SDL_INIT_AUDIO | SDL_INIT_VIDEO) < 0)
00811     {
00812         LOG(llevBug, "Couldn't initialize SDL: %s\n", SDL_GetError());
00813         exit(1);
00814     }
00815 
00816     /* Start the system after starting SDL */
00817     system_start();
00818     list_vid_modes();
00819 
00820     if (!video_set_size())
00821     {
00822         LOG(llevError, "Couldn't set video size: %s\n", SDL_GetError());
00823     }
00824 
00825     sprite_init_system();
00826 
00827     SDL_EnableUNICODE(1);
00828 
00829     text_init();
00830 
00831     load_bitmaps();
00832 
00833     /* TODO: add later better error handling here */
00834     for (i = BITMAP_DOLL; i < BITMAP_MAX; i++)
00835     {
00836         load_bitmap(i);
00837     }
00838 
00839     sound_init();
00840     keybind_load();
00841     load_mapdef_dat();
00842     read_bmaps_p0();
00843     server_files_init();
00844 
00845     sound_start_bg_music("orchestral.ogg", setting_get_int(OPT_CAT_SOUND, OPT_VOLUME_MUSIC), -1);
00846 
00847     script_autoload();
00848 
00849     draw_info_format(COLOR_HGOLD, "Welcome to Atrinik version %s.", package_get_version_full(version, sizeof(version)));
00850     draw_info(COLOR_GREEN, "Init network...");
00851 
00852     if (!socket_initialize())
00853     {
00854         exit(1);
00855     }
00856 
00857     if (!clipboard_init())
00858     {
00859         draw_info(COLOR_RED, "Failed to initialize clipboard support, clipboard actions will not be possible.");
00860     }
00861 
00862     textwin_init();
00863     fps_init();
00864     settings_apply();
00865 
00866     LastTick = anim_tick = SDL_GetTicks();
00867 
00868     while (!done)
00869     {
00870         frame_start_time = SDL_GetTicks();
00871         done = Event_PollInputDevice();
00872 
00873         /* Have we been shutdown? */
00874         if (handle_socket_shutdown())
00875         {
00876             GameStatus = GAME_STATUS_INIT;
00877             /* Make sure no popup is visible. */
00878             popup_destroy_visible();
00879             list_remove_all();
00880             continue;
00881         }
00882 
00883         if (GameStatus > GAME_STATUS_CONNECT)
00884         {
00885             /* Send keepalive command every 2 minutes. */
00886             if (time(NULL) - last_keepalive > 2 * 60)
00887             {
00888                 cs_write_string("ka", 2);
00889                 last_keepalive = time(NULL);
00890             }
00891 
00892             DoClient();
00893         }
00894 
00895         if (GameStatus == GAME_STATUS_PLAY)
00896         {
00897             if (LastTick - anim_tick > 110)
00898             {
00899                 anim_tick = LastTick;
00900                 animate_objects();
00901                 map_udate_flag = 2;
00902             }
00903 
00904             play_action_sounds();
00905         }
00906 
00907         map_udate_flag = 2;
00908 
00909         if (map_udate_flag > 0)
00910         {
00911             display_layer1();
00912             display_layer2();
00913             display_layer3();
00914             display_layer4();
00915 
00916             if (GameStatus != GAME_STATUS_PLAY)
00917             {
00918                 SDL_FillRect(ScreenSurface, NULL, 0);
00919             }
00920 
00921             map_udate_flag = 0;
00922         }
00923 
00924         /* If not connected, walk through connection chain and/or wait for action */
00925         if (GameStatus != GAME_STATUS_PLAY)
00926         {
00927             if (!game_status_chain())
00928             {
00929                 LOG(llevError, "Error connecting: GameStatus: %d  SocketError: %d\n", GameStatus, socket_get_error());
00930             }
00931         }
00932 
00933         /* Show the current dragged item */
00934         if ((drag = draggingInvItem(DRAG_GET_STATUS)))
00935         {
00936             object *Item = NULL;
00937 
00938             if (drag == DRAG_IWIN_INV)
00939             {
00940                 Item = object_find(cpl.win_inv_tag);
00941             }
00942             else if (drag == DRAG_IWIN_BELOW)
00943             {
00944                 Item = object_find(cpl.win_below_tag);
00945             }
00946             else if (drag == DRAG_QUICKSLOT)
00947             {
00948                 Item = object_find(cpl.dragging.tag);
00949             }
00950             else if (drag == DRAG_PDOLL)
00951             {
00952                 Item = object_find(cpl.win_pdoll_tag);
00953             }
00954 
00955             SDL_GetMouseState(&x, &y);
00956 
00957             if (drag == DRAG_QUICKSLOT_SPELL)
00958             {
00959                 blit_face(cpl.dragging.spell->icon, x, y);
00960             }
00961             else
00962             {
00963                 blt_inv_item_centered(Item, x, y);
00964             }
00965         }
00966 
00967         if (GameStatus <= GAME_STATUS_WAITFORPLAY)
00968         {
00969             show_meta_server();
00970         }
00971 
00972         /* Show all kind of the big dialog windows */
00973         show_menu();
00974 
00975         tooltip_show();
00976 
00977         if (f_custom_cursor)
00978         {
00979             DisplayCustomCursor();
00980         }
00981 
00982         LastTick = SDL_GetTicks();
00983 
00984         script_process();
00985         popup_draw();
00986 
00987         SDL_Flip(ScreenSurface);
00988 
00989         if (!setting_get_int(OPT_CAT_CLIENT, OPT_SLEEP_TIME))
00990         {
00991             uint32 elapsed_time = SDL_GetTicks() - frame_start_time;
00992 
00993             if (elapsed_time < 1000 / FRAMES_PER_SECOND)
00994             {
00995                 SDL_Delay(1000 / FRAMES_PER_SECOND - elapsed_time);
00996             }
00997         }
00998         else
00999         {
01000             SDL_Delay(setting_get_int(OPT_CAT_CLIENT, OPT_SLEEP_TIME));
01001         }
01002 
01003         fps_do();
01004     }
01005 
01006     system_end();
01007 
01008     return 0;
01009 }